rewriting some primitives to take advantage of the full language; they

do not need to be written in terms of the base language any more
moving handling of internal define and multiple-body-lambda to the
  compiler where it belongs. macroexpand now only handles syntax.
This commit is contained in:
JeffBezanson 2009-07-18 02:16:18 +00:00
parent 2c304edf42
commit 642d1e1bd4
5 changed files with 111 additions and 89 deletions

View File

@ -1,6 +1,8 @@
; definitions of standard scheme procedures in terms of ; definitions of standard scheme procedures in terms of
; femtolisp procedures ; femtolisp procedures
(define top-level-bound? bound?)
(define vector-ref aref) (define vector-ref aref)
(define vector-set! aset!) (define vector-set! aset!)
(define vector-length length) (define vector-length length)

View File

@ -418,6 +418,12 @@
(else (emit g b)))) (else (emit g b))))
(emit g (if tail? :tcall :call) nargs))))))) (emit g (if tail? :tcall :call) nargs)))))))
(define (expand-define form body)
(if (symbol? form)
`(set! ,form ,(car body))
`(set! ,(car form)
(lambda ,(cdr form) ,@body . ,(car form)))))
(define (fits-i8 x) (and (fixnum? x) (>= x -128) (<= x 127))) (define (fits-i8 x) (and (fixnum? x) (>= x -128) (<= x 127)))
(define (compile-in g env tail? x) (define (compile-in g env tail? x)
@ -449,6 +455,8 @@
(emit g :ret)) (emit g :ret))
(set! (compile-in g env #f (caddr x)) (set! (compile-in g env #f (caddr x))
(compile-sym g env (cadr x) [:seta :setc :setg])) (compile-sym g env (cadr x) [:seta :setc :setg]))
(define (compile-in g env tail?
(expand-define (cadr x) (cddr x))))
(trycatch (compile-in g env #f `(lambda () ,(cadr x))) (trycatch (compile-in g env #f `(lambda () ,(cadr x)))
(unless (1arg-lambda? (caddr x)) (unless (1arg-lambda? (caddr x))
(error "trycatch: second form must be a 1-argument lambda")) (error "trycatch: second form must be a 1-argument lambda"))
@ -461,25 +469,67 @@
(apply compile-f- env f let?) (apply compile-f- env f let?)
ff)) ff))
(define (compile-f- env f . let?) (define get-defined-vars
(let ((g (make-code-emitter)) (letrec ((get-defined-vars-
(args (cadr f))) (lambda (expr)
(cond ((not (null? let?)) (emit g :let)) (cond ((atom? expr) ())
((length> args MAX_ARGS) (emit g (if (null? (lastcdr args)) ((and (eq? (car expr) 'define)
:largc :lvargc) (pair? (cdr expr)))
(length args))) (or (and (symbol? (cadr expr))
((null? (lastcdr args)) (emit g :argc (length args))) (list (cadr expr)))
(else (emit g :vargc (if (atom? args) 0 (length args))))) (and (pair? (cadr expr))
(compile-in g (cons (to-proper args) env) #t (caddr f)) (symbol? (caadr expr))
(emit g :ret) (list (caadr expr)))
(values (function (encode-byte-code (bcode:code g)) ()))
(const-to-idx-vec g) (lastcdr f)) ((eq? (car expr) 'begin)
(aref g 3)))) (apply append (map get-defined-vars- (cdr expr))))
(else ())))))
(lambda (expr) (delete-duplicates (get-defined-vars- expr)))))
(define compile-f-
(let ((*defines-processed-token* (gensym)))
; to eval a top-level expression we need to avoid internal define
(set-top-level-value!
'compile-thunk
(lambda (expr)
(compile `(lambda () ,expr . ,*defines-processed-token*))))
(lambda (env f . let?)
; convert lambda to one body expression and process internal defines
(define (lambda-body e)
(let ((B (if (pair? (cddr e))
(if (pair? (cdddr e))
(cons 'begin (cddr e))
(caddr e))
#f)))
(let ((V (get-defined-vars B)))
(if (null? V)
B
(cons (list* 'lambda V B *defines-processed-token*)
(map (lambda (x) #f) V))))))
(let ((g (make-code-emitter))
(args (cadr f))
(name (if (eq? (lastcdr f) *defines-processed-token*)
'lambda
(lastcdr f))))
(cond ((not (null? let?)) (emit g :let))
((length> args MAX_ARGS) (emit g (if (null? (lastcdr args))
:largc :lvargc)
(length args)))
((null? (lastcdr args)) (emit g :argc (length args)))
(else (emit g :vargc (if (atom? args) 0 (length args)))))
(compile-in g (cons (to-proper args) env) #t
(if (eq? (lastcdr f) *defines-processed-token*)
(caddr f)
(lambda-body f)))
(emit g :ret)
(values (function (encode-byte-code (bcode:code g))
(const-to-idx-vec g) name)
(aref g 3))))))
(define (compile f) (compile-f () f)) (define (compile f) (compile-f () f))
(define (compile-thunk expr) (compile `(lambda () ,expr)))
(define (ref-int32-LE a i) (define (ref-int32-LE a i)
(int32 (+ (ash (aref a (+ i 0)) 0) (int32 (+ (ash (aref a (+ i 0)) 0)
(ash (aref a (+ i 1)) 8) (ash (aref a (+ i 1)) 8)

File diff suppressed because one or more lines are too long

View File

@ -3,26 +3,18 @@
; by Jeff Bezanson (C) 2009 ; by Jeff Bezanson (C) 2009
; Distributed under the BSD License ; Distributed under the BSD License
(set! *syntax-environment* (table)) (if (not (bound? '*syntax-environment*))
(define *syntax-environment* (table)))
(set! set-syntax!
(lambda (s v) (put! *syntax-environment* s v)))
(set-syntax! 'define-macro
(lambda (form . body)
(list 'set-syntax! (list 'quote (car form))
(cons 'lambda (cons (cdr form) body)))))
(define-macro (define form . body)
(if (symbol? form)
(list 'set! form (car body))
(list 'set! (car form)
(list* 'lambda (cdr form) (append body (car form))))))
(define (set-syntax! s v) (put! *syntax-environment* s v))
(define (symbol-syntax s) (get *syntax-environment* s #f)) (define (symbol-syntax s) (get *syntax-environment* s #f))
(define-macro (define-macro form . body)
`(set-syntax! ',(car form)
(lambda ,(cdr form) ,@body)))
(define-macro (label name fn) (define-macro (label name fn)
(list (list 'lambda (list name) (list 'set! name fn)) #f)) `((lambda (,name) (set! ,name ,fn)) #f))
(define (map f lst . lsts) (define (map f lst . lsts)
(define (map1 f lst acc) (define (map1 f lst acc)
@ -42,28 +34,27 @@
(mapn f (cons lst lsts)))) (mapn f (cons lst lsts))))
(define-macro (let binds . body) (define-macro (let binds . body)
((lambda (lname) (let (lname)
(begin (if (symbol? binds)
(if (symbol? binds) (begin (set! lname binds)
(begin (set! lname binds) (set! binds (car body))
(set! binds (car body)) (set! body (cdr body))))
(set! body (cdr body)))) (let ((thelambda
((lambda (thelambda theargs) `(lambda ,(map (lambda (c) (if (pair? c) (car c) c))
(cons (if lname binds)
(list 'label lname thelambda) ,@body))
thelambda) (theargs
theargs)) (map (lambda (c) (if (pair? c) (cadr c) #f)) binds)))
(cons 'lambda (cons (if lname
(cons (map (lambda (c) (if (pair? c) (car c) c)) binds) `(label ,lname ,thelambda)
body)) thelambda)
(map (lambda (c) (if (pair? c) (cadr c) #f)) binds)))) theargs))))
#f))
(define-macro (letrec binds . body) (define-macro (letrec binds . body)
(cons (cons 'lambda (cons (map car binds) `((lambda ,(map car binds)
(nconc (map (lambda (b) (cons 'set! b)) binds) ,.(map (lambda (b) `(set! ,@b)) binds)
body))) ,@body)
(map (lambda (x) #f) binds))) ,.(map (lambda (x) #f) binds)))
(define-macro (cond . clauses) (define-macro (cond . clauses)
(define (cond-clauses->if lst) (define (cond-clauses->if lst)
@ -390,7 +381,7 @@
(else `(memv ,key ',v)))) (else `(memv ,key ',v))))
(let ((g (gensym))) (let ((g (gensym)))
`(let ((,g ,key)) `(let ((,g ,key))
(cond ,@(map (lambda (clause) (cond ,.(map (lambda (clause)
(cons (vals->cond g (car clause)) (cons (vals->cond g (car clause))
(cdr clause))) (cdr clause)))
clauses))))) clauses)))))
@ -411,8 +402,8 @@
,@(cdr test-spec)) ,@(cdr test-spec))
(begin (begin
,@commands ,@commands
(,loop ,@steps)))))) (,loop ,.steps))))))
(,loop ,@inits)))) (,loop ,.inits))))
; SRFI 8 ; SRFI 8
(define-macro (receive formals expr . body) (define-macro (receive formals expr . body)
@ -618,23 +609,6 @@
; toplevel -------------------------------------------------------------------- ; toplevel --------------------------------------------------------------------
(define get-defined-vars
(letrec ((get-defined-vars-
(lambda (expr)
(cond ((atom? expr) ())
((and (eq? (car expr) 'define)
(pair? (cdr expr)))
(or (and (symbol? (cadr expr))
(list (cadr expr)))
(and (pair? (cadr expr))
(symbol? (caadr expr))
(list (caadr expr)))
()))
((eq? (car expr) 'begin)
(apply append (map get-defined-vars- (cdr expr))))
(else ())))))
(lambda (expr) (delete-duplicates (get-defined-vars- expr)))))
(define (macrocall? e) (and (symbol? (car e)) (define (macrocall? e) (and (symbol? (car e))
(get *syntax-environment* (car e) #f))) (get *syntax-environment* (car e) #f)))
@ -645,21 +619,6 @@
e)))) e))))
(define (macroexpand e) (define (macroexpand e)
(define (expand-lambda e env)
(let ((B (if (pair? (cddr e))
(if (pair? (cdddr e))
(cons 'begin (cddr e))
(caddr e))
#f)))
(let ((V (get-defined-vars B))
(Be (macroexpand-in B env)))
(list* 'lambda
(cadr e)
(if (null? V)
Be
(cons (list 'lambda V Be)
(map (lambda (x) #f) V)))
(lastcdr e)))))
(define (macroexpand-in e env) (define (macroexpand-in e env)
(if (atom? e) e (if (atom? e) e
(let ((f (assq (car e) env))) (let ((f (assq (car e) env)))
@ -669,7 +628,15 @@
(if f (if f
(macroexpand-in (apply f (cdr e)) env) (macroexpand-in (apply f (cdr e)) env)
(cond ((eq (car e) 'quote) e) (cond ((eq (car e) 'quote) e)
((eq (car e) 'lambda) (expand-lambda e env)) ((eq (car e) 'lambda)
`(lambda ,(cadr e)
,.(map (lambda (x) (macroexpand-in x env))
(cddr e))
. ,(lastcdr e)))
((eq (car e) 'define)
`(define ,(cadr e)
,.(map (lambda (x) (macroexpand-in x env))
(cddr e))))
((eq (car e) 'let-syntax) ((eq (car e) 'let-syntax)
(let ((binds (cadr e)) (let ((binds (cadr e))
(body `((lambda () ,@(cddr e))))) (body `((lambda () ,@(cddr e)))))

View File

@ -159,6 +159,7 @@ bugs:
. write a function to evaluate directly from list to list, use it for . write a function to evaluate directly from list to list, use it for
Nth arg and for user function rest args Nth arg and for user function rest args
. modify vararg builtins accordingly . modify vararg builtins accordingly
- filter should be stable. right now it reverses.
femtoLisp3...with symbolic C interface femtoLisp3...with symbolic C interface
@ -1040,6 +1041,8 @@ new evaluator todo:
* maxstack calculation, make Stack growable * maxstack calculation, make Stack growable
* stack traces and better debugging support * stack traces and better debugging support
- make maxstack calculation robust against invalid bytecode - make maxstack calculation robust against invalid bytecode
* improve internal define
- try removing MAX_ARGS trickery
- let eversion - let eversion
* lambda lifting * lambda lifting
* let optimization * let optimization