;;; Syntax procedures for chapter 4 ;;; Self-evaluating entities (define (self-evaluating? exp) (or (number? exp) (eq? exp #t) (eq? exp #f) (string? exp))) ; Our prompt (viz., "M-EVAL=> ") is a string. ;;; Variables (define (variable? exp) (symbol? exp)) ;;; Special forms (in general) (define (tagged-list? exp tag) (and (pair? exp) (eq? (car exp) tag))) ;;; Quotations (define (quoted? exp) (tagged-list? exp 'quote)) (define (text-of-quotation exp) (cadr exp)) ;;; Assignment--- SET! (define (assignment? exp) (tagged-list? exp 'set!)) (define (assignment-variable exp) (cadr exp)) (define (assignment-value exp) (caddr exp)) ;;; Definitions (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) (cons 'lambda (cons (cdadr exp) ;formal parameters (cddr exp))))) ;body ;;; LAMBDA expressions (define (lambda? exp) (tagged-list? exp 'lambda)) (define (lambda-parameters lambda-exp) (cadr lambda-exp)) (define (lambda-body lambda-exp) (cddr lambda-exp)) ;;; If conditionals (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) 'the-unspecified-value)) (define (make-if pred conseq alternative) (list 'if pred conseq alternative)) ;;; BEGIN expressions (a.k.a. sequences) (define (begin? exp) (tagged-list? exp 'begin)) (define (begin-actions begin-exp) (cdr begin-exp)) (define (last-exp? seq) (null? (cdr seq))) (define (first-exp seq) (car seq)) (define (rest-exps seq) (cdr seq)) (define (sequence->begin seq) (cond ((null? seq) seq) ((last-exp? seq) (first-exp seq)) (else (make-begin seq)))) (define (make-begin exp) (cons 'begin exp)) ;;; Procedure applications (define (application? exp) (pair? exp)) (define (operator app) (car app)) (define (operands app) (cdr app)) (define (no-operands? args) (null? args)) (define (first-operand args) (car args)) (define (rest-operands args) (cdr args)) ;;; COND Conditionals (define (cond? exp) (tagged-list? exp 'cond)) (define (cond-clauses cndl) (cdr cndl)) (define (cond-no-clauses? clauses) (null? clauses)) (define (cond-first-clause clauses) (car clauses)) (define (cond-rest-clauses clauses) (cdr clauses)) (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 cond-exp) (define (expand clauses) (cond ((cond-no-clauses? clauses) (list 'error "COND: no values matched")) ((cond-else-clause? (cond-first-clause clauses)) (if (cond-no-clauses? (cond-rest-clauses clauses)) (sequence->begin (cond-actions (cond-first-clause clauses))) (error "ELSE clause isn't last -- COND->IF" exp))) (else (make-if (cond-predicate (cond-first-clause clauses)) (sequence->begin (cond-actions (cond-first-clause clauses))) (expand (cond-rest-clauses clauses)))))) (expand (cond-clauses cond-exp))) ;;; LET expressions (define (let? exp) (tagged-list? exp 'let)) (define (let-bound-variables let-exp) (map car (cadr let-exp))) (define (let-values let-exp) (map cadr (cadr let-exp))) (define (let-body let-exp) (sequence->begin (cddr let-exp))) (define (LET->combination let-exp) (let ((names (let-bound-variables let-exp)) (values (let-values let-exp)) (body (let-body let-exp))) (cons (list 'LAMBDA names body) values))) ;;; Declaration syntax for call-by-name interpreter (define declaration? pair?) (define (parameter-name var-decl) (if (pair? var-decl) (car var-decl) var-decl)) (define (lazy? var-decl) (and (pair? var-decl) (eq? 'lazy (cadr var-decl)))) (define (memo? var-decl) (and (pair? var-decl) (eq? 'lazy-memo (cadr var-decl)))) (define (exists p? l) (let loop ((l l)) (cond ((null? l) false) ((p? (car l)) true) (else (loop (cdr l)))))) ;;; Another special form that may be demonstrated. ;;; (For non-deterministic interpreter) (define (amb? exp) (and (pair? exp) (eq? (car exp) 'amb)))