220 likes | 387 Views
CS412/413. Introduction to Compilers and Translators April 23, 1999 Lecture 31: First-class functions. Administration. Programming Assignment 4 due on Wednesday Reading: Appel 15.1-15.6. Advanced Language Support. So far have considered one “advanced” language feature: objects
E N D
CS412/413 Introduction to Compilers and Translators April 23, 1999 Lecture 31: First-class functions
Administration • Programming Assignment 4due on Wednesday • Reading: Appel 15.1-15.6 CS 412/413 Introduction to Compilers and Translators -- Spring '99 Andrew Myers
Advanced Language Support • So far have considered one “advanced” language feature: objects • Next three lectures: more useful language features • first-class functions • parametric polymorphism • dynamic typing and meta-object protocols • May 3, 5: applying compiler techniques to compiler-like systems (interpreters, JITs, source-to-source translators) CS 412/413 Introduction to Compilers and Translators -- Spring '99 Andrew Myers
First-class functions • Many languages allow functions to be used in a more first-class manner than in Iota or Java: C, C++, ML, Modula-3, Pascal, Scheme,... • Passed as arguments to functions/methods • Nested within containing functions (exc. C, C++) • Used as return values (exc. Modula-3, Pascal) CS 412/413 Introduction to Compilers and Translators -- Spring '99 Andrew Myers
Function Types • Iota-F0: Iota+ with function values that can be passed as arguments • Need to declare type of argument; will use program notation function(T1, T2): T3 to denote the type T1T2T3. • Example: sorting with a user-specified ordering: sort(a: array[int], order: function(int, int):bool) { … if (order(a[i], a[j])) { … } ... CS 412/413 Introduction to Compilers and Translators -- Spring '99 Andrew Myers
Passing a Function Value leq(x: int, y: int): bool = x <= y geq(x: int, y:int): bool = x >= y sort(a: array[int], order: function(int, int):bool) …sort(a1, leq) sort(a2, geq) • Allow abstraction over choice of functions CS 412/413 Introduction to Compilers and Translators -- Spring '99 Andrew Myers
Objects subsume functions! interface comparer { compare(x: int, y:int): bool } sort(a: array[int], cmp: comparer) { … if (cmp.compare(a[i], a[j])) { … } … class leq { compare(x: int, y:int) = x <= y; } sort(a1, new leq); CS 412/413 Introduction to Compilers and Translators -- Spring '99 Andrew Myers
Type-checking functions • Same rules as in Iota static semantics, but function invoked in function call may be a general expression • Most general subtyping rule for functions uses the same contravariance/covariance restrictions on arguments/results : can pass a function where a function with different signature is expected CS 412/413 Introduction to Compilers and Translators -- Spring '99 Andrew Myers
Representing functions • For Iota-F0, a function may be represented as a pointer to its code (cheaper than an object) • Old translation:Tid(E1,…,En)=CALL(NAME(id), T E1,…,TEn) • New: TE0(E1,…,En)=CALL(TE0, TE1,…,TEn)Tid = NAME(id)(if id is a global fcn) CS 412/413 Introduction to Compilers and Translators -- Spring '99 Andrew Myers
Nested Functions • Provided by functional languages (Scheme, ML) and Pascal, Modula-3 • Nested function able to access variables of the containing lexical scope • Useful for implementing iterators interface set { add(o: object) contains(o: object): bool members(f: function(o: object)) } CS 412/413 Introduction to Compilers and Translators -- Spring '99 Andrew Myers
Iteration in Iota-F1 (nested fcns) countAnimals(s: set) = { count: int = 0; loop_body(o: object) = { if (o instanceof Animal) count ++; } s.members(loop_body); return count; } • Nested functions may access, update variables from containing scopes! Must change rep. CS 412/413 Introduction to Compilers and Translators -- Spring '99 Andrew Myers
Closure • Representation of a function value is a closure -- A pointer to the code plus a static link to allow access to outer scopes. Static link is implicit argument to code. countAnimals(s: set) = { count: int = 0; loop_body(o: object) = { if (o instanceof Animal) count ++; } s.members(loop_body); return count; } loop_bodycode countAnimalsactivation loop_body members activation code ptr loop_body activation static link static link CS 412/413 Introduction to Compilers and Translators -- Spring '99 Andrew Myers
Supporting Closures TE0(E1,…,En) = ESEQ(MOVE(t1, TE0), CALL(t1, MEM(t1+4), TE1,…, TEn) Tid(..ai: Ti..) : Tr = E= t1 = malloc(8); M[t1] = NAME(id); M[t1+4] = FP; • What about variableaccesses? countAnimalsstack frame loop_body loop_bodycode members stack frame loop_body stack frame static link CS 412/413 Introduction to Compilers and Translators -- Spring '99 Andrew Myers
static link to g static link to f Static Link Chains f() { int a; g() { int b; h() { c = a + b; } } } f stack frame a ...other function stack frames... g stack frame b ...other function stack frames... h stack frame CS 412/413 Introduction to Compilers and Translators -- Spring '99 Andrew Myers
Progress Report • Passed as arguments to functions/methods • Nested within containing functions as local variables • Used as return values • If no nested functions, functions are just pointers to code; can be used as return values • Problem: interaction with nested fcns CS 412/413 Introduction to Compilers and Translators -- Spring '99 Andrew Myers
Iota-F2 (function return) • Augment Iota-F1 to allow the return type of a function to be a function itself. Example: make_counter( ): function( ): int = { // returns a counter function int count; inc( ): int = { count++; } return inc; } CS 412/413 Introduction to Compilers and Translators -- Spring '99 Andrew Myers
Dangling static link! make_counter( ): function( ): int = { // returns a counter function int count; inc( ): int = { count++; } return inc; } make_counterstack frame count inc inc code • Must heap-allocate the make_counter activation record so that it persists after the call returns CS 412/413 Introduction to Compilers and Translators -- Spring '99 Andrew Myers
Heap allocation make_counter( ): function( ): int = { // returns a counter function int count; inc( ): int = { count++; } return inc; } • Activation record stack frame • Even local variable accesses indirected stack frame activation record count inc inc code CS 412/413 Introduction to Compilers and Translators -- Spring '99 Andrew Myers
The GC side-effect • If activation records are heap-allocated, every function call creates an object that must be garbage collected eventually -- increases rate of garbage generation • Activation records of all lexically enclosing functions are reachable from a closure via stack link chains • Putting entire activation record in heap means a lot of garbage is not collectable CS 412/413 Introduction to Compilers and Translators -- Spring '99 Andrew Myers
Escape analysis • Variables only need to be stored on heap if they can escape and be accessed after this function returns • Only happens if • variable is referenced from within some nested function • the nested function is either returned or passed to some function that might store it in a data structure • This determination: escape analysis CS 412/413 Introduction to Compilers and Translators -- Spring '99 Andrew Myers
Benefits of escape analysis • Variables that don’t escape are allocated on stack frame instead of heap: cheap to access • Closures don’t hold down as much garbage • One problem: precise escape analysis is a global analysis, expensive. Escape analysis must be conservative. CS 412/413 Introduction to Compilers and Translators -- Spring '99 Andrew Myers
Summary • Looked at 3 languages progressively making functions more first-class • No lexical nesting (F0): fast. Represent as pointer to code • Lexical nesting, no upward function values or storage in data structures (F1): function value is closure • Fully first-class (F2): heap-allocation of some variables, some escape analysis needed to avoid significant GC, performance hit • Functions become as expensive as objects (but are more convenient for some coding) CS 412/413 Introduction to Compilers and Translators -- Spring '99 Andrew Myers