Scoping

From ABL
Jump to: navigation, search

Scoping isn't particularly difficult in ABL. But in order to code efficiently in ABL one must understand it thoroughly. Scoping is lexical but because of the various syntactic constructs, at certain points identifiers are in scope when one might not expect it.

One scope B is said to be lower than A iff B is lexically contained in A. For example,

sequential behavior A() { // scope A
    mental_act { // scope B
        // ...
    }
}

There are three scopes: global scope, behavior scope, and step scope.

Global Scope

Any identifier declared inside a behavior unit but outside any behavior is declared in global scope. One may refer to such an identifier inside a behavior definition or lower scope, or below the declaration in global scope.

For Example:

    ReasonWME reason = null;

...

    sequential behavior Bind() {
	precondition{temp=(ReasonWME)}
	mental_act{ reason = temp;}
    }

    initial_tree {
	with (priority 200000) subgoal Bind();
        subgoal Strategy();
    }

Behavior Scope

A behavior scope identifier is accessible only lexically within its associated behavior, or in a lower scope.

Declaring Constructs

The following are collectively called test expressions.

  1. context_condition with a binding constraint.
  2. precondition with a binding constraint.

For example, here is a compiling behaving entity which declares a variable in a context condition constraint.

behaving_entity ContextConditionDeclares {

    wme TestWME {
        boolean field;
    }

    sequential behavior Foo() {
        // `stuff' should be in scope below the precondition.
        context_condition {(TestWME field :: stuff)}

        mental_act {
            System.out.println(stuff);
        }
    }

    initial_tree {
        subgoal Foo();
    }
}

Shadowing

The test expressions described above are sequentially bound. That is, the following test expressions will do what you expect, so long as you expect the right thing:

... behavior A() {
    precondition {(OneWME field1 :: a)
                  (TwoWME field2 :: a)}

    // ... reference to a
    // which will contain whatever was in TwoWME.field2
}

As long as TwoWME.field2 is a subtype of OneWME.field1.

Step Scope

A step scope identifier may be referred to inside a step or in a lower scope.

Annotations for a step, such as success tests, introduce a scope of their own which extends to the lexical end of a step. For example,

 with (success_test {(SomeWME field == "value")
                     (SomeWME field2 :: binding)})
    subgoal Something(binding);

will put Something into the Active Behavior Tree with the current value of SomeWME.field2, if SomeWME.field == false, and otherwise proceed to the step after the subgoal.

Generally, step scope is more useful to know about than to use. You need to know about it so that you don't expect the scope of binding above to continue beyond the subgoal associated with the annotation.