adding branch probability annotations
wrote a CPS transformer that can be used to provide coroutines misc. cleanup
This commit is contained in:
		
							parent
							
								
									b99d8715ce
								
							
						
					
					
						commit
						dc50df083c
					
				|  | @ -73,6 +73,14 @@ value_t fl_exit(value_t *args, u_int32_t nargs) | ||||||
|     return NIL; |     return NIL; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | value_t fl_intern(value_t *args, u_int32_t nargs) | ||||||
|  | { | ||||||
|  |     argcount("intern", nargs, 1); | ||||||
|  |     if (!isstring(args[0])) | ||||||
|  |         type_error("intern", "string", args[0]); | ||||||
|  |     return symbol(cvalue_data(args[0])); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| extern value_t LAMBDA; | extern value_t LAMBDA; | ||||||
| 
 | 
 | ||||||
| value_t fl_setsyntax(value_t *args, u_int32_t nargs) | value_t fl_setsyntax(value_t *args, u_int32_t nargs) | ||||||
|  | @ -241,7 +249,7 @@ value_t fl_time_now(value_t *args, u_int32_t nargs) | ||||||
|     return mk_double(clock_now()); |     return mk_double(clock_now()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static double value_to_double(value_t a, char *fname) | static double todouble(value_t a, char *fname) | ||||||
| { | { | ||||||
|     if (isfixnum(a)) |     if (isfixnum(a)) | ||||||
|         return (double)numval(a); |         return (double)numval(a); | ||||||
|  | @ -257,7 +265,7 @@ static double value_to_double(value_t a, char *fname) | ||||||
| value_t fl_time_string(value_t *args, uint32_t nargs) | value_t fl_time_string(value_t *args, uint32_t nargs) | ||||||
| { | { | ||||||
|     argcount("time.string", nargs, 1); |     argcount("time.string", nargs, 1); | ||||||
|     double t = value_to_double(args[0], "time.string"); |     double t = todouble(args[0], "time.string"); | ||||||
|     char buf[64]; |     char buf[64]; | ||||||
|     timestring(t, buf, sizeof(buf)); |     timestring(t, buf, sizeof(buf)); | ||||||
|     return string_from_cstr(buf); |     return string_from_cstr(buf); | ||||||
|  | @ -359,6 +367,7 @@ static builtinspec_t builtin_info[] = { | ||||||
|     { "read", fl_read }, |     { "read", fl_read }, | ||||||
|     { "load", fl_load }, |     { "load", fl_load }, | ||||||
|     { "exit", fl_exit }, |     { "exit", fl_exit }, | ||||||
|  |     { "intern", fl_intern }, | ||||||
|     { "fixnum", fl_fixnum }, |     { "fixnum", fl_fixnum }, | ||||||
|     { "truncate", fl_truncate }, |     { "truncate", fl_truncate }, | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -0,0 +1,167 @@ | ||||||
|  | (define (cond->if form) | ||||||
|  |   (cond-clauses->if (cdr form))) | ||||||
|  | (define (cond-clauses->if lst) | ||||||
|  |   (if (atom lst) | ||||||
|  |       lst | ||||||
|  |     (let ((clause (car lst))) | ||||||
|  |       `(if ,(car clause) | ||||||
|  |            ,(f-body (cdr clause)) | ||||||
|  |          ,(cond-clauses->if (cdr lst)))))) | ||||||
|  | 
 | ||||||
|  | (define (progn->cps forms k) | ||||||
|  |   (cond ((atom forms)       `(,k ,forms)) | ||||||
|  |         ((null (cdr forms)) (cps- (car forms) k)) | ||||||
|  |         (T (let ((_ (gensym)))   ; var to bind ignored value | ||||||
|  |              (cps- (car forms) `(lambda (,_) | ||||||
|  |                                   ,(progn->cps (cdr forms) k))))))) | ||||||
|  | 
 | ||||||
|  | (define (rest->cps xformer form k argsyms) | ||||||
|  |   (let ((g (gensym))) | ||||||
|  |     (cps- (car form) `(lambda (,g) | ||||||
|  |                         ,(xformer (cdr form) k (cons g argsyms)))))) | ||||||
|  | 
 | ||||||
|  | ; (f x) => (cps- f `(lambda (F) ,(cps- x `(lambda (X) (F ,k X))))) | ||||||
|  | (define (app->cps form k argsyms) | ||||||
|  |   (cond ((atom form) | ||||||
|  |          (let ((r (reverse argsyms))) | ||||||
|  |            `(,(car r) ,k ,@(cdr r)))) | ||||||
|  |         (T (rest->cps app->cps form k argsyms)))) | ||||||
|  | 
 | ||||||
|  | ; (+ x) => (cps- x `(lambda (X) (,k (+ X)))) | ||||||
|  | (define (builtincall->cps form k) | ||||||
|  |   (prim->cps (cdr form) k (list (car form)))) | ||||||
|  | (define (prim->cps form k argsyms) | ||||||
|  |   (cond ((atom form) `(,k ,(reverse argsyms))) | ||||||
|  |         (T           (rest->cps prim->cps form k argsyms)))) | ||||||
|  | 
 | ||||||
|  | (define (cps form) | ||||||
|  |   (η-reduce | ||||||
|  |    (β-reduce | ||||||
|  |     (macroexpand | ||||||
|  |      (cps- (macroexpand form) 'identity))))) | ||||||
|  | (define (cps- form k) | ||||||
|  |   (let ((g (gensym))) | ||||||
|  |     (cond ((or (atom form) (constantp form)) | ||||||
|  |            `(,k ,form)) | ||||||
|  | 
 | ||||||
|  |           ((eq (car form) 'lambda) | ||||||
|  |            `(,k (lambda ,(cons g (cadr form)) ,(cps- (caddr form) g)))) | ||||||
|  | 
 | ||||||
|  |           ((eq (car form) 'progn) | ||||||
|  |            (progn->cps (cdr form) k)) | ||||||
|  | 
 | ||||||
|  |           ((eq (car form) 'cond) | ||||||
|  |            (cps- (cond->if form) k)) | ||||||
|  | 
 | ||||||
|  |           ((eq (car form) 'if) | ||||||
|  |            (let ((test (cadr form)) | ||||||
|  |                  (then (caddr form)) | ||||||
|  |                  (else (cadddr form))) | ||||||
|  |              (if (atom k) | ||||||
|  |                  (cps- test `(lambda (,g) | ||||||
|  |                                (if ,g | ||||||
|  |                                    ,(cps- then k) | ||||||
|  |                                  ,(cps- else k)))) | ||||||
|  |                `(let ((,g ,k)) | ||||||
|  |                   ,(cps- form g))))) | ||||||
|  | 
 | ||||||
|  |           ((eq (car form) 'setq) | ||||||
|  |            (let ((var (cadr form)) | ||||||
|  |                  (E   (caddr form))) | ||||||
|  |              (cps- E `(lambda (,g) (,k (setq ,var ,g)))))) | ||||||
|  | 
 | ||||||
|  |           ((eq (car form) 'reset) | ||||||
|  |            `(,k ,(cps- (cadr form) 'identity))) | ||||||
|  | 
 | ||||||
|  |           ((eq (car form) 'shift) | ||||||
|  |            (let ((v (cadr form)) | ||||||
|  |                  (E (caddr form))) | ||||||
|  |              `(let ((,v (lambda (ignored-k val) (,k val)))) | ||||||
|  |                 ,(cps- E 'identity)))) | ||||||
|  | 
 | ||||||
|  |           ((and (constantp (car form)) | ||||||
|  |                 (builtinp (eval (car form)))) | ||||||
|  |            (builtincall->cps form k)) | ||||||
|  | 
 | ||||||
|  |           ; ((lambda (...) body) ...) | ||||||
|  |           ((and (consp (car form)) | ||||||
|  |                 (eq (caar form) 'lambda)) | ||||||
|  |            (let ((largs (cadr (car form))) | ||||||
|  |                  (lbody (caddr (car form)))) | ||||||
|  |              (if (null largs) | ||||||
|  |                  (cps- lbody k)  ; ((lambda () x)) | ||||||
|  |                (cps- (cadr form) `(lambda (,(car largs)) | ||||||
|  |                                     ,(cps- `((lambda ,(cdr largs) ,lbody) | ||||||
|  |                                              ,@(cddr form)) | ||||||
|  |                                            k)))))) | ||||||
|  | 
 | ||||||
|  |           (T | ||||||
|  |            (app->cps form k ()))))) | ||||||
|  | 
 | ||||||
|  | ; (lambda (args...) (f args...)) => f | ||||||
|  | (define (η-reduce form) | ||||||
|  |   (cond ((or (atom form) (constantp form)) form) | ||||||
|  |         ((and (eq (car form) 'lambda) | ||||||
|  |               (let ((body (caddr form)) | ||||||
|  |                     (args (cadr form))) | ||||||
|  |                 (and (consp body) | ||||||
|  |                      (equal (cdr body) args)))) | ||||||
|  |          (η-reduce (car (caddr form)))) | ||||||
|  |         (T (map η-reduce form)))) | ||||||
|  | 
 | ||||||
|  | ; ((lambda (f) (f arg)) X) => (X arg) | ||||||
|  | (define (β-reduce form) | ||||||
|  |   (cond ((or (atom form) (constantp form)) form) | ||||||
|  |         ((and (= (length form) 2) | ||||||
|  |               (consp (car form)) | ||||||
|  |               (eq (caar form) 'lambda) | ||||||
|  |               (let ((args (cadr (car form))) | ||||||
|  |                     (body (caddr (car form)))) | ||||||
|  |                 (and (= (length body) 2) | ||||||
|  |                      (= (length args) 1) | ||||||
|  |                      (eq (car body) (car args)) | ||||||
|  |                      (not (eq (cadr body) (car args))) | ||||||
|  |                      (symbolp (cadr body))))) | ||||||
|  |          `(,(β-reduce (cadr form)) | ||||||
|  |            ,(cadr (caddr (car form))))) | ||||||
|  |         (T (map β-reduce form)))) | ||||||
|  | 
 | ||||||
|  | (defmacro with-delimited-continuations (exp) (cps exp)) | ||||||
|  | 
 | ||||||
|  | (defmacro defgenerator (name args . body) | ||||||
|  |   (let ((ko  (gensym)) | ||||||
|  |         (cur (gensym))) | ||||||
|  |     `(defun ,name ,args | ||||||
|  |        (let ((,ko  ()) | ||||||
|  |              (,cur ())) | ||||||
|  |          (lambda () | ||||||
|  |            (with-delimited-continuations | ||||||
|  |             (if ,ko (,ko ,cur) | ||||||
|  |               (reset | ||||||
|  |                (let ((yield | ||||||
|  |                       (lambda (v) | ||||||
|  |                         (shift yk | ||||||
|  |                                (progn (setq ,ko  yk) | ||||||
|  |                                       (setq ,cur v)))))) | ||||||
|  |                  ,(f-body body)))))))))) | ||||||
|  | 
 | ||||||
|  | ; a test case | ||||||
|  | (defgenerator range-iterator (lo hi) | ||||||
|  |   ((label loop | ||||||
|  |           (lambda (i) | ||||||
|  |             (if (< hi i) | ||||||
|  |                 'done | ||||||
|  |               (progn (yield i) | ||||||
|  |                      (loop (+ 1 i)))))) | ||||||
|  |    lo)) | ||||||
|  | 
 | ||||||
|  | T | ||||||
|  | 
 | ||||||
|  | #| | ||||||
|  | todo: | ||||||
|  | - tag lambdas that accept continuation arguments, compile computed | ||||||
|  |   calls to calls to funcall/cc that does the right thing for both | ||||||
|  |   cc-lambdas and normal lambdas | ||||||
|  | 
 | ||||||
|  | - handle while, and, or | ||||||
|  | |# | ||||||
|  | @ -120,7 +120,14 @@ void cv_autorelease(cvalue_t *cv) | ||||||
| value_t cvalue(fltype_t *type, size_t sz) | value_t cvalue(fltype_t *type, size_t sz) | ||||||
| { | { | ||||||
|     cvalue_t *pcv; |     cvalue_t *pcv; | ||||||
|  |     int str=0; | ||||||
| 
 | 
 | ||||||
|  |     if (type->eltype == bytetype) { | ||||||
|  |         if (sz == 0) | ||||||
|  |             return symbol_value(emptystringsym); | ||||||
|  |         sz++; | ||||||
|  |         str=1; | ||||||
|  |     } | ||||||
|     if (sz <= MAX_INL_SIZE) { |     if (sz <= MAX_INL_SIZE) { | ||||||
|         size_t nw = CVALUE_NWORDS - 1 + NWORDS(sz) + (sz==0 ? 1 : 0); |         size_t nw = CVALUE_NWORDS - 1 + NWORDS(sz) + (sz==0 ? 1 : 0); | ||||||
|         pcv = (cvalue_t*)alloc_words(nw); |         pcv = (cvalue_t*)alloc_words(nw); | ||||||
|  | @ -138,6 +145,10 @@ value_t cvalue(fltype_t *type, size_t sz) | ||||||
|         autorelease(pcv); |         autorelease(pcv); | ||||||
|         malloc_pressure += sz; |         malloc_pressure += sz; | ||||||
|     } |     } | ||||||
|  |     if (str) { | ||||||
|  |         sz--; | ||||||
|  |         ((char*)pcv->data)[sz] = '\0'; | ||||||
|  |     } | ||||||
|     pcv->len = sz; |     pcv->len = sz; | ||||||
|     return tagptr(pcv, TAG_CVALUE); |     return tagptr(pcv, TAG_CVALUE); | ||||||
| } | } | ||||||
|  | @ -179,20 +190,7 @@ value_t cvalue_from_ref(fltype_t *type, void *ptr, size_t sz, value_t parent) | ||||||
| 
 | 
 | ||||||
| value_t cvalue_string(size_t sz) | value_t cvalue_string(size_t sz) | ||||||
| { | { | ||||||
|     value_t cv; |     return cvalue(stringtype, sz); | ||||||
|     char *data; |  | ||||||
|     cvalue_t *pcv; |  | ||||||
| 
 |  | ||||||
|     if (sz == 0) |  | ||||||
|         return symbol_value(emptystringsym); |  | ||||||
|     // secretly allocate space for 1 more byte, hide a NUL there so
 |  | ||||||
|     // any string will always be NUL terminated.
 |  | ||||||
|     cv = cvalue(stringtype, sz+1); |  | ||||||
|     pcv = (cvalue_t*)ptr(cv); |  | ||||||
|     data = cv_data(pcv); |  | ||||||
|     data[sz] = '\0'; |  | ||||||
|     pcv->len = sz; |  | ||||||
|     return cv; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| value_t cvalue_static_cstring(char *str) | value_t cvalue_static_cstring(char *str) | ||||||
|  | @ -449,18 +447,6 @@ static void cvalue_array_init(fltype_t *ft, value_t arg, void *dest) | ||||||
|         type_error("array", "sequence", arg); |         type_error("array", "sequence", arg); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static value_t alloc_array(fltype_t *type, size_t sz) |  | ||||||
| { |  | ||||||
|     value_t cv; |  | ||||||
|     if (type->eltype == bytetype) { |  | ||||||
|         cv = cvalue_string(sz); |  | ||||||
|     } |  | ||||||
|     else { |  | ||||||
|         cv = cvalue(type, sz); |  | ||||||
|     } |  | ||||||
|     return cv; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| value_t cvalue_array(value_t *args, u_int32_t nargs) | value_t cvalue_array(value_t *args, u_int32_t nargs) | ||||||
| { | { | ||||||
|     size_t elsize, cnt, sz; |     size_t elsize, cnt, sz; | ||||||
|  | @ -473,7 +459,7 @@ value_t cvalue_array(value_t *args, u_int32_t nargs) | ||||||
|     elsize = type->elsz; |     elsize = type->elsz; | ||||||
|     sz = elsize * cnt; |     sz = elsize * cnt; | ||||||
| 
 | 
 | ||||||
|     value_t cv = alloc_array(type, sz); |     value_t cv = cvalue(type, sz); | ||||||
|     array_init_fromargs(cv_data((cvalue_t*)ptr(cv)), &args[1], cnt, |     array_init_fromargs(cv_data((cvalue_t*)ptr(cv)), &args[1], cnt, | ||||||
|                         type->eltype, elsize); |                         type->eltype, elsize); | ||||||
|     return cv; |     return cv; | ||||||
|  | @ -727,7 +713,7 @@ value_t cvalue_new(value_t *args, u_int32_t nargs) | ||||||
|             cnt = predict_arraylen(args[1]); |             cnt = predict_arraylen(args[1]); | ||||||
|         else |         else | ||||||
|             cnt = 0; |             cnt = 0; | ||||||
|         cv = alloc_array(ft, elsz * cnt); |         cv = cvalue(ft, elsz * cnt); | ||||||
|         if (nargs == 2) |         if (nargs == 2) | ||||||
|             cvalue_array_init(ft, args[1], cv_data((cvalue_t*)ptr(cv))); |             cvalue_array_init(ft, args[1], cv_data((cvalue_t*)ptr(cv))); | ||||||
|     } |     } | ||||||
|  | @ -771,18 +757,11 @@ static void check_addr_args(char *fname, value_t arr, value_t ind, | ||||||
|         bounds_error(fname, arr, ind); |         bounds_error(fname, arr, ind); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static value_t make_uninitialized_instance(fltype_t *t) |  | ||||||
| { |  | ||||||
|     if (t->eltype != NULL) |  | ||||||
|         return alloc_array(t, t->size); |  | ||||||
|     return cvalue(t, t->size); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static value_t cvalue_array_aref(value_t *args) | static value_t cvalue_array_aref(value_t *args) | ||||||
| { | { | ||||||
|     char *data; ulong_t index; |     char *data; ulong_t index; | ||||||
|     fltype_t *eltype = cv_class((cvalue_t*)ptr(args[0]))->eltype; |     fltype_t *eltype = cv_class((cvalue_t*)ptr(args[0]))->eltype; | ||||||
|     value_t el = make_uninitialized_instance(eltype); |     value_t el = cvalue(eltype, eltype->size); | ||||||
|     check_addr_args("aref", args[0], args[1], &data, &index); |     check_addr_args("aref", args[0], args[1], &data, &index); | ||||||
|     char *dest = cv_data((cvalue_t*)ptr(el)); |     char *dest = cv_data((cvalue_t*)ptr(el)); | ||||||
|     size_t sz = eltype->size; |     size_t sz = eltype->size; | ||||||
|  |  | ||||||
|  | @ -167,10 +167,9 @@ void bounds_error(char *fname, value_t arr, value_t ind) | ||||||
| #define SAFECAST_OP(type,ctype,cnvt)                                          \ | #define SAFECAST_OP(type,ctype,cnvt)                                          \ | ||||||
| ctype to##type(value_t v, char *fname)                                        \ | ctype to##type(value_t v, char *fname)                                        \ | ||||||
| {                                                                             \ | {                                                                             \ | ||||||
|     if (is##type(v))                                                          \ |     if (__likely(is##type(v)))                                                \ | ||||||
|         return (ctype)cnvt(v);                                                \ |         return (ctype)cnvt(v);                                                \ | ||||||
|     type_error(fname, #type, v);                                              \ |     type_error(fname, #type, v);                                              \ | ||||||
|     return (ctype)0;                                                          \ |  | ||||||
| } | } | ||||||
| SAFECAST_OP(cons,  cons_t*,  ptr) | SAFECAST_OP(cons,  cons_t*,  ptr) | ||||||
| SAFECAST_OP(symbol,symbol_t*,ptr) | SAFECAST_OP(symbol,symbol_t*,ptr) | ||||||
|  | @ -290,7 +289,7 @@ static value_t mk_cons(void) | ||||||
| { | { | ||||||
|     cons_t *c; |     cons_t *c; | ||||||
| 
 | 
 | ||||||
|     if (curheap > lim) |     if (__unlikely(curheap > lim)) | ||||||
|         gc(0); |         gc(0); | ||||||
|     c = (cons_t*)curheap; |     c = (cons_t*)curheap; | ||||||
|     curheap += sizeof(cons_t); |     curheap += sizeof(cons_t); | ||||||
|  | @ -303,7 +302,7 @@ static value_t *alloc_words(int n) | ||||||
| 
 | 
 | ||||||
|     assert(n > 0); |     assert(n > 0); | ||||||
|     n = ALIGN(n, 2);   // only allocate multiples of 2 words
 |     n = ALIGN(n, 2);   // only allocate multiples of 2 words
 | ||||||
|     if ((value_t*)curheap > ((value_t*)lim)+2-n) { |     if (__unlikely((value_t*)curheap > ((value_t*)lim)+2-n)) { | ||||||
|         gc(0); |         gc(0); | ||||||
|         while ((value_t*)curheap > ((value_t*)lim)+2-n) { |         while ((value_t*)curheap > ((value_t*)lim)+2-n) { | ||||||
|             gc(1); |             gc(1); | ||||||
|  | @ -672,11 +671,11 @@ static value_t eval_sexpr(value_t e, uint32_t penv, int tail) | ||||||
|             if (*pv == NIL) break; |             if (*pv == NIL) break; | ||||||
|             pv = &vector_elt(*pv, 0); |             pv = &vector_elt(*pv, 0); | ||||||
|         } |         } | ||||||
|         if ((v = sym->binding) == UNBOUND) |         if (__unlikely((v = sym->binding) == UNBOUND)) | ||||||
|             raise(list2(UnboundError, e)); |             raise(list2(UnboundError, e)); | ||||||
|         return v; |         return v; | ||||||
|     } |     } | ||||||
|     if (SP >= (N_STACK-64)) |     if (__unlikely(SP >= (N_STACK-64))) | ||||||
|         lerror(MemoryError, "eval: stack overflow"); |         lerror(MemoryError, "eval: stack overflow"); | ||||||
|     saveSP = SP; |     saveSP = SP; | ||||||
|     v = car_(e); |     v = car_(e); | ||||||
|  | @ -707,7 +706,7 @@ static value_t eval_sexpr(value_t e, uint32_t penv, int tail) | ||||||
|         switch (uintval(f)) { |         switch (uintval(f)) { | ||||||
|         // special forms
 |         // special forms
 | ||||||
|         case F_QUOTE: |         case F_QUOTE: | ||||||
|             if (!iscons(Stack[saveSP])) |             if (__unlikely(!iscons(Stack[saveSP]))) | ||||||
|                 lerror(ArgError, "quote: expected argument"); |                 lerror(ArgError, "quote: expected argument"); | ||||||
|             v = car_(Stack[saveSP]); |             v = car_(Stack[saveSP]); | ||||||
|             break; |             break; | ||||||
|  | @ -926,7 +925,7 @@ static value_t eval_sexpr(value_t e, uint32_t penv, int tail) | ||||||
|             v = Stack[SP-2]; |             v = Stack[SP-2]; | ||||||
|             if (isvector(v)) { |             if (isvector(v)) { | ||||||
|                 i = tofixnum(Stack[SP-1], "aref"); |                 i = tofixnum(Stack[SP-1], "aref"); | ||||||
|                 if ((unsigned)i >= vector_size(v)) |                 if (__unlikely((unsigned)i >= vector_size(v))) | ||||||
|                     bounds_error("aref", v, Stack[SP-1]); |                     bounds_error("aref", v, Stack[SP-1]); | ||||||
|                 v = vector_elt(v, i); |                 v = vector_elt(v, i); | ||||||
|             } |             } | ||||||
|  | @ -943,7 +942,7 @@ static value_t eval_sexpr(value_t e, uint32_t penv, int tail) | ||||||
|             e = Stack[SP-3]; |             e = Stack[SP-3]; | ||||||
|             if (isvector(e)) { |             if (isvector(e)) { | ||||||
|                 i = tofixnum(Stack[SP-2], "aset"); |                 i = tofixnum(Stack[SP-2], "aset"); | ||||||
|                 if ((unsigned)i >= vector_size(e)) |                 if (__unlikely((unsigned)i >= vector_size(e))) | ||||||
|                     bounds_error("aref", v, Stack[SP-1]); |                     bounds_error("aref", v, Stack[SP-1]); | ||||||
|                 vector_elt(e, i) = (v=Stack[SP-1]); |                 vector_elt(e, i) = (v=Stack[SP-1]); | ||||||
|             } |             } | ||||||
|  | @ -992,9 +991,9 @@ static value_t eval_sexpr(value_t e, uint32_t penv, int tail) | ||||||
|         case F_ADD: |         case F_ADD: | ||||||
|             s = 0; |             s = 0; | ||||||
|             for (i=saveSP+1; i < (int)SP; i++) { |             for (i=saveSP+1; i < (int)SP; i++) { | ||||||
|                 if (isfixnum(Stack[i])) { |                 if (__likely(isfixnum(Stack[i]))) { | ||||||
|                     s += numval(Stack[i]); |                     s += numval(Stack[i]); | ||||||
|                     if (!fits_fixnum(s)) { |                     if (__unlikely(!fits_fixnum(s))) { | ||||||
|                         i++; |                         i++; | ||||||
|                         goto add_ovf; |                         goto add_ovf; | ||||||
|                     } |                     } | ||||||
|  | @ -1009,19 +1008,19 @@ static value_t eval_sexpr(value_t e, uint32_t penv, int tail) | ||||||
|             v = fixnum(s); |             v = fixnum(s); | ||||||
|             break; |             break; | ||||||
|         case F_SUB: |         case F_SUB: | ||||||
|             if (nargs < 1) lerror(ArgError, "-: too few arguments"); |             if (__unlikely(nargs < 1)) lerror(ArgError, "-: too few arguments"); | ||||||
|             i = saveSP+1; |             i = saveSP+1; | ||||||
|             if (nargs == 1) { |             if (nargs == 1) { | ||||||
|                 if (isfixnum(Stack[i])) |                 if (__likely(isfixnum(Stack[i]))) | ||||||
|                     v = fixnum(-numval(Stack[i])); |                     v = fixnum(-numval(Stack[i])); | ||||||
|                 else |                 else | ||||||
|                     v = fl_neg(Stack[i]); |                     v = fl_neg(Stack[i]); | ||||||
|                 break; |                 break; | ||||||
|             } |             } | ||||||
|             if (nargs == 2) { |             if (nargs == 2) { | ||||||
|                 if (bothfixnums(Stack[i], Stack[i+1])) { |                 if (__likely(bothfixnums(Stack[i], Stack[i+1]))) { | ||||||
|                     s = numval(Stack[i]) - numval(Stack[i+1]); |                     s = numval(Stack[i]) - numval(Stack[i+1]); | ||||||
|                     if (fits_fixnum(s)) { |                     if (__likely(fits_fixnum(s))) { | ||||||
|                         v = fixnum(s); |                         v = fixnum(s); | ||||||
|                         break; |                         break; | ||||||
|                     } |                     } | ||||||
|  | @ -1039,7 +1038,7 @@ static value_t eval_sexpr(value_t e, uint32_t penv, int tail) | ||||||
|         case F_MUL: |         case F_MUL: | ||||||
|             accum = 1; |             accum = 1; | ||||||
|             for (i=saveSP+1; i < (int)SP; i++) { |             for (i=saveSP+1; i < (int)SP; i++) { | ||||||
|                 if (isfixnum(Stack[i])) { |                 if (__likely(isfixnum(Stack[i]))) { | ||||||
|                     accum *= numval(Stack[i]); |                     accum *= numval(Stack[i]); | ||||||
|                 } |                 } | ||||||
|                 else { |                 else { | ||||||
|  | @ -1048,13 +1047,13 @@ static value_t eval_sexpr(value_t e, uint32_t penv, int tail) | ||||||
|                     return v; |                     return v; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             if (fits_fixnum(accum)) |             if (__likely(fits_fixnum(accum))) | ||||||
|                 v = fixnum(accum); |                 v = fixnum(accum); | ||||||
|             else |             else | ||||||
|                 v = return_from_int64(accum); |                 v = return_from_int64(accum); | ||||||
|             break; |             break; | ||||||
|         case F_DIV: |         case F_DIV: | ||||||
|             if (nargs < 1) lerror(ArgError, "/: too few arguments"); |             if (__unlikely(nargs < 1)) lerror(ArgError, "/: too few arguments"); | ||||||
|             i = saveSP+1; |             i = saveSP+1; | ||||||
|             if (nargs == 1) { |             if (nargs == 1) { | ||||||
|                 v = fl_div2(fixnum(1), Stack[i]); |                 v = fl_div2(fixnum(1), Stack[i]); | ||||||
|  | @ -1146,7 +1145,8 @@ static value_t eval_sexpr(value_t e, uint32_t penv, int tail) | ||||||
|             break; |             break; | ||||||
|         case F_PROG1: |         case F_PROG1: | ||||||
|             // return first arg
 |             // return first arg
 | ||||||
|             if (nargs < 1) lerror(ArgError, "prog1: too few arguments"); |             if (__unlikely(nargs < 1)) | ||||||
|  |                 lerror(ArgError, "prog1: too few arguments"); | ||||||
|             v = Stack[saveSP+1]; |             v = Stack[saveSP+1]; | ||||||
|             break; |             break; | ||||||
|         case F_ASSOC: |         case F_ASSOC: | ||||||
|  | @ -1206,7 +1206,7 @@ static value_t eval_sexpr(value_t e, uint32_t penv, int tail) | ||||||
|         return v; |         return v; | ||||||
|     } |     } | ||||||
|  apply_lambda: |  apply_lambda: | ||||||
|     if (iscons(f)) { |     if (__likely(iscons(f))) { | ||||||
|         // apply lambda expression
 |         // apply lambda expression
 | ||||||
|         f = cdr_(f); |         f = cdr_(f); | ||||||
|         PUSH(f); |         PUSH(f); | ||||||
|  | @ -1219,7 +1219,7 @@ static value_t eval_sexpr(value_t e, uint32_t penv, int tail) | ||||||
|             while (iscons(v)) { |             while (iscons(v)) { | ||||||
|                 // bind args
 |                 // bind args
 | ||||||
|                 if (!iscons(*argsyms)) { |                 if (!iscons(*argsyms)) { | ||||||
|                     if (*argsyms == NIL) |                     if (__unlikely(*argsyms == NIL)) | ||||||
|                         lerror(ArgError, "apply: too many arguments"); |                         lerror(ArgError, "apply: too many arguments"); | ||||||
|                     break; |                     break; | ||||||
|                 } |                 } | ||||||
|  | @ -1234,7 +1234,7 @@ static value_t eval_sexpr(value_t e, uint32_t penv, int tail) | ||||||
|             while (iscons(v)) { |             while (iscons(v)) { | ||||||
|                 // bind args
 |                 // bind args
 | ||||||
|                 if (!iscons(*argsyms)) { |                 if (!iscons(*argsyms)) { | ||||||
|                     if (*argsyms == NIL) |                     if (__unlikely(*argsyms == NIL)) | ||||||
|                         lerror(ArgError, "apply: too many arguments"); |                         lerror(ArgError, "apply: too many arguments"); | ||||||
|                     break; |                     break; | ||||||
|                 } |                 } | ||||||
|  | @ -1269,7 +1269,7 @@ static value_t eval_sexpr(value_t e, uint32_t penv, int tail) | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         if (iscons(*argsyms)) { |         if (__unlikely(iscons(*argsyms))) { | ||||||
|             lerror(ArgError, "apply: too few arguments"); |             lerror(ArgError, "apply: too few arguments"); | ||||||
|         } |         } | ||||||
|         f = cdr_(Stack[saveSP+1]); |         f = cdr_(Stack[saveSP+1]); | ||||||
|  |  | ||||||
|  | @ -151,7 +151,7 @@ void bounds_error(char *fname, value_t arr, value_t ind) __attribute__ ((__noret | ||||||
| extern value_t ArgError, IOError, KeyError; | extern value_t ArgError, IOError, KeyError; | ||||||
| static inline void argcount(char *fname, int nargs, int c) | static inline void argcount(char *fname, int nargs, int c) | ||||||
| { | { | ||||||
|     if (nargs != c) |     if (__unlikely(nargs != c)) | ||||||
|         lerror(ArgError,"%s: too %s arguments", fname, nargs<c ? "few":"many"); |         lerror(ArgError,"%s: too %s arguments", fname, nargs<c ? "few":"many"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -35,14 +35,6 @@ static value_t print_to_string(value_t v, int princ) | ||||||
|     return outp; |     return outp; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| value_t fl_intern(value_t *args, u_int32_t nargs) |  | ||||||
| { |  | ||||||
|     argcount("intern", nargs, 1); |  | ||||||
|     if (!isstring(args[0])) |  | ||||||
|         type_error("intern", "string", args[0]); |  | ||||||
|     return symbol(cvalue_data(args[0])); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| value_t fl_stringp(value_t *args, u_int32_t nargs) | value_t fl_stringp(value_t *args, u_int32_t nargs) | ||||||
| { | { | ||||||
|     argcount("stringp", nargs, 1); |     argcount("stringp", nargs, 1); | ||||||
|  | @ -350,7 +342,6 @@ value_t fl_string_dec(value_t *args, u_int32_t nargs) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static builtinspec_t stringfunc_info[] = { | static builtinspec_t stringfunc_info[] = { | ||||||
|     { "intern", fl_intern }, |  | ||||||
|     { "string", fl_string }, |     { "string", fl_string }, | ||||||
|     { "stringp", fl_stringp }, |     { "stringp", fl_stringp }, | ||||||
|     { "string.length", fl_string_length }, |     { "string.length", fl_string_length }, | ||||||
|  |  | ||||||
|  | @ -149,6 +149,7 @@ | ||||||
| (define (caadr x) (car (car (cdr x)))) | (define (caadr x) (car (car (cdr x)))) | ||||||
| (define (cadar x) (car (cdr (car x)))) | (define (cadar x) (car (cdr (car x)))) | ||||||
| (define (caddr x) (car (cdr (cdr x)))) | (define (caddr x) (car (cdr (cdr x)))) | ||||||
|  | (define (cadddr x) (car (cdr (cdr (cdr x))))) | ||||||
| (define (cdaar x) (cdr (car (car x)))) | (define (cdaar x) (cdr (car (car x)))) | ||||||
| (define (cdadr x) (cdr (car (cdr x)))) | (define (cdadr x) (cdr (car (cdr x)))) | ||||||
| (define (cddar x) (cdr (cdr (car x)))) | (define (cddar x) (cdr (cdr (car x)))) | ||||||
|  |  | ||||||
|  | @ -832,21 +832,22 @@ IOStream API | ||||||
|  princ, sprinc |  princ, sprinc | ||||||
|  iostream         - (stream[ cvalue-as-bytestream]) |  iostream         - (stream[ cvalue-as-bytestream]) | ||||||
|  file |  file | ||||||
|  fifo |  | ||||||
|  socket |  | ||||||
|  stream.eof |  stream.eof | ||||||
|  stream.write     - (stream.write s cvalue) |  stream.write     - (stream.write s cvalue) | ||||||
|  stream.read      - (stream.read s ctype) |  stream.read      - (stream.read s ctype) | ||||||
|  stream.copy      - (stream.copy to from [nbytes]) |  | ||||||
|  stream.copyuntil - (stream.copy to from byte) |  | ||||||
|  stream.flush |  stream.flush | ||||||
|  |  stream.close | ||||||
|  stream.pos       - (stream.pos s [set-pos]) |  stream.pos       - (stream.pos s [set-pos]) | ||||||
|  stream.seek      - (stream.seek s offset) |  stream.seek      - (stream.seek s offset) | ||||||
|  |  stream.getc      - get utf8 character(s) | ||||||
|  |  stream.readline | ||||||
|  |  stream.copy      - (stream.copy to from [nbytes]) | ||||||
|  |  stream.copyuntil - (stream.copy to from byte) | ||||||
|  |  fifo | ||||||
|  |  socket | ||||||
|  stream.seekend   - move to end of stream |  stream.seekend   - move to end of stream | ||||||
|  stream.trunc |  stream.trunc | ||||||
|  stream.getc      - get utf8 character(s) |  | ||||||
|  stream.tostring! - destructively convert stringstream to string |  stream.tostring! - destructively convert stringstream to string | ||||||
|  stream.readline |  | ||||||
|  stream.readlines |  stream.readlines | ||||||
|  stream.readall |  stream.readall | ||||||
|  print-to-string |  print-to-string | ||||||
|  | @ -931,7 +932,6 @@ consolidated todo list as of 8/30: | ||||||
| - expose io stream object | - expose io stream object | ||||||
| - new toplevel | - new toplevel | ||||||
| 
 | 
 | ||||||
| - enable print-shared for cvalues' types |  | ||||||
| - remaining c types | - remaining c types | ||||||
| - remaining cvalues functions | - remaining cvalues functions | ||||||
| - finish ios | - finish ios | ||||||
|  |  | ||||||
|  | @ -87,6 +87,15 @@ typedef u_ptrint_t uptrint_t; | ||||||
| 
 | 
 | ||||||
| #define ALIGN(x, sz) (((x) + (sz-1)) & (-sz)) | #define ALIGN(x, sz) (((x) + (sz-1)) & (-sz)) | ||||||
| 
 | 
 | ||||||
|  | // branch prediction annotations
 | ||||||
|  | #ifdef __GNUC__ | ||||||
|  | #define __unlikely(x) __builtin_expect(!!(x), 0) | ||||||
|  | #define __likely(x)   __builtin_expect(!!(x), 1) | ||||||
|  | #else | ||||||
|  | #define __unlikely(x) (x) | ||||||
|  | #define __likely(x)   (x) | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| #define DBL_MAXINT 9007199254740992LL | #define DBL_MAXINT 9007199254740992LL | ||||||
| #define FLT_MAXINT 16777216 | #define FLT_MAXINT 16777216 | ||||||
| #define U64_MAX    18446744073709551615ULL | #define U64_MAX    18446744073709551615ULL | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 JeffBezanson
						JeffBezanson