Transcript ppt

Announcements

Exam 1 is graded. Curved +10

Rainbow table will be available after class




HW1 and HW2,
Exam 1,
Quizzes 1-3
HW4 will be up after class
Spring 16 CSCI 4430, A Milanova
1
Last Class

Naming, binding and scoping




Notion of binding time
Object lifetime and storage management
Scoping
Today: Catch-up
Spring 16 CSCI 4430, A Milanova
2
Scoping, Catch-up




In most languages a variable name can be used
multiple times
Scoping rules: map variable names to declarations
Scope: region of program text where declaration is
visible (region of program where a binding is active)
Most languages use static scoping


Mapping from uses to declaration is made at compile time
Block structured PLs (referred as Algol-style structure)


Nested subroutines (Pascal, ML, Scheme, etc.)
Nested blocks (C, C++ { … } )
Spring 16 CSCI 4430, A Milanova
3
Static Scoping in Block Structured
Programming Languages


Also known as lexical scoping
Block structure and nesting of blocks gives rise to
the closest nested scope rule



There are local variable declaration within a block
A block inherits variable declarations from enclosing
blocks
Local declarations take precedence over inherited
ones



Hole in scope of inherited declaration
In other words, inherited declaration is hidden
Lookup for non-local variables proceeds
from inner to outer enclosing blocks
Spring 16 CSCI 4430, A Milanova
4
main{
a, b, c: integer;
procedure P(){
c: integer;
procedure S(){
c, d: integer;
procedure R(){
…
} //end R
R;
}//end S
R();
S();
}//end P
procedure R(){
a: integer;
= a, b, c;
}//end R
…; P(); …
} //end main;
Spring 16 CSCI 4430, A Milanova
Rule: a variable is visible
if it is declared in its own block
or in a textually surrounding
block and is not ‘hidden’ by a
binding to it in a closer block
(i.e., hole in scope)
5
Example with Frames
main{
a, b, c: integer;/*1*/
procedure P(){ /*3*/
c: integer;
procedure S(){ /*8*/
c, d: integer;
procedure R(){/*10*/
…
}//end R;/*11*/
R();/*9*/
}//end S;/*12*/
R();/*4*/
S();/*7*/
}//end P;/*13*/
procedure R(){ /*5*/
top
a: integer;
= a, b, c;
}//end R; /*6*/
…; P();/*2*/ …
} //end main /*14*/
at /*1*/
main
----a
b
c
fp - currently
active frame
at /*2*/, main calls
main.P
sp
6
Example
main{
a, b, c: integer;/*1*/
procedure P(){ /*3*/
c: integer;
procedure S(){ /*8*/
c, d: integer;
procedure R(){/*10*/
…
}//end R;/*11*/
R();/*9*/dynamic link
}//end S;/*12*/
(control link;
R();/*4*/
S();/*7*/
called-by chain)
}//end P;/*13*/
procedure R(){ /*5*/
a: integer;
= a, b, c;
}//end R; /*6*/
…; P();/*2*/ …
top
}// end main /*14*/
at /*3*/
main
----a
b
c
main.P
static link
(access link;
static
environment)
fp
c
sp
7
Example
at /*5*/
main{
main
a, b, c: integer;/*1*/
--at /*4*/,
procedure P(){ /*3*/
P calls main.R--c: integer;
procedure S(){ /*8*/
a
c, d: integer;
b
procedure R(){/*10*/
c
…
}//end R;/*11*/
main.P
R();/*9*/
}//end S;/*12*/
R(); /*4*/
S();/*7*/
c
}//end P;/*13*/
main.R
procedure R(){ /*5*/
a: integer;
= a, b, c;
}//end R; /*6*/
a
…; P();/*2*/ …
} //end main /*14*/
And so on…
fp
sp
8
A Note

We assume languages that do not allow
subroutines to be passed as arguments or
returned from other subroutines

Scoping rules become more involved in
languages that allow subroutines to be
passed as arguments and/or returned from
other subroutines
We will return to scoping later

Spring 16 CSCI 4430, A Milanova
9
Dynamic Scoping

Allows for local variable declaration

Inherit non-local variables from subroutines
which are live when current subroutine is
invoked

Use of variable is mapped to the declaration of
that variable in the most recently invoked and
not yet terminated stack frame
Spring 16 CSCI 4430, A Milanova
10
Dynamic Scoping

Lookup for non-local variables proceeds from
closest dynamic predecessor to the farthest

Incurs a runtime cost of the lookup

Used in APL, (old) Lisp, Snobol, Perl
Spring 16 CSCI 4430, A Milanova
11
Example
main{
procedure Z(){
a: integer;
a := 1;
Y();
output a;
}//end Z;
procedure W(){
a: integer;
a := 2;
Y();
output a;
}//end W;
procedure Y(){
a := 0; /*1*/
}//end Y;
Z();
W();
}//end main
Which a is modified at /*1*/
under dynamic scoping?
Z.a or W.a or both?
12
Example
main{
procedure Z(){
a: integer;
a := 1;
Y();
output a;
}//end Z;
procedure W(){
a: integer;
a := 2;
Y();
output a;
}//end W;
procedure Y(){
a := 0; /*1*/
}//end Y;
Z();
W();
}//end main
main calls Z,
Z calls Y,
Y sets Z.a to 0.
13
Example
main{
procedure Z(){
a: integer;
a := 1;
Y();
output a;
}//end Z;
procedure W(){
a: integer;
a := 2;
Y();
output a;
}//end W;
procedure Y(){
a := 0; /*1*/
}//end Y;
Z();
W();
}//end main
main calls W,
W calls Y,
Y sets W.a to 0.
Is this program legal under
static scoping? If so, which
a is modified? If not, why not?
14
Static vs. Dynamic Scoping
program
a, b, c: integer;
procedure P
c: integer;
procedure S
c, d: integer;
procedure R
…
end R;
R();
end S;
R();
S();
end P;
procedure R
a: integer;
main
----a
b
c
main.P
c
main.R
= a, b, c;
end R;
…; P(); …
end program
Static Scoping:
a bound to R.a,
b to main.b,
c to main.c
Dynamic Scoping:
a bound to R.a,
b to main.b,
c to P.c
a
15
Dynamic Scoping

Dynamic Scoping is considered to be a very
bad idea. Why?
Spring 16 CSCI 4430, A Milanova
16
Semantic Analysis
Reading: Scott, Chapter 4.1-4.3
17
Today’s Lecture Outline

Static Semantic Analysis

Syntax vs. Static Semantics
Static Semantic Analysis vs. Dynamic Semantic
Analysis

Attribute Grammars




Synthesized and inherited attributes
S-attributed grammars
L-attributed grammars
Spring 16 CSCI 4430, A Milanova
18
Static Semantics

Earlier we considered syntax analysis


We now look at static semantic analysis


Informally, syntax deals with the form of PL
constructs
Semantics deals with the meaning of PL
constructs
The distinction between the two is fuzzy

In practice, anything that is not expressed in
terms of certain CFG (LALR(1), in particular) is
considered semantics
Spring 16 CSCI 4430, A Milanova
19
Static Semantics vs. Dynamic Semantics

Static semantic analysis (compile-time)

Informally, reasons about properties that can be
determined statically, without program execution


E.g., determine static types of expressions, detect
certain errors
Dynamic semantic analysis (run-time)

Reasons about properties that depend on
program execution

E.g., could z=x/y cause division by zero, could
expression a[i] index out of array bounds, etc.?
Spring 16 CSCI 4430, A Milanova
20
The Role of Semantic Analysis


Detect errors
Static semantic analysis

Detect as many errors as possible early, before execution


Dynamic semantic analysis

Detect errors by performing checks during execution


Type inference and type checking
Tradeoff: dynamic checks slow program execution
Languages differ greatly in the amount of static
semantic analysis and dynamic semantic analysis
they perform
Spring 16 CSCI 4430, A Milanova
21
Question


Let’s look at 3 languages we all are familiar
with: C++, Java and Python
How do these languages differ in the static
semantic analysis and dynamic semantic
analysis they perform?
Spring 16 CSCI 4430, A Milanova
22
Examples of Static Semantic Errors

Type mismatch:



x = y+z+w: type of left-hand-side does not
“match” type of right-hand-side
A a; … ; a.m(): m() cannot be invoked on
a variable of type A
Definite variable assignment in Java: a local
variable must be assigned before it is used
Spring 16 CSCI 4430, A Milanova
23
Examples of Dynamic Semantic
Errors



Array-index-out-of-bounds:

a[i], i goes beyond the bounds of a

What happens in C++? What happens in Java?
Null pointer dereference:

a.m() in Java or a->m() in C++, and a is null

What happens in C++? What happens in Java?
Casting an object to a type of which it is not an
instance


C++? Java?
And more…
Spring 16 CSCI 4430, A Milanova
24
Dynamic Semantic Errors (Cstyle casts in C++)
//#1
void* x = (void *) new B;
A foo()
B* q = (B*) x; //a safe downcast?
int case1 = q->foo();
//#2
B foo()
foo(int)
void* x = (void *) new A;
B* q = (B*) x; //a safe downcast?
int case2 = q->foo(); //what happens?
//#3
void* x = (void *) new A;
B* q = (B*) x; //a safe downcast?
int case3 = q->foo(66); //what happens?
Spring 16 CSCI 4430, A Milanova
25
Dynamic Semantic Errors (Java)
//#1
Object x = new B();
B q = (B) x; //a safe downcast
int case1 = q.foo();
//#2
Object x = new A();
B q = (B) x;
int case2 = q.foo();
//#3
Object x = new A();
B q = (B) x;
int case3 = q.foo(66);
Spring 16 CSCI 4430, A Milanova
A foo()
B
foo()
foo(int)
26
Static Semantics vs. Dynamic Semantics


Again, distinction between the two is fuzzy
For some programs, the compiler can predict
run-time behavior by using static analysis



E.g., #1: q always points to a B object, thus
q.foo()calls B’s foo(), not A’s foo()
E.g., #2: x always points to an A object, thus the
compiler can predict the problematic cast
For arbitrary programs, the compiler cannot
predict run-time behavior!
Spring 16 CSCI 4430, A Milanova
27
Static Semantic Analysis

Optimization





E.g., prove that a is never null in a.m() and remove the
null-pointer-dereference run-time check
E.g., prove that a always refers to a subclass of A
in x = (A) a and eliminate class-cast check
E.g., prove that index i is never out of bounds in a[i]
and eliminate array-out-of-bounds check
E.g., prove that a always refers to a B object and resolve
virtual call a.m() statically
Static debugging tools


E.g., find an execution path where a is null at dereference
point a->m()
Debugging memory management in C++ programs
Spring 16 CSCI 4430, A Milanova
28
Semantic Analyzer
compiler
character stream
scanner
optimizer
token stream
parser
parse trees
semantic analyzer
and intermediate
code generator
modified
intermediate
form
code generator
assembly code
intermediate
form
Semantic analyzer performs static semantic analysis on parse trees and ASTs.
Optimizer performs static semantic analysis on intermediate 3-address code.
Spring 16 CSCI 4430, A Milanova
29
Attribute Grammars:
Foundation for Static Semantic Analysis

Attribute Grammars: generalization of
Context-Free Grammars


Associate meaning with parse trees
Attributes


Each grammar symbol has one or more values called
attributes associated with it
Semantic rules

Each grammar production has associated “rule” which
may refer to and compute the values of attributes
Spring 16 CSCI 4430, A Milanova
30
Example: Attribute Grammar to Compute Value
of Expression (denote grammar by AG1)
SE
EE+T |T
TT*F |F
F  num
Production
SE
E  E1+T
Semantic Rule
print(E.val)
E.val := E1.val + T.val
ET
T  T1*F
E.val := T.val
T.val := T1.val * F.val
TF
F  num
T.val := F.val
F.val := num.val
val: Attributes
Spring 16 CSCI 4430, A Milanova
31
Example

val: Attributes associated to symbols



Indices used to distinguish between symbols with
same name within same production



Intuitively, A.val holds the value of the expression,
represented by the subtree rooted at symbol A
Fresh attributes are associated with every node in the
parse tree
E.g., E  E1+T
E.val := E1.val+T.val
Attributes of terminals supplied by scanner
Attributes of symbols + and * are never used
Spring 16 CSCI 4430, A Milanova
32
Example: Decorated parse tree for input
3*5 + 2*4
SE
E  E1+T
ET
T  T1*F
TF
F  num
S
print(E.val)
E.val := E1.val+T.val
E.val := T.val
T.val := T1.val*F.val
T.val := F.val
F.val := num.val
E 23
E 15 +
T 15
T3
*
F3
num 3
Spring 16 CSCI 4430, A Milanova
T8
T2 *
F5
F2
F4
num 4
num 5 num 2
33
Exercise

LR grammar for arithmetic expressions:
SE
EE+T
ET
T  T * num
T  num

Write an attribute grammar that translates an
expression into prefix notation. The grammar
associates an attribute val with S, which
holds the string in prefix. For example, for
5 + 6 * 7, val of S will be “+ 5 * 6 7“.

Use + to denote string concatenation
Spring 16 CSCI 4430, A Milanova
34
Building an Abstract Syntax Tree (AST)


So far, we talked about parse trees
In fact, compilers use abstract syntax trees

Suitable intermediate representation



Define semantic analyses over ASTs
AST is basis for translation into intermediate code
An AST is an abbreviated parse tree


Operators and keywords do not appear as
leaves, but at the interior node that would have
been their parent
Chains of single productions are collapsed
Spring 16 CSCI 4430, A Milanova
35
Building ASTs for Expressions
Parse tree for 3*5+2*4
Abstract syntax tree (AST)
+
E
+
E
*
T
num:3
T
T
F
num:3
*
T
*
F
F
F
*
num:4
num:2
num:5
num:4
num:5
num:2
How do we construct syntax trees for expressions?
Spring 16 CSCI 4430, A Milanova
36
Attribute Grammar to build AST for
Expression (denote by AG2)

An attribute grammar:
Attribute “nodepointer”
Production
Semantic Rule
E  E1+T
E.nptr := mknode(‘+’, E1.nptr, T.nptr)
ET
E.nptr := T.nptr
T  T1 *F
T.nptr := mknode(‘*’, T1.nptr, F.nptr)
TF
T.nptr := F.nptr
F  num
F.nptr := mkleaf(‘num’, num.val)
Function mknode(op,left,right) creates an operator
node with label op, and two fields containing pointers left
and right
Function mkleaf(num,num.val) creates a leaf node with
label num, and a field containing the value of the number
37
Constructing ASTs for Expressions
Input:
3 * 5 + 2 * 4
S
+,
E
E
T
T
F
num,3
*
E  E1+T
ET
T  T1 *F
TF
F  num
+
*,
,
*,
T
,
F
E.nptr := mknode(‘+’, E1.nptr, T.nptr)
E.nptr := T.nptr
T.nptr := mknode(‘*’, T1.nptr, F.nptr)
T.nptr := F.nptr
F.nptr := mkleaf(‘num’, num.val)
T
F
num,5 num,2
*
,
F
num,4
Another Example
Another LR grammar:
Input: 3/5 - 2/4.
SE
E  E1-T
ET
T  T1/F
TF
F  num
print(E.val)
E.val := E1.val-T.val
E.val := T.val
T.val := T1.val/F.val
T.val := F.val
F.val := num.val
E 0.1
E 0.6 T 0.6
T3
/
F3
num 3
Spring 16 CSCI 4430, A Milanova
T 0.5
T2 /
F5
F2
F4
num 4
num 5 num 2
39
Exercise

We know that the language L = anbncn is not
context free. It can be captured however with
an attribute grammar. Give an underlying
CFG and a set of attribute rules that
associate an attribute ok with the root S of
each parse tree, such that S.ok is true if and
only if the string corresponding to the fringe
of the tree is in L.
Spring 16 CSCI 4430, A Milanova
40
Spring 16 CSCI 4430, A Milanova
41