COMS W4115
Programming Languages and Translators
Lecture 18: Types in Programming Languages
April 2, 2008
Lecture Outline
- Review
- Types
- Type equivalence
- Type inference
- Type conversions
- Run-time storage organization
- Reading
1. Review
- Intermediate representations
- Three-address code
- Semantic analysis
- Types
2. Types
- Type expressions
- The type of a construct in a program can be denoted by a type expression.
- A type expression is either a basic type (e.g.,
integer) or
a type constructor applied to a type expression (e.g., a function from an integer
to an integer).
- Type system: a set of rules for assigning type expressions to the
syntactic constructs of a program.
- Statically typed language: one in which all constructs of a language can be
typed at compile type. C, Java, Haskell are statically typed.
- Dynamically typed language: one in which some of the constructs of a language can only be
typed at run time. Perl, Python, and Lisp are dynamically typed.
- Strongly typed language: one in which every construct in a program can be assigned an
unambiguous type. ML and Haskell are strongly typed.
- Role of types in a programming language
- Reliable software: more robust programs will result if type errors can be caught
at compiler time.
- Type checking: making sure the operands of an operator have compatible types.
- Translation: type determines the location and amount of storage needed for
a name at run time.
3. Type Equivalence
- Name equivalence: two types are equivalent iff they have the same name.
- Structural equivalence: two types are equivalent iff they have the same structure.
- To test for structural equivalence, a compiler must encode the structure
of a type in its representation. A tree (or type graph) is typically
used.
4. Type Inference Rules
- Type inference rules specify for each operator the mapping between the types
of the operands and the type of the result.
- E.g., result types for
x + y:
+ |
int |
float |
int |
int |
float |
float |
float |
float |
Operator and function overloading
- In Java the operator
+ can mean addition or string concatenation
depending on the types of its operands.
- We can choose between two versions of an overloaded function by
looking at the types of their arguments.
Function calls
- Compiler must check that the type of each actual parameter is compatible with
the type of the corresponding formal parameter. It must check that the
type of the returned value is compatible with the type of the function.
- The type signature of a function specifies the types of the formal
parameters and the type of the return value.
- Example:
strlen in C
unsigned int strlen(const char *s);
Type expression:
strlen: const char * → unsigned int
Polymorphic functions
- A polymorphic function allows a function to manipulate data structures
regardless of the types of the elements in the data structure
- Example: Fig. 6.28 (p. 391) -- an ML program for the length of a list
5. Type Conversions
- Implicit type conversions
- In an expression like
f + i where f is a float and
i is an integer a compiler must first convert the integer to a
float before the floating point addition operation is performed. That is, the
expression must be transformed into an intermediate representation like
t1 = INTTOFLOAT i
t2 = x FADD t1
Explicit type conversions
- In C, explicit type conversions can be forced ("coerced") in an expression using a
unary operator called a cast. E.g.,
sqrt((double) n) converts the
value of the integer n to a double before passing it
on to the square root routine sqrt.
6. Run-time Storage Organization
(high address) Runtime stack
↓
free memory
↑
Runtime heap
Static
(low address) Code
Activation records
- Callee's activation record
Local-data area
fp → Caller's fp
Addressability
Return address
Return value
Register-save area
Parameters
7. Reading
aho@cs.columbia.edu