Names, Types, and Functions

Slides:



Advertisements
Similar presentations
Programming Languages and Paradigms
Advertisements

Slide 1 Vitaly Shmatikov CS 345 Functions. slide 2 Reading Assignment uMitchell, Chapter 7 uC Reference Manual, Chapters 4 and 9.
ISBN Chapter 10 Implementing Subprograms.
Copyright © 2006 The McGraw-Hill Companies, Inc. Programming Languages 2nd edition Tucker and Noonan Chapter 5 Types Types are the leaven of computer programming;
UNIVERSITY OF SOUTH CAROLINA Department of Computer Science and Engineering CSCE 330 Programming Language Structures Chapter 4: Names Fall 2009 Marco Valtorta.
Copyright © 2006 The McGraw-Hill Companies, Inc. Programming Languages 2nd edition Tucker and Noonan Chapter 4 Names The first step toward wisdom is calling.
1 Pertemuan 20 Run-Time Environment Matakuliah: T0174 / Teknik Kompilasi Tahun: 2005 Versi: 1/6.
The environment of the computation Declarations introduce names that denote entities. At execution-time, entities are bound to values or to locations:
UNIVERSITY OF SOUTH CAROLINA Department of Computer Science and Engineering CSCE 330 Programming Language Structures Chapter 6: Type Systems Fall 2009.
Copyright © 2006 The McGraw-Hill Companies, Inc. Programming Languages 2nd edition Tucker and Noonan Chapter 6 Type Systems I was eventually persuaded.
CSC321: Programming Languages Names Chapter 4: Names 4.1 Syntactic Issues 4.2 Variables 4.3 Scope 4.4 Symbol Table 4.5 Resolving References 4.6 Dynamic.
Copyright © 2006 The McGraw-Hill Companies, Inc. Programming Languages 2nd edition Tucker and Noonan Chapter 4 Names The first step toward wisdom is calling.
CSC321: Programming Languages1 Programming Languages Tucker and Noonan Chapter 9: Functions 9.1 Basic Terminology 9.2 Function Call and Return 9.3 Parameters.
Copyright © 2006 The McGraw-Hill Companies, Inc. Programming Languages 2nd edition Tucker and Noonan Chapter 9 Functions It is better to have 100 functions.
Imperative Programming. Heart of program is assignment statements Aware that memory contains instructions and data values Commands: variable declarations,
Imperative Programming
5-1 Chapter 5: Names, Bindings, Type Checking, and Scopes Variables The Concept of Binding Type Checking Strong Typing Type Compatibility Scope and Lifetime.
Names and Scope. Scope Suppose that a name is used many times for different entities in text of the program, or in the course of execution. When the name.
Compiler Construction
Chapter 9 Functions It is better to have 100 functions operate on one data structure than 10 functions on 10 data structures. A. Perlis.
224 3/30/98 CSE 143 Recursion [Sections 6.1, ]
Computer Science Department Data Structure & Algorithms Lecture 8 Recursion.
Names. 2 Variables  binding is an association between an entity (such as a variable) and a property (such as its value). A binding is static if the association.
1 Compiler Construction (CS-636) Muhammad Bilal Bashir UIIT, Rawalpindi.
Basic Semantics Associating meaning with language entities.
Dr. Philip Cannata 1 Functions and Recursion. Dr. Philip Cannata 2 10 Java (Object Oriented) ASP RDF (Horn Clause Deduction, Semantic Web) Relation Jython.
Implementing Subprograms What actions must take place when subprograms are called and when they terminate? –calling a subprogram has several associated.
Types(1). Lecture 52 Type(1)  A type is a collection of values and operations on those values. Integer type  values..., -2, -1, 0, 1, 2,...  operations.
Copyright © 2006 The McGraw-Hill Companies, Inc. Basic Terminology Value-returning functions: –known as “non-void functions/methods” in C/C++/Java –called.
Slide 1 Dr. Mohammad El-Ramly Fall 2010 Set 7- II - Functions Slides by Vitaly Shmatikov Cairo University Faculty of Computers and Information CS317 Concepts.
Concepts of programming languages Chapter 5 Names, Bindings, and Scopes Lec. 12 Lecturer: Dr. Emad Nabil 1-1.
CMSC 330: Organization of Programming Languages Operational Semantics a.k.a. “WTF is Project 4, Part 3?”
10-1 Chapter 10: Implementing Subprograms The General Semantics of Calls and Returns Implementing “Simple” Subprograms Implementing Subprograms with Stack-Dynamic.
CMSC 330: Organization of Programming Languages Operational Semantics.
Procedure Definitions and Semantics Procedures support control abstraction in programming languages. In most programming languages, a procedure is defined.
Dr. Philip Cannata 1 Functions and Recursion Programming Languages.
Dr. Philip Cannata 1 Names, Types, and Functions standard hue names.
Run-Time Environments Presented By: Seema Gupta 09MCA102.
CS314 – Section 5 Recitation 9
Implementing Subprograms
Types Type Errors Static and Dynamic Typing Basic Types NonBasic Types
Chapter 10 : Implementing Subprograms
Run-Time Environments Chapter 7
Reminder About Functions
Implementing Subprograms Chapter 10
Functions.
Implementing Subprograms
CS 326 Programming Languages, Concepts and Implementation
CS 326 Programming Languages, Concepts and Implementation
Java Primer 1: Types, Classes and Operators
CS 326 Programming Languages, Concepts and Implementation
Principles of programming languages 4: Parameter passing, Scope rules
Names.
Programmazione I a.a. 2017/2018.
PLAI Types Chapters 24 – 30 Types, Type Judgments, Type Systems and Type Safety - Chapters Type Inference – Chapter 30.
Implementing Subprograms
Chapter 10: Implementing Subprograms Sangho Ha
Implementing Subprograms
Scope, Visibility, and Lifetime
Lecture 15 (Notes by P. N. Hilfinger and R. Bodik)
Implementing Subprograms
Implementing Subprograms
UNIT V Run Time Environments.
Names and Binding In Text: Chapter 5.
Course Overview PART I: overview material PART II: inside a compiler
Lecture 6: Names (Revised based on the Tucker’s slides) 5/27/2019
Implementing Subprograms
Implementing Subprograms
Lecture 7: Types (Revised based on the Tucker’s slides) 10/4/2019
Chapter 10 Def: The subprogram call and return operations of
Presentation transcript:

Names, Types, and Functions standard hue names

Would it be efficient to build the particular values into the program? Different values are usually used to solve different instances of a problem. Would it be efficient to build the particular values into the program? High Level Languages (Imperative or Procedural Languages) Traditionally the concept of a variable with a changeable association between a name and a value is used. Assignments are made to the variable usually multiple times. In other words, the same name may be associated with different values. Relation-based Languages (Functional Languages) Traditionally the concept of a function application is used. In a function application, a function receives argument values and returns values. In other words, a name is only associated with one value.

This Course Jython in Java High Level Languages Java (Object Oriented) 10 High Level Languages Java (Object Oriented) ASP RDF (Horn Clause Deduction, Semantic Web) This Course Jython in Java Relation

Symbol Table Each time a scope is entered, push a new dictionary onto the stack. Each time a scope is exited, pop a dictionary off the top of the stack. For each name declared, generate an appropriate binding and enter the name-binding pair into the dictionary on the top of the stack. Given a name reference, search the dictionary on top of the stack: If found, return the binding. Otherwise, repeat the process on the next dictionary down in the stack. If the name is not found in any dictionary, report an error.

Disjoint scopes nested in Outer scope Scope Concepts The lifetime of a variable is the time interval during which the variable has been allocated a block of memory. int h, i; void B(int w) { int j, k; j = 2 * w * i; i = 2 * w; w = w+1; } void A (int x, int y) { float i, j; i = 3; B(h); ... void main() { int a, b; h = 5; a = 3; b = 2; A(a, b); void sort (float a[ ], int size) { int i, j; for (i = 0; i < size; i++) { // i, j, a, size are local for (j = i + 1; j < size; j++) { if (a[j] < a[i]) { float t; // t is local; i, j, a, size are non-local t = a[i]; a[i] = a[j]; a[j] = t; Symbol Table Lifetime Outer scope: <h, 1> <i, 1> <B, 2> <A, 8> <main, 14> <sort, 21> 1 - 33 Function B nested scope: <w, 2> <j, 3> <k, 3> 2 - 7 Function A nested scope: <x, 8> <y, 8> <i, 9> <j, 9> 8 - 13 Function main nested scope: <a, 15> <b, 15> 15 - 20 Function sort nested scope: <a, 21> <size, 21> <i, 22> <j, 22> 21 - 33 <t, 26> 26 - 30 Disjoint scopes nested in Outer scope Nested scope Dictionaries Variables are “local” if they are in the “active” dictionary otherwise they’re non-local.

Disjoint scopes nested in Outer scope Scope Concepts The lifetime of a variable is the time interval during which the variable has been allocated a block of memory. int h, i; void B(int w) { int j, k; j = 2 * w * i; i = 2 * w; w = w+1; } void A (int x, int y) { float i, j; i = 3; B(h); ... void main() { int a, b; h = 5; a = 3; b = 2; A(a, b); void sort (float a[ ], int size) { int i, j; for (i = 0; i < size; i++) { // i, j, a, size are local for (j = i + 1; j < size; j++) { if (a[j] < a[i]) { float t; // t is local; i, j, a, size are non-local t = a[i]; a[i] = a[j]; a[j] = t; Symbol Table Lifetime Outer scope: <h, 1> <i, 1> <B, 2> <A, 8> <main, 14> <sort, 21> 1 - 33 Function B nested scope: <w, 2> <j, 3> <k, 3> 2 - 7 Function A nested scope: <x, 8> <y, 8> <i, 9> <j, 9> 8 - 13 Function main nested scope: <a, 15> <b, 15> 15 - 20 Function sort nested scope: <a, 21> <size, 21> <i, 22> <j, 22> 21 - 33 <t, 26> 26 - 30 Disjoint scopes nested in Outer scope Nested scope Dictionaries For static scoping, the referencing environment (the set of statements which can validly reference a name) for a name is its defining scope and all nested subscopes. Reference to i (4) resolves to <i, 1> in Outer scope In dynamic scoping, a name is bound to its most recent declaration based on the program’s call history. Since main (17) calls A (10) sets I, A(11) calls  B, the reference to i (4) resolves to <i, 9> in A. What about i at (5)?

Scope Concepts Symbol Table Lifetime Disjoint scopes Nested scope int h, i; void B(int w) { int j, k; j = 2 * w * i; i = 2 * w; w = w+1; } void A (int x, int y) { float i, j; i = 3; B(h); ... void main() { int a, b; h = 5; a = 3; b = 2; A(a, b); void sort (float a[ ], int size) { int i, j; for (i = 0; i < size; i++) { // i, j, a, size are local for (j = i + 1; j < size; j++) { if (a[j] < a[i]) { float t; // t is local; i, j, a, size are non-local t = a[i]; a[i] = a[j]; a[j] = t; Symbol Table Lifetime Outer scope: <h, 1> <i, 1> <B, 2> <A, 8> <main, 14> <sort, 21> 1 - 33 Function B nested scope: <w, 2> <j, 3> <k, 3> 2 - 7 Function A nested scope: <x, 8> <y, 8> <i, 9> <j, 9> 8 - 13 Function main nested scope: <a, 15> <b, 15> 15 - 20 Function sort nested scope: <a, 21> <size, 21> <i, 22> <j, 22> 21 - 33 <t, 26> 26 - 30 Disjoint scopes Nested scope Dictionaries A name is visible if its referencing environment (the set of statements which can validly reference a name) includes the reference and the name is not declared in an inner scope. A name redeclared in an inner scope effectively hides the outer declaration. Some languages provide a mechanism for referencing a hidden name; e.g.: this.x in C++/Java. 1 public class Student { 2 private String name; 3 public Student (String name, ...) { 4 this.name = name;

Scope Concepts Symbol Table Lifetime Disjoint scopes Nested scope int h, i; void B(int w) { int j, k; j = 2 * w * i; i = 2 * w; w = w+1; } void A (int x, int y) { float i, j; i = 3; B(h); ... void main() { int a, b; h = 5; a = 3; b = 2; A(a, b); void sort (float a[ ], int size) { int i, j; for (i = 0; i < size; i++) { // i, j, a, size are local for (j = i + 1; j < size; j++) { if (a[j] < a[i]) { float t; // t is local; i, j, a, size are non-local t = a[i]; a[i] = a[j]; a[j] = t; Symbol Table Lifetime Outer scope: <h, 1> <i, 1> <B, 2> <A, 8> <main, 14> <sort, 21> 1 - 33 Function B nested scope: <w, 2> <j, 3> <k, 3> 2 - 7 Function A nested scope: <x, 8> <y, 8> <i, 9> <j, 9> 8 - 13 Function main nested scope: <a, 15> <b, 15> 15 - 20 Function sort nested scope: <a, 21> <size, 21> <i, 22> <j, 22> 21 - 33 <t, 26> 26 - 30 Disjoint scopes Nested scope Dictionaries Overloading uses the number or type of parameters to distinguish among identical function names or operators. public class PrintStream extends FilterOutputStream { ... public void print(boolean b); public void print(char c); public void print(int i); public void print(long l); public void print(float f); . . .

Types A type is a collection of values and operations on those values. Example: Integer type has values ..., -2, -1, 0, 1, 2, ... and operations +, -, *, /, <, ... Boolean type has values true and false and operations , , . A type system is a precise definition of the bindings between the type of a variable, its values and the possible operations on those values. It provides a basis for detecting type errors. A type error is any error that arises because an operation is attempted on a data type for which it is undefined. Computer types have a finite number of values due to fixed size allocation; problematic for numeric types. Exception - Haskell type Integer represents unbounded integers.

Types A language is statically typed if the types of all variables are fixed when they are declared at compile time. A language is dynamically typed if the type of a variable can vary at run time depending on the value assigned. Some languages perform type checking at compile time (eg, C). Other languages (eg, Perl) perform type checking at run time. Still others do both (eg, Java - downcasting - stringRef = (String) objRef; ).

Types A type conversion is a narrowing conversion if the resulting type permits fewer bits, thus potentially losing information. Otherwise it is termed a widening conversion. An operator or function is overloaded when its meaning varies depending on the types of its operands or arguments or result.

Implicit Type Conversion Assignment supports implicit widening conversions We can transform the abstract syntax tree to insert explicit conversions as needed. The types of the target variable and source expression govern what to insert. Example: Suppose we have an assignment f = i - int(c); (f, i, and c are float, int, and char variables). The abstract syntax tree is:

Implicit Type Conversion Example continued: So an implicit widening is inserted to transform the tree to: Here, c2i denotes conversion from char to int, and itof denotes conversion from int to float. Note: c2i is an explicit conversion given by the operator int() in the program.

Review hmm_nice_demo.zip

Functions and Recursion

Parameter and Arguments Definitions An argument is an expression that appears in a function application/call. A parameter is an identifier that appears in a function definition/declaration. In the code on the right the call A(a, b) has arguments a and b. The function declaration A has parameters x and y. int h, i; void B(int w) { int j = 1, k = 2; i = 2*w; w = w+1; printf("In B - w, j, k, h, i: %d, %d, %d, %d, %d\n", w, j, k, h, i); } void A(int x, int y) { float i = 1.1, j = 2.2; B(h); printf("In A - x, y, i, j, h: %d, %d, %f, %f, %d\n", x, y, i, j, h); int main() { int a, b; h = 5; a = 3; b = 2; A(a, b); printf("In Main a, b, h, i: %d, %d, %d, %d\n", a, b, h, i);

Parameter Passing Mechanisms By value By reference By value-result By name

All arguments in C and Java are passed by value. Pass by Value int h, i; void B(int w) { int j = 1, k = 2; i = 2*w; w = w+1; printf("In B - w, j, k, h, i: %d, %d, %d, %d, %d\n", w, j, k, h, i); } void A(int x, int y) { float i = 1.1, j = 2.2; B(h); printf("In A - x, y, i, j, h: %d, %d, %f, %f, %d\n", x, y, i, j, h); int main() { int a, b; h = 5; a = 3; b = 2; A(a, b); printf("In Main a, b, h, i: %d, %d, %d, %d\n", a, b, h, i); $ ./a In B - w, j, k, h, i: 6, 1, 2, 5, 10 In A - x, y, i, j, h: 3, 2, 1.100000, 2.200000, 5 In Main a, b, h, i: 3, 2, 5, 10 Compute the value of the argument at the time of the call and assign that value to the parameter. So passing by value doesn’t normally allow the called function to modify an argument’s value. All arguments in C and Java are passed by value. But references can be passed to allow argument values to be modified. E.g., void swap(int *a, int *b) { … }

Compute the address of the argument at the time of the Pass by Reference Compute the address of the argument at the time of the call and assign it to the parameter. Since h is passed by reference, its value changes during the call to B. int h, i; void B(int *w) { int j = 1, k = 2; i = 2*(*w); *w = *w + 1; printf("In B - w, j, k, h, i: %d, %d, %d, %d, %d\n", w, j, k, h, i); } void A(int *x, int *y) { float i = 1.1, j = 2.2; B(&h); printf("In A - x, y, i, j, h: %d, %d, %f, %f, %d\n", x, y, i, j, h); int main() { int a, b; h = 5; a = 3; b = 2; A(&a, &b ); printf("In Main a, b, h, i: %d, %d, %d, %d\n", a, b, h, i); $ ./a In B - w, j, k, h, i: 4206640, 1, 2, 6, 10 In A - x, y, i, j, h: 2280676, 2280672, 1.100000, 2.200000, 6 In Main a, b, h, i: 3, 2, 6, 10

Pass by Value Pass by Reference int h, i; void B(int w) { int j = 1, k = 2; i = 2*w; w = w+1; printf("In B - w, j, k, h, i: %d, %d, %d, %d, %d\n", w, j, k, h, i); } void A(int x, int y) { float i = 1.1, j = 2.2; B(h); printf("In A - x, y, i, j, h: %d, %d, %f, %f, %d\n", x, y, i, j, h); int main() { int a, b; h = 5; a = 3; b = 2; A(a, b); printf("In Main a, b, h, i: %d, %d, %d, %d\n", a, b, h, i); $ ./a In B - w, j, k, h, i: 6, 1, 2, 5, 10 In A - x, y, i, j, h: 3, 2, 1.100000, 2.200000, 5 In Main a, b, h, i: 3, 2, 5, 10 int h, i; void B(int *w) { int j = 1, k = 2; i = 2*(*w); *w = *w + 1; printf("In B - w, j, k, h, i: %d, %d, %d, %d, %d\n", w, j, k, h, i); } void A(int *x, int *y) { float i = 1.1, j = 2.2; B(&h); printf("In A - x, y, i, j, h: %d, %d, %f, %f, %d\n", x, y, i, j, h); int main() { int a, b; h = 5; a = 3; b = 2; A(&a, &b ); printf("In Main a, b, h, i: %d, %d, %d, %d\n", a, b, h, i); $ ./a In B - w, j, k, h, i: 4206640, 1, 2, 6, 10 In A - x, y, i, j, h: 2280676, 2280672, 1.100000, 2.200000, 6 In Main a, b, h, i: 3, 2, 6, 10 Pass by Value Pass by Reference

Pass by Value-Results Pass by value at the time of the call and/or copy the result back to the argument at the end of the call – also called copy-in-copy-out.

Pass by Name Textually substitute the argument for every instance of its corresponding parameter in the function body. Originated with Algol 60 (Jensen’s device), but was dropped by Algol’s successors -- Pascal, Ada, Modula. Exemplifies late binding, since evaluation of the argument is delayed until its occurrence in the function body is actually executed. Associated with lazy evaluation in functional languages (e.g., Haskell). real procedure Sum(j, lo, hi, Ej); value lo, hi; integer j, lo, hi; real Ej; begin real S; S := 0; for j := lo step 1 until hi do S := S + Ej; Sum := S end; x[j]*j

Recursive Functions (letrec ((f (lambda (l) (if (null? l) '() (cons (car l) (f (cdr l))))))) (f '(1 2 3 4 5 6))) '(1 2 3 4 5 6) (letrec ((f (lambda (v l) (if (null? l) v (cons (car l) (f v (cdr l))))))) (f '() '(1 2 3 4 5 6))) (letrec ((f (lambda (f1 v l) (if (null? l) (f1 (car l) (f f1 v (cdr l))))))) (f cons '() '(1 2 3 4 5 6))) f == foldr If f1 == cons, foldr is the identity function for a list. It‘s the same as (cons 1 (cons 2 (cons 3( cons 4 (cons 5 (cons 6 '())))))) (cons 1 || (cons 2 || (cons 3 || (cons 4 || (cons 5 || (cons 5 '())))))) (cons 1 || (cons 2 || (cons 3 || (cons 4 || (cons 5 || (cons 5 '())))))) This can be thought of as a stack with “cons”s on it. Here the stack is upside down

Recursive Functions Nothing goes on the stack in this case. (letrec ((f (lambda (f1 v l) (if (null? l) v (f f1 (car l) (cdr l)))))) (f cons '() '(1 2 3 4 5 6))) 6 (f f1 (f1 (car l) v) (cdr l)))))) (f cons '() '(1 2 3 4 5 6))) '(6 5 4 3 2 1) f == foldl If f1 == cons, foldl reverses the list. foldl is tail-recursive because nothing goes on the stack. It‘s the same as (cons 6 (cons 5 (cons 4 ( cons 3 (cons 2 (cons 1 '())))))) Nothing goes on the stack in this case.

Recursive Functions A function that can call itself, either directly or indirectly, is a recursive function. $ cat test.c int factorial (int n) { int i; if (n < 2) { printf("factorial returning 1\n"); return 1; } else i = n * factorial(n-1); printf("factorial returning %d\n", i); return i; int main() { printf("factorial(3) returns: %d\n", factorial(3)); $ ./a factorial returning 1 factorial returning 2 factorial returning 6 factorial(3) returns: 6

Runtime Stack A stack of activation records: Each new call pushes an activation record, and each completing call pops the topmost one. So, the topmost record is the most recent call, and the stack has all active calls at any run-time moment.

parameters and local variables Return address Activation Records A block of information associated with each function call, which includes: parameters and local variables Return address “We call this constructed value a closure because it “closes” the function body over the substitutions that are waiting to occur. When the interpreter encounters a function application, it must ensure that the function’s pending substitutions aren’t forgotten. It must, however, ignore the substitutions pending at the location of the invocation, for that is precisely what led us to dynamic instead of static scope. It must instead use the substitutions of the invocation location to convert the function and argument into values, hope that the function expression evaluated to a closure, then proceed with evaluating the body employing the repository of deferred substitutions stored in the closure.” [textbook. Pages 46-47]

Runtime Stack for Functions Program int h, i; void B(int w) { int j, k; i = 2*w; w = w+1; } void A(int x, int y) { bool i, j; B(h); int main() { int a, b; h = 5; a = 3; b = 2; A(a, b); parameters and local variables Return address Saved registers Temporary variables Return value

Hmm Runtime Stack for Factorial 3 Calling function: factorial BasePtr = 3, printing runtime stack null: null n: 3 answer: null number: 3 BasePtr = 5, printing runtime stack n: 2 BasePtr = 7, printing runtime stack n: 1 BasePtr = 9, printing runtime stack n: 0 int factorial(int n) { if(n < 1) { return 1; } else { return n * factorial(n - 1); int main() { int number, answer; number = 3; answer = factorial(number); print(answer); Exiting function: factorial BasePtr = 9, printing runtime stack null: null n: 0 return#factorial: 1 n: 1 n: 2 n: 3 answer: null number: 3 BasePtr = 7, printing runtime stack BasePtr = 5, printing runtime stack return#factorial: 2 BasePtr = 3, printing runtime stack return#factorial: 6

This Course Jython in Java High Level Languages Java (Object Oriented) 10 High Level Languages Java (Object Oriented) ASP RDF (Horn Clause Deduction, Semantic Web) This Course Jython in Java Relation

PLAI Chapters 4, 5 and 6 Page 27 - " Let can be transformed to lambda. (with (x 1) (+ x x)) (λx.(+ x x) 1) (parse '(with (x 1) (+ x x))) (app (fun 'x (add (id 'x) (id 'x))) (num 1)) (interp (parse '(with (x 1) (+ x x))) (mtSub)) (numV 2) (let ((x 1)) (+ x x)) 2 ((lambda (x) (+ x x)) 1) Page 27 - "

PLAI Chapters 4, 5 and 6 Page 27 - " Let can be transformed to lambda. (with (x 2) (with (y 1) (+ x y))) ((λx.λy.(+ x y) 2) 1) (parse '(with (x 2) (with (y 1) (+ x y)))) (app (fun 'x (app (fun 'y (add (id 'x) (id 'y))) (num 1))) (num 2)) (interp (parse '(with (x 2) (with (y 1) (+ x y)))) (mtSub)) (numV 3) (let ((x 2)) (let ((y 1)) (+ x y))) 3 (((lambda (x) (lambda (y) (+ x y))) 2) 1) Page 27 - "

PLAI Chapters 4, 5 and 6 Page 27 - " Closure – Static and Dynamic Scoping (with (x 5) (with (f (fun (y) (+ x y))) (with (x 3) (f 4))))) (((λx.λf.λx.(f 4) 5) (λy.(+ x y))) 3) (λy.(+ x y) 4) ----- X = 3 ------ f = (λy.(+ x y)) { x = 5 } X = 5 (parse '(with (x 5) (with (f (fun (y) (+ x y))) (with (x 3) (f 4))))) (app (fun 'x (app (fun 'f (app (fun 'x (app (id 'f) (num 4))) (num 3))) (fun 'y (add (id 'x) (id 'y))))) (num 5)) Static Scoping: (interp (parse '(with (x 5) (with (f (fun (y) (+ x y))) (with (x 3) (f 4))))) (mtSub)) (numV 9) Dynamic Scoping: (numV 7) (let ((x 5)) (let ((f (lambda (y) (+ x y)))) (let ((x 3)) (f 4)))) 9 (let ((z 5)) (let ((f (lambda (y) (+ x y)))) (let ((x 3)) (f 4)))) . . reference to an identifier before its definition: x Page 27 - " Environment Closure

PLAI Chapters 4, 5 and 6 Page 27 - " Chapter 4, Page 27 – “To add functions to WAE, we must define their concrete and abstract syntax. In particular, we must both describe a function definition, or declaration, and provide a means for its use, also known as an application or invocation.” Chapter 5, Page 33 – “Well, if the program has size n (measured in abstract syntax tree nodes), then each substitution sweeps the rest of the program once, making the complexity of this interpreter at least O(n2). That seems rather wasteful; surely we can do better. How do we avoid this computational redundancy? We should create and use a repository of deferred substitutions (in the lisp world this is usually called an Environment). Concretely, here’s the idea. Initially, we have no substitutions to perform, so the repository is empty. Every time we encounter a substitution (in the form of a with or application), we augment the repository with one more entry, recording the identifier’s name and the value (if eager) or expression (if lazy) it should eventually be substituted with. We continue to evaluate without actually performing the substitution.” Chapter 5, Page 36 – “Definition 10 (Static Scope) In a language with static scope, the scope of an identifier’s binding is a syntactically delimited region. A typical region would be the body of a function or other binding construct. In contrast: Definition 11 (Dynamic Scope) In a language with dynamic scope, the scope of an identifier’s binding is the entire remainder of the execution during which that binding is in effect.” Page 27 - "

PLAI Chapters 4, 5 and 6 Page 27 - " Chapter 5, Page 37 – “Therefore, at the point of invoking a function, our new interpreter must “forget” about the current substitutions . . . That is, we use the empty repository to initiate evaluation of a function’s body, extending it immediately with the formal parameter but no more.” Chapter 6, Pages 41 & 42 – “first-order Functions are not values in the language. They can only be defined in a designated portion of the program, where they must be given names for use in the remainder of the program. The functions in F1WAE are of this nature, which explains the 1 in the name of the language. higher-order Functions can return other functions as values. first-class Functions are values with all the rights of other values. In particular, they can be supplied as the value of arguments to functions, returned by functions as answers, and stored in data structures. Page 27 - "

PLAI Chapters 4, 5 and 6 Page 27 - " Chapter 6, Page 46 – {with {x 3}{with {f {fun {y} {+ x y}}} {with {x 5} {f 4}}}} (let ((x 3)) (let ((f (lambda (y) (+ x y)))) (let ((x 5)) (f 4)))) . . . We call this constructed value a closure because it “closes” the function body over the substitutions that are waiting to occur.” Chapter 6, Page 47 – “Crucially, while we evaluate arg-expr in ds, the repository active at the invocation location, we evaluate the function’s body in its “remembered” repository. The C programming language implements a middle-ground by allowing functions (technically, pointers to functions) to serve as values but allowing them to be defined only at the top-level. Because they are defined at the top-level, they have no deferred substitutions at the point of declaration; this means the second field of a closure record is always empty, and can therefore be elided, making the function pointer a complete description of the function. This purchases some small implementation efficiency, at the cost of potentially great expressive power, as the examples in Section 6.5 illustrate. Page 27 - "

Differed Substitution and Closures in FAE     (interp (id 'x) (aSub 'y (numV 4) (aSub 'x (numV 3) (mtSub)))) (numV 3) > (interp (id 'y) (aSub 'y (numV 4) (aSub 'x (numV 3) (mtSub)))) (numV 4) Static scoping: (interp (parse '{with {x 5} {f 4}}) (aSub 'f (closureV 'y (add (id 'x) (id 'y)) (aSub 'x (numV 3) (mtSub))) (aSub 'x (numV 3) (mtSub)))) (numV 7) Dynamic Scoping: (interp (parse '{with {x 5} {f 4}}) (aSub 'f (closureV 'y (add (id 'x) (id 'y)) (aSub 'x (numV 3) (mtSub))) (aSub 'x (numV 3) (mtSub)))) (numV 9)

In Crono, “\” mean lambda $ java crono.Crono (let ((z 17)) (let ((z 3) (a 5) (x (\ (x y) (- x (+ y z))))) (let ((z 10) (a 5)) (x z a)))) Evaluating: (let ((z 17)) (let ((z 3) (a 5) (x (\ (x y) (- x (+ y z))))) (let ((z 10) (a 5)) (x z a))))   Environment: empty   Evaluating: (let ((z 3) (a 5) (x (\ (x y) (- x (+ y z))))) (let ((z 10) (a 5)) (x z a)))     Environment:       z: 17     Evaluating: (\ (x y) (- x (+ y z)))       Environment:         z: 17     Result: (\ (x y) (- x (+ y z))) [z: 17]     Evaluating: (let ((z 10) (a 5)) (x z a))       Environment:         a: 5         z: 3         x: (\ (x y) (- x (+ y z))) [z: 17]       Evaluating: (x z a)         Environment:           a: 5           z: 10           x: (\ (x y) (- x (+ y z))) [z: 17]         Evaluating: (- x (+ y z))           Environment:             y: 5             z: 17             x: 10           Evaluating: (+ y z)             Environment:               y: 5               z: 17               x: 10           Result: 22         Result: -12       Result: -12     Result: -12   Result: -12 Result: -12 In Crono, “\” mean lambda

In CronoOptions.java set public static boolean ENVIRONMENT_DYNAMIC = true; Run ant to rebuild crono. $ java crono.Crono (let ((z 17)) (let ((z 3) (a 5) (x (\ (x y) (- x (+ y z))))) (let ((z 10) (a 5)) (x z a)))) Evaluating: (let ((z 17)) (let ((z 3) (a 5) (x (\ (x y) (- x (+ y z))))) (let ((z 10) (a 5)) (x z a))))   Environment: empty   Evaluating: (let ((z 3) (a 5) (x (\ (x y) (- x (+ y z))))) (let ((z 10) (a 5)) (x z a)))     Environment:       z: 17     Evaluating: (\ (x y) (- x (+ y z)))       Environment:         z: 17     Result: (\ (x y) (- x (+ y z))) [z: 17]     Evaluating: (let ((z 10) (a 5)) (x z a))       Environment:         a: 5         z: 3         x: (\ (x y) (- x (+ y z))) [z: 17]       Evaluating: (x z a)         Environment:           a: 5           z: 10           x: (\ (x y) (- x (+ y z))) [z: 17]         Evaluating: (- x (+ y z))           Environment:             a: 5             y: 5             z: 10             x: 10           Evaluating: (+ y z)             Environment:               a: 5               y: 5               z: 10               x: 10           Result: 15         Result: -5       Result: -5     Result: -5   Result: -5 Result: -5

Notice function application here. (let ((z 17)) (let ((z 3) (a 5) (x (\ (x y) (- x (+ y z))))) (let ((z 10) (a 5)) (x z (x 0 0))))) Evaluating: (let ((z 17)) (let ((z 3) (a 5) (x (\ (x y) (- x (+ y z))))) (let ((z 10) (a 5)) (x z (x 0 0)))))   Environment: empty   Evaluating: (let ((z 3) (a 5) (x (\ (x y) (- x (+ y z))))) (let ((z 10) (a 5)) (x z (x 0 0))))     Environment:       z: 17     Evaluating: (\ (x y) (- x (+ y z)))       Environment:         z: 17     Result: (\ (x y) (- x (+ y z))) [z: 17]     Evaluating: (let ((z 10) (a 5)) (x z (x 0 0)))       Environment:         a: 5         z: 3         x: (\ (x y) (- x (+ y z))) [z: 17]       Evaluating: (x z (x 0 0))         Environment:           a: 5           z: 10           x: (\ (x y) (- x (+ y z))) [z: 17]         Evaluating: (x 0 0)           Environment:             a: 5             z: 10             x: (\ (x y) (- x (+ y z))) [z: 17]           Evaluating: (- x (+ y z))             Environment:               y: 0               z: 17               x: 0             Evaluating: (+ y z)               Environment:                 y: 0                 z: 17                 x: 0             Result: 17           Result: -17         Result: -17         Evaluating: (- x (+ y z))           Environment:             y: -17             z: 17             x: 10           Evaluating: (+ y z)             Environment:               y: -17               z: 17               x: 10           Result: 0         Result: 10       Result: 10     Result: 10   Result: 10 Result: 10 Notice function application here.

(let ((z 17)(i 22)) (let ((z 3) (a 5) (x (\ (x y) (- x (+ y z))))) (let ((z 10) (a 5)) (x z (x 0 ((\ (x) x) i)))))) Evaluating: (let ((z 17) (i 22)) (let ((z 3) (a 5) (x (\ (x y) (- x (+ y z))))) (let ((z 10) (a 5)) (x z (x 0 ((\ (x) x) i))))))   Environment: empty   Evaluating: (let ((z 3) (a 5) (x (\ (x y) (- x (+ y z))))) (let ((z 10) (a 5)) (x z (x 0 ((\ (x) x) i)))))     Environment:       i: 22       z: 17     Evaluating: (\ (x y) (- x (+ y z)))       Environment:         i: 22         z: 17     Result: (\ (x y) (- x (+ y z))) [i: 22, z: 17]     Evaluating: (let ((z 10) (a 5)) (x z (x 0 ((\ (x) x) i))))       Environment:         i: 22         a: 5         z: 3         x: (\ (x y) (- x (+ y z))) [i: 22, z: 17]       Evaluating: (x z (x 0 ((\ (x) x) i)))         Environment:           i: 22           a: 5           z: 10           x: (\ (x y) (- x (+ y z))) [i: 22, z: 17]         Evaluating: (x 0 ((\ (x) x) i))           Environment:             i: 22             a: 5             z: 10             x: (\ (x y) (- x (+ y z))) [i: 22, z: 17]           Evaluating: ((\ (x) x) i)             Environment:               i: 22               a: 5               z: 10               x: (\ (x y) (- x (+ y z))) [i: 22, z: 17]             Evaluating: (\ (x) x)               Environment:                 i: 22                 a: 5                 z: 10                 x: (\ (x y) (- x (+ y z))) [i: 22, z: 17]             Result: (\ (x) x) [i: 22, a: 5, z: 10, x: (\ (x y) (- x (+ y z)))]           Result: 22           Evaluating: (- x (+ y z))             Environment:               i: 22               y: 22               z: 17               x: 0             Evaluating: (+ y z)               Environment:                 i: 22                 y: 22                 z: 17                 x: 0             Result: 39           Result: -39         Result: -39         Evaluating: (- x (+ y z))           Environment:             i: 22             y: -39             z: 17             x: 10           Evaluating: (+ y z)             Environment:               i: 22               y: -39               z: 17               x: 10           Result: -22         Result: 32       Result: 32     Result: 32   Result: 32 Result: 32

Binding Later A binding is an association between an entity (such as a variable) and a property (such as its value). A binding is static if the association occurs before run-time. A binding is dynamic if the association occurs at run-time. Name bindings play a fundamental role. The lifetime of a variable name refers to the time interval during which memory is allocated.

Later Variables Static Binding Dynamic Binding Name Type Address Value Lifetime

Something (e.g., Variable) Later Something (e.g., Variable) Static Binding Dynamic Binding Name Type Address Value Lifetime Static v. Dynamic Scoping Static v. Dynamic Typing Static v. Dynamic Binding 