metacircular evaluation
DESCRIPTION
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 - PowerPoint PPT PresentationTRANSCRIPT
Metacircular Evaluation
SICP Chapter 4Mark Boady
Metacircular EvaluatorAn interpreter built for a language using the same
language as it is interpreting.We will be looking at a Scheme interpreter written
in schemeRead Chapter 4 of SICP for a more detailed look at
this interpreterWhy?
Extending an interpreted languageDebuggers
Jikes RVMA Java Research Virtual Machine written in JavaThe RVM runs on the JVMUsed For Research in:
Garbage CollectionDynamic ParallelizationMachine Learning for dynamic compilationDynamic TypingDistributed VM
Scheme Metacircular EvaluatorEval
Takes an expression and an Environment Environment = Variable Names and Values
Returns the result of evaluating the expressionApply
Takes a Procedure and a list of argumentsProduces an expression for eval
(+ (* 4 5) 6)
Eval Definition(define (eval exp env) (cond ((self-evaluating? exp) exp) ((variable? exp) (lookup-variable-value exp env)) ((quoted? exp) (text-of-quotation exp)) ((assignment? exp) (eval-assignment exp env)) ((definition? exp) (eval-definition exp env)) ((if? exp) (eval-if exp env)) ((lambda? exp) (make-procedure (lambda-parameters exp) (lambda-body exp) env)) ((begin? exp) (eval-sequence (begin-actions exp) env)) ((cond? exp) (eval (cond->if exp) env)) ((application? exp) (apply (eval (operator exp) env) (list-of-values (operands exp) env))) (else (error "Unknown expression type -- EVAL" exp))))
(define (beval exp env) (cond ((boolean? exp) exp) ((conjunct? exp) (beval-and exp env))
((disjunct? exp) (beval-or exp env)) ((negate? exp) (beval-not exp env)) ((variable? exp) ... ; You'll need to supply your own
function that takes a frame, returns the assoc. value (else (error "beval: illegal syntax")))))
Apply Definition(define (apply procedure arguments) (cond ((primitive-procedure? procedure) (apply-primitive-procedure procedure arguments)) ((compound-procedure? procedure) (eval-sequence (procedure-body procedure) (extend-environment (procedure-parameters procedure) arguments (procedure-environment procedure)))) (else (error "Unknown procedure type -- APPLY" procedure))))
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
ApplyDetermine the type of procedureAdd to the environmentPass control to Eval
ConceptWe want to eval (+ 4 5)((application? exp)
(apply (eval (operator exp) env) (list-of-values (operands exp) env)))
List-of-values evaluates the inputs to the procedureApply performs the actual procedureWith a primitive (like +) the underlying language
handles itWith a custom procedure, we need to pass back to eval
Metacircular
Basic Example(eval ‘(+ a 5) ‘((a 10) (b 7))Evaluate the expression a+5 with the variables a=10,
b=7Eval starts with a procedure and sees it is an applyEval evaluates the inputs to the procedure
Looks up variable values in this caseApply is asked to handle with (+ 10 5)Apply can determine 10+5=15 using the underlying
system
DetailsGetting the arguments of a Procedure(apply (eval (operator exp) env) (list-of-
values (operands exp) env)))(define (list-of-values exps env) (if (no-
operands? exps) '() (cons (eval (first-operand exps) env) (list-of-values (rest-operands exps) env))))
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
ExpressionsBasic functionality is implemented directlyAssignment
(define (assignment? exp) (tagged-list? exp 'set!))(define (assignment-variable exp) (cadr exp))(define (assignment-value exp) (caddr exp))
Derived ExpressionsSome functionality is implemented using existing
functionality Cond can be transformed into if statements Let statements can be transformed in lambda expressions
Derived ExpressionsLet expressions are derived expressions, because(let ((<var1> <exp1>) ... (<varn> <expn>))
<body>)is equivalent to((lambda (<var1> ... <varn>) <body>) <exp1>
... <expn>)
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 <var> <env>)
returns the value that is bound to the symbol <var> in the environment <env>, or signals an error if the variable is unbound.
(extend-environment <variables> <values> <base-env>) returns a new environment, consisting of a new
frame in which the symbols in the list <variables> are bound to the corresponding elements in the list <values>, where the enclosing environment is the environment <base-env>.
Environment(define-variable! <var> <value> <env>)
adds to the first frame in the environment <env> a new binding that associates the variable <var> with the value <value>.
(set-variable-value! <var> <value> <env>)changes the binding of the variable <var> in the
environment <env> so that the variable is now bound to the value <value>, or signals an error if the variable is unbound.
EnvironmentsThere are multiple scopes in the environmentWe make changes to the most recentExample:
Initial memory: ( ( (a b) (5 7) ) )A new function is called with inputs b=6, c=7We push a new set of variables into the environmentNew Memory: ( ( (b c) (6 7) ) ( (a b) (5 7) ) )When the function call is over we remove it from the
environmentNew Memory: ( ( (a b) (5 7) ) )
Environments(define (lookup-variable-value var env) (define (env-loop env) (define (scan vars vals) (cond ((null? vars) (env-loop (enclosing-environment env))) ((eq? var (car vars)) (car vals)) (else (scan (cdr vars) (cdr vals))))) (if (eq? env the-empty-environment) (error "Unbound variable" var) (let ((frame (first-frame env))) (scan (frame-variables frame) (frame-values frame))))) (env-loop env))
Environments(define (lookup-variable-value var env)
(env-loop env))(define (env-loop env) (if (eq? env the-empty-environment) (error "Unbound variable" var) (let
((frame (first-frame env))) (scan (frame-variables frame) (frame-values frame))
)))(define (scan vars vals) (cond
((null? vars) (env-loop (enclosing-environment env))) ((eq? var (car vars)) (car vals)) (else (scan (cdr vars) (cdr vals)))
) )
Primitives(define primitive-procedures
(list (list 'car car)(list 'cdr cdr)(list 'cons cons)(list 'null? null?)(list '- -) (list '+ +)
))(define (apply-primitive-procedure proc args) (apply-in-underlying-scheme (primitive-implementation proc) args))
Running the EvaluatorLoad 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)
Driver Loop(define input-prompt ";;; M-Eval input:")(define output-prompt ";;; M-Eval value:")(define (driver-loop) (prompt-for-input input-prompt) (let ((input (read))) (let ((output (eval input the-global-environment))) (announce-output output-prompt) (user-print output))) (driver-loop))(define (prompt-for-input string) (newline) (newline) (display string) (newline))
Environments(define (setup-environment)
(let ((initial-env
(extend-environment (primitive-procedure-names)
(primitive-procedure-objects)
the-empty-environment)))
(define-variable! 'true true initial-env)
(define-variable! 'false false initial-env)
initial-env))