CS 598 Scripting Languages Design and Implementation 10. Interpreters Part I: Lisp.

Slides:



Advertisements
Similar presentations
1 Programming Languages (CS 550) Mini Language Interpreter Jeremy R. Johnson.
Advertisements

Scheme in Scheme. Why implement Scheme in Scheme  Implementing a language is a good way to learn more about programming languages  Interpreters are.
1 Programming Languages (CS 550) Lecture Summary Functional Programming and Operational Semantics for Scheme Jeremy R. Johnson.
Functional Programming. Pure Functional Programming Computation is largely performed by applying functions to values. The value of an expression depends.
Scheme in Scheme?!? …the metacircular evaluator….
1 The metacircular evaluator Names Extend the calculator to store intermediate results as named values (define x (+ 4 5)) store result as x (+ x.
1 Programming Languages (CS 550) Operational Semantics of Scheme using Substitution and the Lambda Calculus Jeremy R. Johnson TexPoint fonts used in EMF.
Metacircular Evaluation SICP Chapter 4 Mark Boady.
1 Programming Languages (CS 550) Lecture 7 Summary Operational Semantics of Scheme using Substitution Jeremy R. Johnson TexPoint fonts used in EMF. Read.
מבוא מורחב למדעי המחשב תרגול 13 Lazy Evaluation. Lazy Evaluation Implementation Two types of values – Delayed Values – Actual Values Introduce two functions.
1 The Metacircular Evaluator Chapter 4 Section 4.1 We will not cover every little detail in the lectures, so you MUST read Section 4.1 in full.
מבוא מורחב למדעי המחשב בשפת Scheme תרגול 11. Metacircular Evaluator 4.1, pages definitions file on web 2.
(define applicative-eval (lambda (exp) (cond ((atomic? exp) (eval-atomic exp)) ((special-form? exp) (eval-special-form exp)) ((list-form? exp) (eval-list.
1 Lecture 18 Continue Evaluator. 2 z9 true#t + twice Representing procedures (eval '(define twice (lambda (x) (+ x x))) GE) symbol primitive scheme procedure.
מבוא מורחב - שיעור 10 1 Symbols Manipulating lists and trees of symbols: symbolic differentiation Lecture 10.
Functional programming: LISP Originally developed for symbolic computing Main motivation: include recursion (see McCarthy biographical excerpt on web site).
Lexical vs. Dynamic Scope …where do I point to?. Intro… Remember in Scheme whenever we call a procedure we pop a frame and point it to where the procedure.
6.001 SICP SICP – Evaluation I Recitation 11/19/2004 Eval review Evaluation examples define lambda apply New language elements.
SICP Variations on a Scheme Scheme Evaluator – A Grand Tour Techniques for language design: Interpretation: eval/apply Semantics vs. syntax Syntactic.
Functional programming: LISP Originally developed for symbolic computing First interactive, interpreted language Dynamic typing: values have types, variables.
Scheme More MCE examples. Q1 new special form which defines global variables (static ) search the global environment – Variable exists: does nothing,
SICP Variations on a Scheme (2) Beyond Scheme – designing language variants: Lazy evaluation Complete conversion – normal order evaluator Upward.
The environment model evaluator and compiler 1 The env model evaluator Motivation In one word: Efficiency Saves repeated renaming and substitution: Using.
1 Saves repeated renaming and substitution: explicit substitution is replaced by variable bindings using new data structures (frame, environment). Can.
1 Continue Evaluator. 2 z9 true#t + twice Representing procedures (eval '(define twice (lambda (x) (+ x x))) GE) symbol primitive scheme procedure + symbol.
1 Programming Languages (CS 550) Lecture 5 Summary Object Oriented Programming and Implementation* Jeremy R. Johnson *Lecture based on notes from SICP.
Scheme in Scheme. Why implement Scheme in Scheme  Implementing a language is aa good way to learn more about programming languages  Interpreters are.
1 The metacircular evaluator (Cont.) Defining new procedures (define (lambda? e) (tag-check e 'lambda)) (define (eval exp env) (cond ((number? exp)
Scheme in Scheme 1. Why implement Scheme in Scheme  Implementing a language is a good way to learn more about programming languages  Interpreters are.
CSC3315 (Spring 2009)1 CSC 3315 Programming Paradigms Scheme Language Hamid Harroud School of Science and Engineering, Akhawayn University
CS220 Programming Principles 프로그래밍의 이해 2002 가을학기 Class 15: Meta-Circular Evaluator 한 태숙.
SICP Interpretation Parts of an interpreter Arithmetic calculator Names Conditionals and if Storing procedures in the environment Environment as.
1 Subt. model interpreter: Structure of the interpreter ASP Derived expressions Core Test Data structures Utils A racket lib Proc / Primitive-Proc. Global.
Scheme in Scheme. Why implement Scheme in Scheme  Implementing a language is a good way to learn more about programming languages  Interpreters are.
SICP Explicit-control evaluator Big ideas: how to connect evaluator to machine instructions how to achieve tail recursion Obfuscation: tightly.
The environment-based operational semantics Chapter
18-October-2002cse Symbols © 2002 University of Washington1 Symbols CSE 413, Autumn 2002 Programming Languages
CS220 Programming Principles 프로그래밍의 이해 2002 가을학기 Class 6 한 태숙.
1 Lecture 20 Lazy Evaluation Continued (4.2.1, 4.2.2) MC-eval examples from exams (Time permitting)
1 Read-Eval-Print Loop (define (driver-loop) (prompt-for-input input-prompt) (let ((input (read))) (let ((output (eval input the-global-env))) (announce-output.
Scheme Profs Tim Sheard and Andrew Black CS 311 Computational Structures.
Milos Hauskrecht (PDF) Hieu D. Vu (PPT) LISP PROGARMMING LANGUAGE.
1 Subt. model interpreter: Introduction Abstract Syntax Parser Abstract Syntax Parser Derived Expressions Core Test Data Structures Utils (a racket lib)
1 Programming Languages (CS 550) Lecture 4 Summary Functional Programming and Operational Semantics for Scheme Jeremy R. Johnson.
1 Env. Model Implementation & Analyzer Practice Session #10 Env. Model Implementation & Analyzer Practice Session #10.
1 Lecture 19 Dynamic Scoping Lazy Evaluation (4.2.1, 4.2.2)
1/ SICP Variations on a Scheme Scheme Evaluator – A Grand Tour Making the environment model concrete Defining eval defines the language –Provides.
1 Lecture 19 Review last lecture on evaluator, Dynamic Scoping Lazy Evaluation (4.2.1, 4.2.2)
1 Vectors, binary search, and sorting. 2 We know about lists O(n) time to get the n-th item. Consecutive cons cell are not necessarily consecutive in.
1 The Evaluator. 2 Compiler vs. Interpreter Command Processing Unit The Computer Program in Low Level Machine Language Program in High Level Language.
Evaluators for Functional Programming 1. How to describe (specify) a programming language? 1.Syntax: atoms, primitives, combination and abstraction means.
SICP Interpretation part 2 Store operators in the environment Environment as explicit parameter Defining new procedures.
Operational Semantics of Scheme
Functional Programming
6.001 SICP Variations on a Scheme
Introduction to Scheme
Original material by Eric Grimson
The Metacircular Evaluator
Dynamic Scoping Lazy Evaluation
The Metacircular Evaluator
The Metacircular Evaluator (Continued)
Lecture 26: The Metacircular Evaluator Eval Apply
6.001 SICP Further Variations on a Scheme
Streams, Delayed Evaluation and a Normal Order Interpreter
Lecture #9 מבוא מורחב.
6.001 SICP Variations on a Scheme
6.001 SICP Interpretation Parts of an interpreter
topics interpreters meta-linguistic abstraction eval and apply
Rehearsal: Lazy Evaluation Infinite Streams in our lazy evaluator
Lecture 25: The Metacircular Evaluator Eval Apply
Presentation transcript:

CS 598 Scripting Languages Design and Implementation 10. Interpreters Part I: Lisp

Interpreters Typically, the simplest way to implement a dynamic language. The resulting implementation could be slow, but it is often adequate as testified by the numerous interpreted laguages that are widely used. An interpreter is a practical tool, but also its specification can be used to formally specify the semantics of a language. However, formal definitions are seldom used by practitioners. 2

Lisp Again from the wikipedia: Lisp (historically, LISP) is a family of computer programming languages with a long history and a distinctive, fully parenthesized Polish prefix notation.[1] Originally specified in 1958, Lisp is the second-oldest high-level programming language in widespread use today; only Fortran is older (by one year). Like Fortran, Lisp has changed a great deal since its early days, and a number of dialects have existed over its history. Today, the most widely known general-purpose Lisp dialects are Common Lisp and Scheme. Lisp was invented by John McCarthy in 1958 while he was at the Massachusetts Institute of Technology (MIT). McCarthy published its design in a paper in Communications of the ACM in 1960, entitled Recursive Functions of Symbolic Expressions and Their Computation by Machine, Part I (Part II was never published). He showed that with a few simple operators and a notation for functions, one can build a Turing-complete language for algorithms. 3

Scheme Scheme and Common Lisp are the two principal dialects of the computer programming language Lisp. Unlike Common Lisp, however, Scheme follows a minimalist design philosophy that specifies a small standard core accompanied by powerful tools for language extension. Scheme was created during the 1970s at the MIT AI Lab and released by its developers, Guy L. Steele and Gerald Jay Sussman, via a series of memos now known as the Lambda Papers. It was the first dialect of Lisp to choose lexical scope and the first to require implementations to perform tail-call optimization, giving stronger support for functional programming and associated techniques such as recursive algorithms. 4

Simple scheme tutorial 3/languages/scheme/SchemeTutorialB.html 5

Lisp metacircular evaluator You can read Lisp by reading a reference manual or by studying eval The fact that the definition of eval is available in Lisp means that the programming environment is part of the language. Even today, the fact that eval can be defined in Lisp means that it’s easy to experiment with new models of implementation and debugging. … it must give up the possiblity of many optimizations. In other words, using eval is not without consequences 6

Types of procedures Predicates and Selectors Approach introduced by McCarthy Both types found in VDL 7

Metacircular evaluator Basic procedures ( apply-primmitive-procedure ) ( primitive-procedure? ) – returns whether the procedure is a primitive procedure. ( lookup-variable-value ) – returns the value of in the environment. ( extend-environment ) – adds a frame to with bound to. ( define-variable! ) – adds with value to the environment’s top frame. ( set-variable-value! ) 8

eval (define (eval exp env) (cond((self-evaluating? exp) exp) ((quoted? exp) (text-of -quotation exp)) ((variable? exp) (lookup-variable-value exp env)) ((definition? exp) (eval-definition exp env)) ((assignment? exp) (eval-assignment exp env)) ((lambda? exp)(make-procedure exp env) ) ((conditional? exp) (eval-cond (clauses exp) env) ) ((application? exp) (apply (eval (operator exp) env) (list-of-values (operands exp) env)) (else(error "Unknown expression type/EVAL” exp)))) 9

eval (define (eval exp env) (cond((self-evaluating? exp) exp) ((quoted? exp) (text-of -quotation exp)) ((variable? exp) (lookup-variable-value exp env)) ((definition? exp) (eval-definition exp env)) ((assignment? exp) (eval-assignment exp env)) ((lambda? exp)(make-procedure exp env) ) ((conditional? exp) (eval-cond (clauses exp) env) ) ((application? exp) (apply (eval (operator exp) env) (list-of-values (operands exp) env)) (else(error "Unknown expression type/EVAL” exp)))) 10

apply (define (apply procedure arguments) (cond ((primitive-procedure? procedure) (apply-primitive-procedure procedure arguments)) ((compound-procedure? procedure) (eval-sequence (procedure-body procedure) (extend-environment (parameters procedure) arguments (procedure-environment procedure)))) (else (error "Unknown procedure type\APPLY" procedure)))) 11

apply (define (apply procedure arguments) (cond ((primitive-procedure? procedure) (apply-primitive-procedure procedure arguments)) ((compound-procedure? procedure) (eval-sequence (procedure-body procedure) (extend-environment (parameters procedure) arguments (procedure-environment procedure)))) (else (error "Unknown procedure type\APPLY" procedure)))) 12

eval-sequence (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)))) 13

eval (define (eval exp env) (cond((self-evaluating? exp) exp) ((quoted? exp) (text-of -quotation exp)) ((variable? exp) (lookup-variable-value exp env)) ((definition? exp) (eval-definition exp env)) ((assignment? exp) (eval-assignment exp env)) ((lambda? exp)(make-procedure exp env) ) ((conditional? exp) (eval-cond (clauses exp) env) ) ((application? exp) (apply (eval (operator exp) env) (list-of-values (operands exp) env)) (else(error "Unknown expression type/EVAL” exp)))) 14

list-of-values (define (list-of-values exps env) (cond ((no-operands? exps) '()) (else (cons (eval (first-operand exps) env) (list-of-values (rest-operands exps) env))))) 15

eval (define (eval exp env) (cond((self-evaluating? exp) exp) ((quoted? exp) (text-of -quotation exp)) ((variable? exp) (lookup-variable-value exp env)) ((definition? exp) (eval-definition exp env)) ((assignment? exp) (eval-assignment exp env)) ((lambda? exp)(make-procedure exp env) ) ((conditional? exp) (eval-cond (clauses exp) env) ) ((application? exp) (apply (eval (operator exp) env) (list-of-values (operands exp) env)) (else(error "Unknown expression type/EVAL” exp)))) 16

eval-cond (define (eval-cond clist env) (cond ((no-clauses? clist) nil) ((else-clause? (first-clause clist)) (eval-sequence (actions (first-clause clist)) env) ((true? (eval (predicate (first-clause clist))env)) (eval-sequence (actions (first- clause clist)) env)) (else (eval-cond (rest-clauses clist) env)))) 17

eval (define (eval exp env) (cond((self-evaluating? exp) exp) ((quoted? exp) (text-of -quotation exp)) ((variable? exp) (lookup-variable-value exp env)) ((definition? exp) (eval-definition exp env)) ((assignment? exp) (eval-assignment exp env)) ((lambda? exp)(make-procedure exp env) ) ((conditional? exp) (eval-cond (clauses exp) env) ) ((application? exp) (apply (eval (operator exp) env) (list-of-values (operands exp) env)) (else(error "Unknown expression type/EVAL” exp)))) 18

eval-assignment (define (eval-assignment exp env) (let ((new-value (eval (assignment-value exp) env))) (set-variable-value! (assignment-variable exp) new-value env) new-value)) 19

eval (define (eval exp env) (cond((self-evaluating? exp) exp) ((quoted? exp) (text-of -quotation exp)) ((variable? exp) (lookup-variable-value exp env)) ((definition? exp) (eval-definition exp env)) ((assignment? exp) (eval-assignment exp env)) ((lambda? exp)(make-procedure exp env) ) ((conditional? exp) (eval-cond (clauses exp) env) ) ((application? exp) (apply (eval (operator exp) env) (list-of-values (operands exp) env)) (else(error "Unknown expression type/EVAL” exp)))) 20

eval-definition (define(eval-definition exp env) (define-variable! (definition-variable exp) (eval (definition-value exp) env) env) (definition-variable exp)) 21

eval (define (eval exp env) (cond((self-evaluating? exp) exp) ((quoted? exp) (text-of -quotation exp)) ((variable? exp) (lookup-variable-value exp env)) ((definition? exp) (eval-definition exp env)) ((assignment? exp) (eval-assignment exp env)) ((lambda? exp)(make-procedure exp env) ) ((conditional? exp) (eval-cond (clauses exp) env) ) ((application? exp) (apply (eval (operator exp) env) (list-of-values (operands exp) env)) (else(error "Unknown expression type/EVAL” exp)))) 22

self-evaluating? quoted? variable? The only self-evaluating items are numbers: (define (self-evaluating? exp) (number? exp)) Quotations are expressions of the form (quote ( text-of- quotation ) ) : (define (quoted? exp) (if (atom? exp) nil (eq? (car exp) ‘quote) ) ) (define (text-of-quotation exp) (cadr exp) ) Variables are represented by symbols: (define (variable? exp) (symbol? exp) ) 23 Primitive predicates

eval (define (eval exp env) (cond((self-evaluating? exp) exp) ((quoted? exp) (text-of -quotation exp)) ((variable? exp) (lookup-variable-value exp env)) ((definition? exp) (eval-definition exp env)) ((assignment? exp) (eval-assignment exp env)) ((lambda? exp)(make-procedure exp env) ) ((conditional? exp) (eval-cond (clauses exp) env) ) ((application? exp) (apply (eval (operator exp) env) (list-of-values (operands exp) env)) (else(error "Unknown expression type/EVAL” exp)))) 24

assignment? Assignments are expressions of the form: (set! ) (define (assignment? exp) (if (atom? exp) nil (eq? (car exp) ‘set!))) 25

eval (define (eval exp env) (cond((self-evaluating? exp) exp) ((quoted? exp) (text-of -quotation exp)) ((variable? exp) (lookup-variable-value exp env)) ((definition? exp) (eval-definition exp env)) ((assignment? exp) (eval-assignment exp env)) ((lambda? exp)(make-procedure exp env) ) ((conditional? exp) (eval-cond (clauses exp) env) ) ((application? exp) (apply (eval (operator exp) env) (list-of-values (operands exp) env)) (else(error "Unknown expression type/EVAL” exp)))) 26

definition? Definitions are expressions of the form (define ) or of the form (define (... ) ) The latter form (standard procedure definition) is syntactic sugar for (define (lambda (... ) ) )) 27

definition? The corresponding syntax procedures are the following: (define (definition? exp) (if (atom? exp) nil (eq? (car exp) 'define))) (define (definition-variable exp) (if (variable? (cadr exp) ) (cadr exp) (caadr exp) ) ) (define (definition-value exp) (if (variable? (cadr exp) ) (caddr exp) (cons ‘lambda (cons (cdadr exp) ;formal parameters (cddr exp ))))))) ;body 28

eval (define (eval exp env) (cond((self-evaluating? exp) exp) ((quoted? exp) (text-of -quotation exp)) ((variable? exp) (lookup-variable-value exp env)) ((definition? exp) (eval-definition exp env)) ((assignment? exp) (eval-assignment exp env)) ((lambda? exp)(make-procedure exp env) ) ((conditional? exp) (eval-cond (clauses exp) env) ) ((application? exp) (apply (eval (operator exp) env) (list-of-values (operands exp) env)) (else(error "Unknown expression type/EVAL” exp)))) 29

lambda? (define (lambda? exp) (if (atom? exp) nil (eq? (car exp) 'lambda) ) ) 30

eval (define (eval exp env) (cond((self-evaluating? exp) exp) ((quoted? exp) (text-of -quotation exp)) ((variable? exp) (lookup-variable-value exp env)) ((definition? exp) (eval-definition exp env)) ((assignment? exp) (eval-assignment exp env)) ((lambda? exp)(make-procedure exp env) ) ((conditional? exp) (eval-cond (clauses exp) env) ) ((application? exp) (apply (eval (operator exp) env) (list-of-values (operands exp) env)) (else(error "Unknown expression type/EVAL” exp)))) 31

conditional? clauses (define (conditional? exp) (if (atom? exp) nil (eq? (car exp) 'cond) ) ) (define (clauses exp) (cdr exp) ) 32

eval (define (eval exp env) (cond((self-evaluating? exp) exp) ((quoted? exp) (text-of -quotation exp)) ((variable? exp) (lookup-variable-value exp env)) ((definition? exp) (eval-definition exp env)) ((assignment? exp) (eval-assignment exp env)) ((lambda? exp)(make-procedure exp env) ) ((conditional? exp) (eval-cond (clauses exp) env) ) ((application? exp) (apply (eval (operator exp) env) (list-of-values (operands exp) env)) (else(error "Unknown expression type/EVAL” exp)))) 33

conditional? clauses (define (conditional? exp) (if (atom? exp) nil (eq? (car exp) 'cond) ) ) (define (clauses exp) (cdr exp) ) 34

eval (define (eval exp env) (cond((self-evaluating? exp) exp) ((quoted? exp) (text-of -quotation exp)) ((variable? exp) (lookup-variable-value exp env)) ((definition? exp) (eval-definition exp env)) ((assignment? exp) (eval-assignment exp env)) ((lambda? exp)(make-procedure exp env) ) ((conditional? exp) (eval-cond (clauses exp) env) ) ((application? exp) (apply (eval (operator exp) env) (list-of-values (operands exp) env)) (else(error "Unknown expression type/EVAL” exp)))) 35

eval-cond (define (eval-cond clist env) (cond ((no-clauses? clist) nil) ((else-clause? (first-clause clist)) (eval-sequence (actions (first-clause clist)) env) ((true? (eval (predicate (first-clause clist))env)) (eval-sequence (actions (first- clause clist)) env)) (else (eval-cond (rest-clauses clist) env)))) 36

no-clauses?/first-clause/ rest- clauses/predicate/actions/ true?/else- clause? (define (no-clauses? clauses) (null? clauses) ) (define (first-clause clauses) (car clauses)) (define (rest-clauses clauses) (cdr clauses) ) (define (predicate clause) (car clause) ) (define (actions clause) (cdr clause) ) (define (true? x) (not (null? x) ) ) (define (else-clause? clause) (eq? (predicate clause) 'else) ) 37

apply (define (apply procedure arguments) (cond ((primitive-procedure? procedure) (apply-primitive-procedure procedure arguments)) ((compound-procedure? procedure) (eval-sequence (procedure-body procedure) (extend-environment (parameters procedure) arguments (procedure-environment procedure)))) (else (error "Unknown procedure type\APPLY" procedure)))) 38

eval-sequence (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)))) 39

last-exp?/first-exp/rest-exps (define (last-exp? seq) (null? (cdr seq) ) ) (define (first-exp seq) (car seq) ) (define (rest-exps seq) (cdr seq) ) 40

eval (define (eval exp env) (cond((self-evaluating? exp) exp) ((quoted? exp) (text-of -quotation exp)) ((variable? exp) (lookup-variable-value exp env)) ((definition? exp) (eval-definition exp env)) ((assignment? exp) (eval-assignment exp env)) ((lambda? exp)(make-procedure exp env) ) ((conditional? exp) (eval-cond (clauses exp) env) ) ((application? exp) (apply (eval (operator exp) env) (list-of-values (operands exp) env)) (else(error "Unknown expression type/EVAL” exp)))) 41

application? operator operands ;application if it is non atom and is none of the above (define (application? exp) (not (atom? exp) ) ) (define (operator app) (car app) ) (define (operands app) (cdr app) ) 42

eval (define (eval exp env) (cond((self-evaluating? exp) exp) ((quoted? exp) (text-of -quotation exp)) ((variable? exp) (lookup-variable-value exp env)) ((definition? exp) (eval-definition exp env)) ((assignment? exp) (eval-assignment exp env)) ((lambda? exp)(make-procedure exp env) ) ((conditional? exp) (eval-cond (clauses exp) env) ) ((application? exp) (apply (eval (operator exp) env) (list-of-values (operands exp) env)) (else(error "Unknown expression type/EVAL” exp)))) 43

list-of-values (define (list-of-values exps env) (cond ((no-operands? exps) '()) (else (cons (eval (first-operand exps)env) (list-of-values (rest-operands exps) env))))) 44

no-operands? first-operand rest-operands (define (no-operands? args) (null? args) ) (define (first-operand args) (car args) ) (define (rest-operands args) (cdr args) ) 45

eval (define (eval exp env) (cond((self-evaluating? exp) exp) ((quoted? exp) (text-of -quotation exp)) ((variable? exp) (lookup-variable-value exp env)) ((definition? exp) (eval-definition exp env)) ((assignment? exp) (eval-assignment exp env)) ((lambda? exp)(make-procedure exp env) ) ((conditional? exp) (eval-cond (clauses exp) env) ) ((application? exp) (apply (eval (operator exp) env) (list-of-values (operands exp) env)) (else(error "Unknown expression type/EVAL” exp)))) 46

make-procedure (define (make-procedure lambda-exp env) (list 'procedure lambda-exp env)) Since a lambda expression has the syntax (lambda... ) the result of make-procedure is (procedure (lambda... ) ) 47

eval (define (eval exp env) (cond((self-evaluating? exp) exp) ((quoted? exp) (text-of -quotation exp)) ((variable? exp) (lookup-variable-value exp env)) ((definition? exp) (eval-definition exp env)) ((assignment? exp) (eval-assignment exp env)) ((lambda? exp)(make-procedure exp env) ) ((conditional? exp) (eval-cond (clauses exp) env) ) ((application? exp) (apply (eval (operator exp) env) (list-of-values (operands exp) env)) (else(error "Unknown expression type/EVAL” exp)))) 48

apply (define (apply procedure arguments) (cond ((primitive-procedure? procedure) (apply-primitive-procedure procedure arguments)) ((compound-procedure? procedure) (eval-sequence (procedure-body procedure) (extend-environment (parameters procedure) arguments (procedure-environment procedure)))) (else (error "Unknown procedure type\APPLY" procedure)))) 49

compound-procedure? parameters procedure-body procedure-environment (procedure (lambda... ) ) (define (compound-procedure? proc) (if (atom? proc) nil (eq? (car proc) 'procedure) ) ) (define (parameters proc) (cadr (cadr proc) ) ) (define (procedure-body proc) (cddr (cadr proc) ) ) (define (procedure-environment proc) (caddr proc) ) 50

Metacircular evaluator Basic procedures ( apply-primmitive-procedure ) ( primitive-procedure? ) – returns whether the procedure is a primitive procedure. ( lookup-variable-value ) – returns the value of in the environment. ( extend-environment ) – adds a frame to with bound to. ( define-variable! ) – adds with value to the environment’s top frame. ( set-variable-value! ) 51

lookup-variable-value (define (lookup-variable-value var env) (let ((b (binding-in-env var env))) (if (found-binding? b) (binding-value b) (error "Unbound variable" var)))) (define (binding-in-env var env) (if (no-more-frames? env) no-binding (let ((b (binding-in-frame var (first-frame env)))) (if (found-binding? b) b (binding-in-env var (rest-frames env)))))) 52

Metacircular evaluator Basic procedures ( apply-primmitive-procedure ) ( primitive-procedure? ) – returns whether the procedure is a primitive procedure. ( lookup-variable-value ) – returns the value of in the environment. ( extend-environment ) – adds a frame to with bound to. ( define-variable! ) – adds with value to the environment’s top frame. ( set-variable-value! ) 53

extend-environment set-variable-value! define-variable! define (extend-environment variables values base-env) (adjoin-frame (make-frame variables values) base-env )) (define (set-variable-value! var val env) (let ((b (binding-in-env var env))) (if (found-binding? b) (set-binding-value! b val) (error "Unbound variable" var)))) (define (define-variable! var val env) (let ((b (binding-in-frame var (first-frame env)))) (if (found-binding? b) (set-binding-value! b val) (set-first-frame! env (adjoin-binding (make-binding var val) (first-frame env)))))) 54

Representing environments (define (first-frame env) (car env)) (define (rest-frames env) (cdr env)) (define (no-more-frames? env) (null? env)) (define (adjoin-frame frame env) (cons frame env)) (define (set-first-frame! env new-frame) (set-car! env new-frame)) 55

Frames (define (make-frame variables values) (cond ((and (null? variables) (null? values) ) ‘() ) ((null? variables) (error "Too many values supplied" values) ) ((null? values) (error "Too few values supplied" variables) ) (else (cons (make-binding (car variables) (car values) ) (make-frame (cdr variables) (cdr values)))))) (define (adjoin-binding binding frame) (cons binding frame) ) 56

(define (assq key bindings) (cond ((null? bindings) no-binding) ((eq? key (binding-variable (car bindings))(car bindings)) (else (assq key (cdr bindings))))) (define (binding-in-frame var frame)(assq var frame)) (define (found-binding? b)(not (eq? b no-binding) ) ) (define no-binding nil) 57

Representing bindings (define (make-binding variable value) (cons variable value) ) (define (binding-variable binding) (car binding) ) (define (binding-value binding) (cdr binding) ) (define (set-binding-value! binding value) (set-cdr! binding value) ) 58

(define primitive-procedure-names ‘(car cdr cons ( ) ) ) (define primitive-procedure-objects ( ) ) 59

(define (setup-environment) (let ((initial-env (extend-environment primitive-procedure-name primitive-procedure-objects ‘() ) ) ) (define-variable! 'nil nil initial-env) (define-variable! 't (not nil) initial-env) initial-env) ) (define the-global-environment (setup-environment) ) 60

(define (primitive-procedure? proc) (if (atom? proc) nil (eq? (car proc) 'primitive) ) ) (define (primitive-id proc) (cadr proc) ) (define primitive-procedure-objects ‘( (primitive car)(primitive cdr) (primitive cons) ( ) ) ) 61

(define (apply-primitive-procedure proc args) (let ( (p (primitive-id proc) ) ) (cond ( (eq? p ‘car) (car (car args) ) ) ( (eq? p ‘cdr) (cdr (car args) ) ) ( (eq? p ‘cons) (cons (car args)(cadr args))) ( ) (else (error "Unknown primitive procedure” proc)))) 62

A Lisp interpreter of micro algol From “A FORMAL DESCRIPTION OF A SUBSET OF ALGOL” By John McCarhty, “Microalgol is a language for programming about, not for programming in”. Two statement: – Assignments – if then goto 63

Example of microalgol program root :=1; a: root := 0.5 * (root + x/root); error := root * root – x; perror := if error > 0.0 then error else 0.0 – error; If perror > then goto a; 64

Representation It will be an abstract syntax tree, in the form of a Lisp object as follows: A program is ( … ) A statement is either – (‘assignment ) or – (‘ifstatement ) 65

Selecting a statement by position 66 (define (statement prog pc) (cond ((null? prog) nil) ((= pc 1) (car prog)) (else (statement (cdr prog) (- pc 1)))))

Representation An expression is just represented in prefix notation. For example: z*(x+2.0)*(2.0+y) → (‘prod (‘prod ‘z (‘sum ‘x 2.0)) (‘sum 2.0 ‘y)) and x := t + if error > 0.0 then e else e → (‘assignment ‘x (‘add ‘t (‘ifexpression (‘less 0.0 ‘e) ‘e (‘diff 0.0 ‘e))) 67

Predicates and their selectors variable? number? sum?addendaugend diff?subtraendminuend prod?multipliermultiplicand quotient?numeratordenominator ifexpression?propositionantecedent (then) consequent (else) equal?lefteqrighteq less?leftltrightlt assignment?leftright ifstatement?propositiondestination The form of these predicates is the obvious one. variable? and number? are as above. The others have the following form: (define (prod? exp) (if (atom? exp) nil (eq? (car exp) ’prod) ) ) 68

Selectors (define (addend exp ) (cadr exp)) (define (subtraend exp ) (cadr exp)) (define (multiplier exp ) (cadr exp)) (define (numerator exp ) (cadr exp)) (define (proposition exp ) (cadr exp)) (define (lefteq exp ) (cadr exp)) (define (leftlt exp ) (cadr exp)) (define (left exp ) (cadr exp)) (define (proposition exp ) (cadr exp)) 69

Predicates and their selectors variable? number? sum?addendaugend diff?subtraendminuend prod?multipliermultiplicand quotient?numeratordenominator ifexpression?propositionantecedent (then) consequent (else) equal?lefteqrighteq less?leftltrightlt assignment?leftright ifstmt?propositiondestination The form of these predicates is the obvious one. variable? and number? are as above. The others have the following form: (define (prod? exp) (if (atom? exp) nil (eq? (car exp) ’prod) ) ) 70

Selectors (define (augend exp ) (caddr exp)) (define (minuend exp ) (caddr exp)) (define (multiplicand exp ) (caddr exp)) (define (denominator exp ) (caddr exp)) (define (antecedent exp ) (caddr exp)) (define (consequent exp ) (cadddr exp)) (define (righteq exp ) (caddr exp)) (define (rightlt exp ) (caddr exp)) (define (right exp ) (caddr exp)) (define (destination exp ) (caddr exp)) 71

Interpreter (define (eval prog pc env) (let ((s (statement prog pc))) (cond ((null? s) env) ((assignment? s) (eval prog (+ pc 1) (define-variable! (left s) (op (right s) env) env) env)) ((ifstatement? s) (eval prog (cond ((true? (op (proposition s) env) ) (lookup-variable-value (destination s) env) ((else (+ pc 1))) env)) (else error “Unknown statement type – EVAL”)))) 72

op (define (opexpr env) (cond ((variable? expr) (lookup-variable-value expr eval)) ((number? expr) expr) ((sum? expr) (+ (op (addend expr) env) (op (augend expr) env) ((diff? expr) (- (op (subtraend expr) env) (op (minuend expr) env)) ((prod? expr) (* (op (multiplier expr) env) (op (multiplicand expr) env)) ((quotient? expr) (/ (op (numerator expr) env) (op (denomintor expr) env)) ((ifexpression? expr) (cond (true? (op (proposition expr) env) (op (antecedent expr) env)) (else (op (consequent expr) env))) ((equal? expr) (= (op (lefteq expr) env) (op (righteq expr) env)) ((less? expr) (< (op (leftlt expr) env) (op (rightlt expr) env)) (else error “Unknown operator – EVAL-EXPR”))) 73

Processing the program as a sequence of characters 74 (define (statement pc prog) ; Get statement number pc (if (= pc 1) (delim “;” prog) (statement (- pc 1) (strip “;” prog))) (define (first prog) ; Get first character of program (if (equal? prog “”) “” (substring prog 0 1) ) (define (rest prog) ; Get the whole program but the first character (if (equal? prog “”) “” (substring prog 1 (string-length prog) )

75 (define (delim char prog) ; Get the sequence of characters (if (equal? (first prog) char); before the first “;” “” (string-append (first prog) (delim char (rest prog))))) (define (strip char prog) ; Remove all occurences of char (if (equal? (first prog) char) ; from prog (rest prog) (strip char (rest prog))))

76 (define (sum? exp) (operator exp 0 “+”)) ; Sum operation (define (operator exp lev op) (cond ((equal? exp “”) nil) ((equal? (first exp “(“)) (operator (rest exp) (+ lev 1) op)) ((equal? (first exp “)“)) (operator (rest exp) (- lev 1) op)) ((> lev 0) (operator (rest exp) lev op)) ((equal? (first exp op)) #t) (else (operator (rest exp) pos op))))

77 (define (augend exp) (delimexp “+” 0 exp) (define (delimexp op lev exp) (cond ((equal? (first exp “(“)) (string-append (first exp) (delimexp op (+ lev 1) (rest exp))) ((equal? (first exp “)“)) (string-append (first exp) (delimexp op (- lev 1) (rest exp))) ((> lev 0)) (string-append (first exp) (delimexp op lev (rest exp))) ((equal? (first exp) op) “”) (else (string-append (first exp) (delimexp op lev (rest exp))))

The program as a sequence of tokens Has the advantage that we don’t need to do the lexical scanning as part of the intepretation process. Each token has a symbol assosciated with it, except that variables and numbers are pairs. 78

root :=1; a: root := 0.5 * (root + x/root); error := root * root – x; perror := if error > 0.0 then error else 0.0 – error; If perror > then goto a; (list (‘var. ‘root) ‘assign (‘number. 1) ‘semicolon (‘label ‘a) ‘colon (‘variable. root) ‘assign (‘number 0.5) ‘mpy ‘leftpar (‘variable.‘root) ‘sum (‘variable. ‘x) ‘div (‘variable. ‘root) ‘rightpar ‘semicolon … (‘variable ‘perror) ‘assign ‘if (‘variable. ‘error) ‘gt (‘number. 0.0) ‘then (‘variabl ‘error) ‘else... 79

Example evaluator (number, ‘sum, ‘mpy) (define (eval-exp exp) (cond ((= (length exp) 1) (cdar exp)) ( (operator exp 0 ’sum ) (+ (eval-exp (left-operand exp 0 ’sum)) (eval-exp (right-operand exp 0 ’sum )))) ((operator exp 0 'mpy ) (* (eval-exp (left-operand exp 0 'mpy)) (eval-exp (right-operand exp 0 'mpy)))) (else (eval-exp (depar exp))))) (define (operator exp lev op) (cond ((equal? exp '()) #f) ((equal? (car exp) 'leftpar) (operator (cdr exp) (+ lev 1) op)) ((equal? (car exp) 'rightpar) (operator (cdr exp) (- lev 1) op)) ((> lev 0) (operator (cdr exp) lev op)) ((eq? (car exp) op) #t) (else (operator (cdr exp) lev op)))) 80

(define (left-operand exp lev op) (cond ((equal? exp '()) '()) ((equal? (car exp) 'lp) (cons (car exp) (left-operand (cdr exp) (+ lev 1) op))) ((equal? (car exp) 'rp) (cons (car exp) (left-operand (cdr exp) (- lev 1) op))) ((> lev 0) (cons (car exp) (left-operand (cdr exp) lev op))) ((equal? (car exp) op) '()) (else (cons (car exp ) (left-operand (cdr exp) lev op))))) (define (right-operand exp lev op) (cond ((equal? exp '()) '()) ((equal? (car exp) 'lp) (right-operand (cdr exp) (+ lev 1) op)) ((equal? (car exp) 'rp) (right-operand (cdr exp) (- lev 1) op)) ((> lev 0) (right-operand (cdr exp) lev op)) ((eq? (car exp) op) (cdr exp) ) (else (right-operand (cdr exp) lev op)))) 81

(define (depar exp) (if (equal? (car exp) 'leftpar ) (dep1 (cdr exp)) exp)) (define (dep1 exp) (if (equal? (cdr exp) '()) '() (cons (car exp) (dep1 (cdr exp))))) 82