Handling Global Information


Gentle encourages a declarative style of programming. However, there are cases in which non declarative elements are appropriate.

One problem is parameter lists that tend to get too long if every bit of context information is passed explicitly.

Consider a programming language that features a loop-statement and exit-statement and specifies that an exit-statement can only occur inside a loop statement. To check this constraint, the predicate that processes statements would have to be equipped with a parameter indicating whether one is inside or outside a loop. This parameter must be passed for each statement, e.g. an if-statement, because a constituent of that statement - e.g. the then-part - could contain an exit-statement. On the other hand, the constraint checking involves only the loop-statement and the exit-statement.

Gentle provides global variables. They are often used to represent a concept that is global to the concept processed by a particular rule.

A global variable is introduced by a declaration of the form

  • 'var' Name : Type
For example,

   'var' CurLoopContext: LoopContext
declares a global variable with the name CurLoopContext of type LoopContext (for which we assume values inside and outside).

This variable cannot be used inside expressions and patterns. The only way to manipulate and inspect its value is the update statement and the query statement that can be used as a member in a rule body.

The update statement has the form

  • Name <- Expression
which assigns the value of the Expression to the variable given by Name.

For example,

   CurLoopContext <- outside
sets the variable CurLoopContext to outside. The old value of the variable gets lost.

The query statement has the form

  • Name -> Pattern
It takes the value of the variable and matches it against the given pattern. This may succeed, defining the variable inside the pattern. It may also fail, in which case the query statements fails.

For example,

   CurLoopContext -> outside
succeeds only if the variable holds the value outside.

   CurLoopContext -> K
defines a new local variable of type LoopContext whose value is the current value of CurLoopContext.

It is an error to access a global variable in a query statement if the variable has not been defined by a preceding update statement. This error is checked when the query statement is executed. Hence, term data structures cannot be corrupted by uninitialized global variables.

We now show how the above loop exit constraint can be checked. Assume that a predicate ProcessStatement traverses the abstract syntax of statements (we leave out all details). This could be extended at two points:

   'rule' ProcessStatement(loop(Body)):
      CurLoopContext -> OldLoopContext
      CurLoopContext <- inside
      CurLoopContext <- OldLoopContext

   'rule' ProcessStatement(exit):
      CurLoopContext -> K