changing optional args to allow default values to be computed from

preceding arguments
tidying some stuff with keywords
This commit is contained in:
JeffBezanson 2009-07-28 04:16:20 +00:00
parent eceeddf6d2
commit ecfd81148f
9 changed files with 285 additions and 214 deletions

View File

@ -135,8 +135,7 @@ static value_t fl_keywordp(value_t *args, u_int32_t nargs)
{
argcount("keyword?", nargs, 1);
symbol_t *sym = tosymbol(args[0], "keyword?");
char *str = sym->name;
return fl_is_keyword_name(str, strlen(str)) ? FL_T : FL_F;
return iskeyword(sym) ? FL_T : FL_F;
}
static value_t fl_top_level_value(value_t *args, u_int32_t nargs)
@ -152,7 +151,7 @@ static value_t fl_set_top_level_value(value_t *args, u_int32_t nargs)
{
argcount("set-top-level-value!", nargs, 2);
symbol_t *sym = tosymbol(args[0], "set-top-level-value!");
if (!sym->isconst)
if (!isconstant(sym))
sym->binding = args[1];
return args[1];
}
@ -187,7 +186,7 @@ static value_t fl_constantp(value_t *args, u_int32_t nargs)
{
argcount("constant?", nargs, 1);
if (issymbol(args[0]))
return (isconstant(args[0]) ? FL_T : FL_F);
return (isconstant((symbol_t*)ptr(args[0])) ? FL_T : FL_F);
if (iscons(args[0])) {
if (car_(args[0]) == QUOTE)
return FL_T;

View File

@ -3,30 +3,30 @@
(define Instructions
(let ((e (table))
(keys
[:nop :dup :pop :call :tcall :jmp :brf :brt :jmp.l :brf.l :brt.l :ret
[nop dup pop call tcall jmp brf brt jmp.l brf.l brt.l ret
:eq? :eqv? :equal? :atom? :not :null? :boolean? :symbol?
:number? :bound? :pair? :builtin? :vector? :fixnum? :function?
eq? eqv? equal? atom? not null? boolean? symbol?
number? bound? pair? builtin? vector? fixnum? function?
:cons :list :car :cdr :set-car! :set-cdr!
:apply
cons list car cdr set-car! set-cdr!
apply
:+ :- :* :/ :div0 := :< :compare
+ - * / div0 = < compare
:vector :aref :aset!
vector aref aset!
:loadt :loadf :loadnil :load0 :load1 :loadi8
:loadv :loadv.l
:loadg :loadg.l
:loada :loada.l :loadc :loadc.l
:setg :setg.l
:seta :seta.l :setc :setc.l
loadt loadf loadnil load0 load1 loadi8
loadv loadv.l
loadg loadg.l
loada loada.l loadc loadc.l
setg setg.l
seta seta.l setc setc.l
:closure :argc :vargc :trycatch :copyenv :let :for :tapply
:add2 :sub2 :neg :largc :lvargc
:loada0 :loada1 :loadc00 :loadc01 :call.l :tcall.l
:brne :brne.l :cadr :brnn :brnn.l :brn :brn.l
:optargs
closure argc vargc trycatch copyenv let for tapply
add2 sub2 neg largc lvargc
loada0 loada1 loadc00 loadc01 call.l tcall.l
brne brne.l cadr brnn brnn.l brn brn.l
optargs brbound
dummy_t dummy_f dummy_nil]))
(for 0 (1- (length keys))
@ -34,19 +34,19 @@
(put! e (aref keys i) i)))))
(define arg-counts
(table :eq? 2 :eqv? 2
:equal? 2 :atom? 1
:not 1 :null? 1
:boolean? 1 :symbol? 1
:number? 1 :bound? 1
:pair? 1 :builtin? 1
:vector? 1 :fixnum? 1
:cons 2 :car 1
:cdr 1 :set-car! 2
:set-cdr! 2 := 2
:< 2 :compare 2
:aref 2 :aset! 3
:div0 2))
(table eq? 2 eqv? 2
equal? 2 atom? 1
not 1 null? 1
boolean? 1 symbol? 1
number? 1 bound? 1
pair? 1 builtin? 1
vector? 1 fixnum? 1
cons 2 car 1
cdr 1 set-car! 2
set-cdr! 2 = 2
< 2 compare 2
aref 2 aset! 3
div0 2))
(define (make-code-emitter) (vector () (table) 0 +inf.0))
(define (bcode:code b) (aref b 0))
@ -64,60 +64,60 @@
(aset! b 2 (+ nconst 1)))))))
(define (emit e inst . args)
(if (null? args)
(if (and (eq? inst :car) (pair? (aref e 0))
(eq? (car (aref e 0)) :cdr))
(set-car! (aref e 0) :cadr)
(if (and (eq? inst 'car) (pair? (aref e 0))
(eq? (car (aref e 0)) 'cdr))
(set-car! (aref e 0) 'cadr)
(aset! e 0 (cons inst (aref e 0))))
(begin
(if (memq inst '(:loadv :loadg :setg))
(if (memq inst '(loadv loadg setg))
(set! args (list (bcode:indexfor e (car args)))))
(let ((longform
(assq inst '((:loadv :loadv.l) (:loadg :loadg.l) (:setg :setg.l)
(:loada :loada.l) (:seta :seta.l)))))
(assq inst '((loadv loadv.l) (loadg loadg.l) (setg setg.l)
(loada loada.l) (seta seta.l)))))
(if (and longform
(> (car args) 255))
(set! inst (cadr longform))))
(let ((longform
(assq inst '((:loadc :loadc.l) (:setc :setc.l)))))
(assq inst '((loadc loadc.l) (setc setc.l)))))
(if (and longform
(or (> (car args) 255)
(> (cadr args) 255)))
(set! inst (cadr longform))))
(if (eq? inst :loada)
(if (eq? inst 'loada)
(cond ((equal? args '(0))
(set! inst :loada0)
(set! inst 'loada0)
(set! args ()))
((equal? args '(1))
(set! inst :loada1)
(set! inst 'loada1)
(set! args ()))))
(if (eq? inst :loadc)
(if (eq? inst 'loadc)
(cond ((equal? args '(0 0))
(set! inst :loadc00)
(set! inst 'loadc00)
(set! args ()))
((equal? args '(0 1))
(set! inst :loadc01)
(set! inst 'loadc01)
(set! args ()))))
(let ((lasti (if (pair? (aref e 0))
(car (aref e 0)) ()))
(bc (aref e 0)))
(cond ((and (eq? inst :brf) (eq? lasti :not)
(eq? (cadr bc) :null?))
(aset! e 0 (cons (car args) (cons :brn (cddr bc)))))
((and (eq? inst :brf) (eq? lasti :not))
(aset! e 0 (cons (car args) (cons :brt (cdr bc)))))
((and (eq? inst :brf) (eq? lasti :eq?))
(aset! e 0 (cons (car args) (cons :brne (cdr bc)))))
((and (eq? inst :brf) (eq? lasti :null?))
(aset! e 0 (cons (car args) (cons :brnn (cdr bc)))))
((and (eq? inst :brt) (eq? lasti :null?))
(aset! e 0 (cons (car args) (cons :brn (cdr bc)))))
(cond ((and (eq? inst 'brf) (eq? lasti 'not)
(eq? (cadr bc) 'null?))
(aset! e 0 (cons (car args) (cons 'brn (cddr bc)))))
((and (eq? inst 'brf) (eq? lasti 'not))
(aset! e 0 (cons (car args) (cons 'brt (cdr bc)))))
((and (eq? inst 'brf) (eq? lasti 'eq?))
(aset! e 0 (cons (car args) (cons 'brne (cdr bc)))))
((and (eq? inst 'brf) (eq? lasti 'null?))
(aset! e 0 (cons (car args) (cons 'brnn (cdr bc)))))
((and (eq? inst 'brt) (eq? lasti 'null?))
(aset! e 0 (cons (car args) (cons 'brn (cdr bc)))))
(else
(aset! e 0 (nreconc (cons inst args) bc)))))))
e)
(define (make-label e) (gensym))
(define (mark-label e l) (emit e :label l))
(define (mark-label e l) (emit e 'label l))
; convert symbolic bytecode representation to a byte array.
; labels are fixed-up.
@ -127,13 +127,7 @@
(long? (>= (+ (length v) ; 1 byte for each entry, plus...
; at most half the entries in this vector can be
; instructions accepting 32-bit arguments
(* 3 (div0 (length v) 2))
#;(* 3 (count (lambda (i)
(memq i '(:loadv.l :loadg.l :setg.l
:loada.l :seta.l :loadc.l
:setc.l :jmp :brt :brf
:largc :lvargc)))
cl)))
(* 3 (div0 (length v) 2)))
65536)))
(let ((n (length v))
(i 0)
@ -146,7 +140,7 @@
(while (< i n)
(begin
(set! vi (aref v i))
(if (eq? vi :label)
(if (eq? vi 'label)
(begin (put! label-to-loc (aref v (+ i 1)) (sizeof bcode))
(set! i (+ i 2)))
(begin
@ -155,34 +149,40 @@
(get Instructions
(if long?
(case vi
(:jmp :jmp.l)
(:brt :brt.l)
(:brf :brf.l)
(:brne :brne.l)
(:brnn :brnn.l)
(:brn :brn.l)
(jmp 'jmp.l)
(brt 'brt.l)
(brf 'brf.l)
(brne 'brne.l)
(brnn 'brnn.l)
(brn 'brn.l)
(else vi))
vi))))
(set! i (+ i 1))
(set! nxt (if (< i n) (aref v i) #f))
(cond ((memq vi '(:jmp :brf :brt :brne :brnn :brn))
(cond ((memq vi '(jmp brf brt brne brnn brn))
(put! fixup-to-label (sizeof bcode) nxt)
(io.write bcode ((if long? int32 int16) 0))
(set! i (+ i 1)))
((eq? vi 'brbound)
(io.write bcode (int32 nxt))
(set! i (+ i 1))
(put! fixup-to-label (sizeof bcode) (aref v i))
(io.write bcode (int32 0))
(set! i (+ i 1)))
((number? nxt)
(case vi
((:loadv.l :loadg.l :setg.l :loada.l :seta.l
:largc :lvargc :call.l :tcall.l :optargs)
((loadv.l loadg.l setg.l loada.l seta.l
largc lvargc call.l tcall.l)
(io.write bcode (int32 nxt))
(set! i (+ i 1)))
((:loadc :setc) ; 2 uint8 args
((loadc setc) ; 2 uint8 args
(io.write bcode (uint8 nxt))
(set! i (+ i 1))
(io.write bcode (uint8 (aref v i)))
(set! i (+ i 1)))
((:loadc.l :setc.l) ; 2 int32 args
((loadc.l setc.l optargs) ; 2 int32 args
(io.write bcode (int32 nxt))
(set! i (+ i 1))
(io.write bcode (int32 (aref v i)))
@ -245,7 +245,7 @@
(else
(if (and (constant? s)
(printable? (top-level-value s)))
(emit g :loadv (top-level-value s))
(emit g 'loadv (top-level-value s))
(emit g (aref Is 2) s))))))
(define (compile-if g env tail? x)
@ -262,11 +262,11 @@
(compile-in g env tail? else))
(else
(compile-in g env #f test)
(emit g :brf elsel)
(emit g 'brf elsel)
(compile-in g env tail? then)
(if tail?
(emit g :ret)
(emit g :jmp endl))
(emit g 'ret)
(emit g 'jmp endl))
(mark-label g elsel)
(compile-in g env tail? else)
(mark-label g endl)))))
@ -277,14 +277,14 @@
(compile-in g env tail? (car forms)))
(else
(compile-in g env #f (car forms))
(emit g :pop)
(emit g 'pop)
(compile-begin g env tail? (cdr forms)))))
(define (compile-prog1 g env x)
(compile-in g env #f (cadr x))
(if (pair? (cddr x))
(begin (compile-begin g env #f (cddr x))
(emit g :pop))))
(emit g 'pop))))
(define (compile-while g env cond body)
(let ((top (make-label g))
@ -292,10 +292,10 @@
(compile-in g env #f #f)
(mark-label g top)
(compile-in g env #f cond)
(emit g :brf end)
(emit g :pop)
(emit g 'brf end)
(emit g 'pop)
(compile-in g env #f body)
(emit g :jmp top)
(emit g 'jmp top)
(mark-label g end)))
(define (1arg-lambda? func)
@ -310,7 +310,7 @@
(begin (compile-in g env #f lo)
(compile-in g env #f hi)
(compile-in g env #f func)
(emit g :for))
(emit g 'for))
(error "for: third form must be a 1-argument lambda")))
(define (compile-short-circuit g env tail? forms default branch)
@ -319,16 +319,16 @@
(else
(let ((end (make-label g)))
(compile-in g env #f (car forms))
(emit g :dup)
(emit g 'dup)
(emit g branch end)
(emit g :pop)
(emit g 'pop)
(compile-short-circuit g env tail? (cdr forms) default branch)
(mark-label g end)))))
(define (compile-and g env tail? forms)
(compile-short-circuit g env tail? forms #t :brf))
(compile-short-circuit g env tail? forms #t 'brf))
(define (compile-or g env tail? forms)
(compile-short-circuit g env tail? forms #f :brt))
(compile-short-circuit g env tail? forms #f 'brt))
(define (compile-arglist g env lst)
(for-each (lambda (a)
@ -337,10 +337,10 @@
(length lst))
(define (argc-error head count)
(error (string "compile error: " head " expects " count
(if (= count 1)
" argument."
" arguments."))))
(error "compile error: " head " expects " count
(if (= count 1)
" argument."
" arguments.")))
(define (compile-app g env tail? x)
(let ((head (car x)))
@ -356,28 +356,28 @@
(let ((head (car x))
(args (cdr x)))
(unless (length= args (length (cadr head)))
(error (string "apply: incorrect number of arguments to " head)))
(error "apply: incorrect number of arguments to " head))
(receive (the-f dept) (compile-f- env head #t)
(emit g :loadv the-f)
(emit g 'loadv the-f)
(bcode:cdepth g dept))
(let ((nargs (compile-arglist g env args)))
(emit g :copyenv)
(emit g (if tail? :tcall :call) (+ 1 nargs)))))
(emit g 'copyenv)
(emit g (if tail? 'tcall 'call) (+ 1 nargs)))))
(define builtin->instruction
(let ((b2i (table number? :number? cons :cons
fixnum? :fixnum? equal? :equal?
eq? :eq? symbol? :symbol?
div0 :div0 builtin? :builtin?
aset! :aset! - :- boolean? :boolean? not :not
apply :apply atom? :atom?
set-cdr! :set-cdr! / :/
function? :function? vector :vector
list :list bound? :bound?
< :< * :* cdr :cdr null? :null?
+ :+ eqv? :eqv? compare :compare aref :aref
set-car! :set-car! car :car
pair? :pair? = := vector? :vector?)))
(let ((b2i (table number? 'number? cons 'cons
fixnum? 'fixnum? equal? 'equal?
eq? 'eq? symbol? 'symbol?
div0 'div0 builtin? 'builtin?
aset! 'aset! - '- boolean? 'boolean? not 'not
apply 'apply atom? 'atom?
set-cdr! 'set-cdr! / '/
function? 'function? vector 'vector
list 'list bound? 'bound?
< '< * '* cdr 'cdr null? 'null?
+ '+ eqv? 'eqv? compare 'compare aref 'aref
set-car! 'set-car! car 'car
pair? 'pair? = '= vector? 'vector?)))
(lambda (b)
(get b2i b #f))))
@ -387,25 +387,25 @@
(not (length= (cdr x) count)))
(argc-error head count))
(case b ; handle special cases of vararg builtins
(:list (if (= nargs 0) (emit g :loadnil) (emit g b nargs)))
(:+ (cond ((= nargs 0) (emit g :load0))
((= nargs 2) (emit g :add2))
(else (emit g b nargs))))
(:- (cond ((= nargs 0) (argc-error head 1))
((= nargs 1) (emit g :neg))
((= nargs 2) (emit g :sub2))
(else (emit g b nargs))))
(:* (if (= nargs 0) (emit g :load1)
(emit g b nargs)))
(:/ (if (= nargs 0)
(argc-error head 1)
(emit g b nargs)))
(:vector (if (= nargs 0)
(emit g :loadv [])
(emit g b nargs)))
(:apply (if (< nargs 2)
(argc-error head 2)
(emit g (if tail? :tapply :apply) nargs)))
(list (if (= nargs 0) (emit g 'loadnil) (emit g b nargs)))
(+ (cond ((= nargs 0) (emit g 'load0))
((= nargs 2) (emit g 'add2))
(else (emit g b nargs))))
(- (cond ((= nargs 0) (argc-error head 1))
((= nargs 1) (emit g 'neg))
((= nargs 2) (emit g 'sub2))
(else (emit g b nargs))))
(* (if (= nargs 0) (emit g 'load1)
(emit g b nargs)))
(/ (if (= nargs 0)
(argc-error head 1)
(emit g b nargs)))
(vector (if (= nargs 0)
(emit g 'loadv [])
(emit g b nargs)))
(apply (if (< nargs 2)
(argc-error head 2)
(emit g (if tail? 'tapply 'apply) nargs)))
(else (emit g b)))))
(define (compile-call g env tail? x)
@ -422,7 +422,7 @@
; more than 255 arguments, need long versions of instructions
(begin (compile-in g env #f head)
(let ((nargs (compile-arglist g env (cdr x))))
(emit g (if tail? :tcall.l :call.l) nargs)))
(emit g (if tail? 'tcall.l 'call.l) nargs)))
(let ((b (and (builtin? head)
(builtin->instruction head))))
(if (and (eq? head 'cadr)
@ -430,14 +430,14 @@
(equal? (top-level-value 'cadr) cadr)
(length= x 2))
(begin (compile-in g env #f (cadr x))
(emit g :cadr))
(emit g 'cadr))
(begin
(if (not b)
(compile-in g env #f head))
(let ((nargs (compile-arglist g env (cdr x))))
(if b
(compile-builtin-call g env tail? x head b nargs)
(emit g (if tail? :tcall :call) nargs))))))))))
(emit g (if tail? 'tcall 'call) nargs))))))))))
(define (expand-define form body)
(if (symbol? form)
@ -448,41 +448,41 @@
(define (fits-i8 x) (and (fixnum? x) (>= x -128) (<= x 127)))
(define (compile-in g env tail? x)
(cond ((symbol? x) (compile-sym g env x [:loada :loadc :loadg]))
(cond ((symbol? x) (compile-sym g env x [loada loadc loadg]))
((atom? x)
(cond ((eq? x 0) (emit g :load0))
((eq? x 1) (emit g :load1))
((eq? x #t) (emit g :loadt))
((eq? x #f) (emit g :loadf))
((eq? x ()) (emit g :loadnil))
((fits-i8 x) (emit g :loadi8 x))
(else (emit g :loadv x))))
(cond ((eq? x 0) (emit g 'load0))
((eq? x 1) (emit g 'load1))
((eq? x #t) (emit g 'loadt))
((eq? x #f) (emit g 'loadf))
((eq? x ()) (emit g 'loadnil))
((fits-i8 x) (emit g 'loadi8 x))
(else (emit g 'loadv x))))
(else
(case (car x)
(quote (emit g :loadv (cadr x)))
(quote (emit g 'loadv (cadr x)))
(if (compile-if g env tail? x))
(begin (compile-begin g env tail? (cdr x)))
(prog1 (compile-prog1 g env x))
(lambda (receive (the-f dept) (compile-f- env x)
(begin (emit g :loadv the-f)
(begin (emit g 'loadv the-f)
(bcode:cdepth g dept)
(if (< dept (nnn env))
(emit g :closure)))))
(emit g 'closure)))))
(and (compile-and g env tail? (cdr x)))
(or (compile-or g env tail? (cdr x)))
(while (compile-while g env (cadr x) (cons 'begin (cddr x))))
(for (compile-for g env (cadr x) (caddr x) (cadddr x)))
(return (compile-in g env #t (cadr x))
(emit g :ret))
(emit g 'ret))
(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)))
(unless (1arg-lambda? (caddr x))
(error "trycatch: second form must be a 1-argument lambda"))
(compile-in g env #f (caddr x))
(emit g :trycatch))
(emit g 'trycatch))
(else (compile-app g env tail? x))))))
(define (compile-f env f . let?)
@ -516,19 +516,29 @@
(or (symbol? (car l))
(and (pair? (car l))
(or (every pair? (cdr l))
(error (string "compile error: invalid argument list "
o ". optional arguments must come last."))))
(error (string "compile error: invalid formal argument " (car l)
" in list " o)))
(error "compile error: invalid argument list "
o ". optional arguments must come last.")))
(error "compile error: invalid formal argument " (car l)
" in list " o))
(check-formals (cdr l) o))
(if (eq? l o)
(error (string "compile error: invalid argument list " o))
(error (string "compile error: invalid formal argument " l
" in list " o)))))
(error "compile error: invalid argument list " o)
(error "compile error: invalid formal argument " l " in list " o))))
(check-formals l l)
(map (lambda (s) (if (pair? s) (car s) s))
(to-proper l)))
(define (emit-optional-arg-inits g env opta vars i)
; i is the lexical var index of the opt arg to process next
(if (pair? opta)
(let ((nxt (make-label g)))
(emit g 'brbound i nxt)
(compile-in g (cons (list-head vars i) env) #f (cadar opta))
(emit g 'seta i)
(emit g 'pop)
(mark-label g nxt)
(emit-optional-arg-inits g env (cdr opta) vars (+ i 1)))))
(define compile-f-
(let ((*defines-processed-token* (gensym)))
; to eval a top-level expression we need to avoid internal define
@ -553,31 +563,33 @@
(let ((g (make-code-emitter))
(args (cadr f))
(atail (lastcdr (cadr f)))
(vars (lambda-vars (cadr f)))
(opta (filter pair? (cadr f)))
(name (if (eq? (lastcdr f) *defines-processed-token*)
'lambda
(lastcdr f))))
(let ((nargs (if (atom? args) 0 (length args))))
(let* ((nargs (if (atom? args) 0 (length args)))
(nreq (- nargs (length opta))))
; emit argument checking prologue
(if (not (null? opta))
(begin (bcode:indexfor g (list->vector (map cadr opta)))
(emit g :optargs (- nargs (length opta)))))
(begin (emit g 'optargs (if (null? atail) nreq (- nreq)) nargs)
(emit-optional-arg-inits g env opta vars nreq)))
(cond ((not (null? let?)) (emit g :let))
((> nargs 255) (emit g (if (null? (lastcdr args))
:largc :lvargc)
(cond ((not (null? let?)) (emit g 'let))
((> nargs 255) (emit g (if (null? atail)
'largc 'lvargc)
nargs))
((null? (lastcdr args)) (emit g :argc nargs))
(else (emit g :vargc nargs)))
((not (null? atail)) (emit g 'vargc nargs))
((null? opta) (emit g 'argc nargs)))
; compile body and return
(compile-in g (cons vars env) #t
(if (eq? (lastcdr f) *defines-processed-token*)
(caddr f)
(lambda-body f)))
(emit g :ret)
(emit g 'ret)
(values (function (encode-byte-code (bcode:code g))
(const-to-idx-vec g) name)
(aref g 3)))))))
@ -623,43 +635,49 @@
(if (> i 4) (newline))
(dotimes (xx lev) (princ "\t"))
(princ (hex5 (- i 4)) ": "
(string.tail (string inst) 1) "\t")
(string inst) "\t")
(set! i (+ i 1))
(case inst
((:loadv.l :loadg.l :setg.l)
((loadv.l loadg.l setg.l)
(print-val (aref vals (ref-int32-LE code i)))
(set! i (+ i 4)))
((:loadv :loadg :setg)
((loadv loadg setg)
(print-val (aref vals (aref code i)))
(set! i (+ i 1)))
((:loada :seta :call :tcall :list :+ :- :* :/ :vector
:argc :vargc :loadi8 :apply :tapply)
((loada seta call tcall list + - * / vector
argc vargc loadi8 apply tapply)
(princ (number->string (aref code i)))
(set! i (+ i 1)))
((:loada.l :seta.l :largc :lvargc :call.l :tcall.l :optargs)
((loada.l seta.l largc lvargc call.l tcall.l)
(princ (number->string (ref-int32-LE code i)))
(set! i (+ i 4)))
((:loadc :setc)
((loadc setc)
(princ (number->string (aref code i)) " ")
(set! i (+ i 1))
(princ (number->string (aref code i)))
(set! i (+ i 1)))
((:loadc.l :setc.l)
((loadc.l setc.l optargs)
(princ (number->string (ref-int32-LE code i)) " ")
(set! i (+ i 4))
(princ (number->string (ref-int32-LE code i)))
(set! i (+ i 4)))
((:jmp :brf :brt :brne :brnn :brn)
((brbound)
(princ (number->string (ref-int32-LE code i)) " ")
(set! i (+ i 4))
(princ "@" (hex5 (+ i -4 (ref-int32-LE code i))))
(set! i (+ i 4)))
((jmp brf brt brne brnn brn)
(princ "@" (hex5 (+ i -4 (ref-int16-LE code i))))
(set! i (+ i 2)))
((:jmp.l :brf.l :brt.l :brne.l :brnn.l :brn.l)
((jmp.l brf.l brt.l brne.l brnn.l brn.l)
(princ "@" (hex5 (+ i -4 (ref-int32-LE code i))))
(set! i (+ i 4)))

File diff suppressed because one or more lines are too long

View File

@ -237,13 +237,14 @@ static symbol_t *mk_symbol(char *str)
sym = (symbol_t*)malloc(sizeof(symbol_t)-sizeof(void*) + len + 1);
assert(((uptrint_t)sym & 0x7) == 0); // make sure malloc aligns 8
sym->left = sym->right = NULL;
sym->flags = 0;
if (fl_is_keyword_name(str, len)) {
value_t s = tagptr(sym, TAG_SYM);
setc(s, s);
sym->flags |= 0x2;
}
else {
sym->binding = UNBOUND;
sym->isconst = 0;
}
sym->type = sym->dlcache = NULL;
sym->hash = memhash32(str, len)^0xAAAAAAAA;
@ -932,28 +933,41 @@ static value_t apply_cl(uint32_t nargs)
curr_frame = SP;
NEXT_OP;
OP(OP_OPTARGS)
i = GET_INT32(ip); ip+=4;
n = GET_INT32(ip); ip+=4;
v = fn_vals(Stack[bp-1]);
v = vector_elt(v, 0);
if (nargs >= n) { // if we have all required args
s = vector_size(v);
n += s;
if (nargs < n) { // but not all optional args
i = n - nargs;
SP += i;
Stack[SP-1] = Stack[SP-i-1];
Stack[SP-2] = Stack[SP-i-2];
Stack[SP-3] = Stack[SP-i-3];
Stack[SP-4] = Stack[SP-i-4];
Stack[SP-5] = Stack[SP-i-5];
curr_frame = SP;
s = s - i;
for(n=0; n < i; n++) {
Stack[bp+nargs+n] = vector_elt(v, s+n);
}
nargs += i;
}
if ((int32_t)i < 0) {
if (nargs < -i)
lerror(ArgError, "apply: too few arguments");
}
else if (nargs < i) {
lerror(ArgError, "apply: too few arguments");
}
else if (nargs > n) {
lerror(ArgError, "apply: too many arguments");
}
if (n > nargs) {
n -= nargs;
SP += n;
Stack[SP-1] = Stack[SP-n-1];
Stack[SP-2] = Stack[SP-n-2];
Stack[SP-3] = nargs+n;
Stack[SP-4] = Stack[SP-n-4];
Stack[SP-5] = Stack[SP-n-5];
curr_frame = SP;
for(i=0; i < n; i++) {
Stack[bp+nargs+i] = UNBOUND;
}
nargs += n;
}
NEXT_OP;
OP(OP_BRBOUND)
i = GET_INT32(ip); ip+=4;
if (captured)
v = vector_elt(Stack[bp], i);
else
v = Stack[bp+i];
if (v != UNBOUND) ip += (ptrint_t)GET_INT32(ip);
else ip += 4;
NEXT_OP;
OP(OP_NOP) NEXT_OP;
OP(OP_DUP) SP++; Stack[SP-1] = Stack[SP-2]; NEXT_OP;
@ -1525,7 +1539,7 @@ static value_t apply_cl(uint32_t nargs)
assert(issymbol(v));
sym = (symbol_t*)ptr(v);
v = Stack[SP-1];
if (!sym->isconst)
if (!isconstant(sym))
sym->binding = v;
NEXT_OP;
@ -1686,11 +1700,11 @@ static value_t apply_cl(uint32_t nargs)
#endif
}
static uint32_t compute_maxstack(uint8_t *code, size_t len, value_t vals)
static uint32_t compute_maxstack(uint8_t *code, size_t len)
{
uint8_t *ip = code+4, *end = code+len;
uint8_t op;
uint32_t n, sp = 0, maxsp = 0;
uint32_t i, n, sp = 0, maxsp = 0;
while (1) {
if ((int32_t)sp > (int32_t)maxsp) maxsp = sp;
@ -1713,10 +1727,12 @@ static uint32_t compute_maxstack(uint8_t *code, size_t len, value_t vals)
break;
case OP_LET: break;
case OP_OPTARGS:
ip += 4;
assert(isvector(vals));
if (vector_size(vals) > 0)
sp += vector_size(vector_elt(vals, 0));
i = abs(GET_INT32(ip)); ip+=4;
n = GET_INT32(ip); ip+=4;
sp += (n-i);
break;
case OP_BRBOUND:
ip+=8;
break;
case OP_TCALL: case OP_CALL:
@ -1848,13 +1864,13 @@ static value_t fl_function(value_t *args, uint32_t nargs)
cvalue_t *arr = (cvalue_t*)ptr(args[0]);
cv_pin(arr);
char *data = cv_data(arr);
if (data[4] >= N_OPCODES) {
if ((uint8_t)data[4] >= N_OPCODES) {
// read syntax, shifted 48 for compact text representation
size_t i, sz = cv_len(arr);
for(i=0; i < sz; i++)
data[i] -= 48;
}
uint32_t ms = compute_maxstack((uint8_t*)data, cv_len(arr), args[1]);
uint32_t ms = compute_maxstack((uint8_t*)data, cv_len(arr));
PUT_INT32(data, ms);
function_t *fn = (function_t*)alloc_words(4);
value_t fv = tagptr(fn, TAG_FUNCTION);

View File

@ -15,7 +15,7 @@ typedef struct {
} cons_t;
typedef struct _symbol_t {
value_t isconst;
uptrint_t flags;
value_t binding; // global value binding
struct _fltype_t *type;
uint32_t hash;
@ -87,9 +87,10 @@ typedef struct _symbol_t {
#define fn_name(f) (((value_t*)ptr(f))[3])
#define set(s, v) (((symbol_t*)ptr(s))->binding = (v))
#define setc(s, v) do { ((symbol_t*)ptr(s))->isconst = 1; \
#define setc(s, v) do { ((symbol_t*)ptr(s))->flags |= 1; \
((symbol_t*)ptr(s))->binding = (v); } while (0)
#define isconstant(s) (((symbol_t*)ptr(s))->isconst)
#define isconstant(s) ((s)->flags&0x1)
#define iskeyword(s) ((s)->flags&0x2)
#define symbol_value(s) (((symbol_t*)ptr(s))->binding)
#define ismanaged(v) ((((unsigned char*)ptr(v)) >= fromspace) && \
(((unsigned char*)ptr(v)) < fromspace+heapsize))

View File

@ -27,7 +27,7 @@ enum {
OP_TAPPLY, OP_ADD2, OP_SUB2, OP_NEG, OP_LARGC, OP_LVARGC,
OP_LOADA0, OP_LOADA1, OP_LOADC00, OP_LOADC01, OP_CALLL, OP_TCALLL,
OP_BRNE, OP_BRNEL, OP_CADR, OP_BRNN, OP_BRNNL, OP_BRN, OP_BRNL,
OP_OPTARGS,
OP_OPTARGS, OP_BRBOUND,
OP_BOOL_CONST_T, OP_BOOL_CONST_F, OP_THE_EMPTY_LIST,
@ -70,7 +70,8 @@ enum {
&&L_OP_LVARGC, \
&&L_OP_LOADA0, &&L_OP_LOADA1, &&L_OP_LOADC00, &&L_OP_LOADC01, \
&&L_OP_CALLL, &&L_OP_TCALLL, &&L_OP_BRNE, &&L_OP_BRNEL, &&L_OP_CADR,\
&&L_OP_BRNN, &&L_OP_BRNNL, &&L_OP_BRN, &&L_OP_BRNL, &&L_OP_OPTARGS \
&&L_OP_BRNN, &&L_OP_BRNNL, &&L_OP_BRN, &&L_OP_BRNL, \
&&L_OP_OPTARGS, &&L_OP_BRBOUND \
}
#define VM_APPLY_LABELS \

View File

@ -424,7 +424,7 @@ void fl_print_child(ios_t *f, value_t v)
break;
case TAG_CVALUE:
case TAG_CPRIM:
if (v == UNBOUND) { outs("#<undefined>", f); break; }
if (v == UNBOUND) { outs("#<undefined>", f); break; }
case TAG_VECTOR:
case TAG_CONS:
if (print_circle_prefix(f, v)) return;

View File

@ -280,3 +280,17 @@
lastcdr to-proper reverse reverse! list->vector
table.foreach list-head list-tail assq memq assoc member
assv memv nreconc bq-process))
(define (filt1 pred lst)
(define (filt1- pred lst accum)
(if (null? lst) accum
(if (pred (car lst))
(filt1- pred (cdr lst) (cons (car lst) accum))
(filt1- pred (cdr lst) accum))))
(filt1- pred lst ()))
(define (filto pred lst (accum ()))
(if (atom? lst) accum
(if (pred (car lst))
(filto pred (cdr lst) (cons (car lst) accum))
(filto pred (cdr lst) accum))))

View File

@ -1128,3 +1128,25 @@ typedef struct {
uint32_t SP;
uint32_t curr_frame;
} stackseg_t;
-----------------------------------------------------------------------------
optional and keyword args:
check nargs >= #required
grow frame by ntotal-nargs ; ntotal = #req+#opt+#kw
(sort keyword args into their places)
branch if arg bound around initializer for each opt arg
example: (lambda (a (b 0) (c b)))
minargs 1
framesize 3
brbound 1 L1
load0
seta 0
L1:
brbound 2 L2
loada 1
seta 2
L2: