moving (length) out of core
changing another recursive call to goto adding special cases in compiler for 0 and 1 argument versions of some vararg builtins beginning implementation of bytecode interpreter
This commit is contained in:
		
							parent
							
								
									ea5d334626
								
							
						
					
					
						commit
						debf3fd517
					
				| 
						 | 
					@ -78,6 +78,35 @@ static value_t fl_memq(value_t *args, u_int32_t nargs)
 | 
				
			||||||
    return FL_F;
 | 
					    return FL_F;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static value_t fl_length(value_t *args, u_int32_t nargs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    argcount("length", nargs, 1);
 | 
				
			||||||
 | 
					    value_t a = args[0];
 | 
				
			||||||
 | 
					    cvalue_t *cv;
 | 
				
			||||||
 | 
					    if (isvector(a)) {
 | 
				
			||||||
 | 
					        return fixnum(vector_size(a));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else if (iscprim(a)) {
 | 
				
			||||||
 | 
					        cv = (cvalue_t*)ptr(a);
 | 
				
			||||||
 | 
					        if (cp_class(cv) == bytetype)
 | 
				
			||||||
 | 
					            return fixnum(1);
 | 
				
			||||||
 | 
					        else if (cp_class(cv) == wchartype)
 | 
				
			||||||
 | 
					            return fixnum(u8_charlen(*(uint32_t*)cp_data((cprim_t*)cv)));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else if (iscvalue(a)) {
 | 
				
			||||||
 | 
					        cv = (cvalue_t*)ptr(a);
 | 
				
			||||||
 | 
					        if (cv_class(cv)->eltype != NULL)
 | 
				
			||||||
 | 
					            return size_wrap(cvalue_arraylen(a));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else if (a == NIL) {
 | 
				
			||||||
 | 
					        return fixnum(0);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else if (iscons(a)) {
 | 
				
			||||||
 | 
					        return fixnum(llength(a));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    type_error("length", "sequence", a);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static value_t fl_raise(value_t *args, u_int32_t nargs)
 | 
					static value_t fl_raise(value_t *args, u_int32_t nargs)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    argcount("raise", nargs, 1);
 | 
					    argcount("raise", nargs, 1);
 | 
				
			||||||
| 
						 | 
					@ -387,6 +416,7 @@ static builtinspec_t builtin_info[] = {
 | 
				
			||||||
    { "nconc", fl_nconc },
 | 
					    { "nconc", fl_nconc },
 | 
				
			||||||
    { "assq", fl_assq },
 | 
					    { "assq", fl_assq },
 | 
				
			||||||
    { "memq", fl_memq },
 | 
					    { "memq", fl_memq },
 | 
				
			||||||
 | 
					    { "length", fl_length },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    { "vector.alloc", fl_vector_alloc },
 | 
					    { "vector.alloc", fl_vector_alloc },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,13 +18,13 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    :+ :- :* :/ :< :compare
 | 
					    :+ :- :* :/ :< :compare
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    :vector :aref :aset! :length :for
 | 
					    :vector :aref :aset! :for
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    :loadt :loadf :loadnil :load0 :load1 :loadv :loadv.l
 | 
					    :loadt :loadf :loadnil :load0 :load1 :loadv :loadv.l
 | 
				
			||||||
    :loadg :loada :loadc :loadg.l
 | 
					    :loadg :loada :loadc :loadg.l
 | 
				
			||||||
    :setg  :seta  :setc  :setg.l
 | 
					    :setg  :seta  :setc  :setg.l
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    :closure :trycatch :tcall :tapply]))
 | 
					    :closure :trycatch :tcall :tapply :argc :vargc]))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(define arg-counts
 | 
					(define arg-counts
 | 
				
			||||||
  (table :eq?      2      :eqv?     2
 | 
					  (table :eq?      2      :eqv?     2
 | 
				
			||||||
| 
						 | 
					@ -40,7 +40,7 @@
 | 
				
			||||||
	 :eval*    1      :apply    2
 | 
						 :eval*    1      :apply    2
 | 
				
			||||||
	 :<        2      :for      3
 | 
						 :<        2      :for      3
 | 
				
			||||||
	 :compare  2      :aref     2
 | 
						 :compare  2      :aref     2
 | 
				
			||||||
	 :aset!    3      :length   1))
 | 
						 :aset!    3))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(define 1/Instructions (table.invert Instructions))
 | 
					(define 1/Instructions (table.invert Instructions))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -121,7 +121,7 @@
 | 
				
			||||||
			 (set! i (+ i 1)))
 | 
								 (set! i (+ i 1)))
 | 
				
			||||||
			
 | 
								
 | 
				
			||||||
			((:loada :seta :call :tcall :loadv :loadg :setg
 | 
								((:loada :seta :call :tcall :loadv :loadg :setg
 | 
				
			||||||
				 :list :+ :- :* :/ :vector)
 | 
									 :list :+ :- :* :/ :vector :argc :vargc)
 | 
				
			||||||
			 (io.write bcode (uint8 nxt))
 | 
								 (io.write bcode (uint8 nxt))
 | 
				
			||||||
			 (set! i (+ i 1)))
 | 
								 (set! i (+ i 1)))
 | 
				
			||||||
			
 | 
								
 | 
				
			||||||
| 
						 | 
					@ -154,7 +154,7 @@
 | 
				
			||||||
      cvec)))
 | 
					      cvec)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(define (bytecode g)
 | 
					(define (bytecode g)
 | 
				
			||||||
  (cons (encode-byte-code (aref g 0))
 | 
					  (cons (cvalue.pin (encode-byte-code (aref g 0)))
 | 
				
			||||||
	(const-to-idx-vec g)))
 | 
						(const-to-idx-vec g)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(define (bytecode:code b) (car b))
 | 
					(define (bytecode:code b) (car b))
 | 
				
			||||||
| 
						 | 
					@ -185,7 +185,7 @@
 | 
				
			||||||
			#f)))))
 | 
								#f)))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(define (compile-sym g env s Is)
 | 
					(define (compile-sym g env s Is)
 | 
				
			||||||
  (let ((loc (lookup-sym s env 0 #t)))
 | 
					  (let ((loc (lookup-sym s env -1 #t)))
 | 
				
			||||||
    (case (car loc)
 | 
					    (case (car loc)
 | 
				
			||||||
      (arg     (emit g (aref Is 0) (cadr loc)))
 | 
					      (arg     (emit g (aref Is 0) (cadr loc)))
 | 
				
			||||||
      (closed  (emit g (aref Is 1) (cadr loc) (caddr loc)))
 | 
					      (closed  (emit g (aref Is 1) (cadr loc) (caddr loc)))
 | 
				
			||||||
| 
						 | 
					@ -303,6 +303,14 @@
 | 
				
			||||||
	(begin (just-compile-args g lst env)
 | 
						(begin (just-compile-args g lst env)
 | 
				
			||||||
	       (length lst)))))
 | 
						       (length lst)))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(define (emit-nothing g) g)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(define (argc-error head count)
 | 
				
			||||||
 | 
					  (error (string "compile error: " head " expects " count
 | 
				
			||||||
 | 
							 (if (= count 1)
 | 
				
			||||||
 | 
							     " argument."
 | 
				
			||||||
 | 
							     " arguments."))))
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
(define (compile-app g env tail? x)
 | 
					(define (compile-app g env tail? x)
 | 
				
			||||||
  (let ((head  (car x)))
 | 
					  (let ((head  (car x)))
 | 
				
			||||||
    (let ((head
 | 
					    (let ((head
 | 
				
			||||||
| 
						 | 
					@ -322,13 +330,24 @@
 | 
				
			||||||
	      (let ((count (get arg-counts b #f)))
 | 
						      (let ((count (get arg-counts b #f)))
 | 
				
			||||||
		(if (and count
 | 
							(if (and count
 | 
				
			||||||
			 (not (length= (cdr x) count)))
 | 
								 (not (length= (cdr x) count)))
 | 
				
			||||||
		    (error (string "compile error: " head " expects " count
 | 
							    (argc-error head count))
 | 
				
			||||||
				   (if (= count 1)
 | 
							(case b  ; handle special cases of vararg builtins
 | 
				
			||||||
				       " argument."
 | 
							  (:list (if (= nargs 0) (emit g :loadnil) (emit g b nargs)))
 | 
				
			||||||
				       " arguments."))))
 | 
							  (:+    (if (= nargs 0) (emit g :load0)
 | 
				
			||||||
		(if (memq b '(:list :+ :- :* :/ :vector))
 | 
								     (if (= nargs 1) (emit-nothing g)
 | 
				
			||||||
		    (emit g b nargs)
 | 
									 (emit g b nargs))))
 | 
				
			||||||
		    (emit g (if (and tail? (eq? b :apply)) :tapply b))))
 | 
							  (:-    (if (= nargs 0)
 | 
				
			||||||
 | 
								     (argc-error head 1)
 | 
				
			||||||
 | 
								     (emit g b nargs)))
 | 
				
			||||||
 | 
							  (:*    (if (= nargs 0) (emit g :load1)
 | 
				
			||||||
 | 
								     (if (= nargs 1) (emit-nothing g)
 | 
				
			||||||
 | 
									 (emit g b nargs))))
 | 
				
			||||||
 | 
							  (:/    (if (= nargs 0)
 | 
				
			||||||
 | 
								     (argc-error head 1)
 | 
				
			||||||
 | 
								     (emit g b nargs)))
 | 
				
			||||||
 | 
							  (:vector   (emit g b nargs))
 | 
				
			||||||
 | 
							  (else
 | 
				
			||||||
 | 
							   (emit g (if (and tail? (eq? b :apply)) :tapply b)))))
 | 
				
			||||||
	      (emit g (if tail? :tcall :call) nargs)))))))
 | 
						      (emit g (if tail? :tcall :call) nargs)))))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(define (compile-in g env tail? x)
 | 
					(define (compile-in g env tail? x)
 | 
				
			||||||
| 
						 | 
					@ -360,10 +379,14 @@
 | 
				
			||||||
	   (else   (compile-app g env tail? x))))))
 | 
						   (else   (compile-app g env tail? x))))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(define (compile-f env f)
 | 
					(define (compile-f env f)
 | 
				
			||||||
  (let ((g (make-code-emitter)))
 | 
					  (let ((g    (make-code-emitter))
 | 
				
			||||||
    (compile-in g (cons (to-proper (cadr f)) env) #t (caddr f))
 | 
						(args (cadr f)))
 | 
				
			||||||
 | 
					    (if (null? (lastcdr args))
 | 
				
			||||||
 | 
						(emit g :argc  (length args))
 | 
				
			||||||
 | 
						(emit g :vargc (length args)))
 | 
				
			||||||
 | 
					    (compile-in g (cons (to-proper args) env) #t (caddr f))
 | 
				
			||||||
    (emit g :ret)
 | 
					    (emit g :ret)
 | 
				
			||||||
    `(compiled-lambda ,(cadr f) ,(bytecode g))))
 | 
					    `(compiled-lambda ,args ,(bytecode g))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(define (compile x)
 | 
					(define (compile x)
 | 
				
			||||||
  (bytecode (compile-in (make-code-emitter) () #t x)))
 | 
					  (bytecode (compile-in (make-code-emitter) () #t x)))
 | 
				
			||||||
| 
						 | 
					@ -410,7 +433,8 @@
 | 
				
			||||||
		      (print-val (aref vals (aref code i)))
 | 
							      (print-val (aref vals (aref code i)))
 | 
				
			||||||
		      (set! i (+ i 1)))
 | 
							      (set! i (+ i 1)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		     ((:loada :seta :call :tcall :list :+ :- :* :/ :vector)
 | 
							     ((:loada :seta :call :tcall :list :+ :- :* :/ :vector
 | 
				
			||||||
 | 
							       :argc :vargc)
 | 
				
			||||||
		      (princ (number->string (aref code i)))
 | 
							      (princ (number->string (aref code i)))
 | 
				
			||||||
		      (set! i (+ i 1)))
 | 
							      (set! i (+ i 1)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -223,26 +223,17 @@ int isstring(value_t v)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// convert to malloc representation (fixed address)
 | 
					// convert to malloc representation (fixed address)
 | 
				
			||||||
/*
 | 
					void cv_pin(cvalue_t *cv)
 | 
				
			||||||
static void cv_pin(cvalue_t *cv)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (!cv->flags.inlined)
 | 
					    if (!isinlined(cv))
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    size_t sz = cv->flags.inllen;
 | 
					    size_t sz = cv_len(cv);
 | 
				
			||||||
 | 
					    if (cv_isstr(cv)) sz++;
 | 
				
			||||||
    void *data = malloc(sz);
 | 
					    void *data = malloc(sz);
 | 
				
			||||||
    cv->flags.inlined = 0;
 | 
					    memcpy(data, cv_data(cv), sz);
 | 
				
			||||||
    // TODO: handle flags.cstring
 | 
					 | 
				
			||||||
    if (cv->flags.prim) {
 | 
					 | 
				
			||||||
        memcpy(data, (void*)(&((cprim_t*)cv)->data), sz);
 | 
					 | 
				
			||||||
        ((cprim_t*)cv)->data = data;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    else {
 | 
					 | 
				
			||||||
        memcpy(data, (void*)(&cv->data), sz);
 | 
					 | 
				
			||||||
    cv->data = data;
 | 
					    cv->data = data;
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    autorelease(cv);
 | 
					    autorelease(cv);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define num_init(ctype, cnvt, tag)                              \
 | 
					#define num_init(ctype, cnvt, tag)                              \
 | 
				
			||||||
static int cvalue_##ctype##_init(fltype_t *type, value_t arg,   \
 | 
					static int cvalue_##ctype##_init(fltype_t *type, value_t arg,   \
 | 
				
			||||||
| 
						 | 
					@ -703,6 +694,15 @@ value_t fl_copy(value_t *args, u_int32_t nargs)
 | 
				
			||||||
    return cvalue_copy(args[0]);
 | 
					    return cvalue_copy(args[0]);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					value_t fl_cv_pin(value_t *args, u_int32_t nargs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    argcount("cvalue.pin", nargs, 1);
 | 
				
			||||||
 | 
					    if (!iscvalue(args[0]))
 | 
				
			||||||
 | 
					        lerror(ArgError, "cvalue.pin: must be a byte array");
 | 
				
			||||||
 | 
					    cv_pin((cvalue_t*)ptr(args[0]));
 | 
				
			||||||
 | 
					    return args[0];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void cvalue_init(fltype_t *type, value_t v, void *dest)
 | 
					static void cvalue_init(fltype_t *type, value_t v, void *dest)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    cvinitfunc_t f=type->init;
 | 
					    cvinitfunc_t f=type->init;
 | 
				
			||||||
| 
						 | 
					@ -907,6 +907,7 @@ static builtinspec_t cvalues_builtin_info[] = {
 | 
				
			||||||
    { "sizeof", cvalue_sizeof },
 | 
					    { "sizeof", cvalue_sizeof },
 | 
				
			||||||
    { "builtin", fl_builtin },
 | 
					    { "builtin", fl_builtin },
 | 
				
			||||||
    { "copy", fl_copy },
 | 
					    { "copy", fl_copy },
 | 
				
			||||||
 | 
					    { "cvalue.pin", fl_cv_pin },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    { "logand", fl_logand },
 | 
					    { "logand", fl_logand },
 | 
				
			||||||
    { "logior", fl_logior },
 | 
					    { "logior", fl_logior },
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -50,6 +50,7 @@
 | 
				
			||||||
#include <math.h>
 | 
					#include <math.h>
 | 
				
			||||||
#include "llt.h"
 | 
					#include "llt.h"
 | 
				
			||||||
#include "flisp.h"
 | 
					#include "flisp.h"
 | 
				
			||||||
 | 
					#include "opcodes.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static char *builtin_names[] =
 | 
					static char *builtin_names[] =
 | 
				
			||||||
    { // special forms
 | 
					    { // special forms
 | 
				
			||||||
| 
						 | 
					@ -70,7 +71,7 @@ static char *builtin_names[] =
 | 
				
			||||||
      "+", "-", "*", "/", "<", "compare",
 | 
					      "+", "-", "*", "/", "<", "compare",
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // sequences
 | 
					      // sequences
 | 
				
			||||||
      "vector", "aref", "aset!", "length", "for",
 | 
					      "vector", "aref", "aset!", "for",
 | 
				
			||||||
      "", "", "" };
 | 
					      "", "", "" };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define N_STACK 262144
 | 
					#define N_STACK 262144
 | 
				
			||||||
| 
						 | 
					@ -88,7 +89,7 @@ stackseg_t stackseg0 = { StaticStack, 0, NULL };
 | 
				
			||||||
stackseg_t *current_stack_seg = &stackseg0;
 | 
					stackseg_t *current_stack_seg = &stackseg0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
value_t NIL, FL_T, FL_F, LAMBDA, QUOTE, IF, TRYCATCH;
 | 
					value_t NIL, FL_T, FL_F, LAMBDA, QUOTE, IF, TRYCATCH;
 | 
				
			||||||
value_t BACKQUOTE, COMMA, COMMAAT, COMMADOT;
 | 
					value_t BACKQUOTE, COMMA, COMMAAT, COMMADOT, COMPILEDLAMBDA;
 | 
				
			||||||
value_t IOError, ParseError, TypeError, ArgError, UnboundError, MemoryError;
 | 
					value_t IOError, ParseError, TypeError, ArgError, UnboundError, MemoryError;
 | 
				
			||||||
value_t DivideError, BoundsError, Error, KeyError, EnumerationError;
 | 
					value_t DivideError, BoundsError, Error, KeyError, EnumerationError;
 | 
				
			||||||
value_t conssym, symbolsym, fixnumsym, vectorsym, builtinsym;
 | 
					value_t conssym, symbolsym, fixnumsym, vectorsym, builtinsym;
 | 
				
			||||||
| 
						 | 
					@ -96,6 +97,7 @@ value_t definesym, defmacrosym, forsym, labelsym, printprettysym, setqsym;
 | 
				
			||||||
value_t printwidthsym, tsym, Tsym, fsym, Fsym, booleansym, nullsym, elsesym;
 | 
					value_t printwidthsym, tsym, Tsym, fsym, Fsym, booleansym, nullsym, elsesym;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static value_t eval_sexpr(value_t e, value_t *penv, int tail);
 | 
					static value_t eval_sexpr(value_t e, value_t *penv, int tail);
 | 
				
			||||||
 | 
					static value_t apply_cl(uint32_t nargs);
 | 
				
			||||||
static value_t *alloc_words(int n);
 | 
					static value_t *alloc_words(int n);
 | 
				
			||||||
static value_t relocate(value_t v);
 | 
					static value_t relocate(value_t v);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -770,7 +772,6 @@ static value_t eval_sexpr(value_t e, value_t *penv, int tail)
 | 
				
			||||||
    uint32_t saveSP, bp, envsz, nargs;
 | 
					    uint32_t saveSP, bp, envsz, nargs;
 | 
				
			||||||
    int i, noeval=0;
 | 
					    int i, noeval=0;
 | 
				
			||||||
    fixnum_t s, lo, hi;
 | 
					    fixnum_t s, lo, hi;
 | 
				
			||||||
    cvalue_t *cv;
 | 
					 | 
				
			||||||
    int64_t accum;
 | 
					    int64_t accum;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /*
 | 
					    /*
 | 
				
			||||||
| 
						 | 
					@ -1085,38 +1086,6 @@ static value_t eval_sexpr(value_t e, value_t *penv, int tail)
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case F_LENGTH:
 | 
					 | 
				
			||||||
            argcount("length", nargs, 1);
 | 
					 | 
				
			||||||
            if (isvector(Stack[SP-1])) {
 | 
					 | 
				
			||||||
                v = fixnum(vector_size(Stack[SP-1]));
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            else if (iscprim(Stack[SP-1])) {
 | 
					 | 
				
			||||||
                cv = (cvalue_t*)ptr(Stack[SP-1]);
 | 
					 | 
				
			||||||
                if (cp_class(cv) == bytetype) {
 | 
					 | 
				
			||||||
                    v = fixnum(1);
 | 
					 | 
				
			||||||
                    break;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                else if (cp_class(cv) == wchartype) {
 | 
					 | 
				
			||||||
                    v = fixnum(u8_charlen(*(uint32_t*)cp_data((cprim_t*)cv)));
 | 
					 | 
				
			||||||
                    break;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            else if (iscvalue(Stack[SP-1])) {
 | 
					 | 
				
			||||||
                cv = (cvalue_t*)ptr(Stack[SP-1]);
 | 
					 | 
				
			||||||
                if (cv_class(cv)->eltype != NULL) {
 | 
					 | 
				
			||||||
                    v = size_wrap(cvalue_arraylen(Stack[SP-1]));
 | 
					 | 
				
			||||||
                    break;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            else if (Stack[SP-1] == NIL) {
 | 
					 | 
				
			||||||
                v = fixnum(0); break;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            else if (iscons(Stack[SP-1])) {
 | 
					 | 
				
			||||||
                v = fixnum(llength(Stack[SP-1])); break;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            type_error("length", "sequence", Stack[SP-1]);
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
        case F_AREF:
 | 
					        case F_AREF:
 | 
				
			||||||
            argcount("aref", nargs, 2);
 | 
					            argcount("aref", nargs, 2);
 | 
				
			||||||
            v = Stack[SP-2];
 | 
					            v = Stack[SP-2];
 | 
				
			||||||
| 
						 | 
					@ -1152,7 +1121,7 @@ static value_t eval_sexpr(value_t e, value_t *penv, int tail)
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case F_ATOM:
 | 
					        case F_ATOM:
 | 
				
			||||||
            argcount("atom?", nargs, 1);
 | 
					            argcount("atom?", nargs, 1);
 | 
				
			||||||
            v = ((!iscons(Stack[SP-1])) ? FL_T : FL_F);
 | 
					            v = (iscons(Stack[SP-1]) ? FL_F : FL_T);
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case F_CONSP:
 | 
					        case F_CONSP:
 | 
				
			||||||
            argcount("pair?", nargs, 1);
 | 
					            argcount("pair?", nargs, 1);
 | 
				
			||||||
| 
						 | 
					@ -1325,24 +1294,23 @@ static value_t eval_sexpr(value_t e, value_t *penv, int tail)
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case F_EVAL:
 | 
					        case F_EVAL:
 | 
				
			||||||
            argcount("eval", nargs, 1);
 | 
					            argcount("eval", nargs, 1);
 | 
				
			||||||
            v = Stack[SP-1];
 | 
					            e = Stack[SP-1];
 | 
				
			||||||
            if (selfevaluating(v)) { SP=saveSP; return v; }
 | 
					            if (selfevaluating(e)) { SP=saveSP; return e; }
 | 
				
			||||||
            if (tail) {
 | 
					            if (tail) {
 | 
				
			||||||
                assert((ulong_t)(penv-Stack)<N_STACK);
 | 
					                assert((ulong_t)(penv-Stack)<N_STACK);
 | 
				
			||||||
                penv[-1] = fixnum(2);
 | 
					                penv[-1] = fixnum(2);
 | 
				
			||||||
                penv[0] = NIL;
 | 
					                penv[0] = NIL;
 | 
				
			||||||
                penv[1] = NIL;
 | 
					                penv[1] = NIL;
 | 
				
			||||||
                SP = (penv-Stack) + 2;
 | 
					                SP = (penv-Stack) + 2;
 | 
				
			||||||
                e=v;
 | 
					 | 
				
			||||||
                goto eval_top;
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            else {
 | 
					            else {
 | 
				
			||||||
                PUSH(fixnum(2));
 | 
					                PUSH(fixnum(2));
 | 
				
			||||||
                PUSH(NIL);
 | 
					                PUSH(NIL);
 | 
				
			||||||
                PUSH(NIL);
 | 
					                PUSH(NIL);
 | 
				
			||||||
                v = eval_sexpr(v, &Stack[SP-2], 1);
 | 
					                tail = 1;
 | 
				
			||||||
 | 
					                penv = &Stack[SP-2];
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            break;
 | 
					            goto eval_top;
 | 
				
			||||||
        case F_EVALSTAR:
 | 
					        case F_EVALSTAR:
 | 
				
			||||||
            argcount("eval*", nargs, 1);
 | 
					            argcount("eval*", nargs, 1);
 | 
				
			||||||
            e = Stack[SP-1];
 | 
					            e = Stack[SP-1];
 | 
				
			||||||
| 
						 | 
					@ -1404,9 +1372,14 @@ static value_t eval_sexpr(value_t e, value_t *penv, int tail)
 | 
				
			||||||
        SP = saveSP;
 | 
					        SP = saveSP;
 | 
				
			||||||
        return v;
 | 
					        return v;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (__likely(iscons(f))) {
 | 
					 | 
				
			||||||
        // apply lambda expression
 | 
					 | 
				
			||||||
    f = Stack[bp+1];
 | 
					    f = Stack[bp+1];
 | 
				
			||||||
 | 
					    if (__likely(iscons(f))) {
 | 
				
			||||||
 | 
					        if (car_(f) == COMPILEDLAMBDA) {
 | 
				
			||||||
 | 
					            v = apply_cl(nargs);
 | 
				
			||||||
 | 
					            SP = saveSP;
 | 
				
			||||||
 | 
					            return v;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        // apply lambda expression
 | 
				
			||||||
        f = Stack[bp+1] = cdr_(f);
 | 
					        f = Stack[bp+1] = cdr_(f);
 | 
				
			||||||
        if (!iscons(f)) goto notpair;
 | 
					        if (!iscons(f)) goto notpair;
 | 
				
			||||||
        v = car_(f); // arglist
 | 
					        v = car_(f); // arglist
 | 
				
			||||||
| 
						 | 
					@ -1422,19 +1395,17 @@ static value_t eval_sexpr(value_t e, value_t *penv, int tail)
 | 
				
			||||||
                lerror(ArgError, "apply: too many arguments");
 | 
					                lerror(ArgError, "apply: too many arguments");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else {
 | 
					        else {
 | 
				
			||||||
 | 
					            v = NIL;
 | 
				
			||||||
            if (i > 0) {
 | 
					            if (i > 0) {
 | 
				
			||||||
                list(&v, i, &NIL);
 | 
					                list(&v, i, &NIL);
 | 
				
			||||||
                if (nargs > MAX_ARGS) {
 | 
					                if (nargs > MAX_ARGS) {
 | 
				
			||||||
                    c = (cons_t*)curheap;
 | 
					                    c = (cons_t*)curheap;
 | 
				
			||||||
                    (c-2)->cdr = (c-1)->car;
 | 
					                    (c-2)->cdr = (c-1)->car;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            Stack[SP-i] = v;
 | 
					            Stack[SP-i] = v;
 | 
				
			||||||
            SP -= (i-1);
 | 
					            SP -= (i-1);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
            else {
 | 
					 | 
				
			||||||
                PUSH(NIL);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        f = cdr_(Stack[bp+1]);
 | 
					        f = cdr_(Stack[bp+1]);
 | 
				
			||||||
        if (!iscons(f)) goto notpair;
 | 
					        if (!iscons(f)) goto notpair;
 | 
				
			||||||
        e = car_(f);
 | 
					        e = car_(f);
 | 
				
			||||||
| 
						 | 
					@ -1477,6 +1448,503 @@ static value_t eval_sexpr(value_t e, value_t *penv, int tail)
 | 
				
			||||||
    return NIL;
 | 
					    return NIL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					  stack on entry: <func>  <args...>
 | 
				
			||||||
 | 
					  caller's responsibility:
 | 
				
			||||||
 | 
					  - put the stack in this state
 | 
				
			||||||
 | 
					  - provide arg count
 | 
				
			||||||
 | 
					  - respect tail position
 | 
				
			||||||
 | 
					  - call correct entry point (either eval_sexpr or apply_cl)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  callee's responsibility:
 | 
				
			||||||
 | 
					  - check arg counts
 | 
				
			||||||
 | 
					  - allocate vararg array
 | 
				
			||||||
 | 
					  - push closed env, set up new environment
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ** need 'copyenv' instruction that moves env to heap, installs
 | 
				
			||||||
 | 
					     heap version as the current env, and pushes the result vector.
 | 
				
			||||||
 | 
					     this can be used to implement the copy-closure op in terms of
 | 
				
			||||||
 | 
					     other ops. and it can be the first instruction in lambdas in
 | 
				
			||||||
 | 
					     head position (let optimization).
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					static value_t apply_cl(uint32_t nargs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint32_t i, n, ip, bp;
 | 
				
			||||||
 | 
					    fixnum_t s;
 | 
				
			||||||
 | 
					    int64_t accum;
 | 
				
			||||||
 | 
					    uint8_t op, *code;
 | 
				
			||||||
 | 
					    value_t func, v, bcode, x, e, ftl;
 | 
				
			||||||
 | 
					    value_t *penv, *pvals;
 | 
				
			||||||
 | 
					    symbol_t *sym;
 | 
				
			||||||
 | 
					    cons_t *c;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 apply_cl_top:
 | 
				
			||||||
 | 
					    func = Stack[SP-nargs-1];
 | 
				
			||||||
 | 
					    ftl = cdr_(cdr_(func));
 | 
				
			||||||
 | 
					    bcode = car_(ftl);
 | 
				
			||||||
 | 
					    code = cv_data((cvalue_t*)ptr(car_(bcode)));
 | 
				
			||||||
 | 
					    i = code[1];
 | 
				
			||||||
 | 
					    if (nargs < i)
 | 
				
			||||||
 | 
					        lerror(ArgError, "apply: too few arguments");
 | 
				
			||||||
 | 
					    if (code[0] == OP_VARGC) {
 | 
				
			||||||
 | 
					        s = (fixnum_t)nargs - (fixnum_t)i;
 | 
				
			||||||
 | 
					        v = NIL;
 | 
				
			||||||
 | 
					        if (s > 0) {
 | 
				
			||||||
 | 
					            list(&v, s, &NIL);
 | 
				
			||||||
 | 
					            if (nargs > MAX_ARGS) {
 | 
				
			||||||
 | 
					                c = (cons_t*)curheap;
 | 
				
			||||||
 | 
					                (c-2)->cdr = (c-1)->car;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            // reload movable pointers
 | 
				
			||||||
 | 
					            func = Stack[SP-nargs-1];
 | 
				
			||||||
 | 
					            ftl = cdr_(cdr_(func));
 | 
				
			||||||
 | 
					            bcode = car_(ftl);
 | 
				
			||||||
 | 
					            code = cv_data((cvalue_t*)ptr(car_(bcode)));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        Stack[SP-s] = v;
 | 
				
			||||||
 | 
					        SP -= (s-1);
 | 
				
			||||||
 | 
					        nargs = i+1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else if (nargs > i) {
 | 
				
			||||||
 | 
					        lerror(ArgError, "apply: too many arguments");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bp = SP-nargs;
 | 
				
			||||||
 | 
					    x = cdr_(ftl);   // cloenv
 | 
				
			||||||
 | 
					    Stack[bp-1] = car_(cdr_(func));  // lambda list
 | 
				
			||||||
 | 
					    penv = &Stack[bp-1];
 | 
				
			||||||
 | 
					    PUSH(x);
 | 
				
			||||||
 | 
					    PUSH(cdr_(bcode));
 | 
				
			||||||
 | 
					    pvals = &Stack[SP-1];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ip = 2;
 | 
				
			||||||
 | 
					    while (1) {
 | 
				
			||||||
 | 
					        op = code[ip++];
 | 
				
			||||||
 | 
					        switch (op) {
 | 
				
			||||||
 | 
					        case OP_NOP: break;
 | 
				
			||||||
 | 
					        case OP_DUP: v = Stack[SP-1]; PUSH(v); break;
 | 
				
			||||||
 | 
					        case OP_POP: (void)POP(); break;
 | 
				
			||||||
 | 
					        case OP_TCALL:
 | 
				
			||||||
 | 
					        case OP_CALL:
 | 
				
			||||||
 | 
					            i = code[ip++];  // nargs
 | 
				
			||||||
 | 
					        do_call:
 | 
				
			||||||
 | 
					            s = SP;
 | 
				
			||||||
 | 
					            func = Stack[SP-i-1];
 | 
				
			||||||
 | 
					            if (isbuiltinish(func)) {
 | 
				
			||||||
 | 
					                if (uintval(func) > N_BUILTINS) {
 | 
				
			||||||
 | 
					                    v = ((builtin_t)ptr(func))(&Stack[SP-i], i);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else {
 | 
				
			||||||
 | 
					                if (iscons(func) && car_(func) == COMPILEDLAMBDA) {
 | 
				
			||||||
 | 
					                    if (op == OP_TCALL) {
 | 
				
			||||||
 | 
					                        for(s=-1; s < (fixnum_t)i; s++)
 | 
				
			||||||
 | 
					                            Stack[bp+s] = Stack[SP-i+s];
 | 
				
			||||||
 | 
					                        SP = bp+i;
 | 
				
			||||||
 | 
					                        nargs = i;
 | 
				
			||||||
 | 
					                        goto apply_cl_top;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    else {
 | 
				
			||||||
 | 
					                        v = apply_cl(i);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            SP = s-i-1;
 | 
				
			||||||
 | 
					            PUSH(v);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case OP_JMP: ip = (uint32_t)*(uint16_t*)&code[ip]; break;
 | 
				
			||||||
 | 
					        case OP_BRF:
 | 
				
			||||||
 | 
					            v = POP();
 | 
				
			||||||
 | 
					            if (v == FL_F) ip = (uint32_t)*(uint16_t*)&code[ip];
 | 
				
			||||||
 | 
					            else ip += 2;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case OP_BRT:
 | 
				
			||||||
 | 
					            v = POP();
 | 
				
			||||||
 | 
					            if (v != FL_F) ip = (uint32_t)*(uint16_t*)&code[ip];
 | 
				
			||||||
 | 
					            else ip += 2;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case OP_JMPL: ip = *(uint32_t*)&code[ip]; break;
 | 
				
			||||||
 | 
					        case OP_BRFL:
 | 
				
			||||||
 | 
					            v = POP();
 | 
				
			||||||
 | 
					            if (v == FL_F) ip = *(uint32_t*)&code[ip];
 | 
				
			||||||
 | 
					            else ip += 4;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case OP_BRTL:
 | 
				
			||||||
 | 
					            v = POP();
 | 
				
			||||||
 | 
					            if (v != FL_F) ip = *(uint32_t*)&code[ip];
 | 
				
			||||||
 | 
					            else ip += 4;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case OP_RET: v = POP(); return v;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case OP_EQ:
 | 
				
			||||||
 | 
					            Stack[SP-2] = ((Stack[SP-2] == Stack[SP-1]) ? FL_T : FL_F);
 | 
				
			||||||
 | 
					            POP(); break;
 | 
				
			||||||
 | 
					        case OP_EQV:
 | 
				
			||||||
 | 
					            if (Stack[SP-2] == Stack[SP-1]) {
 | 
				
			||||||
 | 
					                v = FL_T;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else if (!leafp(Stack[SP-2]) || !leafp(Stack[SP-1])) {
 | 
				
			||||||
 | 
					                v = FL_F;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else {
 | 
				
			||||||
 | 
					                v = (numval(compare(Stack[SP-2], Stack[SP-1]))==0) ?
 | 
				
			||||||
 | 
					                    FL_T : FL_F;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            Stack[SP-2] = v; POP();
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case OP_EQUAL:
 | 
				
			||||||
 | 
					            if (Stack[SP-2] == Stack[SP-1]) {
 | 
				
			||||||
 | 
					                v = FL_T;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else if (eq_comparable(Stack[SP-2],Stack[SP-1])) {
 | 
				
			||||||
 | 
					                v = FL_F;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else {
 | 
				
			||||||
 | 
					                v = (numval(compare(Stack[SP-2], Stack[SP-1]))==0) ?
 | 
				
			||||||
 | 
					                    FL_T : FL_F;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            Stack[SP-2] = v; POP();
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case OP_PAIRP:
 | 
				
			||||||
 | 
					            Stack[SP-1] = (iscons(Stack[SP-1]) ? FL_T : FL_F); break;
 | 
				
			||||||
 | 
					        case OP_ATOMP:
 | 
				
			||||||
 | 
					            Stack[SP-1] = (iscons(Stack[SP-1]) ? FL_F : FL_T); break;
 | 
				
			||||||
 | 
					        case OP_NOT:
 | 
				
			||||||
 | 
					            Stack[SP-1] = ((Stack[SP-1]==FL_F) ? FL_T : FL_F); break;
 | 
				
			||||||
 | 
					        case OP_NULLP:
 | 
				
			||||||
 | 
					            Stack[SP-1] = ((Stack[SP-1]==NIL) ? FL_T : FL_F); break;
 | 
				
			||||||
 | 
					        case OP_BOOLEANP:
 | 
				
			||||||
 | 
					            v = Stack[SP-1];
 | 
				
			||||||
 | 
					            Stack[SP-1] = ((v == FL_T || v == FL_F) ? FL_T : FL_F); break;
 | 
				
			||||||
 | 
					        case OP_SYMBOLP:
 | 
				
			||||||
 | 
					            Stack[SP-1] = (issymbol(Stack[SP-1]) ? FL_T : FL_F); break;
 | 
				
			||||||
 | 
					        case OP_NUMBERP:
 | 
				
			||||||
 | 
					            v = Stack[SP-1];
 | 
				
			||||||
 | 
					            Stack[SP-1] = (isfixnum(v) || iscprim(v) ? FL_T : FL_F); break;
 | 
				
			||||||
 | 
					        case OP_FIXNUMP:
 | 
				
			||||||
 | 
					            Stack[SP-1] = (isfixnum(Stack[SP-1]) ? FL_T : FL_F); break;
 | 
				
			||||||
 | 
					        case OP_BOUNDP:
 | 
				
			||||||
 | 
					            sym = tosymbol(Stack[SP-1], "bound?");
 | 
				
			||||||
 | 
					            Stack[SP-1] = ((sym->binding == UNBOUND) ? FL_F : FL_T);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case OP_BUILTINP:
 | 
				
			||||||
 | 
					            v = Stack[SP-1];
 | 
				
			||||||
 | 
					            Stack[SP-1] = ((isbuiltinish(v) && v!=FL_F && v!=FL_T && v!=NIL)
 | 
				
			||||||
 | 
					                           ? FL_T : FL_F);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case OP_VECTORP:
 | 
				
			||||||
 | 
					            Stack[SP-1] = (isvector(Stack[SP-1]) ? FL_T : FL_F); break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case OP_CONS:
 | 
				
			||||||
 | 
					            if (curheap > lim)
 | 
				
			||||||
 | 
					                gc(0);
 | 
				
			||||||
 | 
					            c = (cons_t*)curheap;
 | 
				
			||||||
 | 
					            curheap += sizeof(cons_t);
 | 
				
			||||||
 | 
					            c->car = Stack[SP-2];
 | 
				
			||||||
 | 
					            c->cdr = Stack[SP-1];
 | 
				
			||||||
 | 
					            Stack[SP-2] = tagptr(c, TAG_CONS);
 | 
				
			||||||
 | 
					            POP(); break;
 | 
				
			||||||
 | 
					        case OP_CAR:
 | 
				
			||||||
 | 
					            c = tocons(Stack[SP-1], "car");
 | 
				
			||||||
 | 
					            Stack[SP-1] = c->car;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case OP_CDR:
 | 
				
			||||||
 | 
					            c = tocons(Stack[SP-1], "cdr");
 | 
				
			||||||
 | 
					            Stack[SP-1] = c->cdr;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case OP_SETCAR:
 | 
				
			||||||
 | 
					            car(Stack[SP-2]) = Stack[SP-1];
 | 
				
			||||||
 | 
					            POP(); break;
 | 
				
			||||||
 | 
					        case OP_SETCDR:
 | 
				
			||||||
 | 
					            cdr(Stack[SP-2]) = Stack[SP-1];
 | 
				
			||||||
 | 
					            POP(); break;
 | 
				
			||||||
 | 
					        case OP_LIST:
 | 
				
			||||||
 | 
					            i = code[ip++];
 | 
				
			||||||
 | 
					            list(&v, i, &NIL);
 | 
				
			||||||
 | 
					            POPN(i);
 | 
				
			||||||
 | 
					            PUSH(v);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case OP_EVAL:
 | 
				
			||||||
 | 
					            v = toplevel_eval(POP());
 | 
				
			||||||
 | 
					            PUSH(v);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case OP_EVALSTAR:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case OP_TAPPLY:
 | 
				
			||||||
 | 
					        case OP_APPLY:
 | 
				
			||||||
 | 
					            v = POP();  // arglist
 | 
				
			||||||
 | 
					            i = SP;
 | 
				
			||||||
 | 
					            while (iscons(v)) {
 | 
				
			||||||
 | 
					                if (SP-i == MAX_ARGS) {
 | 
				
			||||||
 | 
					                    PUSH(v);
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                PUSH(car_(v));
 | 
				
			||||||
 | 
					                v = cdr_(v);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            i = SP-i;
 | 
				
			||||||
 | 
					            if (op==OP_TAPPLY) op = OP_TCALL;
 | 
				
			||||||
 | 
					            goto do_call;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case OP_ADD:
 | 
				
			||||||
 | 
					            s = 0;
 | 
				
			||||||
 | 
					            n = code[ip++];
 | 
				
			||||||
 | 
					            i = SP-n;
 | 
				
			||||||
 | 
					            if (n > MAX_ARGS) goto add_ovf;
 | 
				
			||||||
 | 
					            for (; i < (int)SP; i++) {
 | 
				
			||||||
 | 
					                if (__likely(isfixnum(Stack[i]))) {
 | 
				
			||||||
 | 
					                    s += numval(Stack[i]);
 | 
				
			||||||
 | 
					                    if (__unlikely(!fits_fixnum(s))) {
 | 
				
			||||||
 | 
					                        i++;
 | 
				
			||||||
 | 
					                        goto add_ovf;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                else {
 | 
				
			||||||
 | 
					                add_ovf:
 | 
				
			||||||
 | 
					                    v = fl_add_any(&Stack[i], SP-i, s);
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            if (i==SP)
 | 
				
			||||||
 | 
					                v = fixnum(s);
 | 
				
			||||||
 | 
					            POPN(n);
 | 
				
			||||||
 | 
					            PUSH(v);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case OP_SUB:
 | 
				
			||||||
 | 
					            n = code[ip++];
 | 
				
			||||||
 | 
					            if (__unlikely(n < 1)) lerror(ArgError, "-: too few arguments");
 | 
				
			||||||
 | 
					            i = SP-n;
 | 
				
			||||||
 | 
					            if (n == 1) {
 | 
				
			||||||
 | 
					                if (__likely(isfixnum(Stack[i])))
 | 
				
			||||||
 | 
					                    Stack[SP-1] = fixnum(-numval(Stack[i]));
 | 
				
			||||||
 | 
					                else
 | 
				
			||||||
 | 
					                    Stack[SP-1] = fl_neg(Stack[i]);
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            if (n == 2) {
 | 
				
			||||||
 | 
					                if (__likely(bothfixnums(Stack[i], Stack[i+1]))) {
 | 
				
			||||||
 | 
					                    s = numval(Stack[i]) - numval(Stack[i+1]);
 | 
				
			||||||
 | 
					                    if (__likely(fits_fixnum(s))) {
 | 
				
			||||||
 | 
					                        POP();
 | 
				
			||||||
 | 
					                        Stack[SP-1] = fixnum(s);
 | 
				
			||||||
 | 
					                        break;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    Stack[i+1] = fixnum(-numval(Stack[i+1]));
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                else {
 | 
				
			||||||
 | 
					                    Stack[i+1] = fl_neg(Stack[i+1]);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else {
 | 
				
			||||||
 | 
					                // we need to pass the full arglist on to fl_add_any
 | 
				
			||||||
 | 
					                // so it can handle rest args properly
 | 
				
			||||||
 | 
					                PUSH(Stack[i]);
 | 
				
			||||||
 | 
					                Stack[i] = fixnum(0);
 | 
				
			||||||
 | 
					                Stack[i+1] = fl_neg(fl_add_any(&Stack[i], n, 0));
 | 
				
			||||||
 | 
					                Stack[i] = POP();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            v = fl_add_any(&Stack[i], 2, 0);
 | 
				
			||||||
 | 
					            POPN(n);
 | 
				
			||||||
 | 
					            PUSH(v);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case OP_MUL:
 | 
				
			||||||
 | 
					            accum = 1;
 | 
				
			||||||
 | 
					            n = code[ip++];
 | 
				
			||||||
 | 
					            i = SP-n;
 | 
				
			||||||
 | 
					            if (n > MAX_ARGS) goto mul_ovf;
 | 
				
			||||||
 | 
					            for (; i < (int)SP; i++) {
 | 
				
			||||||
 | 
					                if (__likely(isfixnum(Stack[i]))) {
 | 
				
			||||||
 | 
					                    accum *= numval(Stack[i]);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                else {
 | 
				
			||||||
 | 
					                mul_ovf:
 | 
				
			||||||
 | 
					                    v = fl_mul_any(&Stack[i], SP-i, accum);
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            if (i == SP) {
 | 
				
			||||||
 | 
					                if (__likely(fits_fixnum(accum)))
 | 
				
			||||||
 | 
					                    v = fixnum(accum);
 | 
				
			||||||
 | 
					                else
 | 
				
			||||||
 | 
					                    v = return_from_int64(accum);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            POPN(n);
 | 
				
			||||||
 | 
					            PUSH(v);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case OP_DIV:
 | 
				
			||||||
 | 
					            n = code[ip++];
 | 
				
			||||||
 | 
					            if (__unlikely(n < 1)) lerror(ArgError, "/: too few arguments");
 | 
				
			||||||
 | 
					            i = SP-n;
 | 
				
			||||||
 | 
					            if (n == 1) {
 | 
				
			||||||
 | 
					                Stack[SP-1] = fl_div2(fixnum(1), Stack[i]);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else {
 | 
				
			||||||
 | 
					                if (n > 2) {
 | 
				
			||||||
 | 
					                    PUSH(Stack[i]);
 | 
				
			||||||
 | 
					                    Stack[i] = fixnum(1);
 | 
				
			||||||
 | 
					                    Stack[i+1] = fl_mul_any(&Stack[i], n, 1);
 | 
				
			||||||
 | 
					                    Stack[i] = POP();
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                v = fl_div2(Stack[i], Stack[i+1]);
 | 
				
			||||||
 | 
					                POPN(n);
 | 
				
			||||||
 | 
					                PUSH(v);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case OP_LT:
 | 
				
			||||||
 | 
					            if (bothfixnums(Stack[SP-2], Stack[SP-1])) {
 | 
				
			||||||
 | 
					                v = (numval(Stack[SP-2]) < numval(Stack[SP-1])) ? FL_T : FL_F;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else {
 | 
				
			||||||
 | 
					                v = (numval(compare(Stack[SP-2], Stack[SP-1])) < 0) ?
 | 
				
			||||||
 | 
					                    FL_T : FL_F;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            POP();
 | 
				
			||||||
 | 
					            Stack[SP-1] = v;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case OP_COMPARE:
 | 
				
			||||||
 | 
					            Stack[SP-2] = compare(Stack[SP-2], Stack[SP-1]);
 | 
				
			||||||
 | 
					            POP();
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case OP_VECTOR:
 | 
				
			||||||
 | 
					            n = code[ip++];
 | 
				
			||||||
 | 
					            if (n > MAX_ARGS) {
 | 
				
			||||||
 | 
					                i = llength(Stack[SP-1]);
 | 
				
			||||||
 | 
					                n--;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else i = 0;
 | 
				
			||||||
 | 
					            v = alloc_vector(n+i, 0);
 | 
				
			||||||
 | 
					            memcpy(&vector_elt(v,0), &Stack[SP-n], n*sizeof(value_t));
 | 
				
			||||||
 | 
					            if (i > 0) {
 | 
				
			||||||
 | 
					                e = POP();
 | 
				
			||||||
 | 
					                POPN(n);
 | 
				
			||||||
 | 
					                while (iscons(e)) {
 | 
				
			||||||
 | 
					                    vector_elt(v,n) = car_(e);
 | 
				
			||||||
 | 
					                    n++;
 | 
				
			||||||
 | 
					                    e = cdr_(e);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            PUSH(v);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case OP_AREF:
 | 
				
			||||||
 | 
					            v = Stack[SP-2];
 | 
				
			||||||
 | 
					            if (isvector(v)) {
 | 
				
			||||||
 | 
					                i = tofixnum(Stack[SP-1], "aref");
 | 
				
			||||||
 | 
					                if (__unlikely((unsigned)i >= vector_size(v)))
 | 
				
			||||||
 | 
					                    bounds_error("aref", v, Stack[SP-1]);
 | 
				
			||||||
 | 
					                v = vector_elt(v, i);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else if (isarray(v)) {
 | 
				
			||||||
 | 
					                v = cvalue_array_aref(&Stack[SP-2]);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else {
 | 
				
			||||||
 | 
					                type_error("aref", "sequence", v);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            POP();
 | 
				
			||||||
 | 
					            Stack[SP-1] = v;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case OP_ASET:
 | 
				
			||||||
 | 
					            e = Stack[SP-3];
 | 
				
			||||||
 | 
					            if (isvector(e)) {
 | 
				
			||||||
 | 
					                i = tofixnum(Stack[SP-2], "aset!");
 | 
				
			||||||
 | 
					                if (__unlikely((unsigned)i >= vector_size(e)))
 | 
				
			||||||
 | 
					                    bounds_error("aset!", v, Stack[SP-1]);
 | 
				
			||||||
 | 
					                vector_elt(e, i) = (v=Stack[SP-1]);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else if (isarray(e)) {
 | 
				
			||||||
 | 
					                v = cvalue_array_aset(&Stack[SP-3]);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else {
 | 
				
			||||||
 | 
					                type_error("aset!", "sequence", e);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            POPN(2);
 | 
				
			||||||
 | 
					            Stack[SP-1] = v;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case OP_FOR:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case OP_LOADT: PUSH(FL_T); break;
 | 
				
			||||||
 | 
					        case OP_LOADF: PUSH(FL_F); break;
 | 
				
			||||||
 | 
					        case OP_LOADNIL: PUSH(NIL); break;
 | 
				
			||||||
 | 
					        case OP_LOAD0: PUSH(fixnum(0)); break;
 | 
				
			||||||
 | 
					        case OP_LOAD1: PUSH(fixnum(1)); break;
 | 
				
			||||||
 | 
					        case OP_LOADV:
 | 
				
			||||||
 | 
					            v = vector_elt(*pvals, code[ip]); ip++;
 | 
				
			||||||
 | 
					            PUSH(v);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case OP_LOADVL:
 | 
				
			||||||
 | 
					            v = vector_elt(*pvals, *(uint32_t*)code[ip]); ip+=4;
 | 
				
			||||||
 | 
					            PUSH(v);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case OP_LOADGL:
 | 
				
			||||||
 | 
					            v = vector_elt(*pvals, *(uint32_t*)code[ip]); ip+=4;
 | 
				
			||||||
 | 
					            goto do_loadg;
 | 
				
			||||||
 | 
					        case OP_LOADG:
 | 
				
			||||||
 | 
					            v = vector_elt(*pvals, code[ip]); ip++;
 | 
				
			||||||
 | 
					        do_loadg:
 | 
				
			||||||
 | 
					            sym = (symbol_t*)ptr(v);
 | 
				
			||||||
 | 
					            if (sym->binding == UNBOUND)
 | 
				
			||||||
 | 
					                raise(list2(UnboundError, v));
 | 
				
			||||||
 | 
					            PUSH(sym->binding);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case OP_SETGL:
 | 
				
			||||||
 | 
					            v = vector_elt(*pvals, *(uint32_t*)code[ip]); ip+=4;
 | 
				
			||||||
 | 
					            goto do_setg;
 | 
				
			||||||
 | 
					        case OP_SETG:
 | 
				
			||||||
 | 
					            v = vector_elt(*pvals, code[ip]); ip++;
 | 
				
			||||||
 | 
					        do_setg:
 | 
				
			||||||
 | 
					            sym = (symbol_t*)ptr(v);
 | 
				
			||||||
 | 
					            v = Stack[SP-1];
 | 
				
			||||||
 | 
					            if (sym->syntax != TAG_CONST)
 | 
				
			||||||
 | 
					                sym->binding = v;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case OP_LOADA:
 | 
				
			||||||
 | 
					            i = code[ip++];
 | 
				
			||||||
 | 
					            if (penv[0] == NIL)
 | 
				
			||||||
 | 
					                v = vector_elt(penv[1], i+1);
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					                v = Stack[bp+i];
 | 
				
			||||||
 | 
					            PUSH(v);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case OP_SETA:
 | 
				
			||||||
 | 
					            v = Stack[SP-1];
 | 
				
			||||||
 | 
					            i = code[ip++];
 | 
				
			||||||
 | 
					            if (penv[0] == NIL)
 | 
				
			||||||
 | 
					                vector_elt(penv[1], i+1) = v;
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					                Stack[bp+i] = v;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case OP_LOADC:
 | 
				
			||||||
 | 
					        case OP_SETC:
 | 
				
			||||||
 | 
					            s = code[ip++];
 | 
				
			||||||
 | 
					            i = code[ip++];
 | 
				
			||||||
 | 
					            if (penv[0]==NIL) {
 | 
				
			||||||
 | 
					                if (nargs > 0) {
 | 
				
			||||||
 | 
					                    // current frame has been captured
 | 
				
			||||||
 | 
					                    s++;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                v = penv[1];
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else {
 | 
				
			||||||
 | 
					                v = penv[numval(penv[-1])-1];
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            while (s--)
 | 
				
			||||||
 | 
					                v = vector_elt(v, vector_size(v)-1);
 | 
				
			||||||
 | 
					            if (op == OP_SETC)
 | 
				
			||||||
 | 
					                vector_elt(v, i) = Stack[SP-1];
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					                PUSH(vector_elt(v, i));
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case OP_CLOSURE:
 | 
				
			||||||
 | 
					        case OP_TRYCATCH:
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// initialization -------------------------------------------------------------
 | 
					// initialization -------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern void builtins_init();
 | 
					extern void builtins_init();
 | 
				
			||||||
| 
						 | 
					@ -1510,6 +1978,7 @@ static void lisp_init(void)
 | 
				
			||||||
    FL_T = builtin(F_TRUE);
 | 
					    FL_T = builtin(F_TRUE);
 | 
				
			||||||
    FL_F = builtin(F_FALSE);
 | 
					    FL_F = builtin(F_FALSE);
 | 
				
			||||||
    LAMBDA = symbol("lambda");
 | 
					    LAMBDA = symbol("lambda");
 | 
				
			||||||
 | 
					    COMPILEDLAMBDA = symbol("compiled-lambda");
 | 
				
			||||||
    QUOTE = symbol("quote");
 | 
					    QUOTE = symbol("quote");
 | 
				
			||||||
    TRYCATCH = symbol("trycatch");
 | 
					    TRYCATCH = symbol("trycatch");
 | 
				
			||||||
    BACKQUOTE = symbol("backquote");
 | 
					    BACKQUOTE = symbol("backquote");
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -127,9 +127,9 @@ enum {
 | 
				
			||||||
    F_EVAL, F_EVALSTAR, F_APPLY,
 | 
					    F_EVAL, F_EVALSTAR, F_APPLY,
 | 
				
			||||||
    F_ADD, F_SUB, F_MUL, F_DIV, F_LT, F_COMPARE,
 | 
					    F_ADD, F_SUB, F_MUL, F_DIV, F_LT, F_COMPARE,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    F_VECTOR, F_AREF, F_ASET, F_LENGTH, F_FOR,
 | 
					    F_VECTOR, F_AREF, F_ASET, F_FOR,
 | 
				
			||||||
    F_TRUE, F_FALSE, F_NIL,
 | 
					    F_TRUE, F_FALSE, F_NIL,
 | 
				
			||||||
    N_BUILTINS,
 | 
					    N_BUILTINS
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
#define isspecial(v) (uintval(v) <= (unsigned int)F_BEGIN)
 | 
					#define isspecial(v) (uintval(v) <= (unsigned int)F_BEGIN)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -274,6 +274,7 @@ extern fltype_t *builtintype;
 | 
				
			||||||
value_t cvalue(fltype_t *type, size_t sz);
 | 
					value_t cvalue(fltype_t *type, size_t sz);
 | 
				
			||||||
void add_finalizer(cvalue_t *cv);
 | 
					void add_finalizer(cvalue_t *cv);
 | 
				
			||||||
void cv_autorelease(cvalue_t *cv);
 | 
					void cv_autorelease(cvalue_t *cv);
 | 
				
			||||||
 | 
					void cv_pin(cvalue_t *cv);
 | 
				
			||||||
size_t ctype_sizeof(value_t type, int *palign);
 | 
					size_t ctype_sizeof(value_t type, int *palign);
 | 
				
			||||||
value_t cvalue_copy(value_t v);
 | 
					value_t cvalue_copy(value_t v);
 | 
				
			||||||
value_t cvalue_from_data(fltype_t *type, void *data, size_t sz);
 | 
					value_t cvalue_from_data(fltype_t *type, void *data, size_t sz);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue