Programming Languages: Design, Specification, and Implementation G Rob Strom September 21, 2006
Administrative Alternative mailing address for me: Everyone should subscribe to the class mailing list: Readings: Remainder of chapter 3 of Gelernter and Jagannathan; chapter 7; MIT Scheme documentation Gelernter textbook: we will notify about availability of photocopied notes Homework due end of class 4 (Scheme): Convert list of atoms to concrete tree according to the simple grammar Convert concrete tree to abstract tree
Invariants BigA = max(A(1..1)) 1 <= N BigA = max(A(1..I-1)) I <= N BigA = max(1..I)) I <= N BigA = max(A(1..I-1)) A(I) > BigA I <= N BigA = max(A(1..I-1)) BigA >= A(I) I <= N BIGA = A(1) 5DO 20 I = 2, N 30IF (BIGA-A(I)) 10,21,21 10BIGA = A(I) 21 CONTINUE 20CONTINUE PRINT … BigA = max(A(1..I-1)) I-1 <= N A(I) = max(1..I)) I <= N BigA = max(1..I)) I <= N BigA = max(1..I-1)) I-1 <= N 1 <= N BigA = max(A(1..I-1)) I-1 N BigA = max(A(1..N))
FORTRAN: Everything static Dimensions of arrays (although not necessarily visible to subroutines) Number of instances of storage blocks All programs both static and global (except statement functions) All I/O devices static and global
FORTRAN: Summary Introduces: Types with operator overloading Arrays Separate compilation 2 levels of name space: Global and Local Static name spaces Procedures and Functions: call by reference Specialized I/O Pragma (Frequency Statement) Differences w.r.t. modern languages: No Lexical level (tokens) No 1 st class char/string No 1 st class procedure No recursion No dynamic data No nesting No closures/objects Gotchas: Near unrestricted GOTO Name aliasing No checks for Type errors Overwriting constants Overwriting array bounds
Algol 60: Static and Runtime Naming; Scope PROCEDURE MAIN; … x := read(); BEGIN INTEGER ARRAY FOO[1:X]; … j := 20; blat(j, FOO(j)); … PROCEDURE blat(x,y); BEGIN x := 1000; y:= 1000 END … INTEGER PROCEDURE random; BEGIN OWN INTEGER seed; random := seed := some new value … END …
New features Call by name Dynamic array bounds Recursive creation of local stack variables Own variables Nested declarations, scopes Inner procedures
Call by name Requires access to the caller’s environment from within the environment where the name is used Equivalent to a “closure” with no parameters
Beyond: Algol 68; PL/I; C Fully dynamic storage – e.g. PL/I’s storage classes: STATIC – like FORTRAN (local & external) AUTOMATIC – like Algol 60 non-own CONTROLLED – dynamically allocated X BASED(Y) – dynamically allocated with pointer Exception checking and Exception Handlers
Memory Heap (PL/I) DCL 1 ARecordTemplate BASED(P), 2 AField FIXED, 2 AnotherField FLOAT; DCL Q Pointer; /* Untyped */ ALLOCATE ARecordTemplate; Q=P; Q->AField = 2;
Closures (PL/I): A: PROCEDURE (…) DCL X FIXED INIT(3); … AddX: PROCEDURE (Y) RETURNS(FIXED); DCL Y FIXED; RETURN(X+Y); END AddX; Z = AddX(5); CALL AFunc(AddX); … AFunc: PROCEDURE(F); DCL F ENTRY; DCL X FIXED INIT(4); DCL Z FIXED; … Z = F(5); … END AFunc;
Closures AddX is a closure, that is: It is a function whose execution has access to an external environment (the variable X) If invoked from AFunc, it uses: AddX’s environment’s value of X (static binding) Not the most recent value of X on the stack, the one defined inside AFunc (dynamic binding) LISP was the earliest language to do closures, and it did them the other way (dynamic)
New things that can go wrong Memory fills with unaccessible cells Type-mismatches on references and entry variables Dangling references via pointers Dangling closures For an amusing critique of C vs PL/I see:
Scheme (define isort ( lambda (l) (letrec ( ; defines a list of bindings (here just 1) (insert ( ; inserts item x in sorted order to list l lambda (x l) (if (null? l) (list x) (if (<= x (car l)) (cons x l) (cons (car l) (insert x (cdr l)))) )))) ; the below is executed in the context of the bindings (if (null? l) nil (insert (car l) (isort (cdr l)))) ) ))
Essential features in Scheme 1 st class procedures Dynamically created procedures Based on lambda calculus over atoms and pairs; by convention, lists are pairs Continuations Automatic garbage collection Applicative style: binding, no update, no side effects (but there are exceptions to this) Static scoping, but no static typing! Simple syntax (afunction arg1 arg2 …) ; function application Special forms, e.g. (if … )