finishing initial implementation of keyword arguments
fixing up interpreter so it can be used for bootstrapping again removing let/copyenv optimization because it really didn't seem to help much
This commit is contained in:
		
							parent
							
								
									adb702cdf8
								
							
						
					
					
						commit
						15c8cb327d
					
				| 
						 | 
					@ -22,11 +22,11 @@
 | 
				
			||||||
	  setg setg.l
 | 
						  setg setg.l
 | 
				
			||||||
	  seta seta.l setc setc.l
 | 
						  seta seta.l setc setc.l
 | 
				
			||||||
	  
 | 
						  
 | 
				
			||||||
	  closure argc vargc trycatch copyenv let for tapply
 | 
						  closure argc vargc trycatch for tapply
 | 
				
			||||||
	  add2 sub2 neg largc lvargc
 | 
						  add2 sub2 neg largc lvargc
 | 
				
			||||||
	  loada0 loada1 loadc00 loadc01 call.l tcall.l
 | 
						  loada0 loada1 loadc00 loadc01 call.l tcall.l
 | 
				
			||||||
	  brne brne.l cadr brnn brnn.l brn brn.l
 | 
						  brne brne.l cadr brnn brnn.l brn brn.l
 | 
				
			||||||
	  optargs brbound
 | 
						  optargs brbound keyargs
 | 
				
			||||||
	  
 | 
						  
 | 
				
			||||||
	  dummy_t dummy_f dummy_nil]))
 | 
						  dummy_t dummy_f dummy_nil]))
 | 
				
			||||||
    (for 0 (1- (length keys))
 | 
					    (for 0 (1- (length keys))
 | 
				
			||||||
| 
						 | 
					@ -101,15 +101,18 @@
 | 
				
			||||||
	(let ((lasti (if (pair? (aref e 0))
 | 
						(let ((lasti (if (pair? (aref e 0))
 | 
				
			||||||
			 (car (aref e 0)) ()))
 | 
								 (car (aref e 0)) ()))
 | 
				
			||||||
	      (bc (aref e 0)))
 | 
						      (bc (aref e 0)))
 | 
				
			||||||
	  (cond ((and (eq? inst 'brf) (eq? lasti 'not)
 | 
						  (cond ((and
 | 
				
			||||||
 | 
							  (eq? inst 'brf)
 | 
				
			||||||
 | 
							  (cond ((and (eq? lasti 'not)
 | 
				
			||||||
			      (eq? (cadr bc) 'null?))
 | 
								      (eq? (cadr bc) 'null?))
 | 
				
			||||||
			 (aset! e 0 (cons (car args) (cons 'brn (cddr bc)))))
 | 
								 (aset! e 0 (cons (car args) (cons 'brn (cddr bc)))))
 | 
				
			||||||
		((and (eq? inst 'brf) (eq? lasti 'not))
 | 
								((eq? lasti 'not)
 | 
				
			||||||
			 (aset! e 0 (cons (car args) (cons 'brt (cdr bc)))))
 | 
								 (aset! e 0 (cons (car args) (cons 'brt (cdr bc)))))
 | 
				
			||||||
		((and (eq? inst 'brf) (eq? lasti 'eq?))
 | 
								((eq? lasti 'eq?)
 | 
				
			||||||
			 (aset! e 0 (cons (car args) (cons 'brne (cdr bc)))))
 | 
								 (aset! e 0 (cons (car args) (cons 'brne (cdr bc)))))
 | 
				
			||||||
		((and (eq? inst 'brf) (eq? lasti 'null?))
 | 
								((eq? lasti 'null?)
 | 
				
			||||||
			 (aset! e 0 (cons (car args) (cons 'brnn (cdr bc)))))
 | 
								 (aset! e 0 (cons (car args) (cons 'brnn (cdr bc)))))
 | 
				
			||||||
 | 
								(else #f))))
 | 
				
			||||||
		((and (eq? inst 'brt) (eq? lasti 'null?))
 | 
							((and (eq? inst 'brt) (eq? lasti 'null?))
 | 
				
			||||||
		 (aset! e 0 (cons (car args) (cons 'brn (cdr bc)))))
 | 
							 (aset! e 0 (cons (car args) (cons 'brn (cdr bc)))))
 | 
				
			||||||
		(else
 | 
							(else
 | 
				
			||||||
| 
						 | 
					@ -182,11 +185,14 @@
 | 
				
			||||||
			  (io.write bcode (uint8 (aref v i)))
 | 
								  (io.write bcode (uint8 (aref v i)))
 | 
				
			||||||
			  (set! i (+ i 1)))
 | 
								  (set! i (+ i 1)))
 | 
				
			||||||
			 
 | 
								 
 | 
				
			||||||
			 ((loadc.l setc.l optargs)  ; 2 int32 args
 | 
								 ((loadc.l setc.l optargs keyargs)  ; 2 int32 args
 | 
				
			||||||
			  (io.write bcode (int32 nxt))
 | 
								  (io.write bcode (int32 nxt))
 | 
				
			||||||
			  (set! i (+ i 1))
 | 
								  (set! i (+ i 1))
 | 
				
			||||||
			  (io.write bcode (int32 (aref v i)))
 | 
								  (io.write bcode (int32 (aref v i)))
 | 
				
			||||||
			  (set! i (+ i 1)))
 | 
								  (set! i (+ i 1))
 | 
				
			||||||
 | 
								  (if (eq? vi 'keyargs)
 | 
				
			||||||
 | 
								      (begin (io.write bcode (int32 (aref v i)))
 | 
				
			||||||
 | 
									     (set! i (+ i 1)))))
 | 
				
			||||||
			 
 | 
								 
 | 
				
			||||||
			 (else
 | 
								 (else
 | 
				
			||||||
			  ; other number arguments are always uint8
 | 
								  ; other number arguments are always uint8
 | 
				
			||||||
| 
						 | 
					@ -343,26 +349,7 @@
 | 
				
			||||||
	     " arguments.")))
 | 
						     " arguments.")))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(define (compile-app g env tail? x)
 | 
					(define (compile-app g env tail? x)
 | 
				
			||||||
  (let ((head (car x)))
 | 
					  (compile-call g env tail? x))
 | 
				
			||||||
    (if (and (pair? head)
 | 
					 | 
				
			||||||
	     (eq? (car head) 'lambda)
 | 
					 | 
				
			||||||
	     (list? (cadr head))
 | 
					 | 
				
			||||||
	     (every symbol? (cadr head))
 | 
					 | 
				
			||||||
	     (not (length> (cadr head) 255)))
 | 
					 | 
				
			||||||
	(compile-let  g env tail? x)
 | 
					 | 
				
			||||||
	(compile-call g env tail? x))))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
(define (compile-let g env tail? x)
 | 
					 | 
				
			||||||
  (let ((head (car x))
 | 
					 | 
				
			||||||
	(args (cdr x)))
 | 
					 | 
				
			||||||
    (unless (length= args (length (cadr head)))
 | 
					 | 
				
			||||||
	    (error "apply: incorrect number of arguments to " head))
 | 
					 | 
				
			||||||
    (receive (the-f dept) (compile-f- env head #t)
 | 
					 | 
				
			||||||
      (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)))))
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
(define builtin->instruction
 | 
					(define builtin->instruction
 | 
				
			||||||
  (let ((b2i (table number? 'number?  cons 'cons
 | 
					  (let ((b2i (table number? 'number?  cons 'cons
 | 
				
			||||||
| 
						 | 
					@ -485,9 +472,9 @@
 | 
				
			||||||
		     (emit g 'trycatch))
 | 
							     (emit g 'trycatch))
 | 
				
			||||||
	   (else   (compile-app g env tail? x))))))
 | 
						   (else   (compile-app g env tail? x))))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(define (compile-f env f . let?)
 | 
					(define (compile-f env f)
 | 
				
			||||||
  (receive (ff ignore)
 | 
					  (receive (ff ignore)
 | 
				
			||||||
	   (apply compile-f- env f let?)
 | 
						   (compile-f- env f)
 | 
				
			||||||
	   ff))
 | 
						   ff))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(define get-defined-vars
 | 
					(define get-defined-vars
 | 
				
			||||||
| 
						 | 
					@ -507,6 +494,13 @@
 | 
				
			||||||
		    (else ())))))
 | 
							    (else ())))))
 | 
				
			||||||
    (lambda (expr) (delete-duplicates (get-defined-vars- expr)))))
 | 
					    (lambda (expr) (delete-duplicates (get-defined-vars- expr)))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(define (keyword-arg? x) (and (pair? x) (keyword? (car x))))
 | 
				
			||||||
 | 
					(define (keyword->symbol k)
 | 
				
			||||||
 | 
					  (if (keyword? k)
 | 
				
			||||||
 | 
					      (symbol (let ((s (string k)))
 | 
				
			||||||
 | 
							(string.sub s 0 (string.dec s (length s)))))
 | 
				
			||||||
 | 
					      k))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(define (lambda-vars l)
 | 
					(define (lambda-vars l)
 | 
				
			||||||
  (define (check-formals l o)
 | 
					  (define (check-formals l o)
 | 
				
			||||||
    (or
 | 
					    (or
 | 
				
			||||||
| 
						 | 
					@ -517,7 +511,12 @@
 | 
				
			||||||
	  (and (pair? (car l))
 | 
						  (and (pair? (car l))
 | 
				
			||||||
	       (or (every pair? (cdr l))
 | 
						       (or (every pair? (cdr l))
 | 
				
			||||||
		   (error "compile error: invalid argument list "
 | 
							   (error "compile error: invalid argument list "
 | 
				
			||||||
			  o ". optional arguments must come last.")))
 | 
								  o ". optional arguments must come after required."))
 | 
				
			||||||
 | 
						       (if (keyword? (caar l))
 | 
				
			||||||
 | 
							   (or (every keyword-arg? (cdr l))
 | 
				
			||||||
 | 
							       (error "compile error: invalid argument list "
 | 
				
			||||||
 | 
								      o ". keyword arguments must come last."))
 | 
				
			||||||
 | 
							   #t))
 | 
				
			||||||
	  (error "compile error: invalid formal argument " (car l)
 | 
						  (error "compile error: invalid formal argument " (car l)
 | 
				
			||||||
		 " in list " o))
 | 
							 " in list " o))
 | 
				
			||||||
      (check-formals (cdr l) o))
 | 
					      (check-formals (cdr l) o))
 | 
				
			||||||
| 
						 | 
					@ -525,7 +524,7 @@
 | 
				
			||||||
	 (error "compile error: invalid argument list " o)
 | 
						 (error "compile error: invalid argument list " o)
 | 
				
			||||||
	 (error "compile error: invalid formal argument " l " in list " o))))
 | 
						 (error "compile error: invalid formal argument " l " in list " o))))
 | 
				
			||||||
  (check-formals l l)
 | 
					  (check-formals l l)
 | 
				
			||||||
  (map (lambda (s) (if (pair? s) (car s) s))
 | 
					  (map! (lambda (s) (if (pair? s) (keyword->symbol (car s)) s))
 | 
				
			||||||
	(to-proper l)))
 | 
						(to-proper l)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(define (emit-optional-arg-inits g env opta vars i)
 | 
					(define (emit-optional-arg-inits g env opta vars i)
 | 
				
			||||||
| 
						 | 
					@ -547,7 +546,7 @@
 | 
				
			||||||
     (lambda (expr)
 | 
					     (lambda (expr)
 | 
				
			||||||
       (compile `(lambda () ,expr . ,*defines-processed-token*))))
 | 
					       (compile `(lambda () ,expr . ,*defines-processed-token*))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    (lambda (env f . let?)
 | 
					    (lambda (env f)
 | 
				
			||||||
      ; convert lambda to one body expression and process internal defines
 | 
					      ; convert lambda to one body expression and process internal defines
 | 
				
			||||||
      (define (lambda-body e)
 | 
					      (define (lambda-body e)
 | 
				
			||||||
	(let ((B (if (pair? (cddr e))
 | 
						(let ((B (if (pair? (cddr e))
 | 
				
			||||||
| 
						 | 
					@ -570,15 +569,25 @@
 | 
				
			||||||
		      'lambda
 | 
							      'lambda
 | 
				
			||||||
		      (lastcdr f))))
 | 
							      (lastcdr f))))
 | 
				
			||||||
	(let* ((nargs (if (atom? args) 0 (length args)))
 | 
						(let* ((nargs (if (atom? args) 0 (length args)))
 | 
				
			||||||
	       (nreq  (- nargs (length opta))))
 | 
						       (nreq  (- nargs (length opta)))
 | 
				
			||||||
 | 
						       (kwa   (filter keyword-arg? opta)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	  ; emit argument checking prologue
 | 
						  ; emit argument checking prologue
 | 
				
			||||||
	  (if (not (null? opta))
 | 
						  (if (not (null? opta))
 | 
				
			||||||
	      (begin (emit g 'optargs nreq (if (null? atail) nargs (- nargs)))
 | 
						      (begin
 | 
				
			||||||
 | 
							(if (null? kwa)
 | 
				
			||||||
 | 
							    (emit g 'optargs nreq
 | 
				
			||||||
 | 
								  (if (null? atail) nargs (- nargs)))
 | 
				
			||||||
 | 
							    (begin
 | 
				
			||||||
 | 
							      (bcode:indexfor g (make-perfect-hash-table
 | 
				
			||||||
 | 
										 (map cons
 | 
				
			||||||
 | 
										      (map car kwa)
 | 
				
			||||||
 | 
										      (iota (length kwa)))))
 | 
				
			||||||
 | 
							      (emit g 'keyargs nreq (length kwa)
 | 
				
			||||||
 | 
								    (if (null? atail) nargs (- nargs)))))
 | 
				
			||||||
		(emit-optional-arg-inits g env opta vars nreq)))
 | 
							(emit-optional-arg-inits g env opta vars nreq)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	  (cond ((not (null? let?))      (emit g 'let))
 | 
						  (cond ((> nargs 255)           (emit g (if (null? atail)
 | 
				
			||||||
		((> nargs 255)           (emit g (if (null? atail)
 | 
					 | 
				
			||||||
						     'largc 'lvargc)
 | 
											     'largc 'lvargc)
 | 
				
			||||||
					       nargs))
 | 
										       nargs))
 | 
				
			||||||
		((not (null? atail))     (emit g 'vargc nargs))
 | 
							((not (null? atail))     (emit g 'vargc nargs))
 | 
				
			||||||
| 
						 | 
					@ -661,11 +670,16 @@
 | 
				
			||||||
		  (princ (number->string (aref code i)))
 | 
							  (princ (number->string (aref code i)))
 | 
				
			||||||
		  (set! i (+ i 1)))
 | 
							  (set! i (+ i 1)))
 | 
				
			||||||
		 
 | 
							 
 | 
				
			||||||
		 ((loadc.l setc.l optargs)
 | 
							 ((loadc.l setc.l optargs keyargs)
 | 
				
			||||||
		  (princ (number->string (ref-int32-LE code i)) " ")
 | 
							  (princ (number->string (ref-int32-LE code i)) " ")
 | 
				
			||||||
		  (set! i (+ i 4))
 | 
							  (set! i (+ i 4))
 | 
				
			||||||
		  (princ (number->string (ref-int32-LE code i)))
 | 
							  (princ (number->string (ref-int32-LE code i)))
 | 
				
			||||||
		  (set! i (+ i 4)))
 | 
							  (set! i (+ i 4))
 | 
				
			||||||
 | 
							  (if (eq? inst 'keyargs)
 | 
				
			||||||
 | 
							      (begin 
 | 
				
			||||||
 | 
								(princ " ")
 | 
				
			||||||
 | 
								(princ (number->string (ref-int32-LE code i)) " ")
 | 
				
			||||||
 | 
								(set! i (+ i 4)))))
 | 
				
			||||||
		 
 | 
							 
 | 
				
			||||||
		 ((brbound)
 | 
							 ((brbound)
 | 
				
			||||||
		  (princ (number->string (ref-int32-LE code i)) " ")
 | 
							  (princ (number->string (ref-int32-LE code i)) " ")
 | 
				
			||||||
| 
						 | 
					@ -683,4 +697,31 @@
 | 
				
			||||||
		 
 | 
							 
 | 
				
			||||||
		 (else #f)))))))
 | 
							 (else #f)))))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					; From SRFI 89 by Marc Feeley (http://srfi.schemers.org/srfi-89/srfi-89.html)
 | 
				
			||||||
 | 
					; Copyright (C) Marc Feeley 2006. All Rights Reserved.
 | 
				
			||||||
 | 
					;
 | 
				
			||||||
 | 
					; "alist" is a list of pairs of the form "(keyword . value)"
 | 
				
			||||||
 | 
					; The result is a perfect hash-table represented as a vector of
 | 
				
			||||||
 | 
					; length 2*N, where N is the hash modulus.  If the keyword K is in
 | 
				
			||||||
 | 
					; the hash-table it is at index
 | 
				
			||||||
 | 
					;
 | 
				
			||||||
 | 
					;   X = (* 2 ($hash-keyword K N))
 | 
				
			||||||
 | 
					;
 | 
				
			||||||
 | 
					; and the associated value is at index X+1.
 | 
				
			||||||
 | 
					(define (make-perfect-hash-table alist)
 | 
				
			||||||
 | 
					  (define ($hash-keyword key n) (mod0 (abs (hash key)) n))
 | 
				
			||||||
 | 
					  (let loop1 ((n (length alist)))
 | 
				
			||||||
 | 
					    (let ((v (vector.alloc (* 2 n) #f)))
 | 
				
			||||||
 | 
					      (let loop2 ((lst alist))
 | 
				
			||||||
 | 
					        (if (pair? lst)
 | 
				
			||||||
 | 
					            (let ((key (caar lst)))
 | 
				
			||||||
 | 
					              (let ((x (* 2 ($hash-keyword key n))))
 | 
				
			||||||
 | 
					                (if (aref v x)
 | 
				
			||||||
 | 
					                    (loop1 (+ n 1))
 | 
				
			||||||
 | 
					                    (begin
 | 
				
			||||||
 | 
					                      (aset! v x key)
 | 
				
			||||||
 | 
					                      (aset! v (+ x 1) (cdar lst))
 | 
				
			||||||
 | 
					                      (loop2 (cdr lst))))))
 | 
				
			||||||
 | 
					            v)))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#t
 | 
					#t
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| 
						 | 
					@ -391,7 +391,7 @@ void fl_gc_handle(value_t *pv)
 | 
				
			||||||
    GCHandleStack[N_GCHND++] = pv;
 | 
					    GCHandleStack[N_GCHND++] = pv;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void fl_free_gc_handles(int n)
 | 
					void fl_free_gc_handles(uint32_t n)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    assert(N_GCHND >= n);
 | 
					    assert(N_GCHND >= n);
 | 
				
			||||||
    N_GCHND -= n;
 | 
					    N_GCHND -= n;
 | 
				
			||||||
| 
						 | 
					@ -826,11 +826,11 @@ static uint32_t process_keys(value_t kwtable,
 | 
				
			||||||
            lerrorf(ArgError, "keyword %s requires an argument",
 | 
					            lerrorf(ArgError, "keyword %s requires an argument",
 | 
				
			||||||
                    symbol_name(v));
 | 
					                    symbol_name(v));
 | 
				
			||||||
        value_t hv = fixnum(((symbol_t*)ptr(v))->hash);
 | 
					        value_t hv = fixnum(((symbol_t*)ptr(v))->hash);
 | 
				
			||||||
        uint32_t x = 2*(numval(hv) % n);
 | 
					        uint32_t x = 2*(abs(numval(hv)) % n);
 | 
				
			||||||
        if (vector_elt(kwtable, x) == v) {
 | 
					        if (vector_elt(kwtable, x) == v) {
 | 
				
			||||||
            uint32_t idx = numval(vector_elt(kwtable, x+1));
 | 
					            uint32_t idx = numval(vector_elt(kwtable, x+1));
 | 
				
			||||||
            assert(idx < nkw);
 | 
					            assert(idx < nkw);
 | 
				
			||||||
            idx += (nreq+nopt);
 | 
					            idx += nopt;
 | 
				
			||||||
            if (args[idx] == UNBOUND) {
 | 
					            if (args[idx] == UNBOUND) {
 | 
				
			||||||
                // if duplicate key, keep first value
 | 
					                // if duplicate key, keep first value
 | 
				
			||||||
                args[idx] = Stack[bp+i];
 | 
					                args[idx] = Stack[bp+i];
 | 
				
			||||||
| 
						 | 
					@ -995,40 +995,6 @@ static value_t apply_cl(uint32_t nargs)
 | 
				
			||||||
        OP(OP_LVARGC)
 | 
					        OP(OP_LVARGC)
 | 
				
			||||||
            i = GET_INT32(ip); ip+=4;
 | 
					            i = GET_INT32(ip); ip+=4;
 | 
				
			||||||
            goto do_vargc;
 | 
					            goto do_vargc;
 | 
				
			||||||
        OP(OP_LET)
 | 
					 | 
				
			||||||
            // last arg is closure environment to use
 | 
					 | 
				
			||||||
            nargs--;
 | 
					 | 
				
			||||||
            Stack[SP-5] = Stack[SP-4];
 | 
					 | 
				
			||||||
            Stack[SP-4] = nargs;
 | 
					 | 
				
			||||||
            POPN(1);
 | 
					 | 
				
			||||||
            Stack[SP-1] = 0;
 | 
					 | 
				
			||||||
            curr_frame = SP;
 | 
					 | 
				
			||||||
            NEXT_OP;
 | 
					 | 
				
			||||||
        OP(OP_OPTARGS)
 | 
					 | 
				
			||||||
            i = GET_INT32(ip); ip+=4;
 | 
					 | 
				
			||||||
            n = GET_INT32(ip); ip+=4;
 | 
					 | 
				
			||||||
            if (nargs < i)
 | 
					 | 
				
			||||||
                lerror(ArgError, "apply: too few arguments");
 | 
					 | 
				
			||||||
            if ((int32_t)n > 0) {
 | 
					 | 
				
			||||||
                if (nargs > n)
 | 
					 | 
				
			||||||
                    lerror(ArgError, "apply: too many arguments");
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            else n = -n;
 | 
					 | 
				
			||||||
            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)
 | 
					        OP(OP_BRBOUND)
 | 
				
			||||||
            i = GET_INT32(ip); ip+=4;
 | 
					            i = GET_INT32(ip); ip+=4;
 | 
				
			||||||
            if (captured)
 | 
					            if (captured)
 | 
				
			||||||
| 
						 | 
					@ -1038,7 +1004,6 @@ static value_t apply_cl(uint32_t nargs)
 | 
				
			||||||
            if (v != UNBOUND) ip += (ptrint_t)GET_INT32(ip);
 | 
					            if (v != UNBOUND) ip += (ptrint_t)GET_INT32(ip);
 | 
				
			||||||
            else ip += 4;
 | 
					            else ip += 4;
 | 
				
			||||||
            NEXT_OP;
 | 
					            NEXT_OP;
 | 
				
			||||||
        OP(OP_NOP) NEXT_OP;
 | 
					 | 
				
			||||||
        OP(OP_DUP) SP++; Stack[SP-1] = Stack[SP-2]; NEXT_OP;
 | 
					        OP(OP_DUP) SP++; Stack[SP-1] = Stack[SP-2]; NEXT_OP;
 | 
				
			||||||
        OP(OP_POP) POPN(1); NEXT_OP;
 | 
					        OP(OP_POP) POPN(1); NEXT_OP;
 | 
				
			||||||
        OP(OP_TCALL)
 | 
					        OP(OP_TCALL)
 | 
				
			||||||
| 
						 | 
					@ -1716,7 +1681,6 @@ static value_t apply_cl(uint32_t nargs)
 | 
				
			||||||
            NEXT_OP;
 | 
					            NEXT_OP;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        OP(OP_CLOSURE)
 | 
					        OP(OP_CLOSURE)
 | 
				
			||||||
        OP(OP_COPYENV)
 | 
					 | 
				
			||||||
            // build a closure (lambda args body . env)
 | 
					            // build a closure (lambda args body . env)
 | 
				
			||||||
            if (nargs > 0 && !captured) {
 | 
					            if (nargs > 0 && !captured) {
 | 
				
			||||||
                // save temporary environment to the heap
 | 
					                // save temporary environment to the heap
 | 
				
			||||||
| 
						 | 
					@ -1737,7 +1701,6 @@ static value_t apply_cl(uint32_t nargs)
 | 
				
			||||||
            else {
 | 
					            else {
 | 
				
			||||||
                PUSH(Stack[bp]); // env has already been captured; share
 | 
					                PUSH(Stack[bp]); // env has already been captured; share
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            if (ip[-1] == OP_CLOSURE) {
 | 
					 | 
				
			||||||
            pv = alloc_words(4);
 | 
					            pv = alloc_words(4);
 | 
				
			||||||
            e = Stack[SP-2];  // closure to copy
 | 
					            e = Stack[SP-2];  // closure to copy
 | 
				
			||||||
            assert(isfunction(e));
 | 
					            assert(isfunction(e));
 | 
				
			||||||
| 
						 | 
					@ -1747,7 +1710,6 @@ static value_t apply_cl(uint32_t nargs)
 | 
				
			||||||
            pv[3] = ((value_t*)ptr(e))[3];
 | 
					            pv[3] = ((value_t*)ptr(e))[3];
 | 
				
			||||||
            POPN(1);
 | 
					            POPN(1);
 | 
				
			||||||
            Stack[SP-1] = tagptr(pv, TAG_FUNCTION);
 | 
					            Stack[SP-1] = tagptr(pv, TAG_FUNCTION);
 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            NEXT_OP;
 | 
					            NEXT_OP;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        OP(OP_TRYCATCH)
 | 
					        OP(OP_TRYCATCH)
 | 
				
			||||||
| 
						 | 
					@ -1756,6 +1718,40 @@ static value_t apply_cl(uint32_t nargs)
 | 
				
			||||||
            Stack[SP-1] = v;
 | 
					            Stack[SP-1] = v;
 | 
				
			||||||
            NEXT_OP;
 | 
					            NEXT_OP;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        OP(OP_OPTARGS)
 | 
				
			||||||
 | 
					            i = GET_INT32(ip); ip+=4;
 | 
				
			||||||
 | 
					            n = GET_INT32(ip); ip+=4;
 | 
				
			||||||
 | 
					            if (nargs < i)
 | 
				
			||||||
 | 
					                lerror(ArgError, "apply: too few arguments");
 | 
				
			||||||
 | 
					            if ((int32_t)n > 0) {
 | 
				
			||||||
 | 
					                if (nargs > n)
 | 
				
			||||||
 | 
					                    lerror(ArgError, "apply: too many arguments");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else n = -n;
 | 
				
			||||||
 | 
					            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_KEYARGS)
 | 
				
			||||||
 | 
					            v = fn_vals(Stack[bp-1]);
 | 
				
			||||||
 | 
					            v = vector_elt(v, 0);
 | 
				
			||||||
 | 
					            i = GET_INT32(ip); ip+=4;
 | 
				
			||||||
 | 
					            n = GET_INT32(ip); ip+=4;
 | 
				
			||||||
 | 
					            s = GET_INT32(ip); ip+=4;
 | 
				
			||||||
 | 
					            nargs = process_keys(v, i, n, abs(s)-(i+n), bp, nargs, s<0);
 | 
				
			||||||
 | 
					            NEXT_OP;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef USE_COMPUTED_GOTO
 | 
					#ifndef USE_COMPUTED_GOTO
 | 
				
			||||||
        default:
 | 
					        default:
 | 
				
			||||||
            goto dispatch;
 | 
					            goto dispatch;
 | 
				
			||||||
| 
						 | 
					@ -1794,10 +1790,15 @@ static uint32_t compute_maxstack(uint8_t *code, size_t len)
 | 
				
			||||||
            n = GET_INT32(ip); ip+=4;
 | 
					            n = GET_INT32(ip); ip+=4;
 | 
				
			||||||
            sp += (n+2);
 | 
					            sp += (n+2);
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case OP_LET: break;
 | 
					 | 
				
			||||||
        case OP_OPTARGS:
 | 
					        case OP_OPTARGS:
 | 
				
			||||||
            i = abs(GET_INT32(ip)); ip+=4;
 | 
					            i = GET_INT32(ip); ip+=4;
 | 
				
			||||||
 | 
					            n = abs(GET_INT32(ip)); ip+=4;
 | 
				
			||||||
 | 
					            sp += (n-i);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case OP_KEYARGS:
 | 
				
			||||||
 | 
					            i = GET_INT32(ip); ip+=4;
 | 
				
			||||||
            n = GET_INT32(ip); ip+=4;
 | 
					            n = GET_INT32(ip); ip+=4;
 | 
				
			||||||
 | 
					            n = abs(GET_INT32(ip)); ip+=4;
 | 
				
			||||||
            sp += (n-i);
 | 
					            sp += (n-i);
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case OP_BRBOUND:
 | 
					        case OP_BRBOUND:
 | 
				
			||||||
| 
						 | 
					@ -1854,7 +1855,7 @@ static uint32_t compute_maxstack(uint8_t *code, size_t len)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        case OP_LOADT: case OP_LOADF: case OP_LOADNIL: case OP_LOAD0:
 | 
					        case OP_LOADT: case OP_LOADF: case OP_LOADNIL: case OP_LOAD0:
 | 
				
			||||||
        case OP_LOAD1: case OP_LOADA0: case OP_LOADA1: case OP_LOADC00:
 | 
					        case OP_LOAD1: case OP_LOADA0: case OP_LOADA1: case OP_LOADC00:
 | 
				
			||||||
        case OP_LOADC01: case OP_COPYENV: case OP_DUP:
 | 
					        case OP_LOADC01: case OP_DUP:
 | 
				
			||||||
            sp++;
 | 
					            sp++;
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -101,7 +101,7 @@ typedef struct _symbol_t {
 | 
				
			||||||
#define iscbuiltin(x) (iscvalue(x) && (cv_class((cvalue_t*)ptr(x))==builtintype))
 | 
					#define iscbuiltin(x) (iscvalue(x) && (cv_class((cvalue_t*)ptr(x))==builtintype))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void fl_gc_handle(value_t *pv);
 | 
					void fl_gc_handle(value_t *pv);
 | 
				
			||||||
void fl_free_gc_handles(int n);
 | 
					void fl_free_gc_handles(uint32_t n);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "opcodes.h"
 | 
					#include "opcodes.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,7 @@
 | 
				
			||||||
; -*- scheme -*-
 | 
					; -*- scheme -*-
 | 
				
			||||||
 | 
					
 | 
				
			||||||
;(if (not (bound? 'top-level-value)) (set! top-level-value %eval))
 | 
					(if (not (bound? 'top-level-value)) (set! top-level-value %eval))
 | 
				
			||||||
;(if (not (bound? 'set-top-level-value!)) (set! set-top-level-value! set))
 | 
					(if (not (bound? 'set-top-level-value!)) (set! set-top-level-value! set))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
;(load "compiler.lsp")
 | 
					;(load "compiler.lsp")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,11 +23,11 @@ enum {
 | 
				
			||||||
    OP_SETG, OP_SETGL,
 | 
					    OP_SETG, OP_SETGL,
 | 
				
			||||||
    OP_SETA, OP_SETAL, OP_SETC, OP_SETCL,
 | 
					    OP_SETA, OP_SETAL, OP_SETC, OP_SETCL,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    OP_CLOSURE, OP_ARGC, OP_VARGC, OP_TRYCATCH, OP_COPYENV, OP_LET, OP_FOR,
 | 
					    OP_CLOSURE, OP_ARGC, OP_VARGC, OP_TRYCATCH, OP_FOR,
 | 
				
			||||||
    OP_TAPPLY, OP_ADD2, OP_SUB2, OP_NEG, OP_LARGC, OP_LVARGC,
 | 
					    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_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_BRNE, OP_BRNEL, OP_CADR, OP_BRNN, OP_BRNNL, OP_BRN, OP_BRNL,
 | 
				
			||||||
    OP_OPTARGS, OP_BRBOUND,
 | 
					    OP_OPTARGS, OP_BRBOUND, OP_KEYARGS,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    OP_BOOL_CONST_T, OP_BOOL_CONST_F, OP_THE_EMPTY_LIST,
 | 
					    OP_BOOL_CONST_T, OP_BOOL_CONST_F, OP_THE_EMPTY_LIST,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -37,7 +37,7 @@ enum {
 | 
				
			||||||
#ifdef USE_COMPUTED_GOTO
 | 
					#ifdef USE_COMPUTED_GOTO
 | 
				
			||||||
#define VM_LABELS                                                       \
 | 
					#define VM_LABELS                                                       \
 | 
				
			||||||
    static void *vm_labels[] = {                                        \
 | 
					    static void *vm_labels[] = {                                        \
 | 
				
			||||||
&&L_OP_NOP, &&L_OP_DUP, &&L_OP_POP, &&L_OP_CALL, &&L_OP_TCALL, &&L_OP_JMP, \
 | 
					NULL, &&L_OP_DUP, &&L_OP_POP, &&L_OP_CALL, &&L_OP_TCALL, &&L_OP_JMP, \
 | 
				
			||||||
    &&L_OP_BRF, &&L_OP_BRT,                                             \
 | 
					    &&L_OP_BRF, &&L_OP_BRT,                                             \
 | 
				
			||||||
    &&L_OP_JMPL, &&L_OP_BRFL, &&L_OP_BRTL, &&L_OP_RET,                  \
 | 
					    &&L_OP_JMPL, &&L_OP_BRFL, &&L_OP_BRTL, &&L_OP_RET,                  \
 | 
				
			||||||
                                                                        \
 | 
					                                                                        \
 | 
				
			||||||
| 
						 | 
					@ -64,19 +64,18 @@ enum {
 | 
				
			||||||
    &&L_OP_SETA, &&L_OP_SETAL, &&L_OP_SETC, &&L_OP_SETCL,               \
 | 
					    &&L_OP_SETA, &&L_OP_SETAL, &&L_OP_SETC, &&L_OP_SETCL,               \
 | 
				
			||||||
                                                                        \
 | 
					                                                                        \
 | 
				
			||||||
    &&L_OP_CLOSURE, &&L_OP_ARGC, &&L_OP_VARGC, &&L_OP_TRYCATCH,         \
 | 
					    &&L_OP_CLOSURE, &&L_OP_ARGC, &&L_OP_VARGC, &&L_OP_TRYCATCH,         \
 | 
				
			||||||
    &&L_OP_COPYENV,                                                     \
 | 
					    &&L_OP_FOR,                                                         \
 | 
				
			||||||
    &&L_OP_LET, &&L_OP_FOR,                                             \
 | 
					 | 
				
			||||||
    &&L_OP_TAPPLY, &&L_OP_ADD2, &&L_OP_SUB2, &&L_OP_NEG, &&L_OP_LARGC,  \
 | 
					    &&L_OP_TAPPLY, &&L_OP_ADD2, &&L_OP_SUB2, &&L_OP_NEG, &&L_OP_LARGC,  \
 | 
				
			||||||
    &&L_OP_LVARGC,                                                      \
 | 
					    &&L_OP_LVARGC,                                                      \
 | 
				
			||||||
    &&L_OP_LOADA0, &&L_OP_LOADA1, &&L_OP_LOADC00, &&L_OP_LOADC01,       \
 | 
					    &&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_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_BRNN, &&L_OP_BRNNL, &&L_OP_BRN, &&L_OP_BRNL,                 \
 | 
				
			||||||
    &&L_OP_OPTARGS, &&L_OP_BRBOUND                                      \
 | 
					    &&L_OP_OPTARGS, &&L_OP_BRBOUND, &&L_OP_KEYARGS                      \
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define VM_APPLY_LABELS                                                 \
 | 
					#define VM_APPLY_LABELS                                                 \
 | 
				
			||||||
    static void *vm_apply_labels[] = {                                  \
 | 
					    static void *vm_apply_labels[] = {                                  \
 | 
				
			||||||
&&L_OP_NOP, &&L_OP_DUP, &&L_OP_POP, &&L_OP_CALL, &&L_OP_TCALL, &&L_OP_JMP, \
 | 
					NULL, &&L_OP_DUP, &&L_OP_POP, &&L_OP_CALL, &&L_OP_TCALL, &&L_OP_JMP, \
 | 
				
			||||||
    &&L_OP_BRF, &&L_OP_BRT,                                             \
 | 
					    &&L_OP_BRF, &&L_OP_BRT,                                             \
 | 
				
			||||||
    &&L_OP_JMPL, &&L_OP_BRFL, &&L_OP_BRTL, &&L_OP_RET,                  \
 | 
					    &&L_OP_JMPL, &&L_OP_BRFL, &&L_OP_BRTL, &&L_OP_RET,                  \
 | 
				
			||||||
                                                                        \
 | 
					                                                                        \
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -126,6 +126,17 @@
 | 
				
			||||||
(assert (equal? ((lambda ((x 0) . r) (list x r))) '(0 ())))
 | 
					(assert (equal? ((lambda ((x 0) . r) (list x r))) '(0 ())))
 | 
				
			||||||
(assert (equal? ((lambda ((x 0) . r) (list x r)) 1 2 3) '(1 (2 3))))
 | 
					(assert (equal? ((lambda ((x 0) . r) (list x r)) 1 2 3) '(1 (2 3))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					; keyword arguments
 | 
				
			||||||
 | 
					(assert (equal? ((lambda (x (a 2) (b: a) . r) (list x a b r)) 1 0 8 4 5)
 | 
				
			||||||
 | 
							'(1 0 0 (8 4 5))))
 | 
				
			||||||
 | 
					(assert (equal? ((lambda (x (a 2) (b: a) . r) (list x a b r)) 0 b: 3 1)
 | 
				
			||||||
 | 
							'(0 2 3 (1))))
 | 
				
			||||||
 | 
					(define (keys4 (a: 8) (b: 3) (c: 7) (d: 6)) (list a b c d))
 | 
				
			||||||
 | 
					(assert (equal? (keys4 a: 10) '(10 3 7 6)))
 | 
				
			||||||
 | 
					(assert (equal? (keys4 b: 10) '(8 10 7 6)))
 | 
				
			||||||
 | 
					(assert (equal? (keys4 c: 10) '(8 3 10 6)))
 | 
				
			||||||
 | 
					(assert (equal? (keys4 d: 10) '(8 3 7 10)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
; ok, a couple end-to-end tests as well
 | 
					; ok, a couple end-to-end tests as well
 | 
				
			||||||
(define (fib n) (if (< n 2) n (+ (fib (- n 1)) (fib (- n 2)))))
 | 
					(define (fib n) (if (< n 2) n (+ (fib (- n 1)) (fib (- n 2)))))
 | 
				
			||||||
(assert (equal? (fib 20) 6765))
 | 
					(assert (equal? (fib 20) 6765))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue