(*===========================================*) (* ML version of compiled code for *) (* *) (* val x = 3; *) (* fun f(y) = if y=0 then x else y+f(y-1); *) (* f(5); *) (* *) (*===========================================*) (*------- activation record format and environment pointer -------------*) datatype activation = Function_AR of { control_link : activation, access_link : activation, return_result_addr : int ref, parameter : int, tmp : int ref } | Block_AR of { control_link : activation, access_link : activation, value : int } | NOSTACK; val env = ref NOSTACK; (*---------- stack operations for block and function ------------*) fun push_block_AR(a,v) = (* arguments are access link and local value *) let val ar = Block_AR{ control_link=(!env), (* control link always points to previous top *) access_link=a, value=v} in env := ar (* place new activation record on top of stack *) end; fun push_function_AR(a,rv,n) = (* arguments are access link, return-value *) let val ar = Function_AR{ (* address and value of function parameter *) control_link=(!env), access_link=a, return_result_addr=rv, parameter=n, tmp=ref 0} (* assignable temporary location initially 0 *) in env := ar end; fun pop() = case (!env) of NOSTACK => () | Function_AR(ar) => env := #control_link(ar) | Block_AR(ar) => env := #control_link(ar) ; (*--- helper function for accessing value from declaration block ---*) (* These functions will raise exception "Match" if applied to the wrong form of activation record *) fun block_value(Block_AR(ar)) = #value(ar); fun block_access_link(Block_AR(ar)) = #access_link(ar); (*------------------------- body of function f ----------------------*) exception Bad_Activation_Record; fun function_body() = case (!env) of NOSTACK => raise Bad_Activation_Record | Block_AR(ar) => raise Bad_Activation_Record | Function_AR{ control_link= control_link, access_link = access_link, return_result_addr=return_result_addr, parameter= function_parameter, tmp= tmp } => if function_parameter = 0 then return_result_addr := (* ---- missing part ----*) else ( push_function_AR(access_link, tmp, function_parameter-1); function_body(); return_result_addr := function_parameter + !tmp; pop() ); (*- create cell for return value, do declaration and function call -*) val show_this = ref 0; push_block_AR(!env,3); (* declare x=3 *) push_function_AR(!env,show_this,5); (* create function activ record *) function_body(); (* execute function body *) pop(); (* pop activation record *) pop(); (* pop activation record *) !show_this; (* show function return value *)