Identifier

This module represents the semantics of identifiers in the expression language (see expr.bnf)..

  import number

Needed to obtain access to class Number and constructor new_number.

  export Identifier, new_identifier

Exports class Identifier and constructor new_identifier for use by other modules. In this case, only module to use Identifier would be the main module of an expression program (when translated into Slim).

  Identifier : set of Entity := {}

This sets up Identifier as a set of objects. Initially, the set is empty. It is populated with objects as new Identifier objects are created. In other words, Identifier always represents the current instances of class Identifier. Class Identifier is not explicitly declared, but is treated as one and the same as the set of instances.

  name : map from Identifier to String

Name is an associative array that can be indexed with values of type Identifier. Thus name(x) can be set to a string value which represents the name of identifier x. In other words, this declaration sets up name as a string valued attribute of class Identifier. Name need not be exported since every object of class Identifier carries the entire name space of this module with it.

  stored_value : map from String to Number

Every leaf node in the Abstract Syntax Tree (AST) corresponding to an identifier will instantiate a new identifier object when called. In other words, when expression a+a is evaluated, two identifier objects will be created. Since both of them should evaluate to the same value, the value of identifier is not stored as an attribute of the identifier object, but in a separate associative array.

  func new_identifier(n : String) -> Identifier
    result := new(Identifier)
    name(result) := n

This constructs an instance of class Identifier and initializes the only attribute. Following a call to new(Identifier) the new instance is automatically added to Identifier, the set of instances of class Identifier.

  func value(self : Identifier) -> Number
    result := stored_value(name(self))
    if result = Undefined
      repeat
        put name(self)`?' & get v
      until v in number !number is the built-in numeric type
      result := new_number(mkstr(v))
      stored_value(name(self)) := result
    end

The EBNF syntax (expr.bnf) ensures that this method is called whenever an identifier appears in an expression. An expression such as a + 1 translates into

  plus(value(new_identifier(`a')), new_number(`1'))  

The method looks up the value of the identifier, if known. If the value is not known, it obtains it interactively from the user and stores it for future look ups. In other words, for an expression such as a+a, only the first call to value(new_identifier(`a')) will cause an input operation. Note that different instances of class Identifier will access the same storage location if they have the same name.