In syntax-directed translation, we attach ATTRIBUTES to grammar symbols. The values of the attributes are computed by SEMANTIC RULES associated with grammar productions. Conceptually, we have the following flow:
There are two ways to represent the semantic rules we associate with grammar symbols. SYNTAX-DIRECTED DEFINITIONS (SDDs) do not specify the order in which semantic actions should be executed TRANSLATION SCHEMES explicitly specify the ordering of the semantic actions.
Synthesized attributes Synthesized attributes depend only on the attributes of children. They are the most common attribute type.
Calculating synthesized attributes 3*5+4newline
Inherited attributes An inherited attribute is defined in terms of the attributes of the node ’ s parents and/or siblings.
Calculating Inherited attributes id1, id2, id3
Dependency Graphs
S-Attributed example
Type Checking • Language comes with type system – Set of rules – What types are there? – Where do they appear? • Compiler’s job – Assign type expression to each component – Determine that these type expressions – conform to the type system
The purpose of types To define what the program should do. e.g. read an array of integers and return a double To guarantee that the program is meaningful. that it does not add a string to an integer that variables are declared before they are used To document the programmer's intentions. better than comments, which are not checked by the compiler To optimize the use of hardware. reserve the minimal amount of memory, but not more use the most appropriate machine instructions
What belongs to type checking Depending on language, the type checker can prevent application of a function to wrong number of arguments, application of integer functions to floats, use of undeclared variables in expressions, functions that do not return values, division by zero array indices out of bounds, Languages differ greatly in how strict their static semantics is: few of the things above is checked by all programming languages!
Type Checking: Dynamic and Static • Type checking can be done dynamically for any language ( i.e at run-time) – compiler generates code to do the checks at runtime • Better to do it statically (i.e. at compile-time) • A sound type system eliminates the need for dynamic checking. • A language is strongly typed if compiler guarantees that program it accepts will run without type error. – Examples of strongly typed: Java, C#, Pascal, Ruby, Python
Rules for Type Checking • Type Synthesis – Builds the type of an expression from the types of its subexpressions – Requires names to be declared before usage • Type inference – determines the type of a construct from the way it is used
Type Conversions • Type conversion rules vary from language to language • Explicit type conversion – Must be done by the programmer – Called cast • Implicit type conversion – Done automatically by the compiler – Called coercions – Widening (used most often) vs narrowing