fixing a bug in optional args + rest args with no required arguments
adding some code for keyword argument processing
This commit is contained in:
		
							parent
							
								
									08787a01cd
								
							
						
					
					
						commit
						adb702cdf8
					
				| 
						 | 
				
			
			@ -12,7 +12,7 @@ FLAGS = -falign-functions -Wall -Wextra -Wno-strict-aliasing -I$(LLTDIR) $(CFLAG
 | 
			
		|||
LIBS = $(LLT) -lm
 | 
			
		||||
 | 
			
		||||
DEBUGFLAGS = -g -DDEBUG $(FLAGS)
 | 
			
		||||
SHIPFLAGS = -O3 -DNDEBUG $(FLAGS)
 | 
			
		||||
SHIPFLAGS = -O2 -DNDEBUG $(FLAGS)
 | 
			
		||||
 | 
			
		||||
default: release test
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -574,7 +574,7 @@
 | 
			
		|||
 | 
			
		||||
	  ; emit argument checking prologue
 | 
			
		||||
	  (if (not (null? opta))
 | 
			
		||||
	      (begin (emit g 'optargs (if (null? atail) nreq (- nreq)) nargs)
 | 
			
		||||
	      (begin (emit g 'optargs nreq (if (null? atail) nargs (- nargs)))
 | 
			
		||||
		     (emit-optional-arg-inits g env opta vars nreq)))
 | 
			
		||||
 | 
			
		||||
	  (cond ((not (null? let?))      (emit g 'let))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| 
						 | 
				
			
			@ -790,6 +790,78 @@ static value_t do_trycatch()
 | 
			
		|||
    return v;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
  argument layout on stack is
 | 
			
		||||
  |--required args--|--opt args--|--kw args--|--rest args...
 | 
			
		||||
 */
 | 
			
		||||
static uint32_t process_keys(value_t kwtable,
 | 
			
		||||
                             uint32_t nreq, uint32_t nkw, uint32_t nopt,
 | 
			
		||||
                             uint32_t bp, uint32_t nargs, int va)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t extr = nopt+nkw;
 | 
			
		||||
    uint32_t ntot = nreq+extr;
 | 
			
		||||
    value_t args[extr], v;
 | 
			
		||||
    uint32_t i, a = 0, nrestargs;
 | 
			
		||||
    value_t s1 = Stack[SP-1];
 | 
			
		||||
    value_t s2 = Stack[SP-2];
 | 
			
		||||
    value_t s4 = Stack[SP-4];
 | 
			
		||||
    value_t s5 = Stack[SP-5];
 | 
			
		||||
    if (nargs < nreq)
 | 
			
		||||
        lerror(ArgError, "apply: too few arguments");
 | 
			
		||||
    for (i=0; i < extr; i++) args[i] = UNBOUND;
 | 
			
		||||
    for (i=nreq; i < nargs; i++) {
 | 
			
		||||
        v = Stack[bp+i];
 | 
			
		||||
        if (issymbol(v) && iskeyword((symbol_t*)ptr(v)))
 | 
			
		||||
            break;
 | 
			
		||||
        if (a >= nopt)
 | 
			
		||||
            goto no_kw;
 | 
			
		||||
        args[a++] = v;
 | 
			
		||||
    }
 | 
			
		||||
    if (i >= nargs) goto no_kw;
 | 
			
		||||
    // now process keywords
 | 
			
		||||
    uint32_t n = vector_size(kwtable)/2;
 | 
			
		||||
    do {
 | 
			
		||||
        i++;
 | 
			
		||||
        if (i >= nargs)
 | 
			
		||||
            lerrorf(ArgError, "keyword %s requires an argument",
 | 
			
		||||
                    symbol_name(v));
 | 
			
		||||
        value_t hv = fixnum(((symbol_t*)ptr(v))->hash);
 | 
			
		||||
        uint32_t x = 2*(numval(hv) % n);
 | 
			
		||||
        if (vector_elt(kwtable, x) == v) {
 | 
			
		||||
            uint32_t idx = numval(vector_elt(kwtable, x+1));
 | 
			
		||||
            assert(idx < nkw);
 | 
			
		||||
            idx += (nreq+nopt);
 | 
			
		||||
            if (args[idx] == UNBOUND) {
 | 
			
		||||
                // if duplicate key, keep first value
 | 
			
		||||
                args[idx] = Stack[bp+i];
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            lerrorf(ArgError, "unsupported keyword %s", symbol_name(v));
 | 
			
		||||
        }
 | 
			
		||||
        i++;
 | 
			
		||||
        if (i >= nargs) break;
 | 
			
		||||
        v = Stack[bp+i];
 | 
			
		||||
    } while (issymbol(v) && iskeyword((symbol_t*)ptr(v)));
 | 
			
		||||
 no_kw:
 | 
			
		||||
    nrestargs = nargs - i;
 | 
			
		||||
    if (!va && nrestargs > 0)
 | 
			
		||||
        lerror(ArgError, "apply: too many arguments");
 | 
			
		||||
    nargs = ntot + nrestargs;
 | 
			
		||||
    if (nrestargs)
 | 
			
		||||
        memmove(&Stack[bp+ntot], &Stack[bp+i], nrestargs*sizeof(value_t));
 | 
			
		||||
    memcpy(&Stack[bp+nreq], args, extr*sizeof(value_t));
 | 
			
		||||
    SP = bp + nargs;
 | 
			
		||||
    assert(SP < N_STACK-5);
 | 
			
		||||
    PUSH(s5);
 | 
			
		||||
    PUSH(s4);
 | 
			
		||||
    PUSH(nargs);
 | 
			
		||||
    PUSH(s2);
 | 
			
		||||
    PUSH(s1);
 | 
			
		||||
    curr_frame = SP;
 | 
			
		||||
    return nargs;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if _BYTE_ORDER == __BIG_ENDIAN
 | 
			
		||||
#define GET_INT32(a)                            \
 | 
			
		||||
    ((((int32_t)a[0])<<0)  |                    \
 | 
			
		||||
| 
						 | 
				
			
			@ -935,16 +1007,13 @@ static value_t apply_cl(uint32_t nargs)
 | 
			
		|||
        OP(OP_OPTARGS)
 | 
			
		||||
            i = GET_INT32(ip); ip+=4;
 | 
			
		||||
            n = GET_INT32(ip); ip+=4;
 | 
			
		||||
            if ((int32_t)i < 0) {
 | 
			
		||||
                if (nargs < -i)
 | 
			
		||||
                    lerror(ArgError, "apply: too few arguments");
 | 
			
		||||
            }
 | 
			
		||||
            else if (nargs < i) {
 | 
			
		||||
            if (nargs < i)
 | 
			
		||||
                lerror(ArgError, "apply: too few arguments");
 | 
			
		||||
            if ((int32_t)n > 0) {
 | 
			
		||||
                if (nargs > n)
 | 
			
		||||
                    lerror(ArgError, "apply: too many arguments");
 | 
			
		||||
            }
 | 
			
		||||
            else if (nargs > n) {
 | 
			
		||||
                lerror(ArgError, "apply: too many arguments");
 | 
			
		||||
            }
 | 
			
		||||
            else n = -n;
 | 
			
		||||
            if (n > nargs) {
 | 
			
		||||
                n -= nargs;
 | 
			
		||||
                SP += n;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -123,6 +123,8 @@
 | 
			
		|||
(assert (equal? ((lambda (a (b 2) (c 3)) (list a b c)) 1) '(1 2 3)))
 | 
			
		||||
(assert (equal? ((lambda (a (b 2) (c 3)) (list a b c)) 1 8) '(1 8 3)))
 | 
			
		||||
(assert (equal? ((lambda (a (b 2) (c 3)) (list a b c)) 1 8 9) '(1 8 9)))
 | 
			
		||||
(assert (equal? ((lambda ((x 0) . r) (list x r))) '(0 ())))
 | 
			
		||||
(assert (equal? ((lambda ((x 0) . r) (list x r)) 1 2 3) '(1 (2 3))))
 | 
			
		||||
 | 
			
		||||
; ok, a couple end-to-end tests as well
 | 
			
		||||
(define (fib n) (if (< n 2) n (+ (fib (- n 1)) (fib (- n 2)))))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue