interpreter with activation records in register
This commit is contained in:
557
env-register-interpreter.scm
Normal file
557
env-register-interpreter.scm
Normal file
@@ -0,0 +1,557 @@
|
|||||||
|
(use-modules (ice-9 match)
|
||||||
|
(srfi srfi-1)
|
||||||
|
(srfi srfi-9) ;; Record types
|
||||||
|
(srfi srfi-64) ;; Testing framework
|
||||||
|
)
|
||||||
|
;; This interpreter uses a register for env instead of sr values
|
||||||
|
;; Globals
|
||||||
|
(define undefined-value (make-symbol "undefined"))
|
||||||
|
(define g.init (make-parameter '()))
|
||||||
|
(define sg.init (make-vector 100))
|
||||||
|
(define g.current (make-parameter '()))
|
||||||
|
(define sg.current (make-vector 100))
|
||||||
|
(define desc.init (make-parameter '()))
|
||||||
|
(define *env* (make-parameter #f))
|
||||||
|
|
||||||
|
;; Macros
|
||||||
|
(define-syntax with-fresh-globals
|
||||||
|
(syntax-rules ()
|
||||||
|
[(_ expr ...)
|
||||||
|
(parameterize ([g.current '()]
|
||||||
|
[g.init '()]
|
||||||
|
[desc.init '()]
|
||||||
|
[*env* #f])
|
||||||
|
expr ...)]))
|
||||||
|
(define-syntax define-initial
|
||||||
|
(syntax-rules ()
|
||||||
|
[(_ name value)
|
||||||
|
(vector-set! sg.init (g.init-extend! 'name) value)]))
|
||||||
|
(define-syntax define-primitive
|
||||||
|
(syntax-rules ()
|
||||||
|
[(_ name value 0) (define-primitive0 name value)]
|
||||||
|
[(_ name value 1) (define-primitive1 name value)]
|
||||||
|
[(_ name value 2) (define-primitive2 name value)]
|
||||||
|
[(_ name value 3) (define-primitive3 name value)]))
|
||||||
|
(define-syntax-rule (define-primitive0 name value)
|
||||||
|
(define-initial name
|
||||||
|
(letrec ([arity+1 (+ 0 1)]
|
||||||
|
[behavior
|
||||||
|
(lambda (v* k)
|
||||||
|
(if (= (activation-rec-length v*) arity+1)
|
||||||
|
(k (value))
|
||||||
|
(error "Incorrect arity" 'name)))])
|
||||||
|
(description-extend! 'name `(function ,value))
|
||||||
|
behavior)))
|
||||||
|
(define-syntax-rule (define-primitive1 name value)
|
||||||
|
(define-initial name
|
||||||
|
(letrec ([arity+1 (+ 1 1)]
|
||||||
|
[behavior
|
||||||
|
(lambda (v* k)
|
||||||
|
(if (= (activation-rec-length v*) arity+1)
|
||||||
|
(k (value (activation-rec-ref v* 0)))
|
||||||
|
(error "Incorrect arity" 'name)))])
|
||||||
|
(description-extend! 'name `(function ,value a))
|
||||||
|
behavior)))
|
||||||
|
(define-syntax-rule (define-primitive2 name value)
|
||||||
|
(define-initial name
|
||||||
|
(letrec ([arity+1 (+ 2 1)]
|
||||||
|
[behavior
|
||||||
|
(lambda (v* k)
|
||||||
|
(if (= (activation-rec-length v*) arity+1)
|
||||||
|
(k (value (activation-rec-ref v* 0)
|
||||||
|
(activation-rec-ref v* 1)))
|
||||||
|
(error "Incorrect arity" 'name)))])
|
||||||
|
(description-extend! 'name `(function ,value a b))
|
||||||
|
behavior)))
|
||||||
|
(define-syntax-rule (define-primitive3 name value)
|
||||||
|
(define-initial name
|
||||||
|
(letrec ([arity+1 (+ 3 1)]
|
||||||
|
[behavior
|
||||||
|
(lambda (v* k)
|
||||||
|
(if (= (activation-rec-length v*) arity+1)
|
||||||
|
(k (value (activation-rec-ref v* 0)
|
||||||
|
(activation-rec-ref v* 1)
|
||||||
|
(activation-rec-ref v* 2)))
|
||||||
|
(error "Incorrect arity" 'name)))])
|
||||||
|
(description-extend! 'name `(function ,value a b c))
|
||||||
|
behavior)))
|
||||||
|
|
||||||
|
|
||||||
|
;; Record types
|
||||||
|
(define-record-type <activation-record>
|
||||||
|
(make-activation-record next vals)
|
||||||
|
activation-record?
|
||||||
|
(next activation-record-next activation-record-next-set!)
|
||||||
|
(vals activation-record-vals))
|
||||||
|
|
||||||
|
;; Helpers
|
||||||
|
(define (find-indexed pred lst)
|
||||||
|
(find (lambda (kons) (pred (car kons)))
|
||||||
|
(zip lst (iota (length lst)))))
|
||||||
|
|
||||||
|
(define (local-variable env ref)
|
||||||
|
(let scan-env ([env env] [i 0])
|
||||||
|
(if (null? env)
|
||||||
|
#f
|
||||||
|
(let ([the-match (find-indexed (lambda (name) (eq? name ref)) (car env))])
|
||||||
|
(if the-match
|
||||||
|
`(local ,i . ,(cadr the-match))
|
||||||
|
(scan-env (cdr env) (+ i 1)))))))
|
||||||
|
|
||||||
|
(define (global-variable env ref)
|
||||||
|
(assq-ref env ref))
|
||||||
|
|
||||||
|
(define (compute-kind ref r)
|
||||||
|
(or (local-variable r ref)
|
||||||
|
(global-variable (g.current) ref)
|
||||||
|
(global-variable (g.init) ref)))
|
||||||
|
|
||||||
|
(define (g.current-extend! ref)
|
||||||
|
(let ([level (length (g.current))])
|
||||||
|
(g.current (cons (cons ref (cons 'global level)) (g.current)))
|
||||||
|
level))
|
||||||
|
|
||||||
|
(define (g.init-extend! ref)
|
||||||
|
(let ([level (length (g.init))])
|
||||||
|
(g.init (cons (cons ref (cons 'predefined level)) (g.init)))
|
||||||
|
level))
|
||||||
|
|
||||||
|
(define (static-error . args)
|
||||||
|
(apply error "Static Error:" args))
|
||||||
|
;; activation records
|
||||||
|
(define (make-activation-rec size)
|
||||||
|
(make-activation-record #f (make-vector size)))
|
||||||
|
|
||||||
|
|
||||||
|
(define activation-rec-set!
|
||||||
|
(case-lambda
|
||||||
|
[(r k v) (vector-set! (activation-record-vals r) k v)]
|
||||||
|
[(r j k v) (if (zero? j)
|
||||||
|
(activation-rec-set! r k v)
|
||||||
|
(activation-rec-set! (activation-record-next r) (1- j) k v))]))
|
||||||
|
|
||||||
|
(define activation-rec-ref
|
||||||
|
(case-lambda
|
||||||
|
[(r i)
|
||||||
|
(vector-ref (activation-record-vals r) i)]
|
||||||
|
[(r i j)
|
||||||
|
(if (zero? i)
|
||||||
|
(activation-rec-ref r j)
|
||||||
|
(activation-rec-ref (activation-record-next r) (1- i) j))]))
|
||||||
|
(define (activation-rec-length r)
|
||||||
|
(vector-length (activation-record-vals r)))
|
||||||
|
;; function descriptions
|
||||||
|
(define (description-extend! name description)
|
||||||
|
(desc.init (cons (cons name description) (desc.init))))
|
||||||
|
|
||||||
|
(define (get-description name)
|
||||||
|
(let ([p (assq name (desc.init))])
|
||||||
|
(and (pair? p) (cdr p))))
|
||||||
|
|
||||||
|
(define desc-args cddr)
|
||||||
|
|
||||||
|
(define desc-address cadr)
|
||||||
|
|
||||||
|
;; This maybe works maybe
|
||||||
|
(define (thread m* k)
|
||||||
|
(if (null? m*)
|
||||||
|
k
|
||||||
|
(lambda _ ((car m*) (thread (cdr m*) k)))))
|
||||||
|
;; for easy testing
|
||||||
|
(define (list->activation-rec lst)
|
||||||
|
(let lp ([lst lst]
|
||||||
|
[next #f])
|
||||||
|
(if (null? lst)
|
||||||
|
next
|
||||||
|
(lp (cdr lst)
|
||||||
|
(make-activation-record next (list->vector (append (car lst) (list undefined-value))))))))
|
||||||
|
|
||||||
|
(define (env-set! lst)
|
||||||
|
(*env* (list->activation-rec lst)))
|
||||||
|
|
||||||
|
;; environments
|
||||||
|
(define (predefined-fetch i)
|
||||||
|
(vector-ref sg.init i))
|
||||||
|
|
||||||
|
(define (global-fetch i)
|
||||||
|
(vector-ref sg.current i))
|
||||||
|
|
||||||
|
(define (r-extend* r n*)
|
||||||
|
(cons n* r))
|
||||||
|
|
||||||
|
(define (sr-extend* sr v*)
|
||||||
|
(activation-record-next-set! v* sr)
|
||||||
|
v*)
|
||||||
|
|
||||||
|
;; Initial definitions
|
||||||
|
(define-initial t #t)
|
||||||
|
(define-initial f #f)
|
||||||
|
(define-initial nil '())
|
||||||
|
(define-primitive cons cons 2)
|
||||||
|
(define-primitive car car 1)
|
||||||
|
(define-primitive cdr cdr 1)
|
||||||
|
(define-primitive + + 2)
|
||||||
|
(define-primitive = = 2)
|
||||||
|
(define-initial call/cc
|
||||||
|
(let* ([arity 1]
|
||||||
|
[arity+1 (1+ arity)])
|
||||||
|
(lambda (v* k)
|
||||||
|
(if (= arity+1 (activation-rec-length v*))
|
||||||
|
((activation-rec-ref v* 0)
|
||||||
|
(let ([rec (make-activation-rec (+ 1 1))])
|
||||||
|
(activation-rec-set!
|
||||||
|
rec 0
|
||||||
|
(lambda (values kk)
|
||||||
|
(if (= arity+1 (activation-rec-length values))
|
||||||
|
(k (activation-rec-ref values 0))
|
||||||
|
(error "incorrect arity" 'continuation))))
|
||||||
|
rec)
|
||||||
|
k)
|
||||||
|
(error "incorrect arity" 'call/cc)))))
|
||||||
|
|
||||||
|
|
||||||
|
;; Denotations
|
||||||
|
(define (meaning e r tail?)
|
||||||
|
"Core of the denotation. `tail?' allows us to avoid capturing the local environment if we know we will not return"
|
||||||
|
(match e
|
||||||
|
[(? (negate pair?))
|
||||||
|
(if (symbol? e) (meaning-reference e r)
|
||||||
|
(meaning-quotation e))]
|
||||||
|
[('quote e* ...) (meaning-quotation e*)]
|
||||||
|
[('lambda v* e* ...) (meaning-abstraction v* e* r)]
|
||||||
|
[('if e1 e2 e3) (meaning-alternative e1 e2 e3 r tail?)]
|
||||||
|
[('begin e* ...) (meaning-sequence e* r tail?)]
|
||||||
|
[('set! n e) (meaning-assignment n e r)]
|
||||||
|
[(f v* ...) (meaning-application f v* r tail?)]))
|
||||||
|
|
||||||
|
(define (meaning-r r)
|
||||||
|
(lambda (e tail?)
|
||||||
|
(meaning e r tail?)))
|
||||||
|
|
||||||
|
(define (n-tail n tail?)
|
||||||
|
(if (= 1 n)
|
||||||
|
(list tail?)
|
||||||
|
(cons #f (n-tail (1- n) tail?))))
|
||||||
|
|
||||||
|
(define (meaning* e* r)
|
||||||
|
"Go through e* defining meanings, thread the expressions and insert
|
||||||
|
their results into the activation frame"
|
||||||
|
(let ([m* (map (meaning-r r) e* (make-list (length e*) #f))]
|
||||||
|
[activation-rec-size (1+ (length e*))])
|
||||||
|
(lambda (k)
|
||||||
|
(let lp ([m* m*]
|
||||||
|
[rank 0]
|
||||||
|
[k k])
|
||||||
|
(if (null? m*)
|
||||||
|
(k (make-activation-rec activation-rec-size))
|
||||||
|
((car m*) (lambda (v)
|
||||||
|
(lp (cdr m*)
|
||||||
|
(1+ rank)
|
||||||
|
(lambda (v*)
|
||||||
|
(activation-rec-set! v* rank v)
|
||||||
|
(k v*))))))))))
|
||||||
|
;;(meaning*-dotted e* r (length e*) (length n*))
|
||||||
|
(define (meaning*-dotted e* r fixed-size)
|
||||||
|
"Same as `meaning' but put only put `fixed-size' arguments in the
|
||||||
|
activation frame, the rest are made into a list and put at the end"
|
||||||
|
(let ([m* (map (meaning-r r) e* (make-list (length e*) #f))]
|
||||||
|
[activation-rec-size (1+ fixed-size)])
|
||||||
|
(lambda (k)
|
||||||
|
(let lp ([m* m*]
|
||||||
|
[rank 0]
|
||||||
|
[k k])
|
||||||
|
(cond
|
||||||
|
[(null? m*)
|
||||||
|
(let ([v* (make-activation-rec activation-rec-size)])
|
||||||
|
(activation-rec-set! v* fixed-size '())
|
||||||
|
(k v*))]
|
||||||
|
[(< rank fixed-size)
|
||||||
|
((car m*) (lambda (v)
|
||||||
|
(lp (cdr m*)
|
||||||
|
(1+ rank)
|
||||||
|
(lambda (v*)
|
||||||
|
(activation-rec-set! v* rank v)
|
||||||
|
(k v*)))))]
|
||||||
|
[else
|
||||||
|
((car m*) (lambda (v)
|
||||||
|
(lp (cdr m*)
|
||||||
|
(1+ rank)
|
||||||
|
(lambda (v*)
|
||||||
|
(activation-rec-set! v* fixed-size
|
||||||
|
(cons v (activation-rec-ref v* 0 fixed-size)))
|
||||||
|
(k v*)))))])))))
|
||||||
|
|
||||||
|
(define (meaning-quotation e*)
|
||||||
|
(lambda (k)
|
||||||
|
(k e*)))
|
||||||
|
|
||||||
|
(define (meaning-alternative e1 e2 e3 r tail?)
|
||||||
|
(let ([m1 (meaning e1 r #f)]
|
||||||
|
[m2 (meaning e2 r tail?)]
|
||||||
|
[m3 (meaning e3 r tail?)])
|
||||||
|
(lambda (k)
|
||||||
|
(m1 (lambda (v)
|
||||||
|
((if v m2 m3) k))))))
|
||||||
|
|
||||||
|
(define (meaning-sequence e* r tail?)
|
||||||
|
(if (null? e*)
|
||||||
|
(static-error "Illegal syntax (begin)")
|
||||||
|
(let ([m* (map (meaning-r r) e* (n-tail (length e*) tail?))])
|
||||||
|
(lambda (k)
|
||||||
|
((thread m* (lambda (v) (k v))))))))
|
||||||
|
|
||||||
|
(define (meaning-reference n r)
|
||||||
|
(match (compute-kind n r)
|
||||||
|
[('local . (i . j))
|
||||||
|
(lambda (k)
|
||||||
|
(k (activation-rec-ref (*env*) i j)))]
|
||||||
|
[('global . i)
|
||||||
|
(if (eq? (global-fetch i) undefined-value)
|
||||||
|
(lambda (k)
|
||||||
|
(let ([v (global-fetch i)])
|
||||||
|
(if (eq? v undefined-value)
|
||||||
|
(error "Uninitialized variable" n)
|
||||||
|
(k v))))
|
||||||
|
(lambda (k)
|
||||||
|
(k (global-fetch i))))]
|
||||||
|
[('predefined . i)
|
||||||
|
(let ([value (predefined-fetch i)])
|
||||||
|
(lambda (k)
|
||||||
|
(k value)))]
|
||||||
|
[_ (static-error "No such variable" n)]))
|
||||||
|
|
||||||
|
(define (meaning-application f e* r tail?)
|
||||||
|
(cond
|
||||||
|
[(and (symbol? f)
|
||||||
|
(get-description f)
|
||||||
|
(compute-kind f r)) =>
|
||||||
|
(lambda (kind)
|
||||||
|
(if (eq? (car kind) 'predefined)
|
||||||
|
(meaning-primitive-application f e* r)
|
||||||
|
(meaning-regular-application f e* r tail?)))]
|
||||||
|
[(and (pair? f) (eq? (car f) 'lambda))
|
||||||
|
(meaning-closed-application f e* r tail?)]
|
||||||
|
[else (meaning-regular-application f e* r tail?)]))
|
||||||
|
|
||||||
|
(define (meaning-regular-application f e* r tail?)
|
||||||
|
(let [(mf (meaning f r #f))
|
||||||
|
(m* (meaning* e* r))]
|
||||||
|
(if tail?
|
||||||
|
(lambda (k)
|
||||||
|
(mf (lambda (f)
|
||||||
|
(if (procedure? f)
|
||||||
|
(m* (lambda (v*)
|
||||||
|
(f v* k)))
|
||||||
|
(error "Not a function" f)))))
|
||||||
|
(lambda (k)
|
||||||
|
(mf (lambda (f)
|
||||||
|
(if (procedure? f)
|
||||||
|
(m* (lambda (v*)
|
||||||
|
(let ([sr (*env*)])
|
||||||
|
(f v* (lambda (v)
|
||||||
|
(*env* sr)
|
||||||
|
(k v))))))
|
||||||
|
(error "Not a function"))))))))
|
||||||
|
|
||||||
|
(define (meaning-primitive-application f e* r)
|
||||||
|
(let* ([desc (get-description f)]
|
||||||
|
[address (desc-address desc)]
|
||||||
|
[arity (length e*)])
|
||||||
|
(if (= (length (desc-args desc)) arity)
|
||||||
|
(case arity
|
||||||
|
[(0) (lambda (k)
|
||||||
|
(k (address)))]
|
||||||
|
[(1)
|
||||||
|
(let ([m1 (meaning (first e*) r #f)])
|
||||||
|
(lambda (k)
|
||||||
|
(m1 (lambda (v1)
|
||||||
|
(k (address v1))))))]
|
||||||
|
[(2) (let ([m1 (meaning (first e*) r #f)]
|
||||||
|
[m2 (meaning (second e*) r #f)])
|
||||||
|
(lambda (k)
|
||||||
|
(m1 (lambda (v1)
|
||||||
|
(m2 (lambda (v2)
|
||||||
|
(k (address v1 v2))))))))]
|
||||||
|
[(3) (let ([m1 (meaning (first e*) r #f)]
|
||||||
|
[m2 (meaning (second e*) r #f)]
|
||||||
|
[m3 (meaning (third e*) r #f)])
|
||||||
|
(lambda (k)
|
||||||
|
(m1 (lambda (v1)
|
||||||
|
(m2 (lambda (v2)
|
||||||
|
(m3 (lambda (v3)
|
||||||
|
(k (address v1 v2 v3))))))))))])
|
||||||
|
(static-error "Wrong arity for" f arity))))
|
||||||
|
|
||||||
|
(define (meaning-closed-application e ee* r tail?)
|
||||||
|
(let lp ([n* (second e)]
|
||||||
|
[e* ee*]
|
||||||
|
[fixargs '()])
|
||||||
|
(cond
|
||||||
|
[(pair? n*)
|
||||||
|
(if (pair? e*)
|
||||||
|
(lp (cdr n*) (cdr e*) (cons (car n*) fixargs))
|
||||||
|
(static-error "Not enough arguments" e ee*))]
|
||||||
|
[(null? n*)
|
||||||
|
(if (pair? e*)
|
||||||
|
(static-error "Too many arguments" e ee*)
|
||||||
|
(meaning-fixed-closed-application (second e) (drop e 2) ee* r tail?))]
|
||||||
|
[else
|
||||||
|
(meaning-dotted-closed-application (reverse fixargs) n* (drop e 2) ee* r tail?)])))
|
||||||
|
|
||||||
|
(define (meaning-fixed-closed-application n* body e* r tail?)
|
||||||
|
(let* [(m* (meaning* e* r))
|
||||||
|
(r2 (r-extend* r n*))
|
||||||
|
(m+ (meaning-sequence body r2 tail?))]
|
||||||
|
(lambda (k)
|
||||||
|
(m* (lambda (v*)
|
||||||
|
(*env* (sr-extend* (*env*) v*))
|
||||||
|
(m+ k))))))
|
||||||
|
|
||||||
|
(define (meaning-dotted-closed-application n* n body e* r tail?)
|
||||||
|
(let* ([m* (meaning*-dotted e* r (length n*))]
|
||||||
|
[r2 (r-extend* r (append n* (list n)))]
|
||||||
|
[m+ (meaning-sequence body r2 tail?)])
|
||||||
|
(lambda (k)
|
||||||
|
(m* (lambda (v*)
|
||||||
|
(*env* (sr-extend* (*env*) v*))
|
||||||
|
(m+ k))))))
|
||||||
|
|
||||||
|
(define (meaning-assignment n e r)
|
||||||
|
(let ([m (meaning e r #f)]
|
||||||
|
[kind (compute-kind n r)])
|
||||||
|
(if kind
|
||||||
|
(case (car kind)
|
||||||
|
[(local)
|
||||||
|
(let ([i (cadr kind)]
|
||||||
|
[j (cddr kind)])
|
||||||
|
(lambda (k)
|
||||||
|
(m (lambda (v)
|
||||||
|
(activation-rec-set! (*env*) i j v)
|
||||||
|
(k undefined-value)))))]
|
||||||
|
[else (static-error "Cannot set! undefined variable" n)]))))
|
||||||
|
|
||||||
|
(define (meaning-abstraction nn* body r)
|
||||||
|
(let lp ([n* nn*]
|
||||||
|
[fixargs '()])
|
||||||
|
(cond
|
||||||
|
[(pair? n*) (lp (cdr n*) (cons (car n*) fixargs))]
|
||||||
|
[(null? n*) (meaning-fixed-abstraction nn* body r)]
|
||||||
|
[else (meaning-dotted-abstraction (reverse fixargs) n* body r)])))
|
||||||
|
|
||||||
|
(define (meaning-fixed-abstraction n* body r)
|
||||||
|
(let* ([arity (length n*)]
|
||||||
|
[arity+1 (1+ arity)]
|
||||||
|
[r2 (r-extend* r n*)]
|
||||||
|
[m+ (meaning-sequence body r2 #t)])
|
||||||
|
(lambda (k)
|
||||||
|
(let ([sr (*env*)])
|
||||||
|
(k (lambda (v* k1)
|
||||||
|
(if (= arity+1 (activation-rec-length v*))
|
||||||
|
(begin (*env* (sr-extend* sr v*))
|
||||||
|
(m+ k1))
|
||||||
|
(error "Incorrect arity"))))))))
|
||||||
|
|
||||||
|
(define (meaning-dotted-abstraction n* n body r)
|
||||||
|
(let* ([arity (length n*)]
|
||||||
|
[arity+1 (1+ arity)]
|
||||||
|
[r2 (r-extend* r (append n* (list n)))]
|
||||||
|
[m+ (meaning-sequence body r2 #t)])
|
||||||
|
(lambda (k)
|
||||||
|
(let ([sr (*env*)])
|
||||||
|
(k (lambda (v* k1)
|
||||||
|
(if (<= arity+1 (activation-rec-length v*))
|
||||||
|
(begin (listify! v* arity)
|
||||||
|
(*env* (sr-extend* sr v*))
|
||||||
|
(m+ k1))
|
||||||
|
(error "Incorrect arity"))))))))
|
||||||
|
|
||||||
|
(define (listify! v* arity)
|
||||||
|
(let lp ([index (1- (activation-rec-length v*))]
|
||||||
|
[result '()])
|
||||||
|
(if (= arity index)
|
||||||
|
(activation-rec-set! v* arity result)
|
||||||
|
(lp (1- index) (cons (activation-rec-ref v* (1- index))
|
||||||
|
result)))))
|
||||||
|
|
||||||
|
;; Tests
|
||||||
|
(test-begin "env-register-interpreter")
|
||||||
|
;; quotation
|
||||||
|
(test-group "meaning-quotation"
|
||||||
|
(test-eq 'apple
|
||||||
|
((meaning-quotation 'apple) identity))
|
||||||
|
(test-eq '(apple pear)
|
||||||
|
((meaning-quotation '(apple pear)) identity)))
|
||||||
|
;; alternatives
|
||||||
|
(test-group "meaning-alternative"
|
||||||
|
(with-fresh-globals
|
||||||
|
(env-set! '((#t apple pear)))
|
||||||
|
(test-eq 'apple
|
||||||
|
((meaning-alternative 'p 't 'f '((p t f)) #t) identity))
|
||||||
|
(env-set! '((#f apple pear)))
|
||||||
|
(test-eq 'pear
|
||||||
|
((meaning-alternative 'p 't 'f '((p t f)) #t) identity))))
|
||||||
|
;; sequences
|
||||||
|
(test-group "meaning-sequence"
|
||||||
|
(with-fresh-globals
|
||||||
|
(env-set! '((a b)))
|
||||||
|
(test-eq 'b
|
||||||
|
((meaning-sequence '(a b) '((a b)) #t) identity))))
|
||||||
|
;; references
|
||||||
|
(test-group "meaning-reference"
|
||||||
|
(with-fresh-globals
|
||||||
|
(g.current-extend! 'a)
|
||||||
|
(vector-set! sg.current 0 10)
|
||||||
|
(g.init-extend! 'b)
|
||||||
|
(vector-set! sg.init 0 20)
|
||||||
|
(env-set! '((0 1)))
|
||||||
|
(test-eq 1
|
||||||
|
((meaning-reference 'b '((a b))) identity))
|
||||||
|
(env-set! '((0 1) (2)))
|
||||||
|
(test-eq 0
|
||||||
|
((meaning-reference 'b '((a) (b c))) identity))
|
||||||
|
(test-equal 10
|
||||||
|
((meaning-reference 'a '()) identity))
|
||||||
|
(test-equal 20
|
||||||
|
((meaning-reference 'b '()) identity))))
|
||||||
|
;; applications
|
||||||
|
(test-group "meaning-application"
|
||||||
|
(with-fresh-globals
|
||||||
|
(desc.init `((+ function ,+ . (x y))))
|
||||||
|
(define (*-abstraction v* k)
|
||||||
|
(k (* (activation-rec-ref v* 0 0)
|
||||||
|
(activation-rec-ref v* 0 1))))
|
||||||
|
(env-set! `((,*-abstraction)))
|
||||||
|
(test-eq 9
|
||||||
|
((meaning-regular-application '* '(3 3) '((*)) #t) identity))
|
||||||
|
(test-eq 2
|
||||||
|
((meaning-primitive-application '+ '(1 1) '(())) identity))
|
||||||
|
(test-eq 2 ((meaning-closed-application '(lambda (x) x) '(2) '(()) #t) identity))
|
||||||
|
(test-equal '(2 3) ((meaning-closed-application '(lambda (x . y) y) '(1 2 3) '(()) #t) identity))))
|
||||||
|
;; assignment
|
||||||
|
(test-group "meaning-assignment"
|
||||||
|
(with-fresh-globals
|
||||||
|
(*env* (list->activation-rec '((1))))
|
||||||
|
((meaning-assignment 'apples 2 '((apples))) identity)
|
||||||
|
(test-eq 2
|
||||||
|
(activation-rec-ref (*env*) 0 0))))
|
||||||
|
;; abstraction
|
||||||
|
(test-group "meaning-abstraction"
|
||||||
|
(with-fresh-globals
|
||||||
|
(test-assert (procedure? ((meaning-abstraction '(x) '(x) '(())) identity)))
|
||||||
|
(*env* (sr-extend* (*env*) (make-activation-record #f (vector 1 2 undefined-value))))
|
||||||
|
(define (call-with-1-2 f)
|
||||||
|
(f (make-activation-record #f (vector 1 2 undefined-value)) identity))
|
||||||
|
(test-eq 2
|
||||||
|
((meaning-abstraction '(x y) '(y) '(())) call-with-1-2))
|
||||||
|
(test-equal '(2)
|
||||||
|
((meaning-abstraction '(x . y) '(y) '(())) call-with-1-2))))
|
||||||
|
(test-group "call/cc"
|
||||||
|
(test-eq 3 ((meaning '(+ 2 (call/cc (lambda (cc) (cc 1) 2))) '(()) #t) identity))
|
||||||
|
(test-eq 5 ((meaning '((lambda (cont v)
|
||||||
|
(set! v (+ 2 (call/cc (lambda (cc) (set! cont cc) 1))))
|
||||||
|
(if (= v 3)
|
||||||
|
(cont v)
|
||||||
|
v)) #f 0)
|
||||||
|
'(()) #t)
|
||||||
|
identity)))
|
||||||
|
(test-end "env-register-interpreter")
|
||||||
Reference in New Issue
Block a user