abstract machines
play

Abstract Machines What is an abstract machine? - a set of legal - PowerPoint PPT Presentation

Concepts of Program Design Abstract Machines Gabriele Keller Ron Vanderfeesten Abstract Machines What is an abstract machine? - a set of legal states final and initial states as subset - A set of instructions altering the state of the


  1. Concepts of Program Design Abstract Machines Gabriele Keller Ron Vanderfeesten

  2. Abstract Machines • What is an abstract machine? - a set of legal states ‣ final and initial states as subset - A set of instructions altering the state of the machine ‣ it should be possible to implement the operations on a real machine in a finite (preferably constant) number of steps • Why use abstract machines at all? - specifies the semantics of a programming languages - facilitates porting to other architectures - mobile code (e.g., Java Virtual Machine) • We have seen this before - similar to SOS, but with Abstract Machines, we care about performance

  3. Control Flow • Base line: the M-machine - small step semantics for MinHs - transition system embodies essentially a very high-level (= concise, but inefficient) abstract machine - we call it the M-machine • Characteristics of the M-machine - substitution as “machine operation” ‣ why is that bad? ‣ can be avoided by using an environment - control-flow is not explicit ‣ the search rules determine next subexpression to be evaluated ‣ why is that bad?

  4. Control Flow • Example: (Plus (Num n) (Num m)) ↦ Num (n+m) e 1 ↦ e 1 ’ (Plus e 1 e 2 ) ↦ ( Plus e 1 ’ e 2 ) e 2 ↦ e 2 ’ (Plus(Num n) e 2 ) ↦ ( Plus (Num n) e 2 ’ ) Plus(Num 3)(Num 2) ↦ Num 5 Plus(Plus(Num 3)(Num 2))(Num 4) ↦ Plus(Num 5)(Num 4) Plus(Plus(Plus(Num 3)(Num 2))(Num 4))(Num 6) ↦ Plus(Plus(Num 5)(Num 4))(Num 6) depending on the size & nesting depth of the expression, searching for the next reducible subexpression can be very expensive!!!

  5. Control Flow • Single-step evaluation in Haskell: eval(Num n) = Num n eval e = eval (single e) single (Plus (Num n1) (Num n2)) = Num (n1 + n2) single (Plus (Num n1) e) = Plus (Num n1) (single e) single (Plus e1 e2) = Plus (single e1) e2 single (Times .... ‣ Properties: ‣ for each step, the expression has to be traversed to find the next subexpression that has to be evaluated ‣ makes heavy use of the runtime stack

  6. The C-machine • Explicit control flow: C-machine - explicit stack - explicit handling of control flow - variable binding still handled by substitution - we call this machine the C-machine • Machine state - the current expression (as before) - a control stack of subcomputations (frames) which have to be performed before the machine terminates • Initial and final states - initial states: closed expression and an empty stack - final states: expression is a value and the stack is empty

  7. The C-machine • Example: addition in three stages 1. Evaluate first argument ‣ first argument becomes current expression ‣ remember to continue with computation, result as first argument 2. Evaluate second argument ‣ second argument becomes current expression ‣ remember to continue with computation, result as second argument 3. Perform addition

  8. The C-machine • How can we denote a stack frame as a term? • We use terms with holes; e.g., Plus ☐ e 2 ‣ suspended computation of addition ‣ waits for the value of its first argument • Inductive definition of frames: e expr (Plus ☐ e ) frame Plus e 1 ☐ not a frame, because first argument is v value evaluated first! (Plus v ☐ ) frame

  9. Inductive Definition of Frames • Addition e expr (Plus ☐ e ) frame v value (Plus v ☐ ) frame • If-expressions e 1 expr e 2 expr (If ☐ e 1 e 2 ) frame • Application e expr (Apply ☐ e ) frame v value (Apply v ☐ ) frame

  10. Stack and Machine Modes • Stacks: f 1 ▷ f 2 ▷ ◦ - f 1 is the top-most frame - f 2 is the second frame - ◦ is the empty stack • Inductive definition: ◦ stack f frame s stack f ▷ s stack • Machine modes: the C-machine operates in two modes: ‣ s ≻ e : evaluate expression e under stack s ‣ s ≺ v : return value v to stack s

  11. Transition Rules for MinHs • Values (integers, booleans, functions) s ≻ v ↦ c s ≺ v { evaluate the value v under stack s • Addition s ≻ ( Plus e 1 e 2 ) ↦ c (Plus ☐ e 2 ) ▷ s ≻ e 1 (Plus ☐ e 2 ) ▷ s ≺ v ↦ c (Plus v ☐ ) ▷ s ≻ e 2 (Plus(Num n 1 ) ☐ ) ▷ s ≺ Num n 2 ↦ c s ≺ Num( n 1 + n 2 )

  12. Transition Rules for MinHs • if-expressions s ≻ ( If e 1 e 2 e 3 ) ↦ c (If ☐ e 2 e 3 ) ▷ s ≻ e 1 (If ☐ e 2 e 3 ) ▷ s ≻ e 1 (If ☐ e 2 e 3 ) ▷ s ≺ True ↦ c s ≻ e 2 (If ☐ e 2 e 3 ) ▷ s ≺ False ↦ c s ≻ e 3

  13. Transition Rules for MinHs • Function application (Apply ☐ e 2 ) ▷ s ≻ e 1 s ≻ ( Apply e 1 e 2 ) ↦ c (Apply ☐ e 2 ) ▷ s ≺ v ↦ c (Apply v ☐ ) ▷ s ≻ e 2 (Apply(Fun τ 1 τ 2 f.x.e ) ☐ ) ▷ s ≺ v ↦ c s ≻ e [ f:= ( Fun τ 1 τ 2 ( f.x.e) ) , x := v ] writing Fun instead of Recfun from now on to save some space • Observations; ‣ all the inference rules are axioms! ‣ the definition of single-step evaluation in the C-machine is not recursive ‣ the full evaluator is tail recursive (can be implemented using a while-loop)

  14. Environments • Now, let’s get rid of substitution! • We used an environment for TinyC - but we can’t just pass it along, because we wouldn’t know when to delete bindings (Apply(Fun τ 1 τ 2 f.x.e ) ☐ ) ▷ s ≺ v ↦ c s ≻ e [ f := Fun τ 1 τ 2 f.x.e ) , x:= v ] - we need to save the old environment somewhere, and restore it when returning from the function call - can we use the stack to keep track of the environment?

  15. The E-machine • In the E-machine ‣ we have frames defined exactly as before ‣ explicit environments, which are a sequence of variable bindings η env ● env x = v, η env ‣ stacks in the E-machine are sequences of environments and frames f frame s stack η env s stack ◦ stack η ▷ s stack f ▷ s stack ‣ states in the E-machine include an environment s | η ≻ e s | η ≺ v

  16. The E-machine: Transition Rules • Free variables: s | η ≻ x ↦ E s | η ≺ v , if x=v ∈ η • Application: (Apply(Fun τ 1 τ 2 f.x .e ) ☐ ) ▷ s | η ≺ v ↦ E η ▷ s | f = (Fun τ 1 τ 2 f.x.e ) , x = v, η ≻ e • Returning values: η ▷ s | η ’ ≺ v ↦ E s | η ≺ v ,

  17. The E-machine: Transition Rules • Are these rules correct? ‣ let’s look at two example usages • Example ‣ simple function application Apply(Fun Int Int ( f.x . (Plus x 1)) 3 ‣ nested application (corresponds to a function which accepts two arguments and returns the first one) Apply (Apply (Fun(Int →I nt) Int ( f.x . (Fun int int g.y.x )) 3) 1) We omit the type information, and abbreviate apply to app and write n instead of (Num n)

  18. Example 1 ◦ | ● ≻ App(Fun( f.x .( Plus x 1)) 3) ↦ E (App ☐ 3) ▷ ◦ | ● ≻ Fun( f.x . (Plus x 1)) ↦ E (App ☐ 3) ▷ ◦ | ● ≺ Fun( f.x . (Plus x 1)) ↦ E (App(Fun( f.x . (Plus x 1)) ☐ ) ▷ ◦ | ● ≻ 3 ↦ E (App(Fun( f.x . (Plus x 1)) ☐ ) ▷ ◦ | ● ≺ 3 ↦ E ● ▷ ◦ | x = 3 , f= Fun( f.x . (Plus x 1)) , ● ≻ (Plus x 1) ↦ E (Plus ☐ 1) ▷ ● ▷ ◦ | x = 3 , f= Fun( f.x . Plus x 1) , ● ≻ x ↦ E (Plus ☐ 1) ▷ ● ▷ ◦ | x = 3 , f= Fun( f.x . Plus x 1) , ● ≺ 3 ↦ E (Plus 3 ☐ ) ▷ ● ▷ ◦ | x = 3 , f= Fun( f.x . Plus x 1) , ● ≻ 1 ↦ E (Plus 3 ☐ ) ▷ ● ▷ ◦ | x = 3 , f= Fun( f.x . Plus x 1) , ● ≺ 1 ↦ E ● ▷ ◦ | x = 3 , f= Fun( f.x . Plus x 1) , ● ≺ 4 ↦ E ◦ | ● ≺ 4

  19. Example 2 (recfun f x = recfun g y = x) 3 4 (App(App(Fun( f.x . Fun( g.y.x )) 3) 4)

  20. Example 2 ◦ | ● ≻ (App(App(Fun( f.x . Fun( g.y.x )) 3) 4) ↦ E (App ☐ 4) ▷ ◦ | ● ≻ (App(Fun( f.x . Fun( g.y.x )) 3) ↦ E (App ☐ 3) ▷ (App ☐ 4) ▷ ◦ | ● ≻ (Fun( f.x . fun( g.y.x )) ↦ E (App ☐ 3) ▷ (App( ☐ ,4) ▷ ◦ | ● ≺ (Fun( f.x . Fun( g.y.x )) ↦ E ... ↦ E ↦ E (App(Fun( f.x . Fun( g.y.x )) ☐ ) ▷ (App ☐ 4) ▷ ◦ | ● ≺ 3 ↦ E ● ▷ (App ☐ 4) ▷ ◦ | x = 3 , f= Fun( f.x . Fun...), ● ≻ Fun( g.y.x ) ↦ E ● ▷ (App ☐ 4) ▷ ◦ | x = 3 , f= Fun( f.x . Fun...), ● ≺ Fun( g.y.x ) ↦ E (App ☐ 4) ▷ ◦ | ● ≺ Fun( g.y.x ) ↦ E (App(Fun( g.y.x )) ☐ ) ▷ ◦ | ● ≻ 4 ↦ E (App(Fun( g.y.x )) ☐ ) ▷ ◦ | ● ≺ 4 ↦ E ◦ | y = 4 , g= Fun( g.y . x ), ● ≺ x

  21. Dealing with partial application • Something went wrong! - returning the function value and restoring the old (empty) environment, we threw away the binding for the variable x - it now occurs freely in g ! • Problem: functions as results are not handled correctly! - free variables in the function bodies escape the environment they are defined in. - partial applications fails let f x y = x + y g = f 3 in let x = 5 in g x

  22. Dealing with partial application • Solution: - we need to bundle returned functions with current environment - we call this a closure - requires a new form of return values: environment which 《 η , (Fun τ 1 τ 2 f.x .e ) 》 was current when function value was created - Closures only appear as values during execution - there is no source form

  23. Transition Rules • Returning values: η ▷ s | η ’ ≻ (Num n) ↦ E s | η ≺ (Num n) s | η ≻ (Fun τ 1 τ 2 f.x .e ) ↦ E s | η ≺ 《 η , (Fun τ 1 τ 2 f.x .e ) 》 η ▷ s | η ’ ≺ v ↦ E s | η ≺ v • Application of functions: (Apply 《 η ’, (Fun τ 1 τ 2 f.x .e ) 》 ☐ ) ▷ s | η ≺ v ↦ E η ▷ s | f = (Fun τ 1 τ 2 f.x.e ) , x = v, η ’ ≻ e restore environment from closure, add binding for argument x and function f

Download Presentation
Download Policy: The content available on the website is offered to you 'AS IS' for your personal information and use only. It cannot be commercialized, licensed, or distributed on other websites without prior consent from the author. To download a presentation, simply click this link. If you encounter any difficulties during the download process, it's possible that the publisher has removed the file from their server.

Recommend


More recommend