Programming Language for Old Timers

by David A. Moon
February 2006 .. September 2008

Comments and criticisms to dave underscore moon atsign alum dot mit dot edu.

Previous page   Table of Contents   Next page

Def Statement

The def statement is the most commonly used defining statement in PLOT, hence an abbreviated name is justified. It can define a method, a variable, or multiple variables. Variables can be fixed or assignable. Variables can have declared types. The definition can be in a local scope or in the global scope, whichever is the current scope.

The term "variable" is used for traditional reasons, although most definitions are fixed, so the "variable" cannot actually vary.

When defining one or more variables, the def statement evaluates an initial value expression and gives successive values of the expression to successive variables. If the expression does not return sufficient values, the initial values for the remaining variables are false. If the initial value expression is preceded by =, the variable definitions are fixed. If the initial value expression is preceded by :=, the variable definitions are assignable.

When defining a method, the def statement first defines a function, unless the name is already defined in the current scope. Note that if the current scope is a local scope, this definition must be directly in the current scope, not inherited from an enclosing scope. The name must be defined as a function or an operator. Next, the def statement creates a method and adds it to the function or operator.

The syntax of the def statement is as follows. This has been simplified to make it more readable at the cost of not being LL(1).

defmacro def
  ;; variable definition form
  { ?:typed-variable & ~^ , }+ ~^ { = | := } ?value => ...

  ;; method definition form
  ?:method-head [ { first: | last: | next: ?n is name } |
                  sealed: | subsumptive: | intrinsic: ?i is name ]*
                ?:block => ...

In reality, the syntax of a def statement is disambiguated as follows: If the first token after def is a name with a known definition as an operator or a macro (including left parenthesis), then the statement is a method definition and begins with a method-head. Otherwise the statement begins with a typed-variable. If the next token after the typed-variable is a comma, the statement is a multiple variable definition. If the next token after the typed-variable is = or :=, the statement is a single token definition. Otherwise, the statement is a method definition and the typed-variable is the beginning of a method-head. If the typed-variable is followed by a left parenthesis, it is a syntax error if a type was specified since method-head does not allow a type there.

Note that the method-head cannot use the infix-operator form with operators = and := unless the left-hand-side argument to the operator is parenthesized, because of syntactic ambiguity. If present following a typed-variable these particles will be parsed as indications of the variable definition form.

The method option keywords between the method-head and the body block have the following meanings:

first: Dispatch to this method before the main method and before any first methods that are less specific.
last: Dispatch to this method after the main method and after any last methods that are less specific.
next: name In the body of this method, the specified name will be defined to be a function that can be called to invoke the next most specific applicable main method. By convention, a method usually passes its own arguments unchanged when calling the next method this way, but any arguments can be passed. An error occurs if the next method is not applicable to those arguments.
sealed: This method must always be the most specific when applicable. The compiler can optimize based on the knowledge that this method cannot be overridden by a more specific method.
subsumptive: This method has equivalent effect to any more specific method when both are applicable. This enables certain special cases of compiler optimization.
intrinsic: name The compiler has special knowledge of this method under the specified name.

If neither first: nor last: is present, this is a main method.

An example usage of subsumptive methods:

def (x is simple-name) = (y is anything) subsumptive: x eq y
def (x is anything) = (y is simple-name) subsumptive: x eq y
This says that = on simple-names is always eq, and nothing other than a simple-name can be = to a simple-name, without considering what other methods might be defined for =.

Previous page   Table of Contents   Next page