Upload
rolf-wheeler
View
223
Download
0
Tags:
Embed Size (px)
Citation preview
CS 2104 Prog. Lang. Concepts
Dr. Abhik RoychoudhurySchool of Computing
Today’s lecture Finish discussion on type checking
initiated in last lecture Discuss the role of expressions in
programming languages
Issues in Type Checking How to type-check? How to cater for polymorphism? What is your definition of
“compatible type”? When to perform type checking? Is your language strongly or
weakly typed?
2.4 When to perform Type Checking?
Compile-Time
(Static Type Binding)
In theory, you can choose to type check at compile time or run-time.
In practice, languages try to do it as much statically as possible.
Eg. SML, Pascal
Run-Time
(Dynamic Type Binding)
No choice but to do dynamic type checking.
Eg. JavaScript, APL
When is the variable bound to the type?
When can I type check?
When to perform Type Checking? Static Type Checking – done at compile
time. (+) Done only once (+) Earlier detection of errors (–) Less Program Flexibility (Fewer shortcuts
and tricks)
2.4 When to perform Type Checking? Dynamic Type Checking – done at run time.
(–) Done many times (–) Late detection of errors (–) More memory needed, since we need to
maintain type information of all the current values in their respective memory cells.
(–) Slows down overall execution time, since extra code is inserted into the program to detect type error.
(+) Program Flexibility (Allows you to ‘hack’ dirty code.)
Issues in Type Checking How to type-check? How to cater for polymorphism? What is your definition of
“compatible type”? When to perform type checking? Is your language strongly or
weakly typed?
2.5 Strong Type Systems A programming language is defined to be
strongly typed if type errors are always detected STATICALLY.
A language with a strong-type system only allows type-safe programs to be successfully compiled into executables. (Otherwise, language is said to have a weak type system).
Programs of strong-type systems are guaranteed to be executed without type-error. (The only error left to contend with is logic error).
2.5 Strong Type SystemsFortran
Ada
Modula-3
C, C++
Java
Pascal
SML
Haskell
No Allows variable of one type to refer to value of another type through EQUIVALENCE keyword.
No Library function UNCHECKED_CONVERSION suspends type checking.
No Same as Ada through use of keyword LOOPHOLE
No 1. Forced conversion of type through type casting
2. Union Types can compromise type safety
No Type Casting
Almost Variant Records can compromise type safety
Yes
YesAll variables have STATIC TYPE BINDING.
2.5 Weak-Type Systems: Variant Recs Variant Records in C (via union keyword)
compromises Type Safety...
typedef union {
int X;
float Y;
char Z[4];} B;
...
B P;
Weak-Type Sys: Variant Recs
Variant part all have overlapping (same) L-value!!! Problems can occur. What happens to the code below?
P.X = 142;
printf(“%O\n”, P.Z[3])
All 3 data objects have same L-value and occupy same storage. No enforcement of type checking.
Poor language and type system design
Weak-Type Sys: Variant Recs Variant Records in Pascal tries to overcome C’s deficiency. They
have a tagged union type. type whichtype = (inttype, realtype,stringtype);
type uniontype = recordcase V : whichtype of inttype : (X: integer); realtype: (Y: real);
stringtype: (Z:…)end
But the compiler usually doesn’t check the consistency between the variant and the tag. So we can ‘subvert’ the tagged field:
var P: uniontypeP.V = inttype;P.X = 142;P.V = realtype; // type safety compromised
CS 2104 – Prog. Lang. Concepts
Expressions Lecturer : Dr. Abhik Roychoudhury
School of Computing
What is an expression ? The notion of value is central to programming. The allowed set of possible values of a variable denotes
its type. Program variables get instantiated to values at run-time.
Integer variables to integer values String variables to array of characters etc. We previously called values as r-values to distinguish
between values and addresses. With this perspective, we could define an expression
simply as:
An expression is a formal description of a value.
Examples 2 2 * 5 F(4) + 2*5 // Need to define function F A < B A < B \/ C = D // A,B,C,D are variables P(A, B) \/ Q(C, D) // P,Q are predicates // more on this later in the
course
Expression evaluation Evaluating an expression is reducing it to a
simpler but equivalent expression e.g. evaluate 2+3 to 5 Each reduction step in evaluation involves
taking a function application and replacing it by its equivalent value.
E.g. to evaluate 2+3 we replace the application of the + function by the value resulting from addition.
A reduction step represented by =>, 2+3=>5
Prefix, Infix, Postfix Notation Position of Function
Examples
Prefix Left of argument(s) sqrt(16), f(3,4)
Infix Between two arguments 3 f 4, 3 + 4
Postfix Right of arguments 16 sqrt, 3 4 f
Postfix notation Widely used in real compilers for programming
languages. The programmer’s expression is first
converted to an equivalent postfix expression. We can then very easily generate code for
evaluating the postfix expression. Evaluation of postfix expressions have a very
direct correspondence with manipulation of stacks.
Postfix evaluation - Example Expression Code Stack Contents <> 3 5 + 8 6 - * push 3 <3> ^ push 5 <3,5> add <8> 3 5 + 8 6 - * push 8 <8,8> ^ push 6 <8,8,6> sub <8, 2> 3 5 + 8 6 - * mul <16> ^
Postfix Evaluation - Algorithm 1. Start with the leftmost element in the expression. 2. If it is not a function, push it to stack and repeat. 3. If it is a function of k arguments
(a) Take the k elements at the top of the stack (b) Apply the function to these k elements © Replace the k elements by the result of the
function application (d) Move right in the expression and repeat step 2.
4. Reached end of expression, value of expression at stack-top.
Function Definitions So far, our example expressions have shown only built-
in arithmetic functions e.g. +, * The notion of expressions is of course not restricted to
the use of built-in functions. There are several ways of defining a function :
As an equation Let us now study this in more depth.
Functions as Equations Defined as : f(x, y) = x + y * y Standard format used in mathematics. The function is defined with the above equation. The equation itself has no value. Only the expression in the r.h.s. of the equality has a
value. If f/2 appears in an expression 1 + 2 * f(x, y) Then the occurrence of f/2 must be reduced to the value
represented on the r.h.s of the equation of f.
Evaluating functions as eqns Assume f(x1,…,xn) = e Application of function f/n in expression e1 reduced as
follows: Match actual arguments with formal arguments Substitute actual arguments in e Evaluate the result replace occurrence of f/n in e1 with result
Example: 1 + 2 * f(2 +1, 1+ 6) where f(x, y) = x + y * y
Matching : x is 2 + 1, y is 1 +6 Substitution: ( (2 + 1 ) + (1 + 6) * ( 1 + 6)) Evaluate : f (2 +1, 1+ 6) = 52 Replace : 1 + 2 * 52
Side Effects A function has side effect if it changes its parameter(s)
and/or global variables. Example : A + f(A) Suppose execution of f changes the value of A. Consider the following code:
A = 10 B = A + f(A)
Suppose f reduces its argument by 1, and returns this value.
Left – right evaluation : 10 + 9 = 19 Right-left evaluation : 9 + 9 = 18
Side Effects on Global Var. Int A = 5; Int fun1(){
A = 17; Return 3
} Void fun2(){
A = A + fun1(); } What is the value of global variable A in fun2 ? Depends on the order of expression evaluation.
Two solutions Disallow expressions with functional side-
effects Need extra parameters for the functions.
Allow only one evaluation order (say left-to-right).
Will disallow compiler optimizations which re-order operands.
Relational Expressions
- Use relational operators and operands of various types - Evaluate to some boolean representation - Operator symbols used vary somewhat among languages (!=, /=, .NE., <>, #)
Relational Expressions
Boolean Expressions
- Operands are boolean and the result is boolean - Operators: FORTRAN 77 FORTRAN 90 C Ada
.AND. and && and .OR. or || or .NOT. not ! not xor - C has no boolean type--it uses int type with 0 for false and nonzero for true -
Boolean Expressions
Precedence of All Operators:
Pascal: not, unary - *, /, div, mod, and +, -, or relopsAda: **
*, /, mod, remunary -, not+, -, &relopsand, or, xor
C, C++, and Java have over 50 operators and 17 different levels of precedence
Operator Precedence
Evaluating an expression without evaluating all the operands.
e.g. (a > b) and (c > 5)
If we know that a > b is false, then there is no needTo determine whether (c > 5) is true.
Short Circuit Evaluation
Pascal: does not use short-circuit evaluation Problem: table look-up
index := 1; while (index <= length) and (LIST[index] <> value) do index := index + 1
If value is not in LIST, then ???
Short Circuit Evaluation
C, C++, and Java: use short-circuit evaluation for the usual Boolean operators (&& and ||), but also provide bitwise Boolean operators that are not short circuit (& and |)
Ada: programmer can specify either (short-circuit is specified with and then and or else)
FORTRAN 77: short circuit, but any side-affected place must be set to undefined
Short-circuit evaluation exposes the potential problem of side effects in expressions e.g. (a > b) || (b++ / 3)
Short circuit evaluation
Programs as expressions The general notion of expression is so powerful and
fundamental that : Any program could be seen as an expression Any computation could be seen as expression evaluation
In the IMP language (our toy imperative language) we discussed both arithmetic and boolean expressions where
Arithmetic expressions evaluate to numbers Boolean expressions evaluate to true/false
We will now walk through different varieties of expressions where program statements (e.g. if-then-else) will also be viewed as expressions.
1. Constants Semantically, any expression whose name directly
denotes its value. E.g. 2, true, ‘cs2104’ Constants can be of various types : integer, boolean,
string Evaluating a constant will not lead to any further
simplification.
2. Function Applications Application of a function to one or more arguments. E.g. 2 + 3, true /\ true Evaluation will involve using the definition of a function,
in this case the built-in function + Other functions can be assumed to be given in an
equational form, as discussed before.
3. Assignment statement Assigns a value v to a variable X. Can be seen as an expression with operand X returning
v. However such expressions have side-effects. Problem of evaluation order if an assignment expression
is part of a bigger expression. A + (A := C)
4. Conditional Expressions Of the form : if B then E1 else E2 What is the value of if B then E1 else E2
Evaluate B If B evaluates to true, then the value of E1 is the value of
the conditional expression If B evaluates to false then the value of E2 is the value of
the conditional expression Could arbitrarily nest if-then-else to simulate other
imperative program constructs such as switch statements.
4. Let expressions Example: let square(x) = x*x in
square(square(2)) Of the form: let function_definition in
sub_expression The function definition defines a function f in
equational form. The sub-expression contains function
applications of f We assume that definition of f is non-
recursive.
4. Let expressions Evaluation proceeds by replacing applications
of f in sub-expression with the definition of f Example: let square(x) = x*x in
square(square(2)) square(2) * square(2) 2 * 2 * 2 * 2 = 16 Let expressions allow for function definitions. Their evaluation is same as macro-expansion.
Nested Let In fact the let expression can be more general. A let can define variables and /or functions. Since let is itself an expression, it can be nested.
Example: let x = 1 let y = x +1 let f(z) = z +2 in x*y*f(3)
let y = 2 let f(z) = z + 2 in 1*y*f(3) let f(z) = z + 2 in 1*2*f(3) 1*2*(3+2) = 10
5. Recursive Let letrec fact(n) = if zero(n) then 1 else n * fact(n-1) in fact(10) Extension of let allowing recursive definitions. Evaluation of fact(10) proceeds recursively. Letrec expressions can again be nested. Using letrec we can model recursion and iteration.
Summary Expression is a representation of value. Evaluation of an expression returns that value. Arithmetic and boolean expressions are very common in
programming languages. Evaluation of expressions may involve side effects. Evaluation of an expr. may not require all its operands
to be evaluated. Any program can be seen as an expression. Any computation can be seen as expression
evaluation. We will discuss much more about expressions when we
study functional programming (Next lecture)