ref: 70246f96c1b3c628b758e6d6939e0a7c9a71d481
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)
*sp++ = *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 = 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] = sp[s-n];
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){
FL(sp) = sp;
argcount(n, s);
}else if(s != ANYARGS && n < -s){
FL(sp) = sp;
argcount(n, -s);
}
// remove function arg
for(value_t *p = sp-n-1; p < sp-1; p++)
p[0] = p[1];
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 = sp - n;
FL(sp) = sp;
v = ((cvalue_t*)ptr(v))->cbuiltin(p, n);
sp = p;
p[-1] = v;
NEXT_OP;
}
FL(sp) = sp;
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;
FL(sp) = sp;
arity_error(nargs, na);
}
NEXT_OP;
}
OP(OP_LOADA1)
*sp++ = bp[1];
NEXT_OP;
OP(OP_RET) {
value_t v = *(--sp);
sp = FL(curr_frame);
FL(curr_frame) = (value_t*)sp[-3];
if(FL(curr_frame) == top_frame){
FL(sp) = sp;
return v;
}
sp -= 4+nargs;
ipd = FL(curr_frame)-1;
ip = (uint8_t*)*ipd;
nargs = FL(curr_frame)[-2];
bp = FL(curr_frame) - 4 - nargs;
sp[-1] = v;
NEXT_OP;
}
OP(OP_LOAD1)
*sp++ = fixnum(1);
NEXT_OP;
OP(OP_LOADA)
*sp++ = bp[*ip++];
NEXT_OP;
OP(OP_BRN)
ip += *(--sp) == 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;
FL(sp) = sp;
unbound_error(v);
}
*sp++ = sym->binding;
NEXT_OP;
}
OP(OP_LT)
n = *ip++;
LABEL(apply_lt):
{
int i = n;
value_t a = sp[-i], b, v;
for(v = FL_t; i > 1; a = b){
i--;
b = 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;
}
}
}
sp -= n;
*sp++ = v;
}
NEXT_OP;
OP(OP_LOADV) {
value_t v = fn_vals(bp[-1]);
assert(*ip < vector_size(v));
*sp++ = 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 = sp[-1];
int64_t i64;
sp[-1] = isfixnum(v) ? fixnum_neg(v) : fl_neg(v);
}
value_t a, b, q;
a = sp[-2];
b = sp[-1];
if(bothfixnums(a, b) && !sadd_overflow(numval(a), numval(b), &q) && fits_fixnum(q))
v = fixnum(q);
else
v = fl_add_any(sp-2, 2);
sp--;
sp[-1] = v;
NEXT_OP;
}
OP(OP_LOADI8)
*sp++ = fixnum((int8_t)*ip++);
NEXT_OP;
OP(OP_POP)
sp--;
NEXT_OP;
OP(OP_BRNN)
ip += *(--sp) != FL_nil ? GET_INT16(ip) : 2;
NEXT_OP;
OP(OP_DUP)
sp[0] = sp[-1];
sp++;
NEXT_OP;
OP(OP_LOADC0)
*sp++ = vector_elt(bp[nargs], 0);
NEXT_OP;
OP(OP_CAR) {
value_t v = sp[-1];
if(fl_likely(iscons(v)))
v = car_(v);
else if(fl_unlikely(v != FL_nil)){
*ipd = (uintptr_t)ip;
FL(sp) = sp;
type_error("cons", v);
}
sp[-1] = v;
NEXT_OP;
}
OP(OP_CLOSURE) {
int x = *ip++;
assert(x > 0);
FL(sp) = sp;
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++ = sp[-x+i];
sp -= x;
*sp++ = v;
#if !defined(BITS64)
if((x & 1) == 0)
pv++;
#endif
function_t *f = (function_t*)pv;
value_t e = sp[-2]; // closure to copy
assert(isfunction(e));
f->bcode = fn_bcode(e);
f->vals = fn_vals(e);
f->env = sp[-1];
f->name = fn_name(e);
sp--;
sp[-1] = tagptr(f, TAG_FUNCTION);
NEXT_OP;
}
OP(OP_CONS) {
if(FL(curheap) > FL(lim)){
FL(sp) = sp;
fl_gc(0);
sp = FL(sp);
}
cons_t *c = (cons_t*)FL(curheap);
FL(curheap) += sizeof(cons_t);
c->car = sp[-2];
c->cdr = sp[-1];
sp[-2] = tagptr(c, TAG_CONS);
sp--;
NEXT_OP;
}
OP(OP_BRNE)
ip += sp[-2] != sp[-1] ? GET_INT16(ip) : 2;
sp -= 2;
NEXT_OP;
OP(OP_CDR) {
value_t v = sp[-1];
if(fl_likely(iscons(v)))
v = cdr_(v);
else if(fl_unlikely(v != FL_nil)){
*ipd = (uintptr_t)ip;
FL(sp) = sp;
type_error("cons", v);
}
sp[-1] = v;
NEXT_OP;
}
OP(OP_LOADVOID)
*sp++ = FL_void;
NEXT_OP;
OP(OP_NOT)
sp[-1] = sp[-1] == FL_nil ? FL_t : FL_nil;
NEXT_OP;
OP(OP_SETA)
bp[*ip++] = 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;
sp = bp+i+5;
FL(curr_frame) = sp;
}
}else if(fl_unlikely(s < 0)){
*ipd = (uintptr_t)ip;
FL(sp) = sp;
lerrorf(FL_ArgError, "too few arguments");
}else{
sp++;
sp[-2] = i+1;
sp[-3] = sp[-4];
sp[-4] = sp[-5];
sp[-5] = FL_nil;
FL(curr_frame) = sp;
}
ipd = sp-1;
nargs = i+1;
NEXT_OP;
}
OP(OP_SHIFT) {
int i = *ip++;
sp[-1-i] = sp[-1];
sp -= i;
NEXT_OP;
}
OP(OP_SETCAR) {
value_t v = sp[-2];
if(fl_unlikely(!iscons(v))){
*ipd = (uintptr_t)ip;
FL(sp) = sp;
type_error("cons", v);
}
car_(v) = sp[-1];
sp--;
NEXT_OP;
}
OP(OP_LOADNIL)
*sp++ = FL_nil;
NEXT_OP;
OP(OP_BOX) {
int i = *ip++;
FL(sp) = sp;
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)
sp[-1] = iscons(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 = sp[-n];
for(int i = n-1; i > 0; i--){
if(isarray(v)){
sp[-i-1] = v;
v = cvalue_array_aref(sp-i-1);
continue;
}
value_t e = sp[-i];
size_t isz = tosize(e);
if(isvector(v)){
if(fl_unlikely(isz >= vector_size(v))){
FL(sp) = sp;
bounds_error(v, e);
}
v = vector_elt(v, isz);
continue;
}
if(!iscons(v) && v != FL_nil){
FL(sp) = sp;
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))){
FL(sp) = sp;
bounds_error(v0, e);
}
}
}
sp -= n;
*sp++ = v;
NEXT_OP;
}
OP(OP_NANP) {
value_t v = 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;
}
}
sp[-1] = v;
NEXT_OP;
}
OP(OP_LOAD0)
*sp++ = fixnum(0);
NEXT_OP;
OP(OP_SETCDR) {
value_t v = sp[-2];
if(fl_unlikely(!iscons(v))){
*ipd = (uintptr_t)ip;
FL(sp) = sp;
type_error("cons", v);
}
cdr_(v) = sp[-1];
sp--;
NEXT_OP;
}
OP(OP_LOADC1)
*sp++ = vector_elt(bp[nargs], 1);
NEXT_OP;
OP(OP_ASET) {
*ipd = (uintptr_t)ip;
value_t v = sp[-3];
n = 3;
if(0){
LABEL(apply_aset):
v = sp[-n];
for(int i = n-1; i >= 3; i--){
if(isarray(v)){
sp[-i-1] = v;
v = cvalue_array_aref(sp-i-1);
continue;
}
value_t e = sp[-i];
size_t isz = tosize(e);
if(isvector(v)){
if(fl_unlikely(isz >= vector_size(v))){
FL(sp) = sp;
bounds_error(v, e);
}
v = vector_elt(v, isz);
continue;
}
if(!iscons(v) && v != FL_nil){
FL(sp) = sp;
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))){
FL(sp) = sp;
bounds_error(v0, e);
}
}
}
sp[-3] = v;
}
value_t e = sp[-2];
size_t isz = tosize(e);
if(isvector(v)){
if(fl_unlikely(isz >= vector_size(v))){
FL(sp) = sp;
bounds_error(v, e);
}
vector_elt(v, isz) = (e = sp[-1]);
}else if(iscons(v) || v == FL_nil){
for(value_t v0 = v;; isz--){
if(isz == 0){
car_(v) = (e = sp[-1]);
break;
}
v = cdr_(v);
if(fl_unlikely(!iscons(v))){
FL(sp) = sp;
bounds_error(v0, e);
}
}
}else if(isarray(v)){
e = cvalue_array_aset(sp-3);
}else{
FL(sp) = sp;
type_error("sequence", v);
}
sp -= n;
*sp++ = e;
NEXT_OP;
}
OP(OP_EQUAL) {
value_t v;
if(sp[-2] == sp[-1])
v = FL_t;
else
v = fl_compare(sp[-2], sp[-1], true) == 0 ? FL_t : FL_nil;
sp[-2] = v;
sp--;
NEXT_OP;
}
OP(OP_CONSP)
sp[-1] = iscons(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));
*sp++ = vector_elt(v, i);
NEXT_OP;
}
OP(OP_SYMBOLP)
sp[-1] = issymbol(sp[-1]) ? FL_t : FL_nil;
NEXT_OP;
OP(OP_NUMBERP)
sp[-1] = fl_isnumber(sp[-1]) ? FL_t : FL_nil;
NEXT_OP;
OP(OP_BRBOUND)
*sp++ = 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;
FL(sp) = sp;
lerrorf(FL_ArgError, "too few arguments");
}
if(x > 0){
if(fl_unlikely(nargs > x)){
*ipd = (uintptr_t)ip;
FL(sp) = sp;
lerrorf(FL_ArgError, "too many arguments");
}
}else
x = -x;
if(fl_likely(x > nargs)){
x -= nargs;
sp += x;
sp[-1] = sp[-x-1];
sp[-2] = nargs+x;
sp[-3] = sp[-x-3];
sp[-4] = sp[-x-4];
FL(curr_frame) = sp;
ipd = sp-1;
for(i = 0; i < x; i++)
bp[nargs+i] = UNBOUND;
nargs += x;
}
NEXT_OP;
}
OP(OP_EQ)
sp[-2] = sp[-2] == sp[-1] ? FL_t : FL_nil;
sp--;
NEXT_OP;
OP(OP_LIST) {
n = *ip++;
LABEL(apply_list):;
value_t v;
if(n > 0){
v = list(sp-n, n, 0);
sp -= n;
}else{
v = FL_nil;
}
*sp++ = v;
NEXT_OP;
}
OP(OP_BOUNDP) {
*ipd = (uintptr_t)ip;
symbol_t *sym = tosymbol(sp[-1]);
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 = sp[-i], b, v;
for(v = FL_t; i > 1; a = b){
i--;
b = 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;
}
}
sp -= n;
*sp++ = v;
NEXT_OP;
}
OP(OP_CADR) {
value_t v = 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;
FL(sp) = sp;
type_error("cons", v);
}
}
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 = *(--sp); // arglist
value_t *p = sp-(n-2); // n-2 == # leading arguments not in the list
while(iscons(v)){
*sp++ = car_(v);
v = cdr_(v);
}
if(v != FL_nil){
*ipd = (uintptr_t)ip;
FL(sp) = sp;
lerrorf(FL_ArgError, "apply: last argument: not a list");
}
n = sp-p;
goto LABEL(do_call);
}
OP(OP_LOADT)
*sp++ = FL_t;
NEXT_OP;
OP(OP_BUILTINP) {
value_t v = sp[-1];
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 = sp[-1];
int64_t i64;
sp[-1] = isfixnum(v) ? fixnum_neg(v) : fl_neg(v);
NEXT_OP;
}
OP(OP_FIXNUMP)
sp[-1] = isfixnum(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(sp-n, n);
sp -= n;
*sp++ = v;
NEXT_OP;
}
OP(OP_IDIV) {
value_t a = sp[-2];
value_t b = sp[-1];
value_t v;
if(bothfixnums(a, b)){
if(b == 0){
*ipd = (uintptr_t)ip;
FL(sp) = sp;
divide_by_0_error();
}
v = fixnum(numval(a) / numval(b));
}else{
*ipd = (uintptr_t)ip;
v = fl_idiv2(a, b);
}
sp--;
sp[-1] = v;
NEXT_OP;
}
OP(OP_DIV) {
n = *ip++;
LABEL(apply_div):
*ipd = (uintptr_t)ip;
value_t *p = sp-n;
if(n == 1){
sp[-1] = fl_div2(fixnum(1), *p);
}else{
if(fl_unlikely(n > 2)){
*sp++ = *p;
*p = fixnum(1);
p[1] = fl_mul_any(p, n);
*p = *(--sp);
}
value_t v = fl_div2(p[0], p[1]);
sp -= n;
*sp++ = v;
}
NEXT_OP;
}
OP(OP_VECTOR) {
n = *ip++;
LABEL(apply_vector):;
FL(sp) = sp;
value_t v = alloc_vector(n, 0);
if(n){
memcpy(&vector_elt(v, 0), sp-n, n*sizeof(value_t));
sp -= n;
}
*sp++ = v;
NEXT_OP;
}
OP(OP_COMPARE)
sp[-2] = fl_compare(sp[-2], sp[-1], false);
sp--;
NEXT_OP;
OP(OP_FOR) {
*ipd = (uintptr_t)ip;
value_t *p = sp;
value_t v;
fixnum_t s = tofixnum(p[-3]);
fixnum_t hi = tofixnum(p[-2]);
sp += 2;
FL(sp) = sp;
for(v = FL_void; s <= hi; s++){
p[0] = p[-1];
p[1] = fixnum(s);
v = _applyn(1);
}
sp -= 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 = sp[-1];
if(!isconstant(sym))
sym->binding = v;
NEXT_OP;
}
OP(OP_VECTORP)
sp[-1] = isvector(sp[-1]) ? FL_t : FL_nil;
NEXT_OP;
OP(OP_TRYCATCH) {
*ipd = (uintptr_t)ip;
FL(sp) = sp;
value_t v = do_trycatch();
sp--;
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(sp-n, n);
sp -= n;
*sp++ = v;
NEXT_OP;
}
OP(OP_LOADAL)
assert(nargs > 0);
*sp++ = bp[GET_INT32(ip)];
ip += 4;
NEXT_OP;
OP(OP_EQV) {
value_t v;
if(sp[-2] == sp[-1])
v = FL_t;
else if(!leafp(sp[-2]) || !leafp(sp[-1]))
v = FL_nil;
else
v = fl_compare(sp[-2], sp[-1], true) == 0 ? FL_t : FL_nil;
sp[-2] = v;
sp--;
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;
FL(sp) = sp;
nargs = process_keys(v, i, x, labs(s)-(i+x), bp, nargs, s<0);
sp = FL(sp);
ipd = 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 = sp-n;
// we need to pass the full arglist on to fl_add_any
// so it can handle rest args properly
*sp++ = *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] = *(--sp);
v = fl_add_any(p, 2);
sp -= n;
*sp++ = v;
NEXT_OP;
}
OP(OP_BRNL)
ip += *(--sp) == FL_nil ? GET_INT32(ip) : 4;
NEXT_OP;
OP(OP_SETAL)
bp[GET_INT32(ip)] = sp[-1];
ip += 4;
NEXT_OP;
OP(OP_BOXL) {
int i = GET_INT32(ip);
ip += 4;
FL(sp) = sp;
value_t v = mk_cons();
car_(v) = bp[i];
cdr_(v) = FL_nil;
bp[i] = v;
NEXT_OP;
}
OP(OP_FUNCTIONP) {
value_t v = sp[-1];
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 += sp[-2] != sp[-1] ? GET_INT32(ip) : 4;
sp -= 2;
NEXT_OP;
OP(OP_BRNNL)
ip += *(--sp) != FL_nil ? GET_INT32(ip) : 4;
NEXT_OP;
OP(OP_LOADCL)
ip += 4;
*sp++ = 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;
*sp++ = v;
NEXT_OP;
}