correct primitive behavior, call/cc and apply
This commit is contained in:
@@ -43,12 +43,12 @@
|
||||
(define-initial name
|
||||
(letrec ([arity+1 (+ 0 1)]
|
||||
[behavior
|
||||
(lambda (v* k)
|
||||
(lambda (v* sr)
|
||||
(if (= (activation-rec-length v*) arity+1)
|
||||
(k (value))
|
||||
(value)
|
||||
(error "Incorrect arity" 'name)))])
|
||||
(description-extend! 'name `(function ,value))
|
||||
behavior)))
|
||||
(make-closure behavior (*env*)))))
|
||||
(define-syntax-rule (define-primitive1 name value)
|
||||
(define-initial name
|
||||
(letrec ([arity+1 (+ 1 1)]
|
||||
@@ -58,30 +58,30 @@
|
||||
(k (value (activation-rec-ref v* 0)))
|
||||
(error "Incorrect arity" 'name)))])
|
||||
(description-extend! 'name `(function ,value a))
|
||||
behavior)))
|
||||
(make-closure behavior (*env*)))))
|
||||
(define-syntax-rule (define-primitive2 name value)
|
||||
(define-initial name
|
||||
(letrec ([arity+1 (+ 2 1)]
|
||||
[behavior
|
||||
(lambda (v* k)
|
||||
(lambda (v* sr)
|
||||
(if (= (activation-rec-length v*) arity+1)
|
||||
(k (value (activation-rec-ref v* 0)
|
||||
(activation-rec-ref v* 1)))
|
||||
(value (activation-rec-ref v* 0)
|
||||
(activation-rec-ref v* 1))
|
||||
(error "Incorrect arity" 'name)))])
|
||||
(description-extend! 'name `(function ,value a b))
|
||||
behavior)))
|
||||
(make-closure behavior (*env*)))))
|
||||
(define-syntax-rule (define-primitive3 name value)
|
||||
(define-initial name
|
||||
(letrec ([arity+1 (+ 3 1)]
|
||||
[behavior
|
||||
(lambda (v* k)
|
||||
(lambda (v* sr)
|
||||
(if (= (activation-rec-length v*) arity+1)
|
||||
(k (value (activation-rec-ref v* 0)
|
||||
(value (activation-rec-ref v* 0)
|
||||
(activation-rec-ref v* 1)
|
||||
(activation-rec-ref v* 2)))
|
||||
(activation-rec-ref v* 2))
|
||||
(error "Incorrect arity" 'name)))])
|
||||
(description-extend! 'name `(function ,value a b c))
|
||||
behavior)))
|
||||
(make-closure behavior (*env*)))))
|
||||
|
||||
|
||||
;; Record types
|
||||
@@ -217,19 +217,45 @@
|
||||
(define-initial call/cc
|
||||
(let* ([arity 1]
|
||||
[arity+1 (1+ arity)])
|
||||
(lambda (v* k)
|
||||
(make-closure
|
||||
(lambda (v* sr)
|
||||
(if (= arity+1 (activation-rec-length v*))
|
||||
((activation-rec-ref v* 0)
|
||||
(call/cc ;; call/cc is "magic" for our purposes here,
|
||||
;; there are no reified continuations in the denotation
|
||||
(lambda (k)
|
||||
(invoke
|
||||
(activation-rec-ref v* 0)
|
||||
(let ([rec (make-activation-rec (+ 1 1))])
|
||||
(activation-rec-set!
|
||||
rec 0
|
||||
(lambda (values kk)
|
||||
(make-closure
|
||||
(lambda (values r)
|
||||
(if (= arity+1 (activation-rec-length values))
|
||||
(k (activation-rec-ref values 0))
|
||||
(error "incorrect arity" 'continuation))))
|
||||
rec)
|
||||
k)
|
||||
(error "incorrect arity" 'call/cc)))))
|
||||
(error "Incorrect arity" 'continuation)))
|
||||
(*env*)))
|
||||
rec))))
|
||||
(error "Incorrect arity" 'call/cc)))
|
||||
(*env*))))
|
||||
(define-initial apply
|
||||
(make-closure
|
||||
(lambda (v* sr)
|
||||
(if (>= (activation-rec-length v*) 3)
|
||||
(let* ([proc (activation-rec-ref v* 0)]
|
||||
[last-arg-index (- (activation-rec-length v*) 2)]
|
||||
[last-arg (activation-rec-ref v* last-arg-index)]
|
||||
[size (+ last-arg-index (length last-arg))]
|
||||
[rec (make-activation-rec size)])
|
||||
(do ([i 1 (+ i 1)])
|
||||
((= i last-arg-index))
|
||||
(activation-rec-set! rec (- i 1) (activation-rec-ref v* i)))
|
||||
(do ([i (- last-arg-index 1) (+ i 1)]
|
||||
[last-arg last-arg (cdr last-arg)])
|
||||
((null? last-arg))
|
||||
(activation-rec-set! rec i (car last-arg)))
|
||||
(invoke proc rec))
|
||||
(error "Wrong arity" 'apply)))
|
||||
(*env*)))
|
||||
|
||||
|
||||
;; Denotations
|
||||
@@ -239,7 +265,7 @@
|
||||
[(? (negate pair?))
|
||||
(if (symbol? e) (meaning-reference e r)
|
||||
(meaning-quotation e))]
|
||||
[('quote e* ...) (meaning-quotation e*)]
|
||||
[('quote e* ...) (meaning-quotation (car 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?)]
|
||||
@@ -248,6 +274,7 @@
|
||||
|
||||
(define (meaning-quotation e*)
|
||||
(CONSTANT e*))
|
||||
|
||||
(define (CONSTANT value)
|
||||
(lambda () value))
|
||||
|
||||
@@ -604,13 +631,15 @@
|
||||
(call-with-1-2 ((meaning-abstraction '(x y) '(y) '(())))))
|
||||
(test-equal '(2)
|
||||
(call-with-1-2 ((meaning-abstraction '(x . y) '(y) '(())))))))
|
||||
;; (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-group "call/cc"
|
||||
(test-eq 3 ((meaning '(+ 2 (call/cc (lambda (cc) (cc 1) 2))) '(()) #t)))
|
||||
(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))))
|
||||
#;(test-group "apply"
|
||||
(test-eq 3 ((meaning '(apply + 1 2 '()) '(()) #t)))
|
||||
(test-eq 3 ((meaning '(apply + '(1 2)) '(()) #t))))
|
||||
(test-end "direct-style-interpreter")
|
||||
|
||||
Reference in New Issue
Block a user