- Concepts of Programming Languages

Argument Passing

Instructor:

Learning Objectives

How should arguments to functions be passed in?

  • Interpret call-by-value and call-by-reference function calls

Argument Passing

  • What are x, y, "hello", and 10 below:
    1. def f (x:String, y:Int) = x * y
    2. f ("hello", 10)
  • x, y: formal parameters (or parameters)
  • "hello", 10: actual parameters (or arguments)

Argument Passing

  • What does a call to f print?
    1. def g (y:Int) : Int =
    2. y = y + 1
    3. end g
    4. def f () =
    5. var x = 1
    6. g (x)
    7. println (x)
    8. end f
  • Prints 1 because Scala uses call-by-value

Call-By-Value vs. Call-By-Reference

Call-by-Value

  • Most PLs use call-by-value (CBV) by default
  • To run g (e)
    1. evaluate e to a value v
    2. pass a copy of v to g
    3. callee changes to copy of v are not visible to caller

Call-by-Reference

  • Some PLs use call-by-reference (CBR)
  • To run g (e)
    1. evaluate e to an l-value r
    2. pass the address r to g
    3. callee changes via r are visible to caller

Example

  1. def g(y:Int) : Int =
  2. y = y + 1
  3. end g
  4. def f() =
  5. var x = 1
  6. g(x)
  7. println(x)
  8. end f

Call-By-Value

  • Prints 1 in a CBV PL, i.e., x=1 after call to g

Call-By-Reference

  • Prints 2 in a CBR PL, i.e., x=2 after call to g

Formal Semantics of Function Calls

  • How do we specify what a function does?
  • Have: global store for variables and their values
  • Need another store : maps function names to argument names and function bodies
  • Need a local store for arguments and local variables

Call-by-value

Call-by-reference (copy-in, copy-out)

CBR and Temporaries

  • Can temporary values be passed as l-values?
  • g(x+1) is not obviously legitimate in CBR
  • Some languages reject it, some allow it
  • Perl allows it

Call-By-Reference: Perl

  • Perl uses CBR
  1. sub g {
  2. $_[0] = $_[0] + 1;
  3. }
  4. sub f {
  5. my $x = 1;
  6. g ($x);
  7. print ("x = $x\n");
  8. }
  9. f ();
  1. $ perl ./cbr.pl
  2. x = 2

Call-By-Reference: Perl

  • Perl allows temporaries!
  1. sub g {
  2. $_[0] = $_[0] + 1;
  3. }
  4. sub f {
  5. my $x = 1;
  6. g ($x + 1);
  7. print ("x = $x\n");
  8. }
  9. f ();
  1. $ perl ./cbr.pl
  2. x = 1

Call-By-Reference: Perl

  • Simulate CBV by creating copies explicitly
  1. sub g {
  2. my ($y) = @_;
  3. $y = $y + 1;
  4. }
  5. sub f {
  6. my $x = 1;
  7. g ($x);
  8. print ("x = $x\n");
  9. }
  10. f ();
  11. # x=1

Call-By-Value: C

  • Simulate CBR in C by explicitly passing, receiving, accessing a pointer
  1. void g (int *p) {
  2. *p = *p + 1;
  3. }
  4. int main () {
  5. int x = 1;
  6. g (&x);
  7. printf ("x = %d\n", x);
  8. return 0;
  9. }
  10. // x=2

Call-By-Reference: C++

  • C++ reference type int& (unlike int*, creates references implicitly)
  1. void g(int& y) {
  2. y = y + 1;
  3. }
  4. int main() {
  5. int x = 1;
  6. g(x);
  7. // x==2
  8. cout << "x = " << x << endl;
  9. return 0;
  10. }
  • What makes this design error-prone?

Call-By-Reference: C++

  • In C++, at caller CBR is indistinguishable from CBV
  1. void g(int y) { // vs. void g(int& y)
  2. y = y + 1;
  3. }
  4. int main() {
  5. int x = 1;
  6. g(x);
  7. // x==1 vs. x==2 when void g(int& y)
  8. cout << "x = " << x << endl;
  9. return 0;
  10. }
  • Small change in function signature, large effect at caller

Call-By-Reference: C#

  • C# has reference parameters ref int
  1. class Test {
  2. static void g (ref int y) {
  3. y = y + 1;
  4. }
  5. static void Main () {
  6. int x = 1;
  7. g (ref x);
  8. // x == 2
  9. Console.WriteLine("{0}", x);
  10. }
  11. }
  • Unlike int& must also be used by caller

Call-By-Reference: C++

  • Passing a non-lvalue
  1. void g(int& y) {
  2. y = y + 1;
  3. }
  4. int main() {
  5. int x = 1;
  6. g(x + 1);
  7. cout << "x = " << x << endl;
  8. return 0;
  9. }
  1. $ g++ -o reference reference.cpp
  2. reference.cpp: In function ‘int main()’:
  3. referencs.cpp:11:8: error: invalid initialization of non-const
  4. reference of type ‘int&’ from an rvalue of type ‘int’
  5. g (x + 1);
  6. ^
  7. references.cpp:5:6: error: in passing argument 1 of ‘void g(int&)’
  8. void g (int& y) {
  9. ^

Call-By-Value: Java

  • Java has only a restricted form of pointers, called references
    • must point to heap-allocated objects
    • cannot point to stack-allocated data
    • cannot point to primitive types
  • Java references cannot be forged
    • not from integers via casting
    • not from other references via pointer arithmetic
  • Objects only accessed via references
    • unlike C++
    • Java has no address-of & operator

Call-By-Value: Java

  • Simulate CBR In Java: heap-allocated object with field of intended argument type
  • Pass a reference to the object instance by value
  1. class IntRef { int n; }
  2. public class Ref {
  3. static void g(IntRef r) { r.n = r.n + 1; }
  4. public static void main(String[] args) {
  5. IntRef s = new IntRef (); s.n = 1;
  6. g(s);
  7. // s.n == 2
  8. System.out.println (s.n);
  9. }
  10. }

Summary

Call-by-value

  • Pass copies of r-values as arguments
  • Changes not visible to caller
  • Strict evaluation

Call-by-reference

  • Pass l-values as arguments
  • Changes visible to caller
  • Strict evaluation

$$\frac{\substack{\langle \mathtt{e_1},\xi_0,\phi,\rho_0 \rangle \Downarrow \langle v_1,\xi_1,\phi,\rho_1 \rangle \\ \vdots \\ \langle \mathtt{e_n},\xi_{n-1},\phi,\rho_{n-1} \rangle \Downarrow \langle v_n,\xi_n,\phi,\rho_n \rangle} \quad \phi(\mathtt{f})=(\mathtt{x_1,\ldots,x_n}, e) \quad \langle e,\xi_n,\phi,\{ \mathtt{x_1} \mapsto v_1,\ldots,\mathtt{x_n} \mapsto v_n \} \rangle \Downarrow \langle v,\xi',\phi,\rho' \rangle}{\langle \mathtt{f(e_1,\ldots,e_n)},\xi_0,\phi,\rho_0 \rangle \Downarrow \langle v,\xi',\phi,\rho_n \rangle}\text{\tiny(FunCBV)}$$

$$\frac{\substack{\langle \mathtt{e_1},\xi_0,\phi,\rho_0 \rangle \Downarrow \langle v_1,\xi_1,\phi,\rho_1 \rangle \\ \vdots \\ \langle \mathtt{e_n},\xi_{n-1},\phi,\rho_{n-1} \rangle \Downarrow \langle v_n,\xi_n,\phi,\rho_n \rangle} \quad \phi(\mathtt{f})=(\mathtt{x_1,\ldots,x_n}, e) \quad \langle e,\xi_n,\phi,\{ \mathtt{x_1} \mapsto v_1,\ldots,\mathtt{x_n} \mapsto v_n \} \rangle \Downarrow \langle v,\xi',\phi,\rho' \rangle}{\langle \mathtt{f(e_1,\ldots,e_n)},\xi_0,\phi,\rho_0 \rangle \Downarrow \langle v,\xi',\phi,\rho_n \cup \rho'_{\downarrow\{x_1,\ldotsx_n\}} \rangle}\text{\tiny(FunCBR)}$$

# <span class="fa-stack"><i class="fa-solid fa-circle fa-stack-2x"></i><i class="fa-solid fa-cubes fa-stack-1x fa-inverse"></i></span> Formal Semantics of Function Calls - Example: ```scala def f(x) = 2*x f(3) ``` * With stores $\xi=\{\}$, $\phi=\{\mathtt{f} \mapsto (\mathtt{x,2*x})\}$, $\rho=\{\}$ * Deduction tree <div class="flex justify-center text-sm"> <div data-marpit-fragment class="absolute bg-white z-0"> $$ \begin{prooftree} \AXC{} \UIC{} \AXC{} \AXC{} \UIC{} \AXC{} \UIC{} \BIC{} \TIC{$\langle \mathtt{f(3)},\xi,\phi,\rho \rangle \Downarrow \langle 6,\xi,\phi,\rho\rangle$} \end{prooftree} $$ </div> <div data-marpit-fragment class="absolute bg-white z-1"> $$ \begin{prooftree} \AXC{} \UIC{$\langle \mathtt{3},\xi,\phi,\rho \rangle \Downarrow \langle 3,\xi,\phi,\rho\rangle$} \AXC{$\phi(\mathtt{f})=(\mathtt{x,2*x})$} \AXC{} \UIC{} \AXC{} \UIC{} \BIC{$\langle \mathtt{2*x},\xi,\phi,\{\mathtt{x} \mapsto 3\} \rangle \Downarrow \langle 6,\xi,\phi,\rho \rangle$} \RL{(Fun)} \TIC{$\langle \mathtt{f(3)},\xi,\phi,\rho \rangle \Downarrow \langle 6,\xi,\phi,\rho\rangle$} \end{prooftree} $$ </div> <div data-marpit-fragment class="absolute bg-white z-2"> $$ \begin{prooftree} \AXC{} \RL{(Num)} \UIC{$\langle \mathtt{3},\xi,\phi,\rho \rangle \Downarrow \langle 3,\xi,\phi,\rho\rangle$} \AXC{$\phi(\mathtt{f})=(\mathtt{x,2*x})$} \AXC{} \RL{(Num)} \UIC{$\langle \mathtt{2},\xi,\phi,\{\mathtt{x} \mapsto 3\} \rangle \Downarrow \langle 2,\xi,\phi,\{\mathtt{x} \mapsto 3\} \rangle$} \AXC{} \RL{(Var)} \UIC{$\langle \mathtt{x},\xi,\phi,\{\mathtt{x} \mapsto 3\} \rangle \Downarrow \langle 3,\xi,\phi,\{\mathtt{x} \mapsto 3\} \rangle$} \RL{(Mul)} \BIC{$\langle \mathtt{2*x},\xi,\phi,\{\mathtt{x} \mapsto 3\} \rangle \Downarrow \langle 6,\xi,\phi,\rho \rangle$} \RL{(Fun)} \TIC{$\langle \mathtt{f(3)},\xi,\phi,\rho \rangle \Downarrow \langle 6,\xi,\phi,\rho\rangle$} \end{prooftree} $$ </div> </div> ---

**Call-by-name**

- Scala notation to pass parameterless functions as arguments

- Nonstrict evaluation

</div>