|
|
|
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.
|