123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678 |
- (define exit (lambda () (builtin exit)))
- (define gensym (lambda (x) (builtin gensym x)))
- (define display (lambda (x) (builtin display x)))
- (define newline (lambda () (builtin newline)))
- ;(define print (lambda (x) (builtin print x)))
- (define eq? (lambda (x y) (builtin eq? x y)))
- ;(define equal? (lambda (x y) (builtin equal? x y)))
- (define cons (lambda (x y) (builtin cons x y)))
- (define car (lambda (x) (builtin car x)))
- (define cdr (lambda (x) (builtin cdr x)))
- (define set-car! (lambda (x y) (builtin set-car! x y)))
- (define set-cdr! (lambda (x y) (builtin set-cdr! x y)))
- (define null? (lambda (x) (builtin null? x)))
- (define pair? (lambda (x) (builtin pair? x)))
- (define number? (lambda (x) (builtin number? x)))
- (define boolean? (lambda (x) (builtin boolean? x)))
- (define string? (lambda (x) (builtin string? x)))
- (define char? (lambda (x) (builtin char? x)))
- (define symbol? (lambda (x) (builtin symbol? x)))
- (define + (lambda (x y) (builtin + x y)))
- (define - (lambda (x y) (builtin - x y)))
- (define * (lambda (x y) (builtin * x y)))
- (define = (lambda (x y) (builtin = x y)))
- (define < (lambda (x y) (builtin < x y)))
- (define > (lambda (x y) (builtin > x y)))
- (define <= (lambda (x y) (builtin <= x y)))
- (define >= (lambda (x y) (builtin >= x y)))
- (define quotient (lambda (x y) (builtin quotient x y)))
- (define modulo (lambda (x y) (builtin modulo x y)))
- ;(define box (lambda (x) (builtin box x)))
- ;(define unbox (lambda (x) (builtin unbox x)))
- ;(define set-box! (lambda (x y) (builtin set-box! x y)))
- (define vector-ref (lambda (v i) (builtin vector-ref v i)))
- (define vector-set! (lambda (v i e) (builtin vector-set! v i e)))
- (define make-vector (lambda (l d) (builtin make-vector l d)))
- (define vector-length (lambda (v) (builtin vector-length v)))
- ;(define string->list (lambda (s) (builtin string->list s)))
- ;(define symbol->string (lambda (s) (builtin symbol->string s)))
- ;(define list->string (lambda (s) (builtin list->string s)))
- (define make-string (lambda (siz ch) (builtin make-string siz ch)))
- (define string-set! (lambda (s i chr) (builtin string-set! s i chr)))
- (define string-ref (lambda (s i) (builtin string-ref s i)))
- (define string->symbol (lambda (s) (builtin string->symbol s)))
- (define string-length (lambda (s) (builtin string-length s)))
- (define string=? (lambda (s t) (builtin string=? s t)))
- ;(define string->number (lambda (s) (builtin string->number s)))
- (define eof-object? (lambda (s) (builtin eof-object? s)))
- (define read-char (lambda () (builtin read-char)))
- (define peek-char (lambda () (builtin peek-char)))
- (define vector? (lambda (x) (builtin vector? x)))
- (define symbol->string (lambda (x) (builtin symbol->string x)))
- (define char->integer (lambda (x) (builtin char->integer x)))
- (define (caar x) (car (car x)))
- (define (cadr x) (car (cdr x)))
- (define (cdar x) (cdr (car x)))
- (define (cddr x) (cdr (cdr x)))
- (define (caaar x) (car (car (car x))))
- (define (caadr x) (car (car (cdr x))))
- (define (cadar x) (car (cdr (car x))))
- (define (caddr x) (car (cdr (cdr x))))
- (define (cdaar x) (cdr (car (car x))))
- (define (cdadr x) (cdr (car (cdr x))))
- (define (cddar x) (cdr (cdr (car x))))
- (define (cdddr x) (cdr (cdr (cdr x))))
- (define (cadddr x) (car (cdddr x)))
- (define (equal? x y)
- (if (pair? x)
- (if (pair? y)
- (if (equal? (car x) (car y))
- (equal? (cdr x) (cdr y))
- #f)
- #f)
- (eq? x y)))
- (define (not p) (if p #f #t))
- (define (length l)
- (if (null? l)
- 0
- (+ 1 (length (cdr l)))))
- (define (append x y)
- (if (null? x)
- y
- (cons (car x) (append (cdr x) y))))
- (define (revappend l r)
- (if (null? l)
- r
- (revappend (cdr l) (cons (car l) r))))
- (define (reverse l) (revappend l '()))
- (define (member elt l)
- (if (null? l)
- #f
- (if (eq? elt (car l))
- #t
- (member elt (cdr l)))))
- (define (filter p l)
- (if (null? l)
- '()
- (if (p (car l))
- (cons (car l) (filter p (cdr l)))
- (filter p (cdr l)))))
- (define (zero? n) (= n 0))
- (define (even? n) (= 0 (modulo n 2)))
- (define (odd? n) (not (even? n)))
- (define (list? l)
- (if (null? l)
- #t
- (if (pair? l)
- #t
- #f)))
- (define (for-each proc l)
- (if (null? l)
- #t
- (begin (proc (car l))
- (for-each proc (cdr l)))))
- (define (map f l)
- (if (null? l)
- '()
- (cons (f (car l))
- (map f (cdr l)))))
- (define (concat-map func lst)
- (if (null? lst)
- '()
- (append (func (car lst))
- (concat-map func (cdr lst)))))
- (define (assoc key tbl)
- (if (null? tbl)
- #f
- (if (eq? key (caar tbl))
- (car tbl)
- (assoc key (cdr tbl)))))
- (define (error x y z)
- ; (print x)
- ; (print y)
- ; (print z)
- (builtin exit)
- )
- ;(define (print p) (display p) (newline))
- ;; OR and AND
- (define (list1 y) (cons y '()))
- (define (list2 x y) (cons x (cons y '())))
- (define (list3 x y z) (cons x (cons y (cons z '()))))
- (define (list4 x y z w) (cons x (cons y (cons z (cons w '())))))
- (defmacro or
- (lambda (exp)
- (if (null? (cdr exp))
- ;; (or)
- #f
- (if (null? (cddr exp))
- ;; (or v)
- (cadr exp)
- ;; (or ,v . ,vs)
- (let ((v (cadr exp))
- (vs (cddr exp))
- (tmp (gensym 'or-tmp)))
- (list3 'let (list1 (list2 tmp v))
- (list4 'if tmp
- tmp
- (builtin cons 'or vs))))))))
- (defmacro and
- (lambda (exp)
- (if (null? (cdr exp))
- ;; (and)
- #t
- (if (null? (cddr exp))
- ;; (and v)
- (cadr exp)
- ;; (and ,v . ,vs)
- (let ((v (cadr exp))
- (vs (cddr exp))
- (tmp (gensym 'or-tmp)))
- (list3 'let (list1 (list2 tmp v))
- (list4 'if tmp
- (builtin cons 'and vs)
- #f)))))))
- ;; QUASIQUOTE AND UNQUOTE
- (define (unquote? exp)
- (and (pair? exp)
- (eq? (car exp) 'unquote)))
- (define (datum? x)
- (or (boolean? x)
- (number? x)
- (string? x)
- (char? x)))
- (define (do-qq l)
- (if (or (null? l) (symbol? l))
- (list2 'quote l)
- (if (datum? l)
- l
- (if (unquote? l)
- (cadr l)
- (list3 'cons
- (do-qq (car l))
- (do-qq (cdr l)))))))
- (defmacro quasiquote
- (lambda (exp)
- (do-qq (cadr exp))))
- ;;; COND SHAPE PREDICATES
- ;;; AND EXTRACTORS
- (define (cond/0? exp)
- ;; (cond)
- (and (pair? exp) (eq? 'cond (car exp)) (null? (cdr exp))))
- (define (cond/else? exp)
- ;; (cond (else . <rest>))
- (and (pair? exp) (eq? 'cond (car exp)) (pair? (cdr exp))
- (pair? (cadr exp)) (eq? 'else (car (cadr exp)))))
- (define (cond-get-else exp)
- `(begin . ,(cdr (cadr exp))))
- (define (cond/1? exp)
- ;; (cond (<one>) . <rest>)
- (and (pair? exp) (eq? 'cond (car exp)) (pair? (cdr exp))
- (pair? (cadr exp)) (not (eq? 'else (car (cadr exp))))
- (null? (cdr (cadr exp)))))
- (define (cond-get-1 exp)
- (car (cadr exp)))
- (define (cond/clause? exp)
- ;; (cond (<test> . <rest>) . <rest>)
- (and (pair? exp) (eq? 'cond (car exp)) (pair? (cdr exp))
- (pair? (cadr exp)) (not (eq? 'else (car (cadr exp))))))
- (define (cond/clause-get-test exp)
- (car (cadr exp)))
- (define (cond/clause-get-rest exp)
- `(begin . ,(cdr (cadr exp))))
- (define (cond/=>-clause? exp)
- ;; (cond (<test> => <thunk>) . <rest>)
- (and (pair? exp) (eq? 'cond (car exp)) (pair? (cdr exp))
- (pair? (cadr exp)) (not (eq? 'else (car (cadr exp))))
- (pair? (cdr (cadr exp))) (eq? '=> (cadr (cadr exp)))))
- (define (cond/=>-clause-get-thunk exp)
- (caddr (cadr exp)))
- (define (cond-get-next exp)
- `(cond . ,(cddr exp)))
- (defmacro cond
- (lambda (exp)
- (if (cond/0? exp)
- `(builtin exit) ;; todo void
- (if (cond/else? exp)
- (cond-get-else exp)
- (if (cond/1? exp)
- `(or ,(cond-get-1 exp) ,(cond-get-next exp))
- (if (cond/=>-clause? exp)
- (let ((test (cond/clause-get-test exp))
- (thunk (cond/=>-clause-get-thunk exp))
- (tmp (gensym 'cond-tmp)))
- `(let ((,tmp ,test))
- (if ,tmp
- (,thunk ,tmp)
- ,(cond-get-next exp))))
- (if (cond/clause? exp)
- (let ((test (cond/clause-get-test exp))
- (rest (cond/clause-get-rest exp)))
- `(if ,test
- ,rest
- ,(cond-get-next exp)))
- (builtin exit) ;; bad syntax
- )))))))
- (defmacro when
- (lambda (exp)
- (let ((test (cadr exp))
- (body `(begin . ,(cddr exp))))
- `(if ,test
- ,body
- #f))))
- (defmacro unless
- (lambda (exp)
- (let ((test (cadr exp))
- (body `(begin . ,(cddr exp))))
- `(if ,test
- #f
- ,body))))
- ;; <case> ::= (case <exp> <clause> (else <exp>))
- ;;
- ;; <clause> ::= ((<thing>) <exp>)
- ;; (case foo ((x) 1) ((y) 2) (else 3))
- ;; -->
- ;; let tmp foo
- ;; (if (eq? tmp 'x) 1)
- ;; ...((y) 2) (else 3))
- (define (else-clause? head)
- (and (pair? head)
- (eq? 'else (car head))))
- (define (compile-case t clauses)
- (if (null? clauses)
- '(builtin exit)
- (let ((head (car clauses))
- (rest (cdr clauses)))
- (if (else-clause? head)
- (cadr head)
- (let ((test (caar head))
- (body (cdr head)))
- `(if (eq? ,t ',test)
- (begin . ,body)
- ,(compile-case t rest)))))))
- (defmacro case
- (lambda (exp)
- (let ((discriminant (cadr exp))
- (tmp (gensym 'tmp)))
- `(let ((,tmp ,discriminant))
- ,(compile-case tmp (cddr exp))))))
-
- ; MAGIC> (include "runtime/macro-case.scm")
- ; MAGIC> (case (+ 1 1) ((1) 'one) ((2) 'two) (else 'dunno))
- ; two
- (defmacro vector
- (lambda (exp)
- (let ((l (length (cdr exp)))
- (tmp (gensym "tmp")))
- (letrec ((loop (lambda (i elts)
- (if (null? elts)
- tmp
- `(begin
- (vector-set! ,tmp ,i ,(car elts))
- ,(loop (+ i 1) (cdr elts)))))))
- `(let ((,tmp (make-vector ,l #f)))
- ,(loop 0 (cdr exp)))))))
- (defmacro mapply
- (lambda (exp)
- ;;(mapply f xs arg ...)
- (let ((f (cadr exp))
- (xs (caddr exp))
- (args (cdddr exp))
- (x (gensym "x")))
- `(map (lambda (,x) (,f ,x . ,args)) ,xs))))
- (defmacro list
- (lambda (exp)
- (let loop ((xs (cdr exp)))
- (if (null? xs)
- ''()
- `(cons ,(car xs) ,(loop (cdr xs)))))))
- (define (bind-assocs tmp vars body)
- (if (null? vars)
- body
- `(let ((,(car vars) (cdr (assoc ',(car vars) ,tmp))))
- ,(bind-assocs tmp (cdr vars) body))))
- (defmacro match-assoc
- (lambda (exp)
- (let ((thing (cadr exp))
- (vars (caddr exp))
- (body `(begin . ,(cdddr exp)))
- (tmp (gensym "tmp")))
- `(let ((,tmp ,thing))
- ,(bind-assocs tmp vars body)))))
- (define (assoc-replace tbl key val)
- (if (null? tbl)
- (cons (cons key val) '())
- (let ((entry (car tbl)))
- (if (eq? (car entry) key)
- (cons (cons key val) (cdr tbl))
- (cons entry (assoc-replace (cdr tbl) key val))))))
- (define (assoc-update tbl key f default)
- (if (null? tbl)
- (cons (cons key default) '())
- (let ((entry (car tbl)))
- (if (eq? (car entry) key)
- (cons (cons key (f (cdr entry))) (cdr tbl))
- (cons entry (assoc-update (cdr tbl) key f default))))))
- (define (assoc-split table keys k)
- (let loop ((left '()) (right '()) (table table))
- (if (null? table)
- (k left right)
- (let ((entry (car table)))
- (if (member (car entry) keys)
- (loop (cons entry left) right (cdr table))
- (loop left (cons entry right) (cdr table)))))))
- (defmacro transform-assoc
- (lambda (exp)
- (let ((thing (cadr exp))
- (vars (caddr exp))
- (body `(begin . ,(cdddr exp)))
- (tmp (gensym "tmp"))
- (in (gensym "in"))
- (out (gensym "out")))
- `(let ((,tmp ,thing))
- (assoc-split ,tmp ',vars
- (lambda (,in ,out)
- (append (match-assoc ,in ,vars ,body) ,out)))))))
- (define (display-symbol form) (display form))
- (define (display-char ch) (display ch))
- (define (display-chars ch) (for-each display-char ch))
- (define (display-boolean form)
- (if form
- (display-chars '(#\# #\t))
- (display-chars '(#\# #\f))))
- (define (display-int form) (display form))
- (define (vector->list v)
- (let ((l (vector-length v)))
- (let loop ((i 0))
- (if (= i l)
- '()
- (cons (vector-ref v i)
- (loop (+ i 1)))))))
- (define (my-display form)
- (cond ((symbol? form) (display-symbol form))
- ((string? form)
- (display-char #\")
- (display form) ;; TODO escaping
- (display-char #\"))
- ((char? form) (display-char form))
- ((boolean? form) (display-boolean form))
- ((number? form) (display-int form))
- ((null? form) (display-chars '(#\( #\))))
- ((vector? form)
- (display-char #\#)
- (my-display (vector->list form)))
- ((pair? form)
- (display-char #\()
- (let loop ((form form))
- (my-display (car form))
- (cond ((null? (cdr form))
- (display-char #\)))
- ((pair? (cdr form))
- (display-char #\space)
- (loop (cdr form)))
- (else (display-chars '(#\space #\. #\space))
- (my-display (cdr form))
- (display-char #\))))))
- (else
- (display "[????]"))))
- (define (print p) (my-display p) (newline))
- (define (length=? l n)
- ;; tests if a list has a certain length
- ;; failing early if possible
- ;; failing on non-lists
- (let loop ((l l) (n n))
- (cond ((< n 0) #f)
- ((null? l) (= n 0))
- ((pair? l) (loop (cdr l) (- n 1)))
- (else #f))))
- (define (length>=? l n)
- (let loop ((l l) (n n))
- (cond ((< n 0) #f)
- ((= n 0) #t)
- ((null? l) #f)
- ((pair? l) (loop (cdr l) (- n 1)))
- (else #f))))
- (define (extend! b v)
- ;; b is a box containing a mutable list
- ;; v is the element you want added on to the end
- ;; returns the length after extending
- ;;
- (if (null? (unbox b))
- (begin (set-box! b (cons v '())) 1)
- (let loop ((pair (unbox b)) (i 2))
- (if (null? (cdr pair))
- (begin (set-cdr! pair (cons v '())) i)
- (loop (cdr pair) (+ i 1))))))
- (define (index obj lst)
- (let loop ((lst lst) (i 0))
- (if (null? lst)
- #f
- (if (equal? obj (car lst))
- i
- (loop (cdr lst) (+ i 1))))))
- (define (reverse-index obj lst)
- (let loop ((lst (reverse lst)) (i (- (length lst) 1)))
- (if (null? lst)
- #f
- (if (equal? obj (car lst))
- i
- (loop (cdr lst) (- i 1))))))
- (define (copy-list l)
- (if (null? l)
- '()
- (cons (car l) (copy-list (cdr l)))))
- (define map* map)
- (define (vector-for-each proc vec)
- (let ((len (vector-length vec)))
- (let loop ((i 0))
- (unless (= i len)
- (proc (vector-ref vec i))
- (loop (+ i 1))))))
- (define (vector-grow vec extra fill)
- ;; (vector-grow (vector 'a 'b 'c) 2 #f)
- ;; ;=> #(a b c #f #f)
- ;;
- (let ((res (make-vector (+ (vector-length vec) extra) fill)))
- (let ((i (box 0)))
- (vector-for-each
- (lambda (elt)
- (vector-set! res (unbox i) elt)
- (set-box! i (+ (unbox i) 1)))
- vec))
- res))
- (define (vector-append vec-1 vec-2)
- (let ((res (vector-grow vec-1 (vector-length vec-2) #f)))
- (let ((i (box (vector-length vec-1))))
- (vector-for-each
- (lambda (elt)
- (vector-set! res (unbox i) elt)
- (set-box! i (+ (unbox i) 1)))
- vec-2))
- res))
- (define (vector-overlay! vec-1 start vec-2)
- (let ((i (box start)))
- (vector-for-each (lambda (elt)
- (vector-set! vec-1 (unbox i) elt)
- (set-box! i (+ (unbox i) 1)))
- vec-2))
- #t)
- (define (list->vector l)
- (let ((len (length l)))
- (let ((vec (make-vector len #f)))
- (let loop ((i 0) (l l))
- (if (null? l)
- vec
- (begin (vector-set! vec i (car l))
- (loop (+ i 1) (cdr l))))))))
- ; (match <expr>
- ; (<pattern> <expr>)
- ; (<pattern> <expr>)
- ; ...)
- ; pattern ::= number? | symbol? | '<expr> | (<pattern> . <pattern>)
- (define (moo-match e)
- (let ((exp (cadr e))
- (clauses (cddr e))
- (tmp (gensym "tmp")))
- `(let ((,tmp ,exp))
- ,(moo-match-aux tmp clauses))))
- (define (quote? p)
- (and (pair? p) (eq? (car p) 'quote)))
- ; takes: expression to match on, pattern, body, place, failure continuation
- ; returns: code that returns #t if pattern matches and #f if not, and an assoc list of
- ; bindings
- (define (subpattern-match s p)
- (begin ;(print `("in subpatterN" ,s ,p))
- (cond
- ((null? p)
- (cons `((null? ,s))
- '()))
- ((number? p)
- (cons `((number? ,s) (= ,s ,p))
- '()))
- ((symbol? p)
- (cons `(#t)
- `((,p ,s))))
- ((quote? p)
- (cons `((equal? ',(cadr p) ,s))
- '()))
- ((pair? p)
- (let ((l (subpattern-match `(car ,s) (car p)))
- (r (subpattern-match `(cdr ,s) (cdr p))))
- (cons (cons `(pair? ,s) (append (car l) (car r)))
- (append (cdr l) (cdr r)))))
- (else
- (begin
- (print "undefined subpattern")
- (print p))))))
- (define (try t pat body fk)
- (let ((m (subpattern-match t pat)))
- `(if (and . ,(car m))
- ,(if (not (null? (cdr m)))
- `(let ,(cdr m)
- ,body)
- body)
- (,fk))))
-
- (define (moo-match-aux t clauses)
- (if (null? clauses)
- `(error 'match "match fail")
- (let ((pat (caar clauses))
- (body `(begin . ,(cdar clauses)))
- (fk (gensym "fk")))
- `(let ((,fk (lambda ()
- ,(moo-match-aux t (cdr clauses)))))
- ,(try t pat body fk)))))
- (defmacro match moo-match)
- (define (datum? exp) (or (boolean? exp) (number? exp) (char? exp) (string? exp)))
- (define (quote? exp) (and (length=? exp 2) (eq? 'quote (car exp))))
- (define variable? symbol?)
- (define (if? exp) (and (length=? exp 4) (eq? 'if (car exp))))
- (define (begin? exp) (and (pair? exp) (eq? 'begin (car exp))))
- (define (lambda? exp) (and (length>=? exp 3) (eq? 'lambda (car exp))))
- (define (named-let? exp) (and (length>=? exp 4) (eq? 'let (car exp)) (symbol? (cadr exp))))
- (define (let? exp) (and (length>=? exp 3) (eq? 'let (car exp))))
- (define (letrec? exp) (and (length=? exp 3) (eq? 'letrec (car exp))))
- (define (builtin-app? e) (and (pair? e) (eq? 'builtin (car e))))
- (define app? pair?)
- ;; Sequence grammar:
- ;; <s> ::= nil
- ;; | (join <s> <s>)
- ;; | (cat [list of <s>])
- ;; | (elt <element>)
- (define (foldr f z l)
- (if (null? l)
- z
- (f (car l) (foldr f z (cdr l)))))
- (define (sequence->dlist s rest)
- (match s
- ('nil rest)
- (('join x y) (sequence->dlist x (sequence->dlist y rest)))
- (('cat seqs) (foldr sequence->dlist rest seqs))
- (('elt x) (cons x rest))
- (else (error 'sequence->dlist "invalid sequence" s))))
- (define (sequence->list s)
- (sequence->dlist s '()))
- (define (box val) (make-vector 1 val))
- (define (unbox b) (vector-ref b 0))
- (define (set-box! b v) (vector-set! b 0 v))
|