aboutsummaryrefslogtreecommitdiffstats
path: root/csc
diff options
context:
space:
mode:
Diffstat (limited to 'csc')
-rw-r--r--csc/cps-test.csc59
-rw-r--r--csc/cps.csc58
-rw-r--r--csc/ir1.csc2
-rw-r--r--csc/ir2.csc52
-rw-r--r--csc/list-test.csc13
-rw-r--r--csc/list.csc10
6 files changed, 182 insertions, 12 deletions
diff --git a/csc/cps-test.csc b/csc/cps-test.csc
index ea1d177..d51d10c 100644
--- a/csc/cps-test.csc
+++ b/csc/cps-test.csc
@@ -6,6 +6,9 @@
make-constant
make-define-syntax
make-if
+ make-lambda
+ make-lambda-case
+ make-letrec
make-lexical-ref
make-lexical-set
make-library-ref
@@ -15,9 +18,11 @@
make-atom
make-branch
make-call-closure
+ make-closure
make-kargs
make-klabel
make-ktail
+ make-lambda-args
make-update)
(only (csc loop)
loop
@@ -130,3 +135,57 @@
(cons 2 (make-klabel (make-atom (make-constant 2) 1))))
(soup->alist (ir1->ir2 (make-sequence (make-constant 1)
(make-constant 2))))))
+
+
+(test closure
+ (assert-equal soup=?
+ (list
+ (cons 0 (make-klabel
+ (make-closure
+ (list (make-lambda-args 2 #t 3))
+ 1)))
+ (cons 1 (make-ktail))
+ (cons 2 (make-ktail))
+ (cons 3 (make-kargs (list (make-lexical-ref 'a #f)
+ (make-lexical-ref 'b #f)
+ (make-lexical-ref 'c #f))
+ (make-atom (make-constant 5) 2))))
+ (soup->alist (ir1->ir2 (make-lambda
+ (make-lambda-case
+ '(a b)
+ 'c
+ '(#f #f #f)
+ (make-constant 5)
+ #f))))))
+
+
+(test letrec-to-lambda
+ (assert-equal soup=?
+ (list
+ ; God help you when it's time to debug this test.
+ (cons 0 (make-klabel
+ (make-closure
+ (list
+ (make-lambda-args 1 #f 7))
+ 3)))
+ (cons 1 (make-ktail))
+ (cons 2 (make-kargs (list (make-lexical-ref 'generated-symbol #f))
+ (make-call-closure
+ (make-lexical-ref 'generated-symbol #f)
+ (list (make-lexical-ref 'generated-symbol #f))
+ 1)))
+ (cons 3 (make-kargs (list (make-lexical-ref 'generated-symbol #f))
+ (make-atom (make-constant #f) 2)))
+ (cons 4 (make-ktail))
+ (cons 5 (make-klabel
+ (make-atom (make-constant 2) 4)))
+ (cons 6 (make-kargs (list (make-lexical-ref 'generated-symbol #f))
+ (make-update (make-lexical-ref 'a #f) (make-lexical-ref 'generated-symbol #f) 5)))
+ (cons 7 (make-kargs (list (make-lexical-ref 'a #f))
+ (make-atom (make-constant 1) 6))))
+ (soup->alist (ir1->ir2 (make-letrec
+ #t
+ '(a)
+ '(#f)
+ (list (make-constant 1))
+ (make-constant 2))))))
diff --git a/csc/cps.csc b/csc/cps.csc
index 55e7e81..0c85707 100644
--- a/csc/cps.csc
+++ b/csc/cps.csc
@@ -16,6 +16,18 @@
if-consequent
if-test
if?
+ lambda-body
+ lambda-case-alternate
+ lambda-case-arguments
+ lambda-case-body
+ lambda-case-gensyms
+ lambda-case-rest
+ lambda?
+ letrec-expression
+ letrec-gensyms
+ letrec-names
+ letrec-values
+ letrec?
lexical-ref?
lexical-set-expression
lexical-set-ref
@@ -24,8 +36,13 @@
library-define-ref
library-define?
library-ref?
+ make-call
make-constant
+ make-lambda
+ make-lambda-case
make-lexical-ref
+ make-lexical-set
+ make-sequence
sequence-head
sequence-tail
sequence?)
@@ -33,9 +50,11 @@
make-atom
make-branch
make-call-closure
+ make-closure
make-kargs
make-klabel
make-ktail
+ make-lambda-args
make-update)
(only (csc loop)
loop
@@ -105,6 +124,45 @@
(make-klabel
(to-cps (sequence-tail expr) continuation add-continuation)))
add-continuation))
+ ((lambda? expr)
+ (make-closure
+ (loop with tail = (add-continuation (make-ktail))
+ for lambda-case = (lambda-body expr) then (lambda-case-alternate lambda-case)
+ while lambda-case
+ collect (let ((args (lambda-case-arguments lambda-case))
+ (rest (lambda-case-rest lambda-case)))
+ (make-lambda-args
+ (length args)
+ (not (not rest))
+ (add-continuation
+ (make-kargs (map make-lexical-ref
+ (append args (list rest))
+ (lambda-case-gensyms lambda-case))
+ (to-cps (lambda-case-body lambda-case) tail add-continuation))))))
+ continuation))
+ ((letrec? expr)
+ ; We re-write a letrec into a corresponding lambda form.
+ (let ((names (letrec-names expr))
+ (gensyms (letrec-gensyms expr)))
+ (to-cps
+ (make-call
+ (make-lambda
+ (make-lambda-case
+ names
+ #f
+ gensyms
+ (make-sequence
+ (loop for name in names
+ for gensym in gensyms
+ for value in (letrec-values expr)
+ for set = (make-lexical-set (make-lexical-ref name gensym) value)
+ for body = set then (make-sequence body set)
+ finally (return body))
+ (letrec-expression expr))
+ #f))
+ (map (lambda (x) (make-constant #f)) names))
+ continuation
+ add-continuation)))
(else (error "unexpected type in to-cps" expr))))
diff --git a/csc/ir1.csc b/csc/ir1.csc
index cf745c6..26b885b 100644
--- a/csc/ir1.csc
+++ b/csc/ir1.csc
@@ -170,7 +170,7 @@
; body is the name of the clause (??). If the procedure is called with an
; appropriate number of arguments, body is evaluated in tail position.
; Otherwise if there is an alternate, it should be a <lambda-case>
- ; expression, representing the next clause to try. If alternate is nil, an
+ ; expression, representing the next clause to try. If alternate is #f, an
; error is signaled.
(define-record-type <lambda-case>
(make-lambda-case arguments rest gensyms body alternate)
diff --git a/csc/ir2.csc b/csc/ir2.csc
index fc31ce3..1872b65 100644
--- a/csc/ir2.csc
+++ b/csc/ir2.csc
@@ -10,6 +10,9 @@
call-closure-args
call-closure-closure
call-closure?
+ closure-cases
+ closure-continuation
+ closure?
ir2=?
kargs-expression
kargs-refs
@@ -17,12 +20,18 @@
klabel-expression
klabel?
ktail?
+ lambda-args-kargs
+ lambda-args-nargs
+ lambda-args-rest
+ lambda-args?
make-atom
make-branch
make-call-closure
+ make-closure
make-kargs
make-klabel
make-ktail
+ make-lambda-args
make-update
update-atom
update-continuation
@@ -61,6 +70,7 @@
make-lexical-ref
make-lexical-set
make-library-ref)
+ (only (csc list) all)
(only (csc loop)
loop
return))
@@ -128,6 +138,26 @@
(continuation call-closure-continuation))
+ ; One branch of a case-lambda. nargs encodes the number of required
+ ; arguments, and rest is a boolean indicating whether the function takes a
+ ; rest parameter. kargs is a continuation ID pointing to a
+ ; kargs continuation.
+ (define-record-type <lambda-args>
+ (make-lambda-args nargs rest kargs)
+ lambda-args?
+ (nargs lambda-args-nargs)
+ (rest lambda-args-rest)
+ (kargs lambda-args-kargs))
+
+
+ ; A lambda expression.
+ (define-record-type <closure>
+ (make-closure cases continuation)
+ closure?
+ (cases closure-cases)
+ (continuation closure-continuation))
+
+
; CPS continuations.
@@ -171,22 +201,24 @@
(y-args (call-closure-args y)))
(and (ir1=? (call-closure-closure x) (call-closure-closure y))
(= (length x-args) (length y-args))
- (loop for x-arg in (call-closure-args x)
- for y-arg in (call-closure-args y)
- unless (ir1=? x-arg y-arg)
- return #f
- finally (return #t))
+ (all (lambda (x) x) (map ir1=? x-args y-args))
(= (call-closure-continuation x) (call-closure-continuation y)))))
+ ((and (lambda-args? x) (lambda-args? y))
+ (and (= (lambda-args-nargs x) (lambda-args-nargs y))
+ (boolean=? (lambda-args-rest x) (lambda-args-rest y))
+ (= (lambda-args-kargs x) (lambda-args-kargs y))))
+ ((and (closure? x) (closure? y))
+ (let ((x-cases (closure-cases x))
+ (y-cases (closure-cases y)))
+ (and (= (length x-cases) (length y-cases))
+ (all (lambda (x) x) (map ir2=? x-cases y-cases))
+ (= (closure-continuation x) (closure-continuation y)))))
((and (ktail? x) (ktail? y)) #t)
((and (kargs? x) (kargs? y))
(let ((x-refs (kargs-refs x))
(y-refs (kargs-refs y)))
(and (= (length x-refs) (length y-refs))
- (loop for x-ref in x-refs
- for y-ref in y-refs
- unless (ir1=? x-ref y-ref)
- return #f
- finally (return #t))
+ (all (lambda (x) x) (map ir1=? x-refs y-refs))
(ir2=? (kargs-expression x) (kargs-expression y)))))
((and (klabel? x) (klabel? y))
(ir2=? (klabel-expression x) (klabel-expression y)))
diff --git a/csc/list-test.csc b/csc/list-test.csc
index d4c145a..faa90b6 100644
--- a/csc/list-test.csc
+++ b/csc/list-test.csc
@@ -98,5 +98,18 @@
(test unzip-empty
(assert (values= (values '() '()) (unzip '()))))
+
(test unzip-simple
(assert (values= (values '(1 2 3) '(4 5 6)) (unzip '((1 . 4) (2 . 5) (3 . 6))))))
+
+
+(test all-even
+ (assert-equal
+ #t
+ (all (lambda (x) (= 0 (remainder x 2))) '(2 12 8))))
+
+
+(test some-odd
+ (assert-equal
+ #f
+ (all (lambda (x) (= 0 (remainder x 2))) '(2 13 8))))
diff --git a/csc/list.csc b/csc/list.csc
index 95fff04..cc64168 100644
--- a/csc/list.csc
+++ b/csc/list.csc
@@ -1,5 +1,6 @@
(define-library (csc list)
(export
+ all
enumerate
filter
intercalate
@@ -70,4 +71,11 @@
(loop for x in l
collect (car x) into xs
collect (cdr x) into ys
- finally (return (values xs ys))))))
+ finally (return (values xs ys))))
+
+
+ (define (all pred l)
+ (loop for x in l
+ unless (pred x)
+ return #f
+ finally (return #t)))))