Expressions in Gamma consist of a few basic types, which are submitted to an evaluator to produce a return value. Every evaluation returns a result. Any Gamma object may be submitted to the evaluator. The evaluator behaves differently according to the type of the evaluated object.
Table 11.1. Type Evaluation
Type of Object | Evaluation result |
---|---|
symbol | The value of the symbol in the current scope. |
list | Function or method call. |
all others | Itself. |
If a symbol is being used as a variable, then its value will depend on the scope in which it is being evaluated. A new scope is entered whenever a user-defined function is executed, or when a with statement is executed. A symbol is defined within a scope when it appears in the argument list of a function, or when it appears in the variable list of a local statement. If a symbol is not defined within the current scope, then the value of the symbol in the next most local scope is used. This is called dynamic scoping, since the scope of a symbol used in a function may depend on the calling sequence that executed that function. The value of a symbol may be any Gamma object. See examples on dynamic scoping in Tutorial II.
Since Gamma is built on top of Lisp, all Gamma statements and expressions are translated into lists, which represent the equivalent function call. For example, the expression 2 + 3; is translated into the function call (+ 2 3) at read time, and evaluated as a list at run time. (Operators like + are functions in Lisp.) For more details on Lisp function syntax, see Getting On_Line Help for Functions.
When a list is submitted to the evaluator, it will be treated as either a function call or a method call. The first element in the list is evaluated, and the result examined. If the first element evaluates to a function definition, then the remainder of the list is treated as the arguments to this function, and the function is called. If the first element evaluates to an instance of a class, then the second element is evaluated.
If the second element evaluates to a class, then the third argument must be a symbol that names a method for that class. If the second element does not evaluate to a class, then it must be a symbol that names a method for the class of the instance, or a method of one of the instance's parent classes.
Once a method has been identified, the remaining elements of the list are treated as the arguments to the method, and the method is called on the instance. For example, here we call a function with the given arguments:
(function arg1 arg2...)
Here we call a method from an instance's own class.
(instance method_name arg1 arg2...)
And here we call a method from the instance's class hierarchy.
(instance class method_name arg1...)
If an explicit class is provided, it is normally a parent (base) class of the given instance. This is not enforced by the evaluator, so it is possible to call a method for an instance which is not a member of the class for which the method was defined. This is not normally a good idea, and can be highly confusing to anybody reading the code.
Most Gamma object types evaluate to themselves, meaning that the result of submitting the object to the evaluator is the object which was submitted, unmodified. Any object except a list or a symbol will simply return itself when evaluated. For example, the number 5, when evaluated, will return 5, which is itself.
Copyright © 1995-2010 by Cogent Real-Time Systems, Inc. All rights reserved.