diff --git a/ex-5_23-xx.scm b/ex-5_23-xx.scm index 605cde9..d7eeea9 100644 --- a/ex-5_23-xx.scm +++ b/ex-5_23-xx.scm @@ -1,5 +1,17 @@ (load "util.scm") (load "misc/sicp-regsim.scm") +(load "misc/sicp-eceval.scm") -(display "\nex-5.23\n") +(define the-global-environment (setup-environment)) +(set-register-contents! eceval 'exp '(+ 1 2)) +(start eceval) +(assert (get-register-contents eceval 'val) 3) + +(display "\nex-5.23 - derived-expressions\n") + + +(display "\nex-5.24\n") + + +;(display "\nex-5.25\n") diff --git a/misc/sicp-eceval-support.scm b/misc/sicp-eceval-support.scm new file mode 100644 index 0000000..06677bc --- /dev/null +++ b/misc/sicp-eceval-support.scm @@ -0,0 +1,188 @@ +;;;;SIMULATION OF ECEVAL MACHINE OPERATIONS -- +;;;;loaded by load-eceval.scm and by load-eceval-compiler.scm + +;;;;FIRST A LOT FROM 4.1.2-4.1.4 + +;(load "ch5-syntax.scm"); ;section 4.1.2 syntax procedures +(load "misc/sicp-eceval-syntax.scm") ;section 4.1.2 syntax procedures + +;;;SECTION 4.1.3 +;;; operations used by compiled code and eceval except as noted + +(define (true? x) + (not (eq? x false))) + +;;* not used by eceval itself -- used by compiled code when that +;; is run in the eceval machine +(define (false? x) + (eq? x false)) + +;;following compound-procedure operations not used by compiled code +(define (make-procedure parameters body env) + (list 'procedure parameters body env)) + +(define (compound-procedure? p) + (tagged-list? p 'procedure)) + +(define (procedure-parameters p) (cadr p)) +(define (procedure-body p) (caddr p)) +(define (procedure-environment p) (cadddr p)) +;;(end of compound procedures) + + +(define (enclosing-environment env) (cdr env)) + +(define (first-frame env) (car env)) + +(define the-empty-environment '()) + +(define (make-frame variables values) + (cons variables values)) + +(define (frame-variables frame) (car frame)) +(define (frame-values frame) (cdr frame)) + +(define (add-binding-to-frame! var val frame) + (set-car! frame (cons var (car frame))) + (set-cdr! frame (cons val (cdr frame)))) + +(define (extend-environment vars vals base-env) + (if (= (length vars) (length vals)) + (cons (make-frame vars vals) base-env) + (if (< (length vars) (length vals)) + (error "Too many arguments supplied" vars vals) + (error "Too few arguments supplied" vars vals)))) + + +(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)) + +(define (set-variable-value! var val env) + (define (env-loop env) + (define (scan vars vals) + (cond ((null? vars) + (env-loop (enclosing-environment env))) + ((eq? var (car vars)) + (set-car! vals val)) + (else (scan (cdr vars) (cdr vals))))) + (if (eq? env the-empty-environment) + (error "Unbound variable -- SET!" var) + (let ((frame (first-frame env))) + (scan (frame-variables frame) + (frame-values frame))))) + (env-loop env)) + +(define (define-variable! var val env) + (let ((frame (first-frame env))) + (define (scan vars vals) + (cond ((null? vars) + (add-binding-to-frame! var val frame)) + ((eq? var (car vars)) + (set-car! vals val)) + (else (scan (cdr vars) (cdr vals))))) + (scan (frame-variables frame) + (frame-values frame)))) + + +;;;SECTION 4.1.4 + +(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)) + +(define (primitive-procedure? proc) + (tagged-list? proc 'primitive)) + +(define (primitive-implementation proc) (cadr proc)) + +(define primitive-procedures + (list (list 'car car) + (list 'cdr cdr) + (list 'cons cons) + (list 'null? null?) + ;;above from book -- here are some more + (list '+ +) + (list '- -) + (list '* *) + (list '= =) + (list '/ /) + (list '> >) + (list '< <) + )) + +(define (primitive-procedure-names) + (map car + primitive-procedures)) + +(define (primitive-procedure-objects) + (map (lambda (proc) (list 'primitive (cadr proc))) + primitive-procedures)) + +(define apply-in-underlying-scheme apply) + +(define (apply-primitive-procedure proc args) + (apply-in-underlying-scheme + (primitive-implementation proc) args)) + + +(define (prompt-for-input string) + (newline) (newline) (display string) (newline)) + +(define (announce-output string) + (newline) (display string) (newline)) + +(define (user-print object) + (if (compound-procedure? object) + (display (list 'compound-procedure + (procedure-parameters object) + (procedure-body object) + ')) + (display object))) + +;;; Simulation of new machine operations needed by +;;; eceval machine (not used by compiled code) + +;;; From section 5.4.1 footnote +(define (empty-arglist) '()) +(define (adjoin-arg arg arglist) + (append arglist (list arg))) +(define (last-operand? ops) + (null? (cdr ops))) + +;;; From section 5.4.2 footnote, for non-tail-recursive sequences +(define (no-more-exps? seq) (null? seq)) + +;;; From section 5.4.4 footnote +(define (get-global-environment) + the-global-environment) +;; will do following when ready to run, not when load this file +;;(define the-global-environment (setup-environment)) + + +;;; Simulation of new machine operations needed for compiled code +;;; and eceval/compiler interface (not used by plain eceval machine) +;;; From section 5.5.2 footnote +(define (make-compiled-procedure entry env) + (list 'compiled-procedure entry env)) +(define (compiled-procedure? proc) + (tagged-list? proc 'compiled-procedure)) +(define (compiled-procedure-entry c-proc) (cadr c-proc)) +(define (compiled-procedure-env c-proc) (caddr c-proc)) + diff --git a/misc/sicp-eceval-syntax.scm b/misc/sicp-eceval-syntax.scm new file mode 100644 index 0000000..30618ab --- /dev/null +++ b/misc/sicp-eceval-syntax.scm @@ -0,0 +1,120 @@ +;;;;SCHEME SYNTAX FROM SECTION 4.1.2 OF STRUCTURE AND INTERPRETATION OF +;;; COMPUTER PROGRAMS, TO SUPPORT CHAPTER 5 +;;;;Loaded by compiler.scm (for use by compiler), and by eceval-support.scm +;;;; (for simulation of eceval machine operations) + +(define (self-evaluating? exp) + (cond ((number? exp) true) + ((string? exp) true) + (else false))) + + +(define (quoted? exp) + (tagged-list? exp 'quote)) + +(define (text-of-quotation exp) (cadr exp)) + +(define (tagged-list? exp tag) + (if (pair? exp) + (eq? (car exp) tag) + false)) + + +(define (variable? exp) (symbol? exp)) + +(define (assignment? exp) + (tagged-list? exp 'set!)) + +(define (assignment-variable exp) (cadr exp)) + +(define (assignment-value exp) (caddr exp)) + + +(define (definition? exp) + (tagged-list? exp 'define)) + +(define (definition-variable exp) + (if (symbol? (cadr exp)) + (cadr exp) + (caadr exp))) + +(define (definition-value exp) + (if (symbol? (cadr exp)) + (caddr exp) + (make-lambda (cdadr exp) + (cddr exp)))) + +(define (lambda? exp) (tagged-list? exp 'lambda)) + +(define (lambda-parameters exp) (cadr exp)) +(define (lambda-body exp) (cddr exp)) + +(define (make-lambda parameters body) + (cons 'lambda (cons parameters body))) + +(define (if? exp) (tagged-list? exp 'if)) + +(define (if-predicate exp) (cadr exp)) + +(define (if-consequent exp) (caddr exp)) + +(define (if-alternative exp) + (if (not (null? (cdddr exp))) + (cadddr exp) + 'false)) + + +(define (begin? exp) (tagged-list? exp 'begin)) +(define (begin-actions exp) (cdr exp)) + +(define (last-exp? seq) (null? (cdr seq))) +(define (first-exp seq) (car seq)) +(define (rest-exps seq) (cdr seq)) + +(define (application? exp) (pair? exp)) +(define (operator exp) (car exp)) +(define (operands exp) (cdr exp)) + +(define (no-operands? ops) (null? ops)) +(define (first-operand ops) (car ops)) +(define (rest-operands ops) (cdr ops)) + +;;;**following needed only to implement COND as derived expression, +;;; not needed by eceval machine in text. But used by compiler + +;; from 4.1.2 +(define (make-if predicate consequent alternative) + (list 'if predicate consequent alternative)) + + +(define (sequence->exp seq) + (cond ((null? seq) seq) + ((last-exp? seq) (first-exp seq)) + (else (make-begin seq)))) + +(define (make-begin seq) (cons 'begin seq)) + +(define (cond? exp) (tagged-list? exp 'cond)) +(define (cond-clauses exp) (cdr exp)) +(define (cond-else-clause? clause) + (eq? (cond-predicate clause) 'else)) +(define (cond-predicate clause) (car clause)) +(define (cond-actions clause) (cdr clause)) + +(define (cond->if exp) + (expand-clauses (cond-clauses exp))) + +(define (expand-clauses clauses) + (if (null? clauses) + 'false ; no else clause + (let ((first (car clauses)) + (rest (cdr clauses))) + (if (cond-else-clause? first) + (if (null? rest) + (sequence->exp (cond-actions first)) + (error "ELSE clause isn't last -- COND->IF" + clauses)) + (make-if (cond-predicate first) + (sequence->exp (cond-actions first)) + (expand-clauses rest)))))) +;; end of Cond support diff --git a/misc/sicp-eceval.scm b/misc/sicp-eceval.scm new file mode 100644 index 0000000..2f2dd09 --- /dev/null +++ b/misc/sicp-eceval.scm @@ -0,0 +1,289 @@ +;;;;EXPLICIT-CONTROL EVALUATOR FROM SECTION 5.4 OF +;;;; STRUCTURE AND INTERPRETATION OF COMPUTER PROGRAMS + +;;;;Matches code in ch5.scm + +;;; To use it +;;; -- load "load-eceval.scm", which loads this file and the +;;; support it needs (including the register-machine simulator) + +;;; -- To initialize and start the machine, do + +;: (define the-global-environment (setup-environment)) + +;: (start eceval) +(load "misc/sicp-eceval-support.scm") + +;; To restart, can do just +;: (start eceval) +;;;;;;;;;; + + +;;**NB. To [not] monitor stack operations, comment in/[out] the line after +;; print-result in the machine controller below +;;**Also choose the desired make-stack version in regsim.scm + +(define eceval-operations + (list + ;;primitive Scheme operations + (list 'read read) + + ;;operations in syntax.scm + (list 'self-evaluating? self-evaluating?) + (list 'quoted? quoted?) + (list 'text-of-quotation text-of-quotation) + (list 'variable? variable?) + (list 'assignment? assignment?) + (list 'assignment-variable assignment-variable) + (list 'assignment-value assignment-value) + (list 'definition? definition?) + (list 'definition-variable definition-variable) + (list 'definition-value definition-value) + (list 'lambda? lambda?) + (list 'lambda-parameters lambda-parameters) + (list 'lambda-body lambda-body) + (list 'if? if?) + (list 'if-predicate if-predicate) + (list 'if-consequent if-consequent) + (list 'if-alternative if-alternative) + (list 'begin? begin?) + (list 'begin-actions begin-actions) + (list 'last-exp? last-exp?) + (list 'first-exp first-exp) + (list 'rest-exps rest-exps) + (list 'application? application?) + (list 'operator operator) + (list 'operands operands) + (list 'no-operands? no-operands?) + (list 'first-operand first-operand) + (list 'rest-operands rest-operands) + + ;;operations in eceval-support.scm + (list 'true? true?) + (list 'make-procedure make-procedure) + (list 'compound-procedure? compound-procedure?) + (list 'procedure-parameters procedure-parameters) + (list 'procedure-body procedure-body) + (list 'procedure-environment procedure-environment) + (list 'extend-environment extend-environment) + (list 'lookup-variable-value lookup-variable-value) + (list 'set-variable-value! set-variable-value!) + (list 'define-variable! define-variable!) + (list 'primitive-procedure? primitive-procedure?) + (list 'apply-primitive-procedure apply-primitive-procedure) + (list 'prompt-for-input prompt-for-input) + (list 'announce-output announce-output) + (list 'user-print user-print) + (list 'empty-arglist empty-arglist) + (list 'adjoin-arg adjoin-arg) + (list 'last-operand? last-operand?) + (list 'no-more-exps? no-more-exps?) ;for non-tail-recursive machine + (list 'get-global-environment get-global-environment)) + ) + +(define eceval + (make-machine + '(exp env val proc argl continue unev) + eceval-operations + '( + + (perform (op initialize-stack)) + (assign env (op get-global-environment)) + (assign continue (label ev-done)) + (goto (label eval-dispatch)) + +unknown-expression-type + (assign val (const unknown-expression-type-error)) + (goto (label signal-error)) + +unknown-procedure-type + (restore continue) + (assign val (const unknown-procedure-type-error)) + (goto (label signal-error)) + +signal-error + (perform (op user-print) (reg val)) + (goto (label ev-done)) + +;;SECTION 5.4.1 +eval-dispatch + (test (op self-evaluating?) (reg exp)) + (branch (label ev-self-eval)) + (test (op variable?) (reg exp)) + (branch (label ev-variable)) + (test (op quoted?) (reg exp)) + (branch (label ev-quoted)) + (test (op assignment?) (reg exp)) + (branch (label ev-assignment)) + (test (op definition?) (reg exp)) + (branch (label ev-definition)) + (test (op if?) (reg exp)) + (branch (label ev-if)) + (test (op lambda?) (reg exp)) + (branch (label ev-lambda)) + (test (op begin?) (reg exp)) + (branch (label ev-begin)) + (test (op application?) (reg exp)) + (branch (label ev-application)) + (goto (label unknown-expression-type)) + +ev-self-eval + (assign val (reg exp)) + (goto (reg continue)) +ev-variable + (assign val (op lookup-variable-value) (reg exp) (reg env)) + (goto (reg continue)) +ev-quoted + (assign val (op text-of-quotation) (reg exp)) + (goto (reg continue)) +ev-lambda + (assign unev (op lambda-parameters) (reg exp)) + (assign exp (op lambda-body) (reg exp)) + (assign val (op make-procedure) + (reg unev) (reg exp) (reg env)) + (goto (reg continue)) + +ev-application + (save continue) + (save env) + (assign unev (op operands) (reg exp)) + (save unev) + (assign exp (op operator) (reg exp)) + (assign continue (label ev-appl-did-operator)) + (goto (label eval-dispatch)) +ev-appl-did-operator + (restore unev) + (restore env) + (assign argl (op empty-arglist)) + (assign proc (reg val)) + (test (op no-operands?) (reg unev)) + (branch (label apply-dispatch)) + (save proc) +ev-appl-operand-loop + (save argl) + (assign exp (op first-operand) (reg unev)) + (test (op last-operand?) (reg unev)) + (branch (label ev-appl-last-arg)) + (save env) + (save unev) + (assign continue (label ev-appl-accumulate-arg)) + (goto (label eval-dispatch)) +ev-appl-accumulate-arg + (restore unev) + (restore env) + (restore argl) + (assign argl (op adjoin-arg) (reg val) (reg argl)) + (assign unev (op rest-operands) (reg unev)) + (goto (label ev-appl-operand-loop)) +ev-appl-last-arg + (assign continue (label ev-appl-accum-last-arg)) + (goto (label eval-dispatch)) +ev-appl-accum-last-arg + (restore argl) + (assign argl (op adjoin-arg) (reg val) (reg argl)) + (restore proc) + (goto (label apply-dispatch)) +apply-dispatch + (test (op primitive-procedure?) (reg proc)) + (branch (label primitive-apply)) + (test (op compound-procedure?) (reg proc)) + (branch (label compound-apply)) + (goto (label unknown-procedure-type)) + +primitive-apply + (assign val (op apply-primitive-procedure) + (reg proc) + (reg argl)) + (restore continue) + (goto (reg continue)) + +compound-apply + (assign unev (op procedure-parameters) (reg proc)) + (assign env (op procedure-environment) (reg proc)) + (assign env (op extend-environment) + (reg unev) (reg argl) (reg env)) + (assign unev (op procedure-body) (reg proc)) + (goto (label ev-sequence)) + +;;;SECTION 5.4.2 +ev-begin + (assign unev (op begin-actions) (reg exp)) + (save continue) + (goto (label ev-sequence)) + +ev-sequence + (assign exp (op first-exp) (reg unev)) + (test (op last-exp?) (reg unev)) + (branch (label ev-sequence-last-exp)) + (save unev) + (save env) + (assign continue (label ev-sequence-continue)) + (goto (label eval-dispatch)) +ev-sequence-continue + (restore env) + (restore unev) + (assign unev (op rest-exps) (reg unev)) + (goto (label ev-sequence)) +ev-sequence-last-exp + (restore continue) + (goto (label eval-dispatch)) + +;;;SECTION 5.4.3 + +ev-if + (save exp) + (save env) + (save continue) + (assign continue (label ev-if-decide)) + (assign exp (op if-predicate) (reg exp)) + (goto (label eval-dispatch)) +ev-if-decide + (restore continue) + (restore env) + (restore exp) + (test (op true?) (reg val)) + (branch (label ev-if-consequent)) +ev-if-alternative + (assign exp (op if-alternative) (reg exp)) + (goto (label eval-dispatch)) +ev-if-consequent + (assign exp (op if-consequent) (reg exp)) + (goto (label eval-dispatch)) + +ev-assignment + (assign unev (op assignment-variable) (reg exp)) + (save unev) + (assign exp (op assignment-value) (reg exp)) + (save env) + (save continue) + (assign continue (label ev-assignment-1)) + (goto (label eval-dispatch)) +ev-assignment-1 + (restore continue) + (restore env) + (restore unev) + (perform + (op set-variable-value!) (reg unev) (reg val) (reg env)) + (assign val (const ok)) + (goto (reg continue)) + +ev-definition + (assign unev (op definition-variable) (reg exp)) + (save unev) + (assign exp (op definition-value) (reg exp)) + (save env) + (save continue) + (assign continue (label ev-definition-1)) + (goto (label eval-dispatch)) +ev-definition-1 + (restore continue) + (restore env) + (restore unev) + (perform + (op define-variable!) (reg unev) (reg val) (reg env)) + (assign val (const ok)) + (goto (reg continue)) +ev-done + ))) + +'(EXPLICIT CONTROL EVALUATOR LOADED)