General Information
Tutorials
Reference Manuals
Libraries
Translation Tasks
Tools
Administration
|
Tutorial on Type AnalysisKernel Language
We start with a very simple kernel language where a Here is a simple example program: SimpleExamp[1]== begin var int i, int j, bool b, bool c, int r, int s; i = 1; b = true; r = 3; j = i; c = b; s = r; end This macro is attached to a product file. Structure and notation of the kernel language is specified here by its abstract syntax. Abstract Kernel syntax[2]== RULE: Program ::= Block END; RULE: Block ::= 'begin' Declarations Statements 'end' END; RULE: Declarations LISTOF Declaration END; RULE: Statements LISTOF Statement END; RULE: Declaration ::= 'var' ObjDecls ';' END; RULE: ObjDecls LISTOF ObjDecl END; RULE: ObjDecl ::= TypeDenoter DefIdent END; RULE: TypeDenoter ::= 'int' END; RULE: TypeDenoter ::= 'bool' END; RULE: TypeDenoter ::= 'void' END; RULE: Statement ::= Variable '=' Expression ';' END; RULE: Statement ::= Expression ';' END; RULE: Expression ::= Variable END; RULE: Expression ::= IntNumber END; RULE: Expression ::= 'true' END; RULE: Expression ::= 'false' END; RULE: Variable ::= UseIdent END; RULE: DefIdent ::= Ident END; RULE: UseIdent ::= Ident END; This macro is invoked in definition 16.
Concrete syntax rules corresponding to the
Basic Scope Rules
The basic task of name analysis is consistent renaming.
For each identifier occurrence a The scope rules of a language determine how identifier occurrences are bound to program entities. We specify Algol-like scope rules for our language. The basic Algol-like scope rule reads:
A definition of an identifier Hence, a definition in an outer range is hidden by a definition of the same identifier in an inner range for the whole inner range. Identifiers may be applied before they are defined. We instantiate a library module that provides computations according to this scope rule: Basic scope module[3]== $/Name/AlgScope.gnrc:inst This macro is invoked in definition 14.
The use of that module requires that every identifier occurrence
has the attribute
The computational roles Kernel scope rules[4]== TERM Ident: int; ATTR Sym: int; CLASS SYMBOL IdentOcc COMPUTE SYNT.Sym = TERM; END; SYMBOL Block INHERITS RangeScope END; SYMBOL DefIdent INHERITS IdDefScope, IdentOcc END; SYMBOL UseIdent INHERITS IdUseEnv, IdentOcc END; This macro is invoked in definition 16. Erroneous programs may violate the scope rules in two different situations:
Such situations shall be indicated by error messages. Furthermore, we want every defining occurrence of a multiply defined identifier be marked by a message. For that purpose we use the following two library modules: Message support[5]== $/Tech/Strings.specs $/Prop/OccCnt.gnrc:inst This macro is invoked in definition 14.
The
The
The check for existence of a definition is directly obtained from
the module role Scope checks[6]== SYMBOL UseIdent INHERITS ChkIdUse END; SYMBOL DefIdent INHERITS ChkUnique END; SYMBOL ChkUnique INHERITS Count, TotalCnt COMPUTE IF (GT (THIS.TotalCnt, 1), message (ERROR, CatStrInd ("identifier is multiply defined: ", THIS.Sym), 0, COORDREF)); END; This macro is invoked in definition 16.
Types in the Kernel Language
We use the modules $/Type/Typing.gnrc:inst $/Type/StructEquiv.fw This macro is invoked in definition 14. So, we have to adopt the modules' strategy for representing types:
Types are represented by
The kernel language has only language defined types:
voidType -> IsType = {1}; This macro is invoked in definition 15.
All type keys have a property
The following computations set the RULE: TypeDenoter ::= 'int' COMPUTE TypeDenoter.Type = intType; END; RULE: TypeDenoter ::= 'bool' COMPUTE TypeDenoter.Type = boolType; END; RULE: TypeDenoter ::= 'void' COMPUTE TypeDenoter.Type = voidType; END; This macro is invoked in definition 16.
Further forms of
We now consider a variable declaration as an example for
a language construct that defines a typed entity.
In our language a variable declaration may define several
variables. An
The pair of module roles Declarations[10]== SYMBOL ObjDecl INHERITS TypedDefinition END; SYMBOL DefIdent INHERITS TypedDefId END; ATTR Type: DefTableKey; RULE: ObjDecl ::= TypeDenoter DefIdent COMPUTE ObjDecl.Type = TypeDenoter.Type; END; This macro is invoked in definition 16.
The module roles Typed identifiers[11]== SYMBOL UseIdent INHERITS TypedUseId, ChkTypedUseId END; This macro is invoked in definition 16.
In order to report some results of the type analysis
we associate two properties to every type key:
a string value Output properties[12]== TypeName: CharPtr; "Strings.h" TypeLine: int; intType -> TypeName = {"int"}; boolType -> TypeName = {"bool"}; voidType -> TypeName = {"void"}; intType -> TypeLine = {0}; boolType -> TypeLine = {0}; voidType -> TypeLine = {0}; This macro is invoked in definition 15. For every used identifier the name and the defining line of its type is printed: Kernel output[13]== SYMBOL UseIdent INHERITS PrtType END; SYMBOL PrtType COMPUTE printf ("line %d Type %s defined in line %d\n", LINE, GetTypeName (THIS.Type, "no type name"), GetTypeLine (THIS.Type, 0)) <- INCLUDING Program.TypeIsSet; END; This macro is invoked in definition 16. Kernel.specs[14]== Basic scope module[3] Message support[5] Type analysis module[7] This macro is attached to a product file. Kernel.pdl[15]== Language defined type keys[8] Output properties[12] This macro is attached to a product file. Kernel.lido[16]== Abstract Kernel syntax[2] Kernel scope rules[4] Scope checks[6] Language defined types[9] Declarations[10] Typed identifiers[11] Kernel output[13] This macro is attached to a product file. Kernel.gla[17]== Token notation[137] This macro is attached to a product file. Kernel.con[18]== Concrete Kernel syntax[135] This macro is attached to a product file. Oprand.sym[19]== Expression mapping[136] This macro is attached to a product file.
|