Weeks 6&7: Procedures and Parameter Passing

Similar documents
CS558 Programming Languages

CS558 Programming Languages Winter 2018 Lecture 4a. Andrew Tolmach Portland State University

Concepts Introduced in Chapter 7

CS558 Programming Languages. Winter 2013 Lecture 4

G Programming Languages - Fall 2012

Scope, Functions, and Storage Management

G Programming Languages Spring 2010 Lecture 4. Robert Grimm, New York University

Procedure and Object- Oriented Abstraction

Typical Runtime Layout. Tiger Runtime Environments. Example: Nested Functions. Activation Trees. code. Memory Layout

CSE 504. Expression evaluation. Expression Evaluation, Runtime Environments. One possible semantics: Problem:

CS 314 Principles of Programming Languages

Run Time Environment. Activation Records Procedure Linkage Name Translation and Variable Access

Example. program sort; var a : array[0..10] of integer; procedure readarray; : function partition (y, z :integer) :integer; var i, j,x, v :integer; :

Chapter 9 Subprograms

Functions - Lecture 7. Nested functions. Another example. A Nested Function. Josef Svenningsson

CS 330 Lecture 18. Symbol table. C scope rules. Declarations. Chapter 5 Louden Outline

CSC 533: Organization of Programming Languages. Spring 2005

Chapter 5. Names, Bindings, and Scopes

Topics Covered Thus Far. CMSC 330: Organization of Programming Languages. Language Features Covered Thus Far. Programming Languages Revisited

Names, Bindings, Scopes

CSc 520 final exam Wednesday 13 December 2000 TIME = 2 hours

CMSC 330: Organization of Programming Languages

Programming Languages Third Edition. Chapter 7 Basic Semantics

Programming Languages Third Edition. Chapter 10 Control II Procedures and Environments

Types and Type Inference

G Programming Languages - Fall 2012

CA Compiler Construction

cs242 Kathleen Fisher Reading: Concepts in Programming Languages, Chapter 6 Thanks to John Mitchell for some of these slides.

Chapter 5 Names, Binding, Type Checking and Scopes

Compilers. 8. Run-time Support. Laszlo Böszörmenyi Compilers Run-time - 1

Run-time Environments

Run-time Environments

Names, Scopes, and Bindings II. Hwansoo Han

CS 345. Functions. Vitaly Shmatikov. slide 1

Closures. Mooly Sagiv. Michael Clarkson, Cornell CS 3110 Data Structures and Functional Programming

Run-time Environments - 2

CS558 Programming Languages

Design Issues. Subroutines and Control Abstraction. Subroutines and Control Abstraction. CSC 4101: Programming Languages 1. Textbook, Chapter 8

Informatica 3 Marcello Restelli

Principles of Programming Languages

Closures. Mooly Sagiv. Michael Clarkson, Cornell CS 3110 Data Structures and Functional Programming

References and pointers

Procedures and Run-Time Storage

CSE 307: Principles of Programming Languages

CIT Week13 Lecture

Principles of Programming Languages Topic: Scope and Memory Professor Louis Steinberg Fall 2004

Compiler construction

CS 415 Midterm Exam Spring 2002

NOTE: Answer ANY FOUR of the following 6 sections:

Procedures and Run-Time Storage

Run Time Environment. Procedure Abstraction. The Procedure as a Control Abstraction. The Procedure as a Control Abstraction

Types and Type Inference

Functions CHAPTER 5. FIGURE 1. Concrete syntax for the P 2 subset of Python. (In addition to that of P 1.)

Run-time Environments - 3

Organization of Programming Languages CS 3200/5200N. Lecture 09

CS558 Programming Languages

CS1622. Semantic Analysis. The Compiler So Far. Lecture 15 Semantic Analysis. How to build symbol tables How to use them to find

Subprograms. Copyright 2015 Pearson. All rights reserved. 1-1

COP4020 Programming Languages. Subroutines and Parameter Passing Prof. Robert van Engelen

CS558 Programming Languages

Programmiersprachen (Programming Languages)

Module 27 Switch-case statements and Run-time storage management

Declaration Syntax. Declarations. Declarators. Declaration Specifiers. Declaration Examples. Declaration Examples. Declarators include:

Subprograms. Bilkent University. CS315 Programming Languages Pinar Duygulu

CS 314 Principles of Programming Languages. Lecture 13

CS558 Programming Languages. Winter 2013 Lecture 3

Informal Semantics of Data. semantic specification names (identifiers) attributes binding declarations scope rules visibility

The Procedure Abstraction

Programming Languages & Paradigms PROP HT Course Council. Subprograms. Meeting on friday! Subprograms, abstractions, encapsulation, ADT

Programming Languages Third Edition. Chapter 9 Control I Expressions and Statements

Chapter 9. Subprograms

Programmin Languages/Variables and Storage

Chapter 9. Subprograms

Types. Type checking. Why Do We Need Type Systems? Types and Operations. What is a type? Consensus

Lecture 16: Static Semantics Overview 1

G Programming Languages - Fall 2012

Compiler construction

CSE 504: Compiler Design. Runtime Environments

UNIT V Sub u P b ro r g o r g a r m a s

CS 314 Principles of Programming Languages

CMSC 4023 Chapter 9. Fundamentals of Subprograms Introduction

1 Lexical Considerations

Programming Languages: Lecture 11

Memory Management and Run-Time Systems

CPS 506 Comparative Programming Languages. Programming Language

Types, Type Inference and Unification

CS558 Programming Languages

The PCAT Programming Language Reference Manual

CS125 : Introduction to Computer Science. Lecture Notes #38 and #39 Quicksort. c 2005, 2003, 2002, 2000 Jason Zych

Lectures Basics in Procedural Programming: Machinery

Lecture 9: Procedures & Functions. CS 540 George Mason University

High Performance Computing and Programming, Lecture 3

Run-time Environments. Lecture 13. Prof. Alex Aiken Original Slides (Modified by Prof. Vijay Ganesh) Lecture 13

Attributes of Variable. Lecture 13: Run-Time Storage Management. Lifetime. Value & Location

Administration CS 412/413. Advanced Language Support. First-class vs. Second-class. First-class functions. Function Types

CSE 504: Compilers. Expressions. R. Sekar

CSCI312 Principles of Programming Languages!

Intermediate Representations & Symbol Tables

Semantic Analysis and Type Checking

Compiler Theory. (Semantic Analysis and Run-Time Environments)

Transcription:

CS320 Principles of Programming Languages Weeks 6&7: Procedures and Parameter Passing Jingke Li Portland State University Fall 2017 PSU CS320 Fall 17 Weeks 6&7: Procedures and Parameter Passing 1 / 45

Program Abstractions There are two main approaches for abstractions in a program: Procedural abstractions: Organizing large programs into collections of procedures and functions procedural programming paradigm relies on this approach Data abstractions: Organizing large programs into collections of communicating data objects object-oriented programming paradigm relies on this approach These two approaches share the same goal of treating complex things as simple black boxes, and hiding details inside the boxes. PSU CS320 Fall 17 Weeks 6&7: Procedures and Parameter Passing 2 / 45

Issues Concerning Procedural Abstractions Runtime support for function activations Nested functions (handling scopes) Higher-order functions (handling function values) Parameter passing methods Polymorphism (later) In this unit, we treat the two words, procedure and function, asinterchangeable. PSU CS320 Fall 17 Weeks 6&7: Procedures and Parameter Passing 3 / 45

Function Activations Each instance of function invocation at runtime is called an activation. Each activation has an associated state, which includes things such as return address, values of arguments, values of local variables, etc. The storage for these activation data is called an activation record: Saved Registers Local Variables Arguments... Return Address Normally, an activation record is created when a function is invoked and is destroyed when the function returns. PSU CS320 Fall 17 Weeks 6&7: Procedures and Parameter Passing 4 / 45

Stack-Based AR Allocation For most non-functional programming languages, a sequence of function calls in a program are always nested, i.e. The callee function returns before the caller function does. This makes it easy to allocate activation records on a stack. Activation records, therefore, are also called stack frames. Example: f calls g. Before the call:. Caller f s AR Dynamic Link Saved Registers Local Variables Arguments... Return Address Stack PSU CS320 Fall 17 Weeks 6&7: Procedures and Parameter Passing 5 / 45

Stack-Based AR Allocation Example: f calls g. During the call:. Caller f s AR Callee g s AR Stack Dynamic Link Saved Registers Local Variables Arguments... Return Address Dynamic Link Saved Registers Local Variables Arguments... Return Address always pointing to caller s AR PSU CS320 Fall 17 Weeks 6&7: Procedures and Parameter Passing 6 / 45

Stack-Based AR Allocation Example: f calls g. After the call:. Caller f s AR Dynamic Link Saved Registers Local Variables Arguments... Return Address Stack PSU CS320 Fall 17 Weeks 6&7: Procedures and Parameter Passing 7 / 45

Free Variables Recall that variables in a function are either bound or free: function s parameters and local variables are bound other variables that are referenced in the function are free Example: In the following programs, the varaible x is a free variable: C int g(int z) { return x + z; Haskell g z = x + z Note: Free variables can happen in functions of both imperative and functional programs Free variables are still defined, it s just that they are not defined inside the function where they are being referenced PSU CS320 Fall 17 Weeks 6&7: Procedures and Parameter Passing 8 / 45

Free Variables Question: In the functional language s case, does the occurrence of free variables in a function violate the referential transparent property? Haskell g z = x + z Answer: No. At the time a function is defined, all its free variables must be bound to immutable values. PSU CS320 Fall 17 Weeks 6&7: Procedures and Parameter Passing 9 / 45

Free Variables There are three situations where free variables may occur. Case 1. In languages such as C, functions are all defined at the global scope level, but they can still reference global variables that are defined outside of their own scope: int x = 100; int g(int z) { return x + z; C // x is a global variable No special handling is needed for this case. Global variables are stored in the static area; their references can be handled at compile time through the use of symbolic addresses. PSU CS320 Fall 17 Weeks 6&7: Procedures and Parameter Passing 10 / 45

Free Variables Case 2. In object-oriented languages such as Java, methods are defined within classes, and they can reference objects instance variables that are defined outside of their scope: class Test { int x = 100; int g(int z) { return x + z; Java // x is an instance variable Since objects are stored in the heap area, the addresses of instance variables are not known at compile time. Special treatment is needed for accessing these variables. (We ll see the treatment a little later.) PSU CS320 Fall 17 Weeks 6&7: Procedures and Parameter Passing 11 / 45

Free Variables Case 3. In block-structure languages such as Algol and Pascal, and functional languages such as ML and Haskell, functions can be defined in other functions. A nested function can reference variables defined in any of the outer scopes: Pseudo C int f(int x, int y) { // x is a param in outer scope int g(int z) { return x + z; return g(x + y); Variables defined in outer function scopes are stored in their respective function s activation records, which are allocated at runtime. Therefore, their addresses are not known at compile time. Similar to the previous case, special treatment is needed. Let s first look at why some languages support the nested function feature. PSU CS320 Fall 17 Weeks 6&7: Procedures and Parameter Passing 12 / 45

Benefits of Nested Functions Example: Sketch of a quicksort-based sorting program. Assume initial data and final results are both in files. Steps: 1. Read data from input file to an array 2. Quicksort the array 2.1 Find a pivot element 2.2 Partition the array into two sub-arrays using the pivot 2.3 Recursively quicksort the two sub-arrays 3. Write the sorted array to output file PSU CS320 Fall 17 Weeks 6&7: Procedures and Parameter Passing 13 / 45

Benefits of Nested Functions Version 1: All functions are defined at the top scope level: C void sort(file in, File out) { int[] a;... a... readarray... quicksort... writearray... void readarray(file in, int *a) {... in... a... void writearray(int *a, File out) {... a... out... void quicksort(int *a, int lo, int hi) { int pivot =...;... a... pivot... partition... quicksort... void partition(int *a, int pivot, int lo, int hi) {... a... pivot... swap... void swap(int *a, int i, int j) {... a[i]... a[j]... Each function is only referenced in a local scope. PSU CS320 Fall 17 Weeks 6&7: Procedures and Parameter Passing 14 / 45

Benefits of Nested Functions Version 2: After moving swap inside partition: Pseudo C void sort(file in, File out) { int[] a;... a... readarray... quicksort... writearray... void readarray(file in, int *a) {... in... a... void writearray(int *a, File out) {... a... out... void quicksort(int *a, int lo, int hi) { int pivot =...;... a... pivot... partition... quicksort... void partition(int *a, int pivot, int lo, int hi) { void swap(int i, int j) {... a[i]... a[j]...... a... pivot... swap... Function swap now has fewer parameters. PSU CS320 Fall 17 Weeks 6&7: Procedures and Parameter Passing 15 / 45

Benefits of Nested Functions Version 3: After moving partition inside quicksort: Pseudo C void sort(file in, File out) { int[] a;... a... readarray... quicksort... writearray... void readarray(file in, int *a) {... in... a... void writearray(int *a, File out) {... a... out... void quicksort(int *a, int lo, int hi) { int pivot =...; void partition() { void swap(int i, int j) {... a[i]... a[j]...... a... pivot... swap...... a... pivot... partition... quicksort... Function partition now has no parameter at all! PSU CS320 Fall 17 Weeks 6&7: Procedures and Parameter Passing 16 / 45

Benefits of Nested Functions Version 4: After moving readarray, writearray, quicksort inside sort: Pseudo C void sort(file in, File out) { int[] a; void readarray() {... in... a... void writearray() {... a... out... void quicksort(int lo, int hi) { int pivot =...; void partition() { void swap(int i, int j) {... a[i]... a[j]...... a... pivot... swap...... a... pivot... partition... quicksort...... a... readarray... quicksort... writearray... Now all functions are defined in the scope they are referenced; and all nested functions have fewer parameters! PSU CS320 Fall 17 Weeks 6&7: Procedures and Parameter Passing 17 / 45

Free Variables and Dynamic Scoping In dynamic-scoped languages, nested scopes always exist, even if there is no lexical nest in the program: Pseudo C int x = 0; /* global scope level */ void level1() { int y = 1; /* dynamic scope level 1 */ level2(); void level2() { int z = 2; /* dynamic scope level 2 */ level3(); void level3() {... /* dynamic scope level 3 */ print(x+y+z); From within level3(), variables defined in all levels can be accessed. In dynamic-scoped languages, a function s free variables can come from other, non-enclosing functions. PSU CS320 Fall 17 Weeks 6&7: Procedures and Parameter Passing 18 / 45

Handling Free Variables To support calls to nested functions, we can give the callee a pointer to the activation record of the lexically enclosing function This is known as a static link (or access link). Caller AR Callee AR Stack Dynamic Link Saved Registers Local Variables Arguments Static Link Return Addr Dynamic Link Saved Registers Local Variables Arguments Static Link Return Addr enclosing function s AR enclosing functions s AR * In the case of an OOP method, the pointer points to the heap object it belongs to. PSU CS320 Fall 17 Weeks 6&7: Procedures and Parameter Passing 19 / 45

Handling Free Variables Example: Given the following definition: int f(int x, int y) { int g(int z) { return x+z; return g(x+y); and a call f(4,2), thestackmight look something like the display to the right during the call to g. In particular, the value for x can be found by following the static link g to function f s AR (f happens to be g s caller) f s AR g s AR y=2 x=4 static link f return addr f dynamic link f z=6 static link g return addr g dynamic link g PSU CS320 Fall 17 Weeks 6&7: Procedures and Parameter Passing 20 / 45

Handling Free Variables Note that the enclosing function is not always the caller function, i.e. static link dynamiclink Suppose we have the definition: int f(int x, int y) { int g(int z) { return h(x+h(z)); int h(int u) { return y*u; return g(x+y); The static link that g uses in calls to h points to f s AR, not g s AR f s AR g s AR h s AR y x static link f return addr f dynamic link f z static link g return addr g dynamic link g u static link h return addr h dynamic link h PSU CS320 Fall 17 Weeks 6&7: Procedures and Parameter Passing 21 / 45

Handling Free Variables For dynamic-scoped languages, handling free variables is easier After the current AR, the next AR to visit is always the caller s AR! There is no need to introduce a static link, just use the dynamic link: Pseudo C int x = 0; /* global scope */ void level1() { int y = 1; /* dynamic scope level 1 */ level2(); void level2() { int z = 2; /* dynamic scope level 2 */ level3(); void level3() {... /* dynamic scope level 3 */ print(x+y+z); level1 s AR level2 s AR level3 s AR y=1 return addr f dynamic link f z=2 return addr g dynamic link g... return addr h dynamic link h PSU CS320 Fall 17 Weeks 6&7: Procedures and Parameter Passing 22 / 45

Higher-Order Functions Recall that functions that take other functions as arguments or return other functions as results are sometimes called higher-order functions. Example: int(int) f(int x) { int g(int z) { return x+z; return g; Note: int(int) represents atypeforfunctionsthat take an int argument and return an int result. In this case, g may be called after f has returned... so g may need to access f s x parameter after f has returned... so we can t just dispose of the activation record as soon as a function exits PSU CS320 Fall 17 Weeks 6&7: Procedures and Parameter Passing 23 / 45

Handling Higher-Order Functions A solution in this case is to allocate the activation record for f on the heap, and not on the stack Compared to stack allocation, a high overhead incurs every time an activation record is to be allocated in the heap, since a search for suitable block may need to be performed However, unused activation records can be recovered by garbage collection instead of by popping them off the stack PSU CS320 Fall 17 Weeks 6&7: Procedures and Parameter Passing 24 / 45

Handling Higher-Order Functions An alternative solution exists. If we don t want to keep the activation records in the heap, then we will need to save a copy of free variable x s value in the representation for g before f returns. Such a representation is called a closure. While closures are generally still allocated in the heap, they take up much less space than activation records Furthermore, closures serve as a clean representation for function values This scheme is used in many functional language implementations (and, increasingly now, also in other settings such as C++, Python, and Javascript implementations) PSU CS320 Fall 17 Weeks 6&7: Procedures and Parameter Passing 25 / 45

Representing Function Values Recall lambda expressions They provide a way to write functions without giving them a name. x λx.e e Many modern languages include support for anonymous functions with lambda expressions: Haskell \x -> x + 1 LISP (lambda (x) (+ x 1)) Python lambda x: x + 1 Javascript function (x) x + 1 C++11 [](int x) -> int { return x + 1; Java 8 (int x) -> x + 1 PSU CS320 Fall 17 Weeks 6&7: Procedures and Parameter Passing 26 / 45

Representing Function Values Example: The previous function definition: int(int) f(int x, int y) { int g(int z) { return x+z; return g; Rewritten using a lambda expression: int(int) f(int x, int y) { return (\z -> x+z); PSU CS320 Fall 17 Weeks 6&7: Procedures and Parameter Passing 27 / 45

Representing Function Values Question: How should we represent function values of type int(int)? There are many different values, including: (\z -> x+z), (\x -> x+1), (\x -> x*2), (\x -> f(g(x))),... We need a uniform, but flexible way to represent them A common answer is to represent functions like these by a pointer to a closure, a heap allocated record that contains: a code pointer (i.e., the code for the function) the values of its free variables Note: Because we re making copies of the free variables, we usually require them to be immutable. PSU CS320 Fall 17 Weeks 6&7: Procedures and Parameter Passing 28 / 45

Closures Every function of type int(int) will be represented using the same basic structure: codeptr The code pointer and list of free variables vary from one function value to the next: (\z -> x+z) codeptr1 x (\x -> x+1) (\x -> x*2) codeptr2 codeptr3 (\x -> f(g(x))) codeptr4 f g PSU CS320 Fall 17 Weeks 6&7: Procedures and Parameter Passing 29 / 45

Constructing and Calling Closures Constructing a closure: make an runtime system call to allocate the closure record store the values of the free variables into the record Calling a function via a closure: add a pointer to the closure as an extra initial argument (to provide access to any free variables) make an indirect call to the code pointed to by the first field of the closure Accessing free variables: within the function code, free variables are referenced via the closure argument known functions without free variables don t need a closure argument and can be called directly PSU CS320 Fall 17 Weeks 6&7: Procedures and Parameter Passing 30 / 45

Closures vs. Objects Invoking an unknown function through a closure is very similar to invoking a method of an object: Method invocations pass the object itself as an implicit argument Closures are like objects with a single method Free variables correspond to object fields In Java 8, lambda expressions are just a convenient way to write local, anonymous definitions of single-method classes. PSU CS320 Fall 17 Weeks 6&7: Procedures and Parameter Passing 31 / 45

Parameter Passing Each function operates in in its own local environment plus surrounding environments defined by the language s scope rules. When a function is invoked, it is necessary to pass parameters from the caller to the callee. A basic question concerning parameter passing is: Question: For each parameter, what exactly is passed from the caller to the callee the parameter s address (l-value)? its content (r-value)? or something else? Answers to this question define parameter passing methods: Call-by-value (passing r-values) Call-by-reference (passing l-values) Call-by-name (passing via name substitutions) Call-by-value-result (hybrid between by-value and by-reference) PSU CS320 Fall 17 Weeks 6&7: Procedures and Parameter Passing 32 / 45

Call-by-Value Each actual argument is evaluated to a value before call. On entry, value is copied to formal parameter; which behaves just like a local variable. Advantages: Simple; easy to understand! Formal parameters can be used as local variables, Updating them doesn t affect actuals in calling function: double hyp(double a, double b) { a = a * a; b = b * b; return sqrt(a+b); PSU CS320 Fall 17 Weeks 6&7: Procedures and Parameter Passing 33 / 45

Problems with Call-by-Value Can be inefficient if value is large: typedef struct {double a1, a2,..., a10; vector; double dotprod(vector v, vector w) { return v.a1 * w.a1 + v.a2 * w.a2 +... + v.a10 * w.a10; vector v1,v2; double d = dotprod(v1,v2); // copy 20 doubles Cannot affect calling environment directly: void swap(int i, int j) { int t; t = i; i = j; j = t; swap(a[p], a[q]); // has no effect on array a! Can return result only through (the single) return value. PSU CS320 Fall 17 Weeks 6&7: Procedures and Parameter Passing 34 / 45

Call-by-Reference Pass the address of each actual parameter. On entry, the formal is bound to the address, providing a reference to the actual parameter from within the callee. If actual argument doesn t have an l-value (e.g., 2 + 3 ), either: evaluateitintoatemporarylocationandpassitsaddress,or treatasanerror Advantages: No more large copying Actual parameter can be updated Now swap, etc.,workfine! PSU CS320 Fall 17 Weeks 6&7: Procedures and Parameter Passing 35 / 45

Problems with Call-by-Reference Accesses are slower address must be dereferenced to get value Lots of opportunity for aliasing problems, e.g., // multiplying matrices a and b into c int** mtxmult(int n, int **a, int **b, int **c) { int i, j, k; for (i=0; i<n; i++) for (j=0; j<n; j++) for (k=0; k<n; k++) c[i][j] += a[i][k] * b[k][j]; return c; mtxmult(a, b, a); // oops! Question: Can we combine the simplicity of call-by-value with the efficiency for large values of call-by-reference? PSU CS320 Fall 17 Weeks 6&7: Procedures and Parameter Passing 36 / 45

CandC++ ssolutions Calwaysusescall-by-value. But record (struct) r-values are the actual contents, while array r-values are pointers to the contents; hence array contents do not get copied when arrays are passed as parameters In addition, programmers can take the address of a variable explicitly, and pass that to obtain call-by-ref-like behavior swap(int *a, int *b) { int t; t = *a; *a = *b; *b = t; swap(&a[p],&a[q]); PSU CS320 Fall 17 Weeks 6&7: Procedures and Parameter Passing 37 / 45

CandC++ ssolutions C++ inherits the above properties of C. Furthermore, it supports call-by-reference parameters through the use of reference variables. swap(int &a, int &b) { int t; t = a; a = b; b = t; swap(a[p], a[q]); Note: Mixing explicit and implicit pointers can be very confusing! swap(int &a, int *b) { int t; t = a; a = *b; *b = t; swap(a[p],&a[q]); PSU CS320 Fall 17 Weeks 6&7: Procedures and Parameter Passing 38 / 45

Pascal and Ada s Solutions In Pascal, Ada, and similar languages, r-values of both arrays and records are the actual contents. However, they permit the programmer to specify the intended use of each parameter: in param is for passing value of the actual into the function out param is for passing value of the formal param back to the actual in out param is for passing value into as well as out from the function The idea is to let the compiler to decide which parameter passing method to use for each parameter. PSU CS320 Fall 17 Weeks 6&7: Procedures and Parameter Passing 39 / 45

Java s Solution Java has only call-by-value mode. However, in Java, a variable representing an object is a reference to the object, instead of its content. When an object is passed as a parameter, only its reference is copied. This reference model of variables also provides some call-by-reference-like benefits when an object is passed as an actual parameter, its content can be updated in the function: class A { int i = 0;... class B { void sub(a a) { a.i = 5; void test() { A x = new A(); sub(x); System.out.println(x.i); // prints 5 PSU CS320 Fall 17 Weeks 6&7: Procedures and Parameter Passing 40 / 45

How Does This Differ from Call-by-Reference? Consider: class A { int i = 0;... class B { void sub(a a) { a = new A(); // parameter a gets modified here a.i = 5; void test() { A x = new A(); sub(x); System.out.println(x.i); // prints 0 Updating formal parameters in the function affects only local copy. PSU CS320 Fall 17 Weeks 6&7: Procedures and Parameter Passing 41 / 45

Call-by-Name The idea is from β-reduction of functional programming. In C and some other languages, macros are used to define simple functions. The user interface of a macro resembles that of a function: #define max(a,b) ((a)>(b)? (a) : (b)) v = max(x,y); When a macro is called, each formal parameter is literally replaced by the corresponding actual parameter: max(x+1,y-2) ((x+1)>(y-2)? (x+1) : (y-2)) However, macros and functions are fundamentally different: Macros are called at compile-time (or pre-compile-time), functions are called at runtime Macros can not contain recursion PSU CS320 Fall 17 Weeks 6&7: Procedures and Parameter Passing 42 / 45

Call-by-Name (cont.) But blind substitution is dangerous because of possible variable capture : #define swap(x,y) {int t; t=x; x=y; y=t; swap(a[t],a[q]); The call expands to {int t; t=a[t]; a[t]=a[q]; a[q]=t; Here t is captured by the declaration in the macro, and is undefined at its first use. Call-by-name is actually substitution with renaming where necessary. Flexible, but potentially very confusing, and inefficient to implement If language has no updatable variables (as in pure functional languages), call-by-name gives a beautifully simple semantics for function calls PSU CS320 Fall 17 Weeks 6&7: Procedures and Parameter Passing 43 / 45

Call-by-Value-Result Each actual argument is evaluated to a value before call On entry, value is bound to formal parameter just like a local variable Updating formal parameters doesn t affect actuals in calling function... so far it looks just like call-by-value Upon exit, the final contents of the formal parameters are copied into the actuals It behaves very much like call-by-reference in most normal situations, but may give different results when concurrency or aliasing are involved: type t is record a,b: integer; end record; r : t; procedure foo(s: in out t) is begin r.a := 2; s.a := s.a + 3; end foo; r.a := 1; foo(r); print(r.a); (* what's the value of r.a? *) PSU CS320 Fall 17 Weeks 6&7: Procedures and Parameter Passing 44 / 45

Summary Each function invocation requires a storage to keep its state information, which is called an activation record (AR); For non-functional languages, ARs are allocated on the runtime stack For handling nested functions, a common approach is to set up a static link in a function AR to point to the enclosing function s AR Function values can be represented by closure records that pair a code pointer with a list of variable values For a language with higher-order functions, ARs or closures need to be allocated on the heap, because a function value may have a longer lifetime than the function that created it There are several parameter passing methods: by value, by reference, by name, and by value-result; each method has its unique advantages over the others PSU CS320 Fall 17 Weeks 6&7: Procedures and Parameter Passing 45 / 45