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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
 | 
			
		||||
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());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static double value_to_double(value_t a, char *fname)
 | 
			
		||||
static double todouble(value_t a, char *fname)
 | 
			
		||||
{
 | 
			
		||||
    if (isfixnum(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)
 | 
			
		||||
{
 | 
			
		||||
    argcount("time.string", nargs, 1);
 | 
			
		||||
    double t = value_to_double(args[0], "time.string");
 | 
			
		||||
    double t = todouble(args[0], "time.string");
 | 
			
		||||
    char buf[64];
 | 
			
		||||
    timestring(t, buf, sizeof(buf));
 | 
			
		||||
    return string_from_cstr(buf);
 | 
			
		||||
| 
						 | 
				
			
			@ -359,6 +367,7 @@ static builtinspec_t builtin_info[] = {
 | 
			
		|||
    { "read", fl_read },
 | 
			
		||||
    { "load", fl_load },
 | 
			
		||||
    { "exit", fl_exit },
 | 
			
		||||
    { "intern", fl_intern },
 | 
			
		||||
    { "fixnum", fl_fixnum },
 | 
			
		||||
    { "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)
 | 
			
		||||
{
 | 
			
		||||
    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) {
 | 
			
		||||
        size_t nw = CVALUE_NWORDS - 1 + NWORDS(sz) + (sz==0 ? 1 : 0);
 | 
			
		||||
        pcv = (cvalue_t*)alloc_words(nw);
 | 
			
		||||
| 
						 | 
				
			
			@ -138,6 +145,10 @@ value_t cvalue(fltype_t *type, size_t sz)
 | 
			
		|||
        autorelease(pcv);
 | 
			
		||||
        malloc_pressure += sz;
 | 
			
		||||
    }
 | 
			
		||||
    if (str) {
 | 
			
		||||
        sz--;
 | 
			
		||||
        ((char*)pcv->data)[sz] = '\0';
 | 
			
		||||
    }
 | 
			
		||||
    pcv->len = sz;
 | 
			
		||||
    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 cv;
 | 
			
		||||
    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;
 | 
			
		||||
    return cvalue(stringtype, sz);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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)
 | 
			
		||||
{
 | 
			
		||||
    size_t elsize, cnt, sz;
 | 
			
		||||
| 
						 | 
				
			
			@ -473,7 +459,7 @@ value_t cvalue_array(value_t *args, u_int32_t nargs)
 | 
			
		|||
    elsize = type->elsz;
 | 
			
		||||
    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,
 | 
			
		||||
                        type->eltype, elsize);
 | 
			
		||||
    return cv;
 | 
			
		||||
| 
						 | 
				
			
			@ -727,7 +713,7 @@ value_t cvalue_new(value_t *args, u_int32_t nargs)
 | 
			
		|||
            cnt = predict_arraylen(args[1]);
 | 
			
		||||
        else
 | 
			
		||||
            cnt = 0;
 | 
			
		||||
        cv = alloc_array(ft, elsz * cnt);
 | 
			
		||||
        cv = cvalue(ft, elsz * cnt);
 | 
			
		||||
        if (nargs == 2)
 | 
			
		||||
            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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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)
 | 
			
		||||
{
 | 
			
		||||
    char *data; ulong_t index;
 | 
			
		||||
    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);
 | 
			
		||||
    char *dest = cv_data((cvalue_t*)ptr(el));
 | 
			
		||||
    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)                                          \
 | 
			
		||||
ctype to##type(value_t v, char *fname)                                        \
 | 
			
		||||
{                                                                             \
 | 
			
		||||
    if (is##type(v))                                                          \
 | 
			
		||||
    if (__likely(is##type(v)))                                                \
 | 
			
		||||
        return (ctype)cnvt(v);                                                \
 | 
			
		||||
    type_error(fname, #type, v);                                              \
 | 
			
		||||
    return (ctype)0;                                                          \
 | 
			
		||||
}
 | 
			
		||||
SAFECAST_OP(cons,  cons_t*,  ptr)
 | 
			
		||||
SAFECAST_OP(symbol,symbol_t*,ptr)
 | 
			
		||||
| 
						 | 
				
			
			@ -290,7 +289,7 @@ static value_t mk_cons(void)
 | 
			
		|||
{
 | 
			
		||||
    cons_t *c;
 | 
			
		||||
 | 
			
		||||
    if (curheap > lim)
 | 
			
		||||
    if (__unlikely(curheap > lim))
 | 
			
		||||
        gc(0);
 | 
			
		||||
    c = (cons_t*)curheap;
 | 
			
		||||
    curheap += sizeof(cons_t);
 | 
			
		||||
| 
						 | 
				
			
			@ -303,7 +302,7 @@ static value_t *alloc_words(int n)
 | 
			
		|||
 | 
			
		||||
    assert(n > 0);
 | 
			
		||||
    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);
 | 
			
		||||
        while ((value_t*)curheap > ((value_t*)lim)+2-n) {
 | 
			
		||||
            gc(1);
 | 
			
		||||
| 
						 | 
				
			
			@ -672,11 +671,11 @@ static value_t eval_sexpr(value_t e, uint32_t penv, int tail)
 | 
			
		|||
            if (*pv == NIL) break;
 | 
			
		||||
            pv = &vector_elt(*pv, 0);
 | 
			
		||||
        }
 | 
			
		||||
        if ((v = sym->binding) == UNBOUND)
 | 
			
		||||
        if (__unlikely((v = sym->binding) == UNBOUND))
 | 
			
		||||
            raise(list2(UnboundError, e));
 | 
			
		||||
        return v;
 | 
			
		||||
    }
 | 
			
		||||
    if (SP >= (N_STACK-64))
 | 
			
		||||
    if (__unlikely(SP >= (N_STACK-64)))
 | 
			
		||||
        lerror(MemoryError, "eval: stack overflow");
 | 
			
		||||
    saveSP = SP;
 | 
			
		||||
    v = car_(e);
 | 
			
		||||
| 
						 | 
				
			
			@ -707,7 +706,7 @@ static value_t eval_sexpr(value_t e, uint32_t penv, int tail)
 | 
			
		|||
        switch (uintval(f)) {
 | 
			
		||||
        // special forms
 | 
			
		||||
        case F_QUOTE:
 | 
			
		||||
            if (!iscons(Stack[saveSP]))
 | 
			
		||||
            if (__unlikely(!iscons(Stack[saveSP])))
 | 
			
		||||
                lerror(ArgError, "quote: expected argument");
 | 
			
		||||
            v = car_(Stack[saveSP]);
 | 
			
		||||
            break;
 | 
			
		||||
| 
						 | 
				
			
			@ -926,7 +925,7 @@ static value_t eval_sexpr(value_t e, uint32_t penv, int tail)
 | 
			
		|||
            v = Stack[SP-2];
 | 
			
		||||
            if (isvector(v)) {
 | 
			
		||||
                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]);
 | 
			
		||||
                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];
 | 
			
		||||
            if (isvector(e)) {
 | 
			
		||||
                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]);
 | 
			
		||||
                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:
 | 
			
		||||
            s = 0;
 | 
			
		||||
            for (i=saveSP+1; i < (int)SP; i++) {
 | 
			
		||||
                if (isfixnum(Stack[i])) {
 | 
			
		||||
                if (__likely(isfixnum(Stack[i]))) {
 | 
			
		||||
                    s += numval(Stack[i]);
 | 
			
		||||
                    if (!fits_fixnum(s)) {
 | 
			
		||||
                    if (__unlikely(!fits_fixnum(s))) {
 | 
			
		||||
                        i++;
 | 
			
		||||
                        goto add_ovf;
 | 
			
		||||
                    }
 | 
			
		||||
| 
						 | 
				
			
			@ -1009,19 +1008,19 @@ static value_t eval_sexpr(value_t e, uint32_t penv, int tail)
 | 
			
		|||
            v = fixnum(s);
 | 
			
		||||
            break;
 | 
			
		||||
        case F_SUB:
 | 
			
		||||
            if (nargs < 1) lerror(ArgError, "-: too few arguments");
 | 
			
		||||
            if (__unlikely(nargs < 1)) lerror(ArgError, "-: too few arguments");
 | 
			
		||||
            i = saveSP+1;
 | 
			
		||||
            if (nargs == 1) {
 | 
			
		||||
                if (isfixnum(Stack[i]))
 | 
			
		||||
                if (__likely(isfixnum(Stack[i])))
 | 
			
		||||
                    v = fixnum(-numval(Stack[i]));
 | 
			
		||||
                else
 | 
			
		||||
                    v = fl_neg(Stack[i]);
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            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]);
 | 
			
		||||
                    if (fits_fixnum(s)) {
 | 
			
		||||
                    if (__likely(fits_fixnum(s))) {
 | 
			
		||||
                        v = fixnum(s);
 | 
			
		||||
                        break;
 | 
			
		||||
                    }
 | 
			
		||||
| 
						 | 
				
			
			@ -1039,7 +1038,7 @@ static value_t eval_sexpr(value_t e, uint32_t penv, int tail)
 | 
			
		|||
        case F_MUL:
 | 
			
		||||
            accum = 1;
 | 
			
		||||
            for (i=saveSP+1; i < (int)SP; i++) {
 | 
			
		||||
                if (isfixnum(Stack[i])) {
 | 
			
		||||
                if (__likely(isfixnum(Stack[i]))) {
 | 
			
		||||
                    accum *= numval(Stack[i]);
 | 
			
		||||
                }
 | 
			
		||||
                else {
 | 
			
		||||
| 
						 | 
				
			
			@ -1048,13 +1047,13 @@ static value_t eval_sexpr(value_t e, uint32_t penv, int tail)
 | 
			
		|||
                    return v;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            if (fits_fixnum(accum))
 | 
			
		||||
            if (__likely(fits_fixnum(accum)))
 | 
			
		||||
                v = fixnum(accum);
 | 
			
		||||
            else
 | 
			
		||||
                v = return_from_int64(accum);
 | 
			
		||||
            break;
 | 
			
		||||
        case F_DIV:
 | 
			
		||||
            if (nargs < 1) lerror(ArgError, "/: too few arguments");
 | 
			
		||||
            if (__unlikely(nargs < 1)) lerror(ArgError, "/: too few arguments");
 | 
			
		||||
            i = saveSP+1;
 | 
			
		||||
            if (nargs == 1) {
 | 
			
		||||
                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;
 | 
			
		||||
        case F_PROG1:
 | 
			
		||||
            // 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];
 | 
			
		||||
            break;
 | 
			
		||||
        case F_ASSOC:
 | 
			
		||||
| 
						 | 
				
			
			@ -1206,7 +1206,7 @@ static value_t eval_sexpr(value_t e, uint32_t penv, int tail)
 | 
			
		|||
        return v;
 | 
			
		||||
    }
 | 
			
		||||
 apply_lambda:
 | 
			
		||||
    if (iscons(f)) {
 | 
			
		||||
    if (__likely(iscons(f))) {
 | 
			
		||||
        // apply lambda expression
 | 
			
		||||
        f = cdr_(f);
 | 
			
		||||
        PUSH(f);
 | 
			
		||||
| 
						 | 
				
			
			@ -1219,7 +1219,7 @@ static value_t eval_sexpr(value_t e, uint32_t penv, int tail)
 | 
			
		|||
            while (iscons(v)) {
 | 
			
		||||
                // bind args
 | 
			
		||||
                if (!iscons(*argsyms)) {
 | 
			
		||||
                    if (*argsyms == NIL)
 | 
			
		||||
                    if (__unlikely(*argsyms == NIL))
 | 
			
		||||
                        lerror(ArgError, "apply: too many arguments");
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
| 
						 | 
				
			
			@ -1234,7 +1234,7 @@ static value_t eval_sexpr(value_t e, uint32_t penv, int tail)
 | 
			
		|||
            while (iscons(v)) {
 | 
			
		||||
                // bind args
 | 
			
		||||
                if (!iscons(*argsyms)) {
 | 
			
		||||
                    if (*argsyms == NIL)
 | 
			
		||||
                    if (__unlikely(*argsyms == NIL))
 | 
			
		||||
                        lerror(ArgError, "apply: too many arguments");
 | 
			
		||||
                    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");
 | 
			
		||||
        }
 | 
			
		||||
        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;
 | 
			
		||||
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");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -35,14 +35,6 @@ static value_t print_to_string(value_t v, int princ)
 | 
			
		|||
    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)
 | 
			
		||||
{
 | 
			
		||||
    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[] = {
 | 
			
		||||
    { "intern", fl_intern },
 | 
			
		||||
    { "string", fl_string },
 | 
			
		||||
    { "stringp", fl_stringp },
 | 
			
		||||
    { "string.length", fl_string_length },
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -149,6 +149,7 @@
 | 
			
		|||
(define (caadr x) (car (car (cdr x))))
 | 
			
		||||
(define (cadar x) (car (cdr (car x))))
 | 
			
		||||
(define (caddr x) (car (cdr (cdr x))))
 | 
			
		||||
(define (cadddr x) (car (cdr (cdr (cdr x)))))
 | 
			
		||||
(define (cdaar x) (cdr (car (car x))))
 | 
			
		||||
(define (cdadr x) (cdr (car (cdr x))))
 | 
			
		||||
(define (cddar x) (cdr (cdr (car x))))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -832,21 +832,22 @@ IOStream API
 | 
			
		|||
 princ, sprinc
 | 
			
		||||
 iostream         - (stream[ cvalue-as-bytestream])
 | 
			
		||||
 file
 | 
			
		||||
 fifo
 | 
			
		||||
 socket
 | 
			
		||||
 stream.eof
 | 
			
		||||
 stream.write     - (stream.write s cvalue)
 | 
			
		||||
 stream.read      - (stream.read s ctype)
 | 
			
		||||
 stream.copy      - (stream.copy to from [nbytes])
 | 
			
		||||
 stream.copyuntil - (stream.copy to from byte)
 | 
			
		||||
 stream.flush
 | 
			
		||||
 stream.close
 | 
			
		||||
 stream.pos       - (stream.pos s [set-pos])
 | 
			
		||||
 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.trunc
 | 
			
		||||
 stream.getc      - get utf8 character(s)
 | 
			
		||||
 stream.tostring! - destructively convert stringstream to string
 | 
			
		||||
 stream.readline
 | 
			
		||||
 stream.readlines
 | 
			
		||||
 stream.readall
 | 
			
		||||
 print-to-string
 | 
			
		||||
| 
						 | 
				
			
			@ -931,7 +932,6 @@ consolidated todo list as of 8/30:
 | 
			
		|||
- expose io stream object
 | 
			
		||||
- new toplevel
 | 
			
		||||
 | 
			
		||||
- enable print-shared for cvalues' types
 | 
			
		||||
- remaining c types
 | 
			
		||||
- remaining cvalues functions
 | 
			
		||||
- finish ios
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -87,6 +87,15 @@ typedef u_ptrint_t uptrint_t;
 | 
			
		|||
 | 
			
		||||
#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 FLT_MAXINT 16777216
 | 
			
		||||
#define U64_MAX    18446744073709551615ULL
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue