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 on Type Analysis

Previous Chapter Next Chapter Table of Contents


Type Checking in Expressions

Expressions consist of typed names and literals and of operators that are applied to operands of certain types and yield a result of a certain type. Determining the types of expressions and checking the related type rules of the language is a significant subtask of type analysis. The type rules of languages are usually formulated in terms of concepts like "type of program constructs and entities", "signature of operators", "operator overloading", "type conversion". They have common and well-understood meaning for type analysis in general. Of course, the type rules established for a particular language instantiate these concepts in a specific way, e.g. define a specific set of operators with their signature and state which conversions may be applied to resolve overloading.

Eli's type analysis module Expression provides reusable roles and computations to formulate the language specific instantiation of the concepts mentioned above. The type analysis for expressions is generated from such a specification.

Expression module[20]==

$/Type/Expression.gnrc:inst
This macro is invoked in definition 26.

This module carries out type analysis on expression trees, which are subtrees made up of connected expression nodes. An expression node is a node representing a program construct that yields a value of a certain type. The module provides the role ExpressionSymbol to be inherited by symbols that are expression symbols in that sense:

Expression symbols[21]==

SYMBOL Expression INHERITS ExpressionSymbol END;
SYMBOL Variable INHERITS ExpressionSymbol END;
This macro is invoked in definition 27.

The type of each expression node is characterized by two attributes: ExpressionSymbol.Type describes the type of the values this expression may yield. ExpressionSymbol.Required may be used to specify that the upper context requires the expression to yield a value of a particular type. As ExpressionSymbol.Required is used to compute ExpressionSymbol.Type, it may not depend on the Type attribute.

Expression symbols may occur in different contexts with respect to the structure of the expression trees: root contexts, leaf contexts, and inner contexts. The module provides different computational roles for those contexts. In leaf contexts the type of the leaf expression must be stated using the computational role PrimaryContext. Note that in the third role below the expression node is a leaf with respect to the expression tree, although the context has one subtree, that is not an expression node:

Leaf nodes[22]==

RULE: Expression ::= IntNumber COMPUTE
  PrimaryContext (Expression, intType);
END;

RULE: Expression ::= 'true' COMPUTE
  PrimaryContext (Expression, boolType);
END;

RULE: Expression ::= 'false' COMPUTE
  PrimaryContext (Expression, boolType);
END;

RULE: Variable ::= UseIdent COMPUTE
  PrimaryContext (Variable, UseIdent.Type);
END;
This macro is invoked in definition 27.

The computational role TransferContext is used for contexts that have an expression node on the left-hand side and one on the right-hand side, and both have the same type properties:

Transfer nodes[23]==

RULE: Expression ::= Variable COMPUTE
  TransferContext (Expression, Variable);
END;
This macro is invoked in definition 27.

The node representing an assignment statement has two children. Both are considered as roots of expression trees. For the Variable the assignment context does not impose any restriction on its type; hence, nothing is specified for that node:

Assignment[24]==

RULE: Statement ::= Variable '=' Expression ';' COMPUTE
  RootContext (Variable.Type, , Expression);
  Indication (assignOpr);
END;
This macro is invoked in definition 27.

explain the purpose of assignOpr??

The Expression on the right-hand side of the assignment is required to yield a value of the type of the Variable.

An expression in the role of a statement is another example for a root context. On execution the value of the expression will just be discarded. Hence, there is no requirement on its type to be stated or checked: Expression statement[25]==

RULE: Statement ::=  Expression ';' END;
This macro is invoked in definition 27.

Expression.specs[26]==

Expression module[20]
This macro is attached to a product file.

Expression.lido[27]==

Expression symbols[21]
Leaf nodes[22]
Transfer nodes[23]
Assignment[24]
Expression statement[25]
This macro is attached to a product file.


Previous Chapter Next Chapter Table of Contents