ref: b08031edac53f6a4aed024e6662a9bbacc25458c
dir: /vm.inc/
OP(OP_LOADA0) PUSH(FL(stack)[bp]); NEXT_OP; OP(OP_LOADA1) PUSH(FL(stack)[bp+1]); NEXT_OP; OP(OP_LOADV) v = fn_vals(FL(stack)[bp-1]); assert(*ip < vector_size(v)); PUSH(vector_elt(v, *ip++)); NEXT_OP; OP(OP_BRF) ip += POP() != FL_f ? 2 : GET_INT16(ip); NEXT_OP; OP(OP_POP) POPN(1); NEXT_OP; OP(OP_TCALLL) tail = true; if(0){ OP(OP_CALLL) tail = false; } n = GET_INT32(ip); ip += 4; if(0){ OP(OP_TCALL) tail = true; if(0){ OP(OP_CALL) tail = false; } n = *ip++; // nargs } LABEL(do_call): FL(stack)[ipd] = (uintptr_t)ip; func = FL(stack)[FL(sp)-n-1]; if(tag(func) == TAG_FUNCTION){ if(func > (N_BUILTINS<<3)){ if(tail){ FL(curr_frame) = FL(stack)[FL(curr_frame)-3]; for(s = -1; s < (fixnum_t)n; s++) FL(stack)[bp+s] = FL(stack)[FL(sp)-n+s]; FL(sp) = bp+n; } nargs = n; goto apply_cl_top; }else{ i = uintval(func); if(isbuiltin(func)){ s = builtins[i].nargs; if(s >= 0) argcount(n, (unsigned)s); else if(s != ANYARGS && (signed)n < -s) argcount(n, (unsigned)-s); // remove function arg for(s = FL(sp)-n-1; s < (int)FL(sp)-1; s++) FL(stack)[s] = FL(stack)[s+1]; FL(sp)--; switch(i){ case OP_LIST: goto LABEL(apply_list); case OP_VECTOR: goto LABEL(apply_vector); case OP_APPLY: goto LABEL(apply_apply); case OP_ADD: goto LABEL(apply_add); case OP_SUB: goto LABEL(apply_sub); case OP_MUL: goto LABEL(apply_mul); case OP_DIV: goto LABEL(apply_div); case OP_AREF: goto LABEL(apply_aref); case OP_ASET: goto LABEL(apply_aset); default: #if defined(COMPUTED_GOTO) goto *ops[i]; #else op = i; continue; #endif } } } }else if(__likely(iscbuiltin(func))){ s = FL(sp) - n; v = (((builtin_t*)ptr(func))[3])(&FL(stack)[s], n); FL(sp) = s; FL(stack)[s-1] = v; NEXT_OP; } type_error("function", func); OP(OP_LOADGL) v = fn_vals(FL(stack)[bp-1]); v = vector_elt(v, GET_INT32(ip)); ip += 4; if(0){ OP(OP_LOADG) v = fn_vals(FL(stack)[bp-1]); assert(*ip < vector_size(v)); v = vector_elt(v, *ip); ip++; } assert(issymbol(v)); sym = (symbol_t*)ptr(v); if(__unlikely(sym->binding == UNBOUND)){ FL(stack)[ipd] = (uintptr_t)ip; unbound_error(v); } PUSH(sym->binding); NEXT_OP; OP(OP_LOADA) i = *ip++; v = FL(stack)[bp+i]; PUSH(v); NEXT_OP; OP(OP_LOADC) i = *ip++; v = FL(stack)[bp+nargs]; assert(isvector(v)); assert(i < vector_size(v)); PUSH(vector_elt(v, i)); NEXT_OP; OP(OP_BOX) i = *ip++; v = mk_cons(); car_(v) = FL(stack)[bp+i]; cdr_(v) = FL_nil; FL(stack)[bp+i] = v; NEXT_OP; OP(OP_BOXL) i = GET_INT32(ip); ip += 4; v = mk_cons(); car_(v) = FL(stack)[bp+i]; cdr_(v) = FL_nil; FL(stack)[bp+i] = v; NEXT_OP; OP(OP_SHIFT) i = *ip++; FL(stack)[FL(sp)-1-i] = FL(stack)[FL(sp)-1]; FL(sp) -= i; NEXT_OP; OP(OP_RET) v = POP(); FL(sp) = FL(curr_frame); FL(curr_frame) = FL(stack)[FL(sp)-3]; if(FL(curr_frame) == top_frame) return v; FL(sp) -= 4+nargs; ipd = FL(curr_frame)-1; ip = (uint8_t*)FL(stack)[ipd]; nargs = FL(stack)[FL(curr_frame)-2]; bp = FL(curr_frame) - 4 - nargs; FL(stack)[FL(sp)-1] = v; NEXT_OP; OP(OP_DUP) FL(stack)[FL(sp)] = FL(stack)[FL(sp)-1]; FL(sp)++; NEXT_OP; OP(OP_CAR) v = FL(stack)[FL(sp)-1]; if(__likely(iscons(v))) v = car_(v); else if(__unlikely(v != FL_nil)){ FL(stack)[ipd] = (uintptr_t)ip; type_error("cons", v); } FL(stack)[FL(sp)-1] = v; NEXT_OP; OP(OP_CDR) v = FL(stack)[FL(sp)-1]; if(__likely(iscons(v))) v = cdr_(v); else if(__unlikely(v != FL_nil)){ FL(stack)[ipd] = (uintptr_t)ip; type_error("cons", v); } FL(stack)[FL(sp)-1] = v; NEXT_OP; OP(OP_CLOSURE) n = *ip++; assert(n > 0); pv = alloc_words(n + 1); v = tagptr(pv, TAG_VECTOR); i = 0; pv[i++] = fixnum(n); do{ pv[i] = FL(stack)[FL(sp)-n + i-1]; i++; }while(i <= n); POPN(n); PUSH(v); if(__unlikely((value_t*)FL(curheap) > (value_t*)FL(lim)-2)) gc(0); pv = (value_t*)FL(curheap); FL(curheap) += 4*sizeof(value_t); e = FL(stack)[FL(sp)-2]; // closure to copy assert(isfunction(e)); pv[0] = ((value_t*)ptr(e))[0]; pv[1] = ((value_t*)ptr(e))[1]; pv[2] = FL(stack)[FL(sp)-1]; // env pv[3] = ((value_t*)ptr(e))[3]; POPN(1); FL(stack)[FL(sp)-1] = tagptr(pv, TAG_FUNCTION); NEXT_OP; OP(OP_SETA) v = FL(stack)[FL(sp)-1]; i = *ip++; FL(stack)[bp+i] = v; NEXT_OP; OP(OP_JMP) ip += GET_INT16(ip); NEXT_OP; OP(OP_LOADC0) PUSH(vector_elt(FL(stack)[bp+nargs], 0)); NEXT_OP; OP(OP_CONSP) FL(stack)[FL(sp)-1] = iscons(FL(stack)[FL(sp)-1]) ? FL_t : FL_f; NEXT_OP; OP(OP_BRNE) ip += FL(stack)[FL(sp)-2] != FL(stack)[FL(sp)-1] ? GET_INT16(ip) : 2; POPN(2); NEXT_OP; OP(OP_LOADT) PUSH(FL_t); NEXT_OP; OP(OP_LOADVOID) PUSH(FL_void); NEXT_OP; OP(OP_LOAD0) PUSH(fixnum(0)); NEXT_OP; OP(OP_LOADC1) PUSH(vector_elt(FL(stack)[bp+nargs], 1)); NEXT_OP; OP(OP_AREF2) n = 2; if(0){ OP(OP_AREF) FL(stack)[ipd] = (uintptr_t)ip; n = 3 + *ip++; } LABEL(apply_aref): v = FL(stack)[FL(sp)-n]; for(i = n-1; i > 0; i--){ if(isarray(v)){ FL(stack)[FL(sp)-i-1] = v; v = cvalue_array_aref(&FL(stack)[FL(sp)-i-1]); continue; } e = FL(stack)[FL(sp)-i]; isz = tosize(e); if(isvector(v)){ if(__unlikely(isz >= vector_size(v))) bounds_error(v, e); v = vector_elt(v, isz); continue; } if(!iscons(v) && v != FL_nil) type_error("sequence", v); for(value_t v0 = v;; isz--){ if(isz == 0){ v = car_(v); break; } v = cdr_(v); if(__unlikely(!iscons(v))) bounds_error(v0, e); } } POPN(n); PUSH(v); NEXT_OP; OP(OP_ATOMP) FL(stack)[FL(sp)-1] = iscons(FL(stack)[FL(sp)-1]) ? FL_f : FL_t; NEXT_OP; OP(OP_BRT) ip += POP() != FL_f ? GET_INT16(ip) : 2; NEXT_OP; OP(OP_BRNN) ip += POP() != FL_nil ? GET_INT16(ip) : 2; NEXT_OP; OP(OP_LOAD1) PUSH(fixnum(1)); NEXT_OP; OP(OP_LT) { value_t a = FL(stack)[FL(sp)-2], b = FL(stack)[FL(sp)-1]; POPN(1); if(bothfixnums(a, b)){ FL(stack)[FL(sp)-1] = (fixnum_t)a < (fixnum_t)b ? FL_t : FL_f; }else{ x = numeric_compare(a, b, false, false, false); if(x > 1) x = numval(fl_compare(a, b)); FL(stack)[FL(sp)-1] = x < 0 ? FL_t : FL_f; } } NEXT_OP; OP(OP_ADD2) LABEL(do_add2): FL(stack)[ipd] = (uintptr_t)ip; if(0){ OP(OP_SUB2) LABEL(do_sub2): FL(stack)[ipd] = (uintptr_t)ip; FL(stack)[FL(sp)-1] = fl_neg(FL(stack)[FL(sp)-1]); } { fixnum_t a, b, c; a = FL(stack)[FL(sp)-2]; b = FL(stack)[FL(sp)-1]; if(bothfixnums(a, b) && !sadd_overflow(numval(a), numval(b), &c) && fits_fixnum(c)){ v = fixnum(c); }else{ v = fl_add_any(&FL(stack)[FL(sp)-2], 2); } } POPN(1); FL(stack)[FL(sp)-1] = v; NEXT_OP; OP(OP_SETCDR) v = FL(stack)[FL(sp)-2]; if(__unlikely(!iscons(v))){ FL(stack)[ipd] = (uintptr_t)ip; type_error("cons", v); } cdr_(v) = FL(stack)[FL(sp)-1]; POPN(1); NEXT_OP; OP(OP_LOADF) PUSH(FL_f); NEXT_OP; OP(OP_CONS) if(FL(curheap) > FL(lim)) gc(0); c = (cons_t*)FL(curheap); FL(curheap) += sizeof(cons_t); c->car = FL(stack)[FL(sp)-2]; c->cdr = FL(stack)[FL(sp)-1]; FL(stack)[FL(sp)-2] = tagptr(c, TAG_CONS); POPN(1); NEXT_OP; OP(OP_EQ) FL(stack)[FL(sp)-2] = FL(stack)[FL(sp)-2] == FL(stack)[FL(sp)-1] ? FL_t : FL_f; POPN(1); NEXT_OP; OP(OP_SYMBOLP) FL(stack)[FL(sp)-1] = issymbol(FL(stack)[FL(sp)-1]) ? FL_t : FL_f; NEXT_OP; OP(OP_NOT) FL(stack)[FL(sp)-1] = FL(stack)[FL(sp)-1] == FL_f ? FL_t : FL_f; NEXT_OP; OP(OP_CADR) v = FL(stack)[FL(sp)-1]; if(__likely(iscons(v))){ v = cdr_(v); if(__likely(iscons(v))) v = car_(v); else goto LABEL(cadr_nil); }else{ LABEL(cadr_nil): if(__unlikely(v != FL_nil)){ FL(stack)[ipd] = (uintptr_t)ip; type_error("cons", v); } } FL(stack)[FL(sp)-1] = v; NEXT_OP; OP(OP_NEG) LABEL(do_neg): FL(stack)[ipd] = (uintptr_t)ip; FL(stack)[FL(sp)-1] = fl_neg(FL(stack)[FL(sp)-1]); NEXT_OP; OP(OP_NULLP) FL(stack)[FL(sp)-1] = FL(stack)[FL(sp)-1] == FL_nil ? FL_t : FL_f; NEXT_OP; OP(OP_BOOLEANP) v = FL(stack)[FL(sp)-1]; FL(stack)[FL(sp)-1] = (v == FL_t || v == FL_f) ? FL_t : FL_f; NEXT_OP; OP(OP_NUMBERP) v = FL(stack)[FL(sp)-1]; FL(stack)[FL(sp)-1] = fl_isnumber(v) ? FL_t : FL_f; NEXT_OP; OP(OP_FIXNUMP) FL(stack)[FL(sp)-1] = isfixnum(FL(stack)[FL(sp)-1]) ? FL_t : FL_f; NEXT_OP; OP(OP_BOUNDP) FL(stack)[ipd] = (uintptr_t)ip; sym = tosymbol(FL(stack)[FL(sp)-1]); FL(stack)[FL(sp)-1] = sym->binding == UNBOUND ? FL_f : FL_t; NEXT_OP; OP(OP_BUILTINP) v = FL(stack)[FL(sp)-1]; FL(stack)[FL(sp)-1] = (isbuiltin(v) || iscbuiltin(v)) ? FL_t : FL_f; NEXT_OP; OP(OP_FUNCTIONP) v = FL(stack)[FL(sp)-1]; FL(stack)[FL(sp)-1] = ((tag(v) == TAG_FUNCTION && (isbuiltin(v) || v>(N_BUILTINS<<3))) || iscbuiltin(v)) ? FL_t : FL_f; NEXT_OP; OP(OP_VECTORP) FL(stack)[FL(sp)-1] = isvector(FL(stack)[FL(sp)-1]) ? FL_t : FL_f; NEXT_OP; OP(OP_JMPL) ip += GET_INT32(ip); NEXT_OP; OP(OP_BRFL) ip += POP() == FL_f ? GET_INT32(ip) : 4; NEXT_OP; OP(OP_BRTL) ip += POP() != FL_f ? GET_INT32(ip) : 4; NEXT_OP; OP(OP_BRNEL) ip += FL(stack)[FL(sp)-2] != FL(stack)[FL(sp)-1] ? GET_INT32(ip) : 4; POPN(2); NEXT_OP; OP(OP_BRNNL) ip += POP() != FL_nil ? GET_INT32(ip) : 4; NEXT_OP; OP(OP_BRN) ip += POP() == FL_nil ? GET_INT16(ip) : 2; NEXT_OP; OP(OP_BRNL) ip += POP() == FL_nil ? GET_INT32(ip) : 4; NEXT_OP; OP(OP_EQV) if(FL(stack)[FL(sp)-2] == FL(stack)[FL(sp)-1]) v = FL_t; else if(!leafp(FL(stack)[FL(sp)-2]) || !leafp(FL(stack)[FL(sp)-1])) v = FL_f; else v = compare_(FL(stack)[FL(sp)-2], FL(stack)[FL(sp)-1], 1) == 0 ? FL_t : FL_f; FL(stack)[FL(sp)-2] = v; POPN(1); NEXT_OP; OP(OP_EQUAL) if(FL(stack)[FL(sp)-2] == FL(stack)[FL(sp)-1]) v = FL_t; else v = compare_(FL(stack)[FL(sp)-2], FL(stack)[FL(sp)-1], 1) == 0 ? FL_t : FL_f; FL(stack)[FL(sp)-2] = v; POPN(1); NEXT_OP; OP(OP_SETCAR) v = FL(stack)[FL(sp)-2]; if(__unlikely(!iscons(v))){ FL(stack)[ipd] = (uintptr_t)ip; type_error("cons", v); } car_(v) = FL(stack)[FL(sp)-1]; POPN(1); NEXT_OP; OP(OP_LIST) n = *ip++; LABEL(apply_list): if(n > 0){ v = list(&FL(stack)[FL(sp)-n], n, 0); POPN(n); PUSH(v); }else{ PUSH(FL_nil); } NEXT_OP; OP(OP_TAPPLY) tail = true; if(0){ OP(OP_APPLY) tail = false; } n = *ip++; LABEL(apply_apply): v = POP(); // arglist n = FL(sp)-(n-2); // n-2 == # leading arguments not in the list while(iscons(v)){ if(FL(sp) >= FL(nstack)) grow_stack(); PUSH(car_(v)); v = cdr_(v); } if(v != FL_nil){ FL(stack)[ipd] = (uintptr_t)ip; lerrorf(FL(ArgError), "apply: last argument: not a list"); } n = FL(sp)-n; goto LABEL(do_call); OP(OP_ADD) n = *ip++; if(n == 2) goto LABEL(do_add2); LABEL(apply_add): FL(stack)[ipd] = (uintptr_t)ip; v = fl_add_any(&FL(stack)[FL(sp)-n], n); POPN(n); PUSH(v); NEXT_OP; OP(OP_SUB) n = *ip++; LABEL(apply_sub): if(n == 2) goto LABEL(do_sub2); if(n == 1) goto LABEL(do_neg); FL(stack)[ipd] = (uintptr_t)ip; i = FL(sp)-n; // we need to pass the full arglist on to fl_add_any // so it can handle rest args properly PUSH(FL(stack)[i]); FL(stack)[i] = fixnum(0); FL(stack)[i+1] = fl_neg(fl_add_any(&FL(stack)[i], n)); FL(stack)[i] = POP(); v = fl_add_any(&FL(stack)[i], 2); POPN(n); PUSH(v); NEXT_OP; OP(OP_MUL) n = *ip++; LABEL(apply_mul): FL(stack)[ipd] = (uintptr_t)ip; v = fl_mul_any(&FL(stack)[FL(sp)-n], n); POPN(n); PUSH(v); NEXT_OP; OP(OP_DIV) n = *ip++; LABEL(apply_div): FL(stack)[ipd] = (uintptr_t)ip; i = FL(sp)-n; if(n == 1){ FL(stack)[FL(sp)-1] = fl_div2(fixnum(1), FL(stack)[i]); }else{ if(n > 2){ PUSH(FL(stack)[i]); FL(stack)[i] = fixnum(1); FL(stack)[i+1] = fl_mul_any(&FL(stack)[i], n); FL(stack)[i] = POP(); } v = fl_div2(FL(stack)[i], FL(stack)[i+1]); POPN(n); PUSH(v); } NEXT_OP; OP(OP_IDIV) FL(stack)[ipd] = (uintptr_t)ip; v = FL(stack)[FL(sp)-2]; e = FL(stack)[FL(sp)-1]; if(bothfixnums(v, e)){ if(e == 0) DivideByZeroError(); v = fixnum(numval(v) / numval(e)); }else{ v = fl_idiv2(v, e); } POPN(1); FL(stack)[FL(sp)-1] = v; NEXT_OP; OP(OP_NUMEQ) v = FL(stack)[FL(sp)-2]; e = FL(stack)[FL(sp)-1]; if(bothfixnums(v, e)) v = v == e ? FL_t : FL_f; else{ FL(stack)[ipd] = (uintptr_t)ip; v = numeric_compare(v, e, true, false, true) == 0 ? FL_t : FL_f; } POPN(1); FL(stack)[FL(sp)-1] = v; NEXT_OP; OP(OP_COMPARE) FL(stack)[FL(sp)-2] = compare_(FL(stack)[FL(sp)-2], FL(stack)[FL(sp)-1], 0); POPN(1); NEXT_OP; OP(OP_ARGC) n = *ip++; if(0){ OP(OP_LARGC) n = GET_INT32(ip); ip += 4; } FL(stack)[ipd] = (uintptr_t)ip; argcount(nargs, n); NEXT_OP; OP(OP_VECTOR) n = *ip++; LABEL(apply_vector): v = alloc_vector(n, 0); if(n){ memcpy(&vector_elt(v, 0), &FL(stack)[FL(sp)-n], n*sizeof(value_t)); POPN(n); } PUSH(v); NEXT_OP; OP(OP_ASET) FL(stack)[ipd] = (uintptr_t)ip; v = FL(stack)[FL(sp)-3]; n = 3; if(0){ LABEL(apply_aset): v = FL(stack)[FL(sp)-n]; for(i = n-1; i >= 3; i--){ if(isarray(v)){ FL(stack)[FL(sp)-i-1] = v; v = cvalue_array_aref(&FL(stack)[FL(sp)-i-1]); continue; } e = FL(stack)[FL(sp)-i]; isz = tosize(e); if(isvector(v)){ if(__unlikely(isz >= vector_size(v))) bounds_error(v, e); v = vector_elt(v, isz); continue; } if(!iscons(v) && v != FL_nil) type_error("sequence", v); for(value_t v0 = v;; isz--){ if(isz == 0){ v = car_(v); break; } v = cdr_(v); if(__unlikely(!iscons(v))) bounds_error(v0, e); } } FL(stack)[FL(sp)-3] = v; } e = FL(stack)[FL(sp)-2]; isz = tosize(e); if(isvector(v)){ if(__unlikely(isz >= vector_size(v))) bounds_error(v, e); vector_elt(v, isz) = (e = FL(stack)[FL(sp)-1]); }else if(iscons(v) || v == FL_nil){ for(value_t v0 = v;; isz--){ if(isz == 0){ car_(v) = (e = FL(stack)[FL(sp)-1]); break; } v = cdr_(v); if(__unlikely(!iscons(v))) bounds_error(v0, e); } }else if(isarray(v)){ e = cvalue_array_aset(&FL(stack)[FL(sp)-3]); }else{ type_error("sequence", v); } POPN(n); PUSH(e); NEXT_OP; OP(OP_FOR) FL(stack)[ipd] = (uintptr_t)ip; s = tofixnum(FL(stack)[FL(sp)-3]); hi = tofixnum(FL(stack)[FL(sp)-2]); v = FL_void; FL(sp) += 2; n = FL(sp); for(; s <= hi; s++){ FL(stack)[FL(sp)-2] = FL(stack)[FL(sp)-3]; FL(stack)[FL(sp)-1] = fixnum(s); v = _applyn(1); FL(sp) = n; } POPN(4); FL(stack)[FL(sp)-1] = v; NEXT_OP; OP(OP_LOADNIL) PUSH(FL_nil); NEXT_OP; OP(OP_LOADI8) s = (int8_t)*ip++; PUSH(fixnum(s)); NEXT_OP; OP(OP_LOADVL) v = fn_vals(FL(stack)[bp-1]); v = vector_elt(v, GET_INT32(ip)); ip += 4; PUSH(v); NEXT_OP; OP(OP_SETGL) v = fn_vals(FL(stack)[bp-1]); v = vector_elt(v, GET_INT32(ip)); ip += 4; if(0){ OP(OP_SETG) v = fn_vals(FL(stack)[bp-1]); assert(*ip < vector_size(v)); v = vector_elt(v, *ip); ip++; } assert(issymbol(v)); sym = (symbol_t*)ptr(v); v = FL(stack)[FL(sp)-1]; if(!isconstant(sym)) sym->binding = v; NEXT_OP; OP(OP_LOADAL) assert(nargs > 0); i = GET_INT32(ip); ip += 4; v = FL(stack)[bp+i]; PUSH(v); NEXT_OP; OP(OP_SETAL) v = FL(stack)[FL(sp)-1]; i = GET_INT32(ip); ip += 4; FL(stack)[bp+i] = v; NEXT_OP; OP(OP_LOADCL) i = GET_INT32(ip); ip += 4; v = FL(stack)[bp+nargs]; PUSH(vector_elt(v, i)); NEXT_OP; OP(OP_VARGC) i = *ip++; if(0){ OP(OP_LVARGC) i = GET_INT32(ip); ip += 4; } s = (fixnum_t)nargs - (fixnum_t)i; if(s > 0){ v = list(&FL(stack)[bp+i], s, 0); FL(stack)[bp+i] = v; if(s > 1){ FL(stack)[bp+i+1] = FL(stack)[bp+nargs+0]; FL(stack)[bp+i+2] = FL(stack)[bp+nargs+1]; FL(stack)[bp+i+3] = i+1; FL(stack)[bp+i+4] = 0; FL(sp) = bp+i+5; FL(curr_frame) = FL(sp); } }else if(__unlikely(s < 0)){ FL(stack)[ipd] = (uintptr_t)ip; lerrorf(FL(ArgError), "too few arguments"); }else{ FL(sp)++; FL(stack)[FL(sp)-2] = i+1; FL(stack)[FL(sp)-3] = FL(stack)[FL(sp)-4]; FL(stack)[FL(sp)-4] = FL(stack)[FL(sp)-5]; FL(stack)[FL(sp)-5] = FL_nil; FL(curr_frame) = FL(sp); } ipd = FL(sp)-1; nargs = i+1; NEXT_OP; OP(OP_TRYCATCH) FL(stack)[ipd] = (uintptr_t)ip; v = do_trycatch(); POPN(1); FL(stack)[FL(sp)-1] = v; NEXT_OP; OP(OP_OPTARGS) i = GET_INT32(ip); ip += 4; n = GET_INT32(ip); ip += 4; if(__unlikely(nargs < i)){ FL(stack)[ipd] = (uintptr_t)ip; lerrorf(FL(ArgError), "too few arguments"); } if((int32_t)n > 0){ if(__unlikely(nargs > n)){ FL(stack)[ipd] = (uintptr_t)ip; lerrorf(FL(ArgError), "too many arguments"); } }else n = -n; if(__likely(n > nargs)){ n -= nargs; FL(sp) += n; FL(stack)[FL(sp)-1] = FL(stack)[FL(sp)-n-1]; FL(stack)[FL(sp)-2] = nargs+n; FL(stack)[FL(sp)-3] = FL(stack)[FL(sp)-n-3]; FL(stack)[FL(sp)-4] = FL(stack)[FL(sp)-n-4]; FL(curr_frame) = FL(sp); ipd = FL(sp)-1; for(i = 0; i < n; i++) FL(stack)[bp+nargs+i] = UNBOUND; nargs += n; } NEXT_OP; OP(OP_BRBOUND) i = GET_INT32(ip); ip += 4; v = FL(stack)[bp+i]; PUSH(v != UNBOUND ? FL_t : FL_f); NEXT_OP; OP(OP_KEYARGS) v = fn_vals(FL(stack)[bp-1]); v = vector_elt(v, 0); i = GET_INT32(ip); ip += 4; n = GET_INT32(ip); ip += 4; s = GET_INT32(ip); ip += 4; FL(stack)[ipd] = (uintptr_t)ip; nargs = process_keys(v, i, n, labs(s)-(i+n), bp, nargs, s<0); ipd = FL(sp)-1; NEXT_OP;