Operational Semantics
Lecture 5
Table of Contents
Functions
Looked at the assignment statment
What about conditionals?
What is a function?
Functions as an abstraction
- Abstracts away details of implementation
- Names computation
- Specified by input/output behavior
What is the behavior of a function call?
int f(int x) { return x * x; } int main() { f(9); // what is the behavior of this? int y = input(); f(y++); // what about this? }
Informal semantics of a function call
- Evaluate arguments first
- Replace (bind) formal argument names with evaluated values
- Create new context (scope) for function call with arguments
- Evaluate body of function call under new context
- Evaluate return value
Formal semantics of a function call
// functions: functions are call-by-value, have a local storage // context, and produce a return value (formals, st, e) = functions.lookup(f) // evaluate arguments before binding under caller context S : <actuals[1]> => v[1] ... S : <actuals[N]> => v[N] // bind formal arguments to actuals, creating new local context Slocal = {formals[i] = v[i]} for all i = 1..N // evaluate body after binding arguments Slocal : <st> => Slocal' // evaluate return value Slocal' : <e> => v ------------------------------------------- S : <f(actuals)> => v // store function in global functions store functions.put(f, (formals, st, e)) ---------------------------------- <f(formals) st return e;>
Semantic choices
- Call-by-value vs. call-by-name
- Static vs. dynamic scope
- Eager evaluation vs. lazy evaluation
- See Winskel ch 9 and 11
Other function semantics
- Call-by-value (substitute before evaluation)
- Differing scope rules (add to scope vs. get a fresh scope)
- Global vs. local, nested scopes, let-bindings
- Functions as values, closures
- See Winskel ch 11
Personal project opportunities
- Adding new language constructs
- Syntactic sugar, e.g., for loops, if-then-else, elif, etc.
- Pointers
- Arrays
- Objects
- Adding new language features
- Other data types
- Type constructors
- Type inference
More advanced semantics
Pointers
Separate identifiers from memory locations (l-values)
Arrays, structs, pointer arithmetic
int *x; int *y; *y = 10; *(x + 1);
First-class functions
- Functions as values
- Can return functions (create functions on the fly)
- Lambda calculus to model such functions
- How would we implement such functions?
f = lambda x: x * x print(f(2)) def outer(x): y = x + 1 def inner(inner_param): return y + inner_param return inner curried_inner = outer(10) print(curried_inner) print(curried_inner(3)) curried_inner = outer(0) print(curried_inner) print(curried_inner(3))
Homework
Setup
This homework assumed ANTLR is already installed, which was the first homework assignment of the semester. For my ANTLR installation, via apt install antlr
on Ubuntu 20.04 but you may also try apt install antlr4
, the antlr4
executable is in /usr/bin
, the runtime library is at /usr/share/java/antlr4-runtime.jar
and the ANTLR TestRig is at /usr/share/antlr4/grun
.
Steps to prepare for the assignment.
- Download ANTLR examples
- Extract code/tour/LabeledExpr.g4 from the zipfile
Generate the parser for LabeledExpr.g4
antlr4 -visitor LabeledExpr.g4
Compile the parser
javac -cp /usr/share/java/antlr4-runtime.jar LabeledExpr*.java
Try printing the tokens
echo "1+2*3" | /usr/share/antlr4/grun LabeledExpr prog -tokens
Try printing a tree
echo "1+2*3" | /usr/share/antlr4/grun LabeledExpr prog -tree
Try generating a tree diagram
echo "1+2*3" | /usr/share/antlr4/grun LabeledExpr prog -gui
You can export this image.
Homework assignment
Create your own valid input program for the LabeledExpr parser and turn in an image (via -gui
) of the tree generated by the grun
TestRig by following the directions above. If your installation is headless, turn in the text-based tree (via -tree
) instead.