ref: 300cfb6caacb43cbe98e61d2d0e4e071fb507f75
dir: /src/vm.inc/
#define fixnum_neg(x) ( \
i64 = -(int64_t)(numval(x)), \
i64 == INT64_MIN \
? mk_mpint(uvtomp((uint64_t)INT64_MAX+1, nil)) \
: (fits_fixnum(i64) ? fixnum(i64) : mk_mpint(vtomp(i64, nil))) \
)
OP(OP_LOADA0)
PUSH(*bp);
NEXT_OP;
OP(OP_CALL) {
tail = false;
if(0){
OP(OP_TCALL)
tail = true;
}
n = *ip++; // nargs
if(0){
OP(OP_TCALLL)
tail = true;
if(0){
OP(OP_CALLL)
tail = false;
}
n = GET_INT32(ip);
ip += 4;
}
LABEL(do_call):
*ipd = (uintptr_t)ip;
value_t v = FL(sp)[-n-1];
if(tag(v) == TAG_FUNCTION){
if(v > (N_BUILTINS<<3)){
if(tail){
FL(curr_frame) = (value_t*)FL(curr_frame)[-3];
for(fixnum_t s = -1; s < (fixnum_t)n; s++)
bp[s] = FL(sp)[s-n];
FL(sp) = bp+n;
}
nargs = n;
goto apply_cl_top;
}
int i = uintval(v);
assert(isbuiltin(v));
fixnum_t s = builtins[i].nargs;
if(s >= 0)
argcount(n, s);
else if(s != ANYARGS && n < -s)
argcount(n, -s);
// remove function arg
for(value_t *p = FL(sp)-n-1; p < FL(sp)-1; p++)
p[0] = p[1];
FL(sp)--;
switch(i){
case OP_VECTOR: goto LABEL(apply_vector);
case OP_ADD: goto LABEL(apply_add);
case OP_LIST: goto LABEL(apply_list);
case OP_APPLY: goto LABEL(apply_apply);
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);
case OP_LT: goto LABEL(apply_lt);
case OP_NUMEQ: goto LABEL(apply_numeq);
default:
#if defined(COMPUTED_GOTO)
goto *ops[i];
#else
op = i;
continue;
#endif
}
}else if(fl_likely(iscbuiltin(v))){
value_t *p = FL(sp) - n;
v = ((cvalue_t*)ptr(v))->cbuiltin(p, n);
FL(sp) = p;
p[-1] = v;
NEXT_OP;
}
type_error("function", v);
}
OP(OP_ARGC) {
int na = *ip++;
if(0){
OP(OP_ARGCL)
na = GET_INT32(ip);
ip += 4;
}
if(fl_unlikely(nargs != na)){
*ipd = (uintptr_t)ip;
arity_error(nargs, na);
}
NEXT_OP;
}
OP(OP_LOADA1)
PUSH(bp[1]);
NEXT_OP;
OP(OP_RET) {
value_t v = POP();
FL(sp) = FL(curr_frame);
FL(curr_frame) = (value_t*)FL(sp)[-3];
if(FL(curr_frame) == top_frame)
return v;
FL(sp) -= 4+nargs;
ipd = FL(curr_frame)-1;
ip = (uint8_t*)*ipd;
nargs = FL(curr_frame)[-2];
bp = FL(curr_frame) - 4 - nargs;
FL(sp)[-1] = v;
NEXT_OP;
}
OP(OP_LOAD1)
PUSH(fixnum(1));
NEXT_OP;
OP(OP_LOADA)
PUSH(bp[*ip++]);
NEXT_OP;
OP(OP_BRN)
ip += POP() == FL_nil ? GET_INT16(ip) : 2;
NEXT_OP;
OP(OP_LOADG) {
value_t v = fn_vals(bp[-1]);
assert(*ip < vector_size(v));
v = vector_elt(v, *ip);
ip++;
if(0){
OP(OP_LOADGL)
v = fn_vals(bp[-1]);
v = vector_elt(v, GET_INT32(ip));
ip += 4;
}
assert(issymbol(v));
symbol_t *sym = ptr(v);
if(fl_unlikely(sym->binding == UNBOUND)){
*ipd = (uintptr_t)ip;
unbound_error(v);
}
PUSH(sym->binding);
NEXT_OP;
}
OP(OP_LT)
n = *ip++;
LABEL(apply_lt):
{
int i = n;
value_t a = FL(sp)[-i], b, v;
for(v = FL_t; i > 1; a = b){
i--;
b = FL(sp)[-i];
if(bothfixnums(a, b)){
if((fixnum_t)a >= (fixnum_t)b){
v = FL_nil;
break;
}
}else{
int x = numeric_compare(a, b, false, false, false);
if(x > 1)
x = numval(fl_compare(a, b, false));
if(x >= 0){
v = FL_nil;
break;
}
}
}
POPN(n);
PUSH(v);
}
NEXT_OP;
OP(OP_LOADV) {
value_t v = fn_vals(bp[-1]);
assert(*ip < vector_size(v));
PUSH(vector_elt(v, *ip++));
NEXT_OP;
}
OP(OP_ADD2) {
value_t v;
LABEL(do_add2):
*ipd = (uintptr_t)ip;
if(0){
OP(OP_SUB2)
LABEL(do_sub2):
*ipd = (uintptr_t)ip;
v = FL(sp)[-1];
int64_t i64;
FL(sp)[-1] = isfixnum(v) ? fixnum_neg(v) : fl_neg(v);
}
value_t a, b, q;
a = FL(sp)[-2];
b = FL(sp)[-1];
if(bothfixnums(a, b) && !sadd_overflow(numval(a), numval(b), &q) && fits_fixnum(q))
v = fixnum(q);
else
v = fl_add_any(FL(sp)-2, 2);
POPN(1);
FL(sp)[-1] = v;
NEXT_OP;
}
OP(OP_LOADI8)
PUSH(fixnum((int8_t)*ip++));
NEXT_OP;
OP(OP_POP)
POPN(1);
NEXT_OP;
OP(OP_BRNN)
ip += POP() != FL_nil ? GET_INT16(ip) : 2;
NEXT_OP;
OP(OP_DUP)
FL(sp)[0] = FL(sp)[-1];
FL(sp)++;
NEXT_OP;
OP(OP_LOADC0)
PUSH(vector_elt(bp[nargs], 0));
NEXT_OP;
OP(OP_CAR) {
value_t v = FL(sp)[-1];
if(fl_likely(iscons(v)))
v = car_(v);
else if(fl_unlikely(v != FL_nil)){
*ipd = (uintptr_t)ip;
type_error("cons", v);
}
FL(sp)[-1] = v;
NEXT_OP;
}
OP(OP_CLOSURE) {
int x = *ip++;
assert(x > 0);
value_t *pv = alloc_words(
1+x+
#if !defined(BITS64)
!(x&1)+
#endif
sizeof(function_t)/sizeof(value_t));
value_t v = tagptr(pv, TAG_VECTOR);
*pv++ = fixnum(x);
for(int i = 0; i < x; i++)
*pv++ = FL(sp)[-x+i];
POPN(x);
PUSH(v);
#if !defined(BITS64)
if((x & 1) == 0)
pv++;
#endif
function_t *f = (function_t*)pv;
value_t e = FL(sp)[-2]; // closure to copy
assert(isfunction(e));
f->bcode = fn_bcode(e);
f->vals = fn_vals(e);
f->env = FL(sp)[-1];
f->name = fn_name(e);
POPN(1);
FL(sp)[-1] = tagptr(f, TAG_FUNCTION);
NEXT_OP;
}
OP(OP_CONS) {
if(FL(curheap) > FL(lim))
fl_gc(0);
cons_t *c = (cons_t*)FL(curheap);
FL(curheap) += sizeof(cons_t);
c->car = FL(sp)[-2];
c->cdr = FL(sp)[-1];
FL(sp)[-2] = tagptr(c, TAG_CONS);
POPN(1);
NEXT_OP;
}
OP(OP_BRNE)
ip += FL(sp)[-2] != FL(sp)[-1] ? GET_INT16(ip) : 2;
POPN(2);
NEXT_OP;
OP(OP_CDR) {
value_t v = FL(sp)[-1];
if(fl_likely(iscons(v)))
v = cdr_(v);
else if(fl_unlikely(v != FL_nil)){
*ipd = (uintptr_t)ip;
type_error("cons", v);
}
FL(sp)[-1] = v;
NEXT_OP;
}
OP(OP_LOADVOID)
PUSH(FL_void);
NEXT_OP;
OP(OP_NOT)
FL(sp)[-1] = FL(sp)[-1] == FL_nil ? FL_t : FL_nil;
NEXT_OP;
OP(OP_SETA)
bp[*ip++] = FL(sp)[-1];
NEXT_OP;
OP(OP_VARGC) {
int i = *ip++;
if(0){
OP(OP_VARGCL)
i = GET_INT32(ip);
ip += 4;
}
fixnum_t s = (fixnum_t)nargs - (fixnum_t)i;
if(s > 0){
value_t v = list(bp+i, s, 0);
bp[i] = v;
if(s > 1){
bp[i+1] = bp[nargs+0];
bp[i+2] = bp[nargs+1];
bp[i+3] = i+1;
bp[i+4] = 0;
FL(sp) = bp+i+5;
FL(curr_frame) = FL(sp);
}
}else if(fl_unlikely(s < 0)){
*ipd = (uintptr_t)ip;
lerrorf(FL_ArgError, "too few arguments");
}else{
FL(sp)++;
FL(sp)[-2] = i+1;
FL(sp)[-3] = FL(sp)[-4];
FL(sp)[-4] = FL(sp)[-5];
FL(sp)[-5] = FL_nil;
FL(curr_frame) = FL(sp);
}
ipd = FL(sp)-1;
nargs = i+1;
NEXT_OP;
}
OP(OP_SHIFT) {
int i = *ip++;
FL(sp)[-1-i] = FL(sp)[-1];
FL(sp) -= i;
NEXT_OP;
}
OP(OP_SETCAR) {
value_t v = FL(sp)[-2];
if(fl_unlikely(!iscons(v))){
*ipd = (uintptr_t)ip;
type_error("cons", v);
}
car_(v) = FL(sp)[-1];
POPN(1);
NEXT_OP;
}
OP(OP_LOADNIL)
PUSH(FL_nil);
NEXT_OP;
OP(OP_BOX) {
int i = *ip++;
value_t v = mk_cons();
car_(v) = bp[i];
cdr_(v) = FL_nil;
bp[i] = v;
NEXT_OP;
}
OP(OP_JMP)
ip += GET_INT16(ip);
NEXT_OP;
OP(OP_ATOMP)
FL(sp)[-1] = iscons(FL(sp)[-1]) ? FL_nil : FL_t;
NEXT_OP;
OP(OP_AREF2) {
n = 2;
if(0){
OP(OP_AREF)
*ipd = (uintptr_t)ip;
n = 3 + *ip++;
}
LABEL(apply_aref):;
value_t v = FL(sp)[-n];
for(int i = n-1; i > 0; i--){
if(isarray(v)){
FL(sp)[-i-1] = v;
v = cvalue_array_aref(FL(sp)-i-1);
continue;
}
value_t e = FL(sp)[-i];
size_t isz = tosize(e);
if(isvector(v)){
if(fl_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(fl_unlikely(!iscons(v)))
bounds_error(v0, e);
}
}
POPN(n);
PUSH(v);
NEXT_OP;
}
OP(OP_NANP) {
value_t v = FL(sp)[-1];
if(!iscprim(v))
v = FL_nil;
else{
void *p = ptr(v);
switch(cp_numtype(p)){
case T_DOUBLE:
v = isnan(*(double*)cp_data(p)) ? FL_t : FL_nil;
break;
case T_FLOAT:
v = isnan(*(float*)cp_data(p)) ? FL_t : FL_nil;
break;
default:
v = FL_nil;
break;
}
}
FL(sp)[-1] = v;
NEXT_OP;
}
OP(OP_LOAD0)
PUSH(fixnum(0));
NEXT_OP;
OP(OP_SETCDR) {
value_t v = FL(sp)[-2];
if(fl_unlikely(!iscons(v))){
*ipd = (uintptr_t)ip;
type_error("cons", v);
}
cdr_(v) = FL(sp)[-1];
POPN(1);
NEXT_OP;
}
OP(OP_LOADC1)
PUSH(vector_elt(bp[nargs], 1));
NEXT_OP;
OP(OP_ASET) {
*ipd = (uintptr_t)ip;
value_t v = FL(sp)[-3];
n = 3;
if(0){
LABEL(apply_aset):
v = FL(sp)[-n];
for(int i = n-1; i >= 3; i--){
if(isarray(v)){
FL(sp)[-i-1] = v;
v = cvalue_array_aref(FL(sp)-i-1);
continue;
}
value_t e = FL(sp)[-i];
size_t isz = tosize(e);
if(isvector(v)){
if(fl_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(fl_unlikely(!iscons(v)))
bounds_error(v0, e);
}
}
FL(sp)[-3] = v;
}
value_t e = FL(sp)[-2];
size_t isz = tosize(e);
if(isvector(v)){
if(fl_unlikely(isz >= vector_size(v)))
bounds_error(v, e);
vector_elt(v, isz) = (e = FL(sp)[-1]);
}else if(iscons(v) || v == FL_nil){
for(value_t v0 = v;; isz--){
if(isz == 0){
car_(v) = (e = FL(sp)[-1]);
break;
}
v = cdr_(v);
if(fl_unlikely(!iscons(v)))
bounds_error(v0, e);
}
}else if(isarray(v)){
e = cvalue_array_aset(FL(sp)-3);
}else{
type_error("sequence", v);
}
POPN(n);
PUSH(e);
NEXT_OP;
}
OP(OP_EQUAL) {
value_t v;
if(FL(sp)[-2] == FL(sp)[-1])
v = FL_t;
else
v = fl_compare(FL(sp)[-2], FL(sp)[-1], true) == 0 ? FL_t : FL_nil;
FL(sp)[-2] = v;
POPN(1);
NEXT_OP;
}
OP(OP_CONSP)
FL(sp)[-1] = iscons(FL(sp)[-1]) ? FL_t : FL_nil;
NEXT_OP;
OP(OP_LOADC) {
value_t v = bp[nargs];
int i = *ip++;
assert(isvector(v));
assert(i < (int)vector_size(v));
PUSH(vector_elt(v, i));
NEXT_OP;
}
OP(OP_SYMBOLP)
FL(sp)[-1] = issymbol(FL(sp)[-1]) ? FL_t : FL_nil;
NEXT_OP;
OP(OP_NUMBERP)
FL(sp)[-1] = fl_isnumber(FL(sp)[-1]) ? FL_t : FL_nil;
NEXT_OP;
OP(OP_BRBOUND)
PUSH(bp[GET_INT32(ip)] != UNBOUND ? FL_t : FL_nil);
ip += 4;
NEXT_OP;
OP(OP_OPTARGS) {
int i = GET_INT32(ip);
ip += 4;
int x = GET_INT32(ip);
ip += 4;
if(fl_unlikely(nargs < i)){
*ipd = (uintptr_t)ip;
lerrorf(FL_ArgError, "too few arguments");
}
if(x > 0){
if(fl_unlikely(nargs > x)){
*ipd = (uintptr_t)ip;
lerrorf(FL_ArgError, "too many arguments");
}
}else
x = -x;
if(fl_likely(x > nargs)){
x -= nargs;
FL(sp) += x;
FL(sp)[-1] = FL(sp)[-x-1];
FL(sp)[-2] = nargs+x;
FL(sp)[-3] = FL(sp)[-x-3];
FL(sp)[-4] = FL(sp)[-x-4];
FL(curr_frame) = FL(sp);
ipd = FL(sp)-1;
for(i = 0; i < x; i++)
bp[nargs+i] = UNBOUND;
nargs += x;
}
NEXT_OP;
}
OP(OP_EQ)
FL(sp)[-2] = FL(sp)[-2] == FL(sp)[-1] ? FL_t : FL_nil;
POPN(1);
NEXT_OP;
OP(OP_LIST)
n = *ip++;
LABEL(apply_list):
if(n > 0){
value_t v = list(FL(sp)-n, n, 0);
POPN(n);
PUSH(v);
}else{
PUSH(FL_nil);
}
NEXT_OP;
OP(OP_BOUNDP) {
*ipd = (uintptr_t)ip;
symbol_t *sym = tosymbol(FL(sp)[-1]);
FL(sp)[-1] = sym->binding == UNBOUND ? FL_nil : FL_t;
NEXT_OP;
}
OP(OP_NUMEQ)
n = *ip++;
LABEL(apply_numeq):
{
int i = n;
value_t a = FL(sp)[-i], b, v;
for(v = FL_t; i > 1; a = b){
i--;
b = FL(sp)[-i];
if(bothfixnums(a, b)){
if(a != b){
v = FL_nil;
break;
}
}else if(numeric_compare(a, b, true, false, true) != 0){
v = FL_nil;
break;
}
}
POPN(n);
PUSH(v);
}
NEXT_OP;
OP(OP_CADR) {
value_t v = FL(sp)[-1];
if(fl_likely(iscons(v))){
v = cdr_(v);
if(fl_likely(iscons(v)))
v = car_(v);
else
goto LABEL(cadr_nil);
}else{
LABEL(cadr_nil):
if(fl_unlikely(v != FL_nil)){
*ipd = (uintptr_t)ip;
type_error("cons", v);
}
}
FL(sp)[-1] = v;
NEXT_OP;
}
OP(OP_TAPPLY) {
tail = true;
if(0){
OP(OP_APPLY)
tail = false;
}
n = *ip++;
LABEL(apply_apply):;
value_t v = POP(); // arglist
value_t *p = FL(sp)-(n-2); // n-2 == # leading arguments not in the list
while(iscons(v)){
PUSH(car_(v));
v = cdr_(v);
}
if(v != FL_nil){
*ipd = (uintptr_t)ip;
lerrorf(FL_ArgError, "apply: last argument: not a list");
}
n = FL(sp)-p;
goto LABEL(do_call);
}
OP(OP_LOADT)
PUSH(FL_t);
NEXT_OP;
OP(OP_BUILTINP) {
value_t v = FL(sp)[-1];
FL(sp)[-1] = (isbuiltin(v) || iscbuiltin(v)) ? FL_t : FL_nil;
NEXT_OP;
}
OP(OP_NEG) {
LABEL(do_neg):
*ipd = (uintptr_t)ip;
value_t v = FL(sp)[-1];
int64_t i64;
FL(sp)[-1] = isfixnum(v) ? fixnum_neg(v) : fl_neg(v);
NEXT_OP;
}
OP(OP_FIXNUMP)
FL(sp)[-1] = isfixnum(FL(sp)[-1]) ? FL_t : FL_nil;
NEXT_OP;
OP(OP_MUL) {
n = *ip++;
LABEL(apply_mul):
*ipd = (uintptr_t)ip;
value_t v = fl_mul_any(FL(sp)-n, n);
POPN(n);
PUSH(v);
NEXT_OP;
}
OP(OP_IDIV) {
value_t a = FL(sp)[-2];
value_t b = FL(sp)[-1];
value_t v;
if(bothfixnums(a, b)){
if(b == 0){
*ipd = (uintptr_t)ip;
divide_by_0_error();
}
v = fixnum(numval(a) / numval(b));
}else{
*ipd = (uintptr_t)ip;
v = fl_idiv2(a, b);
}
POPN(1);
FL(sp)[-1] = v;
NEXT_OP;
}
OP(OP_DIV) {
n = *ip++;
LABEL(apply_div):
*ipd = (uintptr_t)ip;
value_t *p = FL(sp)-n;
if(n == 1){
FL(sp)[-1] = fl_div2(fixnum(1), *p);
}else{
if(fl_unlikely(n > 2)){
PUSH(*p);
*p = fixnum(1);
p[1] = fl_mul_any(p, n);
*p = POP();
}
value_t v = fl_div2(p[0], p[1]);
POPN(n);
PUSH(v);
}
NEXT_OP;
}
OP(OP_VECTOR) {
n = *ip++;
LABEL(apply_vector):;
value_t v = alloc_vector(n, 0);
if(n){
memcpy(&vector_elt(v, 0), FL(sp)-n, n*sizeof(value_t));
POPN(n);
}
PUSH(v);
NEXT_OP;
}
OP(OP_COMPARE)
FL(sp)[-2] = fl_compare(FL(sp)[-2], FL(sp)[-1], false);
POPN(1);
NEXT_OP;
OP(OP_FOR) {
*ipd = (uintptr_t)ip;
value_t *p = FL(sp);
value_t v;
fixnum_t s = tofixnum(p[-3]);
fixnum_t hi = tofixnum(p[-2]);
FL(sp) += 2;
for(v = FL_void; s <= hi; s++){
p[0] = p[-1];
p[1] = fixnum(s);
v = _applyn(1);
}
POPN(4);
p[1] = v;
NEXT_OP;
}
OP(OP_SETG) {
int i = *ip++;
if(0){
OP(OP_SETGL)
i = GET_INT32(ip);
ip += 4;
}
value_t v = fn_vals(bp[-1]);
assert(i < (int)vector_size(v));
v = vector_elt(v, i);
assert(issymbol(v));
symbol_t *sym = ptr(v);
v = FL(sp)[-1];
if(!isconstant(sym))
sym->binding = v;
NEXT_OP;
}
OP(OP_VECTORP)
FL(sp)[-1] = isvector(FL(sp)[-1]) ? FL_t : FL_nil;
NEXT_OP;
OP(OP_TRYCATCH) {
*ipd = (uintptr_t)ip;
value_t v = do_trycatch();
POPN(1);
FL(sp)[-1] = v;
NEXT_OP;
}
OP(OP_ADD) {
n = *ip++;
if(n == 2)
goto LABEL(do_add2);
LABEL(apply_add):
*ipd = (uintptr_t)ip;
value_t v = fl_add_any(FL(sp)-n, n);
POPN(n);
PUSH(v);
NEXT_OP;
}
OP(OP_LOADAL)
assert(nargs > 0);
PUSH(bp[GET_INT32(ip)]);
ip += 4;
NEXT_OP;
OP(OP_EQV) {
value_t v;
if(FL(sp)[-2] == FL(sp)[-1])
v = FL_t;
else if(!leafp(FL(sp)[-2]) || !leafp(FL(sp)[-1]))
v = FL_nil;
else
v = fl_compare(FL(sp)[-2], FL(sp)[-1], true) == 0 ? FL_t : FL_nil;
FL(sp)[-2] = v;
POPN(1);
NEXT_OP;
}
OP(OP_KEYARGS) {
value_t v = fn_vals(bp[-1]);
v = vector_elt(v, 0);
int i = GET_INT32(ip);
ip += 4;
int x = GET_INT32(ip);
ip += 4;
fixnum_t s = GET_INT32(ip);
ip += 4;
*ipd = (uintptr_t)ip;
nargs = process_keys(v, i, x, labs(s)-(i+x), bp, nargs, s<0);
ipd = FL(sp)-1;
NEXT_OP;
}
OP(OP_SUB) {
n = *ip++;
LABEL(apply_sub):
if(n == 2)
goto LABEL(do_sub2);
if(n == 1)
goto LABEL(do_neg);
*ipd = (uintptr_t)ip;
value_t *p = FL(sp)-n;
// we need to pass the full arglist on to fl_add_any
// so it can handle rest args properly
PUSH(*p);
*p = fixnum(0);
value_t v = fl_add_any(p, n);
int64_t i64;
p[1] = isfixnum(v) ? fixnum_neg(v) : fl_neg(v);
p[0] = POP();
v = fl_add_any(p, 2);
POPN(n);
PUSH(v);
NEXT_OP;
}
OP(OP_BRNL)
ip += POP() == FL_nil ? GET_INT32(ip) : 4;
NEXT_OP;
OP(OP_SETAL)
bp[GET_INT32(ip)] = FL(sp)[-1];
ip += 4;
NEXT_OP;
OP(OP_BOXL) {
int i = GET_INT32(ip);
ip += 4;
value_t v = mk_cons();
car_(v) = bp[i];
cdr_(v) = FL_nil;
bp[i] = v;
NEXT_OP;
}
OP(OP_FUNCTIONP) {
value_t v = FL(sp)[-1];
FL(sp)[-1] =
((tag(v) == TAG_FUNCTION &&
(isbuiltin(v) || v>(N_BUILTINS<<3))) ||
iscbuiltin(v)) ? FL_t : FL_nil;
NEXT_OP;
}
OP(OP_JMPL)
ip += GET_INT32(ip);
NEXT_OP;
OP(OP_BRNEL)
ip += FL(sp)[-2] != 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_LOADCL)
ip += 4;
PUSH(vector_elt(bp[nargs], GET_INT32(ip)));
ip += 4;
NEXT_OP;
OP(OP_LOADVL) {
value_t v = fn_vals(bp[-1]);
v = vector_elt(v, GET_INT32(ip));
ip += 4;
PUSH(v);
NEXT_OP;
}