Presentation on theme: "Metacircular Evaluation SICP Chapter 4 Mark Boady."— Presentation transcript:
Metacircular Evaluation SICP Chapter 4 Mark Boady
Metacircular Evaluator An interpreter built for a language using the same language as it is interpreting. We will be looking at a Scheme interpreter written in scheme Read Chapter 4 of SICP for a more detailed look at this interpreter Why? Extending an interpreted language Debuggers
Jikes RVM A Java Research Virtual Machine written in Java The RVM runs on the JVM Used For Research in: Garbage Collection Dynamic Parallelization Machine Learning for dynamic compilation Dynamic Typing Distributed VM
Scheme Metacircular Evaluator Eval Takes an expression and an Environment Environment = Variable Names and Values Returns the result of evaluating the expression Apply Takes a Procedure and a list of arguments Produces an expression for eval (+ (* 4 5) 6)
What do eval and apply do? Eval Takes the expression and determines what the expression is Passes the work to a helper function that evaluates the specific type For procedures, pass control to apply Apply Determine the type of procedure Add to the environment Pass control to Eval
Concept We want to eval (+ 4 5) ((application? exp) (apply (eval (operator exp) en v) (list-of-values (operands exp) env))) List-of-values evaluates the inputs to the procedure Apply performs the actual procedure With a primitive (like +) the underlying language handles it With a custom procedure, we need to pass back to eval
Basic Example (eval ‘(+ a 5) ‘((a 10) (b 7)) Evaluate the expression a+5 with the variables a=10, b=7 Eval starts with a procedure and sees it is an apply Eval evaluates the inputs to the procedure Looks up variable values in this case Apply is asked to handle with (+ 10 5) Apply can determine 10+5=15 using the underlying system
If Statements (define (eval-if exp env) (if (true? (eval (if- predicate exp) env)) (eval (if- consequent exp) env) (eval (if- alternative exp) env))) Only Evaluate based on the true case (define (true? X) (not (eq? x false))) (define (if-alternative exp) (if (not (null? (cdddr exp))) (cadddr exp) 'false))
Evaluating Sequences (define (eval-sequence exps env) (cond ((last- exp? exps) (eval (first- exp exps) env)) (else (eval (first- exp exps) env) (eval-sequence (rest- exps exps) env)))) Evaluate the sequence of expressions in a procedure body
Assigning Variables (define (eval-assignment exp env) (set-variable- value! (assignment- variable exp) (eval (assignment- value exp) env) env) 'ok) set-variable-value! Bounds a value to a name
Expressions Basic functionality is implemented directly Assignment (define (assignment? exp) (tagged- list? exp 'set!)) (define (assignment- variable exp) (cadr exp)) (define (assignment- value exp) (caddr exp)) Derived Expressions Some functionality is implemented using existing functionality Cond can be transformed into if statements Let statements can be transformed in lambda expressions
Derived Expressions Let expressions are derived expressions, because (let (( )... ( )) ) is equivalent to ((lambda (... ) )... )
Derived Expressions (let ((a 4) (b 6)) (+ a b)) Value 10 ( (lambda (a b) (+ a b)) 4 6) Value 10 We can write a command that will translate a let to a lambda. Let eval handle the lambda command using existing tools.
Environment (lookup-variable-value ) returns the value that is bound to the symbol in the environment, or signals an error if the variable is unbound. (extend-environment ) returns a new environment, consisting of a new frame in which the symbols in the list are bound to the corresponding elements in the list, where the enclosing environment is the environment.
Environment (define-variable! ) adds to the first frame in the environment a new binding that associates the variable with the value. (set-variable-value! ) changes the binding of the variable in the environment so that the variable is now bound to the value, or signals an error if the variable is unbound.
Environments There are multiple scopes in the environment We make changes to the most recent Example: Initial memory: ( ( (a b) (5 7) ) ) A new function is called with inputs b=6, c=7 We push a new set of variables into the environment New Memory: ( ( (b c) (6 7) ) ( (a b) (5 7) ) ) When the function call is over we remove it from the environment New Memory: ( ( (a b) (5 7) ) )
Running the Evaluator Load the File (load "ch4-mcevalM.scm") Initialize the Global Environment (define the-global-environment (setup-environment)) Initialize the Evaluator (driver-loop) We can now execute code!
Running (load "ch4-mcevalM.scm") (define the-global-environment (setup-environment)) (driver-loop) ;;; M-Eval input: (define (append x y) (if (null? x) y (cons (car x) (append (cdr x) y)))) ;;; M-Eval value: ok ;;; M-Eval input: (append '(a b c) '(d e f)) ;;; M-Eval value: (a b c d e f)