next up previous
Next: Nested environments Up: Identifier classification Previous: Tracking current context


Binding identifier occurrences

IdnOrType saves information about the identifier it classifies. If this is a defining occurrence of an ordinary identifier, and binding is permitted, then the given identifier should be bound in the current scope with the appropriate classification.

State variable declarations[37]:

typedef struct {
  int BindingOK;   /* 1 if binding is allowed */
  int Symbol;      /* Identifier to be bound */
  Environment Env; /* Environment in which to bind */
  int SynCode;     /* Identifier classification */
} BindData;

extern BindData CurrentId;
This macro is defined in definitions 30, 37, and 39.
This macro is invoked in definition 56.

Scope rules are embodied in the concept of an environment, which is a set of bindings for identifiers. The Eli library's envmod module implements a countour-model environment suitable for classifying C identifiers:

Instantiate an environment module for identifier analysis[38]:

$/Name/envmod.specs
This macro is invoked in definition 57.

State variable declarations[39]:

extern Environment CurrentEnv;
This macro is defined in definitions 30, 37, and 39.
This macro is invoked in definition 56.

Initialize the set of bindings[40]:

CurrentEnv = NewEnv();
This macro is invoked in definition 59.

IdnOrType captures the current state, adds the specific identifier, and determines the appropriate classification:

Instance information for binding[41]:

CurrentId.BindingOK = Context.BindingOK;
CurrentId.Symbol    = *rep;
CurrentId.Env       = CurrentEnv;
CurrentId.SynCode   = Context.SynCode == typedef_def ? typedef_name
                                                     : identifier;
This macro is invoked in definition 28.

The environment module binds the identifier to a definition table key; the classification must be stored as a property of that key:

Phrase.pdl[42]:

SynCode: int;
This macro is attached to a product file.

Bind(void)[43]:

{
  if (CurrentId.BindingOK)
    ResetSynCode(DefineIdn(CurrentId.Env, CurrentId.Symbol), CurrentId.SynCode);
}
This macro is invoked in definition 55.

In some constructs the state must be saved and the actual binding made when the end of that construct is reached; in other cases the binding must be done immediately. Deferred bindings are nested, so they can be stored on a stack:

Instantiate a stack module for deferred bindings[44]:

$/Adt/Stack.gnrc +instance=Bind +referto=BindData :inst
This macro is invoked in definition 57.

Defer the binding[45]:
BindStackPush(CurrentId);
This macro is invoked in definition 17.

Deferred binding[46]:
CurrentId = BindStackTop; BindStackPop; Bind();
This macro is invoked in definitions 12, 17, and 27.

Bind[47]:
Bind();
This macro is invoked in definitions 15 and 17.


next up previous
Next: Nested environments Up: Identifier classification Previous: Tracking current context
2008-08-30