Eli   Documents

General Information

 o Eli: Translator Construction Made Easy
 o Global Index
 o Frequently Asked Questions
 o Typical Eli Usage Errors

Tutorials

 o Quick Reference Card
 o Guide For new Eli Users
 o Release Notes of Eli
 o Tutorial on Name Analysis
 o Tutorial on Scope Graphs
 o Tutorial on Type Analysis
 o Typical Eli Usage Errors

Reference Manuals

 o User Interface
 o Eli products and parameters
 o LIDO Reference Manual
 o Typical Eli Usage Errors

Libraries

 o Eli library routines
 o Specification Module Library

Translation Tasks

 o Lexical analysis specification
 o Syntactic Analysis Manual
 o Computation in Trees

Tools

 o LIGA Control Language
 o Debugging Information for LIDO
 o Graphical ORder TOol

 o FunnelWeb User's Manual

 o Pattern-based Text Generator
 o Property Definition Language
 o Operator Identification Language
 o Tree Grammar Specification Language
 o Command Line Processing
 o COLA Options Reference Manual

 o Generating Unparsing Code

 o Monitoring a Processor's Execution

Administration

 o System Administration Guide

Mail Home

Tutorial for Name Analysis Using ScopeGraphs

Previous Chapter Next Chapter Table of Contents


Predefined Identifiers

Most programming languages use pre-defined identifiers to represent a few basic entities. For example, it would be useful for NameLan to have a pre-defined class Object. The effect would be as though the following class had a defining occurrence in the range of the compilation:

class Object {
  int hashCode() { }
}

Object would act as the direct superclass of any class that did not specify a direct superclass. The result would be that Object is a superclass of every class, and all classes inherit the entities declared in Object unless those entities are hidden. A variable of type Object could hold a reference to an object of any class. Here is a program that uses these properties:

object.nl[145]==

class C {
  int h() { hashCode(); }
}

class D { }

{ C c; c.hashCode();
  D d; d.hashCode();
  Object o; o.hashCode();
}
This macro is attached to a non-product file.

This chapter explains how to extend NameLan with a pre-defined Object superclass.

Pre-defined identifiers have no actual defining occurrences in the program text, so their bindings must be created by the generated processor. Eli provides a module (SGPreDefId) to support specification of pre-defined identifiers (see Pre-defined Identifiers of Name Analysis Reference Manual).

The developer needs to instantiate SGPreDefId with the instance parameter that was used in the instantiation of the ScopeGraphs module in which the pre-definitions must be implemented. The scope rules for both the pre-defined class Object and the entities declared in its body are implemented by the set of four isomporphic scope graphs discussed in Section 5.1 (see Reusing identifiers in the same scope). Those scope graphs are supported by our first instantiation of the ScopeGraphs module (see Basic Scope Rules of Name analysis according to scope rules). That instantiation carried no instance parameter, so we also instantiate the SGPreDefId module with no instance parameter:

Specification files[146]==

$/Name/SGPreDefId.gnrc  +referto=(Predef.d)     :inst
$/Tech/MakeName.gnrc    +instance=Ident         :inst
This macro is defined in definitions 12, 16, 23, 27, 74, 78, 81,
   91, 117, 121, 139, 142, 146, and 152.
This macro is invoked in definition 13.

We use the operations provided by SGPreDefId to pre-define two identifiers, Object and hashCode, and the scope graph node tuple owned by the class Object. Each predefinition is established by an appropriate macro call (see Pre-defined Identifiers of Name Analysis Reference Manual).

Object
The identifier Object is bound to the known key ObjectKey in the root environment of the scope graph for classes:

Scope graph node
The NodeTuplePtr value defining the environment of the class Object is created and assigned to ObjectEnv:

hashCode
The identifier hashCode is bound to the known key hashCodeKey in the ObjectEnv environment of the scope graph for methods:

The three macro calls appear in the file whose name was given by the SGPreDefId instantiation's referto parameter:

Predef.d[147]==

PreDefKeyNdx ("Object", ObjectKey, classGraph)
PreDefNode(ObjectKey, ObjectEnv)
PreDefKeyEnvNdx("hashCode", hashCodeKey, ObjectEnv, methodGraph)
This macro is attached to a non-product file.

The developer must define ObjectKey and hashCodeKey as known keys, with appropriate properties set (see How to declare properties of Property definition language).

Properties and property computations[148]==

"ScopeGraphs.h"
ObjectKey       -> GraphIndex={classGraph}, IsType={1};
hashCodeKey     -> GraphIndex={methodGraph};
This macro is defined in definitions 79, 94, 126, 132, 143, and 148.
This macro is invoked in definition 80.

See Multiple Scope Graphs, for the GraphIndex property. See Connect to the Typing module, for the IsType property.

ObjectEnv is a NodeTuplePtr-valued variable that will hold the generated node tuple owned by the class Object (see Pre-defined Identifiers of Name Analysis Reference Manual). The developer must establish this variable in a C file and provide an appropriate header file:

Predef.c[149]==

#include "Predef.h"
NodeTuplePtr ObjectEnv; /* Establish the variable ObjectEnv */
This macro is attached to a product file.

Predef.h[150]==

#ifndef PREDEF_H        /* Prevent multiple inclusions */
#define PREDEF_H
#include "Model.h"      /* Define the NodeTuplePtr type */
extern NodeTuplePtr ObjectEnv;
#endif
This macro is attached to a product file.

ObjectEnv will be referred to in generated code, so the developer needs to ensure that `Predef.h' is included in that generated code (see Implementing Tree Computations of LIDO -- Computations in Trees).

Predef.head[151]==

#include "Predef.h"
This macro is attached to a product file.

These three files are all additional specifications:

Specification files[152]==

Predef.head
Predef.h
Predef.c
This macro is defined in definitions 12, 16, 23, 27, 74, 78, 81,
   91, 117, 121, 139, 142, 146, and 152.
This macro is invoked in definition 13.

This completes the pre-definition of Object. We now need to establish path edges to Object from each class using the default inheritance (see Classes). The relevant abstract syntax is:

RULE: Inheritance ::= Default   END;
RULE: Default     ::=           END;
The computation is close to that for specific super classes (see Inheritance). It uses the BoundEdge role instead of the WLCreateEdge role because the edge tip is known (see Path edge creation roles of Name Analysis Reference Manual).

Abstract syntax tree[153]==

SYMBOL Default INHERITS BoundEdge COMPUTE
  SYNT.tailEnv = INCLUDING Inheritance.SubClassEnv;
  SYNT.tipEnv = ObjectEnv;
END;
This macro is defined in definitions 10, 18, 22, 38, 47, 52, 53,
   65, 69, 71, 88, 89, 92, 93, 95, 96, 101, 105, 108, 110, 111,
   112, 113, 122, 133, 134, 135, 136, 137, 144, and 153.
This macro is invoked in definition 11.

Exercises

These exercises are based on files defined in the Tutorial. To obtain copies of those files in your current directory, enter Eli and give the following command:

-> $elipkg/Name/LearnSG%Predef > .

None of these files will have write permission in your current directory.

  1. Draw the scope graph that will be created for `object.nl'. Which nodes and edges were created by the pre-definition module?

  2. Use file `Bindings.specs' to generate a processor named `pd' that will show bindings for applied occurrences, and apply it to `object.nl'. Is the result what you expected?

  3. Why does `pd' not report applied occurrences of the predefined identifiers Object and hashCode?


Previous Chapter Next Chapter Table of Contents