COMS W4115
Programming Languages and Translators
Lecture 16: Types in Programming Languages
November 4, 2009
Lecture Outline
- Review
- Ways of thinking about types
- Type systems
- Typing in programming languages
- Type inference rules
- Type conversions
1. Review
- Intermediate representations
- Type expressions
- Type equivalence
2. Ways of Thinking about Types
- Denotational: a type is a set of values called a domain.
- Constructive: a type is either a primitive type (such as an integer or a character)
or a composite type created by applying a type constructor (such as a structure
or an array) to one or more simpler types.
- Abstraction-based: a type is an interface consisting of a set of operations
with well-defined and mutually consistent semantics.
3. Type Systems
- 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 and for specifying
- type equivalence (when the types of two values are the same),
- type compatibility (when a value of a given type can be used in
a given context), and
- type inference (rules that determine the type of a langauge construct based
on how it is used).
4. Typing in Programming Languages
- Statically typed language: one in which all constructs of a language can be
typed at compile type. C, ML, and 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 the compiler can guarantee that the
programs it accepts will run without type errors.
ML and Haskell are strongly typed.
- Type-safe language: one in which the only operations that can be performed
on data in the language are those sanctioned by the type of the data. [Vijay
Saraswat]
5. 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
6. 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.
7. Reading
aho@cs.columbia.edu