450 likes | 457 Views
CS 476 – Programming Language Design. William Mansky. HW3 #3: Building a Proof Tree. HW3 #4: Writing Proof Rules. Adding Functions. With variables, assignment, declarations, and control flow, we have a simple imperative language
E N D
CS 476 – Programming Language Design William Mansky
Adding Functions • With variables, assignment, declarations, and control flow, we have a simple imperative language • But every imperative language in use has at least one more feature: functions
Adding Functions • Main goal: code reuse • Requires: • Definitions and calls • Arguments and local state • Argument and return types • Ability to call a function from inside a function (even recursively!)
Functions: Syntax of Definitions E ::= … T ::= int | bool D ::= T <ident> | D; D F ::= T <ident>(T <ident>, …, T <ident>){ ?} P ::= D; C C ::= …
Functions: Syntax of Definitions E ::= … T ::= int | bool D ::= T <ident> | D; D F ::= T <ident>(T <ident>, …, T <ident>){ D; C }| F; F P ::= D; F; C C ::= …
Functions: Syntax of Definitions E ::= … T ::= int | bool D ::= T <ident> | D; D F ::= T <ident>(T <ident>, …, T <ident>){ D; C; return E } | F; F P ::= D; F; C C ::= …
Functions: Syntax of Calls E ::= … T ::= int | bool D ::= T <ident> | D; D F ::= T <ident>(T <ident>, …, T <ident>){ D; C } | F; F P ::= D; F; C C ::= … | return E
Functions: Syntax of Calls E ::= … | <ident>(E, …, E) T ::= int | bool D ::= T <ident> | D; D F ::= T <ident>(T <ident>, …, T <ident>){ D; C } | F; F P ::= D; F; C C ::= … | return E
Functions: Syntax of Calls E ::= … T ::= int | bool D ::= T <ident> | D; D F ::= T <ident>(T <ident>, …, T <ident>){ D; C } | F; F P ::= D; F; C C ::= … | return E | <ident> := <ident>(E, …, E)
Functions: Types • is a declared function • Each of has the right type • The return type of matches the type of • We can store this information in
Functions: Types int f(int x, int y){ return x + y } f is a function with return type int, and arguments int x and int y • We can store this information in
Functions: Types • is a declared function • Each of has the right type • The return type of matches the type of
Processing Function Declarations int f(int x, int y){ return x + y } function declaration new context old context
Processing Function Declarations int f(int x, int y){ return x + y } • The function’s parameters should be available in the function body
Processing Function Declarations int f(int x, int y){ return x + y } • The function’s parameters should be available in the function body • And so should the previously declared functions • (Mutually recursive functions would require an extra step)
Processing Function Declarations int f(int x, int y){ return x + y } • The function’s parameters should be available in the function body • And so should the previously declared functions • We can use a fake variable to type any return commands
Functions: Syntax of Calls E ::= … T ::= int | bool D ::= T <ident> | D; D F ::= T <ident>(T <ident>, …, T <ident>){ D; C } | F; F P ::= D; F; C C ::= … | return E | <ident> := <ident>(E, …, E)
Functions: Types • is a declared function • Each of has the right type • The return type of matches the type of
Functions: Semantics of Calls • Evaluate the arguments • Look up in • Execute the body of and produce a return value • Assign the return value to
Functions: Semantics of Calls • Evaluate the arguments • Look up in • Execute the body of and produce a return value • Assign the return value to
Functions: Semantics of Calls • Evaluate the arguments • Look up in • Execute the body of and produce a return value • Assign the return value to
Functions: Semantics of Calls • Evaluate the arguments • Look up in • Execute the body of and produce a return value • Assign the return value to
Functions: Semantics of Calls • Evaluate the arguments • Look up in • Execute the body of and produce a return value • Assign the return value to
Functions: Semantics of Calls • Small-step relation is now , where is a stack of states
Functions: Semantics of Calls • Small-step relation is now , where is a stack of states
Functions: Semantics of Calls • Small-step relation is now , where is a stack of states
Functions: Semantics of Calls where ,
Functions: What Does This Mean? • Big-step and small-step describe the same behavior • Small-step semantics now need a whole extra piece of state • And that state corresponds to a feature of real language implementations!
Functions: Interpreter vs. Compiled let rec eval_cmd e s = match e with | Call (x, f, es) ->
Functions: Interpreter vs. Compiled let rec eval_cmd e s = match e with | Call (x, f, es) -> match eval_exps es s with Some vs -> match s f with Some (xs, c) -> match eval_cmd c (merge (funs s) (make_statexs vs)) with | Some (Ret v) -> Some (State (update s x v))
Functions: Interpreter vs. Compiled let rec eval_cmd e s = match e with | Call (x, f, es) -> match eval_exps es s with Some vs -> match s f with Some (xs, c) -> match eval_cmd c (merge (funs s) (make_statexs vs)) with | Some (Ret v) -> Some (State (update s x v)) push stackframe f: store args <compiled code for c> store ret addr pop stackframe jmp f jmp ret addr
Imperative Languages • Arithmetic and boolean expressions • Variables and assignment • Control flow (conditionals, loops) • Variable declarations • Exceptions and exception handling • Function declarations and calls • There’s more, but we’ve covered the essentials! • Next up: object-oriented languages