ref: 93bd3615bb21d25526198596a09a3ac4815fd1bc
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(FL(stack)[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):
FL(stack)[ipd] = (uintptr_t)ip;
value_t v = FL(stack)[FL(sp)-n-1];
if(tag(v) == TAG_FUNCTION){
if(v > (N_BUILTINS<<3)){
if(tail){
FL(curr_frame) = FL(stack)[FL(curr_frame)-3];
for(fixnum_t s = -1; s < (fixnum_t)n; s++)
FL(stack)[bp+s] = FL(stack)[FL(sp)+s-n];
FL(sp) = bp+n;
}
nargs = n;
goto apply_cl_top;
}
uint32_t i = uintval(v);
assert(isbuiltin(v));
fixnum_t 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_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))){
fixnum_t s = FL(sp) - n;
v = ((cvalue_t*)ptr(v))->cbuiltin(&FL(stack)[s], n);
FL(sp) = s;
FL(stack)[s-1] = v;
NEXT_OP;
}
type_error("function", v);
}
OP(OP_ARGC) {
uint32_t na = *ip++;
if(0){
OP(OP_ARGCL)
na = GET_INT32(ip);
ip += 4;
}
if(fl_unlikely(nargs != na)){
FL(stack)[ipd] = (uintptr_t)ip;
arity_error(nargs, na);
}
NEXT_OP;
}
OP(OP_LOADA1)
PUSH(FL(stack)[bp+1]);
NEXT_OP;
OP(OP_RET) {
value_t 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_LOAD1)
PUSH(fixnum(1));
NEXT_OP;
OP(OP_LOADA)
PUSH(FL(stack)[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(FL(stack)[bp-1]);
assert(*ip < vector_size(v));
v = vector_elt(v, *ip);
ip++;
if(0){
OP(OP_LOADGL)
v = fn_vals(FL(stack)[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)){
FL(stack)[ipd] = (uintptr_t)ip;
unbound_error(v);
}
PUSH(sym->binding);
NEXT_OP;
}
OP(OP_LT)
n = *ip++;
LABEL(apply_lt):
{
uint32_t i = n;
value_t a = FL(stack)[FL(sp)-i], b, v;
for(v = FL_t; i > 1; a = b){
i--;
b = FL(stack)[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(FL(stack)[bp-1]);
assert(*ip < vector_size(v));
PUSH(vector_elt(v, *ip++));
NEXT_OP;
}
OP(OP_ADD2) {
value_t v;
LABEL(do_add2):
FL(stack)[ipd] = (uintptr_t)ip;
if(0){
OP(OP_SUB2)
LABEL(do_sub2):
FL(stack)[ipd] = (uintptr_t)ip;
v = FL(stack)[FL(sp)-1];
int64_t i64;
FL(stack)[FL(sp)-1] = isfixnum(v) ? fixnum_neg(v) : fl_neg(v);
}
value_t a, b, q;
a = FL(stack)[FL(sp)-2];
b = FL(stack)[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(stack)[FL(sp)-2], 2);
POPN(1);
FL(stack)[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(stack)[FL(sp)] = FL(stack)[FL(sp)-1];
FL(sp)++;
NEXT_OP;
OP(OP_LOADC0)
PUSH(vector_elt(FL(stack)[bp+nargs], 0));
NEXT_OP;
OP(OP_CAR) {
value_t v = FL(stack)[FL(sp)-1];
if(fl_likely(iscons(v)))
v = car_(v);
else if(fl_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) {
uint32_t 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(uint32_t i = 0; i < x; i++)
*pv++ = FL(stack)[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(stack)[FL(sp)-2]; // closure to copy
assert(isfunction(e));
f->bcode = fn_bcode(e);
f->vals = fn_vals(e);
f->env = FL(stack)[FL(sp)-1];
f->name = fn_name(e);
POPN(1);
FL(stack)[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(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_BRNE)
ip += FL(stack)[FL(sp)-2] != FL(stack)[FL(sp)-1] ? GET_INT16(ip) : 2;
POPN(2);
NEXT_OP;
OP(OP_CDR) {
value_t v = FL(stack)[FL(sp)-1];
if(fl_likely(iscons(v)))
v = cdr_(v);
else if(fl_unlikely(v != FL_nil)){
FL(stack)[ipd] = (uintptr_t)ip;
type_error("cons", v);
}
FL(stack)[FL(sp)-1] = v;
NEXT_OP;
}
OP(OP_LOADVOID)
PUSH(FL_void);
NEXT_OP;
OP(OP_NOT)
FL(stack)[FL(sp)-1] = FL(stack)[FL(sp)-1] == FL_nil ? FL_t : FL_nil;
NEXT_OP;
OP(OP_SETA)
FL(stack)[bp + *ip++] = FL(stack)[FL(sp)-1];
NEXT_OP;
OP(OP_VARGC) {
uint32_t 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(&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(fl_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_SHIFT) {
uint32_t i = *ip++;
FL(stack)[FL(sp)-1-i] = FL(stack)[FL(sp)-1];
FL(sp) -= i;
NEXT_OP;
}
OP(OP_SETCAR) {
value_t v = FL(stack)[FL(sp)-2];
if(fl_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_LOADNIL)
PUSH(FL_nil);
NEXT_OP;
OP(OP_BOX) {
uint32_t i = *ip++;
value_t v = mk_cons();
car_(v) = FL(stack)[bp+i];
cdr_(v) = FL_nil;
FL(stack)[bp+i] = v;
NEXT_OP;
}
OP(OP_JMP)
ip += GET_INT16(ip);
NEXT_OP;
OP(OP_ATOMP)
FL(stack)[FL(sp)-1] = iscons(FL(stack)[FL(sp)-1]) ? FL_nil : FL_t;
NEXT_OP;
OP(OP_AREF2) {
n = 2;
if(0){
OP(OP_AREF)
FL(stack)[ipd] = (uintptr_t)ip;
n = 3 + *ip++;
}
LABEL(apply_aref):;
value_t v = FL(stack)[FL(sp)-n];
for(uint32_t 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;
}
value_t e = FL(stack)[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(stack)[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(stack)[FL(sp)-1] = v;
NEXT_OP;
}
OP(OP_LOAD0)
PUSH(fixnum(0));
NEXT_OP;
OP(OP_SETCDR) {
value_t v = FL(stack)[FL(sp)-2];
if(fl_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_LOADC1)
PUSH(vector_elt(FL(stack)[bp+nargs], 1));
NEXT_OP;
OP(OP_ASET) {
FL(stack)[ipd] = (uintptr_t)ip;
value_t v = FL(stack)[FL(sp)-3];
n = 3;
if(0){
LABEL(apply_aset):
v = FL(stack)[FL(sp)-n];
for(uint32_t 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;
}
value_t e = FL(stack)[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(stack)[FL(sp)-3] = v;
}
value_t e = FL(stack)[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(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(fl_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_EQUAL) {
value_t v;
if(FL(stack)[FL(sp)-2] == FL(stack)[FL(sp)-1])
v = FL_t;
else
v = fl_compare(FL(stack)[FL(sp)-2], FL(stack)[FL(sp)-1], true) == 0 ? FL_t : FL_nil;
FL(stack)[FL(sp)-2] = v;
POPN(1);
NEXT_OP;
}
OP(OP_CONSP)
FL(stack)[FL(sp)-1] = iscons(FL(stack)[FL(sp)-1]) ? FL_t : FL_nil;
NEXT_OP;
OP(OP_LOADC) {
value_t v = FL(stack)[bp+nargs];
uint32_t i = *ip++;
assert(isvector(v));
assert(i < vector_size(v));
PUSH(vector_elt(v, i));
NEXT_OP;
}
OP(OP_SYMBOLP)
FL(stack)[FL(sp)-1] = issymbol(FL(stack)[FL(sp)-1]) ? FL_t : FL_nil;
NEXT_OP;
OP(OP_NUMBERP)
FL(stack)[FL(sp)-1] = fl_isnumber(FL(stack)[FL(sp)-1]) ? FL_t : FL_nil;
NEXT_OP;
OP(OP_BRBOUND)
PUSH(FL(stack)[bp+GET_INT32(ip)] != UNBOUND ? FL_t : FL_nil);
ip += 4;
NEXT_OP;
OP(OP_OPTARGS) {
uint32_t i = GET_INT32(ip);
ip += 4;
uint32_t x = GET_INT32(ip);
ip += 4;
if(fl_unlikely(nargs < i)){
FL(stack)[ipd] = (uintptr_t)ip;
lerrorf(FL_ArgError, "too few arguments");
}
if((int32_t)x > 0){
if(fl_unlikely(nargs > x)){
FL(stack)[ipd] = (uintptr_t)ip;
lerrorf(FL_ArgError, "too many arguments");
}
}else
x = -x;
if(fl_likely(x > nargs)){
x -= nargs;
FL(sp) += x;
FL(stack)[FL(sp)-1] = FL(stack)[FL(sp)-x-1];
FL(stack)[FL(sp)-2] = nargs+x;
FL(stack)[FL(sp)-3] = FL(stack)[FL(sp)-x-3];
FL(stack)[FL(sp)-4] = FL(stack)[FL(sp)-x-4];
FL(curr_frame) = FL(sp);
ipd = FL(sp)-1;
for(i = 0; i < x; i++)
FL(stack)[bp+nargs+i] = UNBOUND;
nargs += x;
}
NEXT_OP;
}
OP(OP_EQ)
FL(stack)[FL(sp)-2] = FL(stack)[FL(sp)-2] == FL(stack)[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(stack)[FL(sp)-n], n, 0);
POPN(n);
PUSH(v);
}else{
PUSH(FL_nil);
}
NEXT_OP;
OP(OP_BOUNDP) {
FL(stack)[ipd] = (uintptr_t)ip;
symbol_t *sym = tosymbol(FL(stack)[FL(sp)-1]);
FL(stack)[FL(sp)-1] = sym->binding == UNBOUND ? FL_nil : FL_t;
NEXT_OP;
}
OP(OP_NUMEQ)
n = *ip++;
LABEL(apply_numeq):
{
uint32_t i = n;
value_t a = FL(stack)[FL(sp)-i], b, v;
for(v = FL_t; i > 1; a = b){
i--;
b = FL(stack)[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(stack)[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)){
FL(stack)[ipd] = (uintptr_t)ip;
type_error("cons", v);
}
}
FL(stack)[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
n = FL(sp)-(n-2); // n-2 == # leading arguments not in the list
while(iscons(v)){
PUSHSAFE(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_LOADT)
PUSH(FL_t);
NEXT_OP;
OP(OP_BUILTINP) {
value_t v = FL(stack)[FL(sp)-1];
FL(stack)[FL(sp)-1] = (isbuiltin(v) || iscbuiltin(v)) ? FL_t : FL_nil;
NEXT_OP;
}
OP(OP_NEG) {
LABEL(do_neg):
FL(stack)[ipd] = (uintptr_t)ip;
value_t v = FL(stack)[FL(sp)-1];
int64_t i64;
FL(stack)[FL(sp)-1] = isfixnum(v) ? fixnum_neg(v) : fl_neg(v);
NEXT_OP;
}
OP(OP_FIXNUMP)
FL(stack)[FL(sp)-1] = isfixnum(FL(stack)[FL(sp)-1]) ? FL_t : FL_nil;
NEXT_OP;
OP(OP_MUL) {
n = *ip++;
LABEL(apply_mul):
FL(stack)[ipd] = (uintptr_t)ip;
value_t v = fl_mul_any(&FL(stack)[FL(sp)-n], n);
POPN(n);
PUSH(v);
NEXT_OP;
}
OP(OP_IDIV) {
value_t a = FL(stack)[FL(sp)-2];
value_t b = FL(stack)[FL(sp)-1];
value_t v;
if(bothfixnums(a, b)){
if(b == 0){
FL(stack)[ipd] = (uintptr_t)ip;
divide_by_0_error();
}
v = fixnum(numval(a) / numval(b));
}else{
FL(stack)[ipd] = (uintptr_t)ip;
v = fl_idiv2(a, b);
}
POPN(1);
FL(stack)[FL(sp)-1] = v;
NEXT_OP;
}
OP(OP_DIV) {
n = *ip++;
LABEL(apply_div):
FL(stack)[ipd] = (uintptr_t)ip;
uint32_t 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();
}
value_t v = fl_div2(FL(stack)[i], FL(stack)[i+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(stack)[FL(sp)-n], n*sizeof(value_t));
POPN(n);
}
PUSH(v);
NEXT_OP;
}
OP(OP_COMPARE)
FL(stack)[FL(sp)-2] = fl_compare(FL(stack)[FL(sp)-2], FL(stack)[FL(sp)-1], false);
POPN(1);
NEXT_OP;
OP(OP_FOR) {
FL(stack)[ipd] = (uintptr_t)ip;
uint32_t i = FL(sp);
value_t v;
fixnum_t s = tofixnum(FL(stack)[i-3]);
fixnum_t hi = tofixnum(FL(stack)[i-2]);
FL(sp) += 2;
for(v = FL_void; s <= hi; s++){
FL(stack)[i+0] = FL(stack)[i-1];
FL(stack)[i+1] = fixnum(s);
v = _applyn(1);
}
POPN(4);
FL(stack)[i+1] = v;
NEXT_OP;
}
OP(OP_SETGL) {
value_t 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));
symbol_t *sym = ptr(v);
v = FL(stack)[FL(sp)-1];
if(!isconstant(sym))
sym->binding = v;
NEXT_OP;
}
OP(OP_VECTORP)
FL(stack)[FL(sp)-1] = isvector(FL(stack)[FL(sp)-1]) ? FL_t : FL_nil;
NEXT_OP;
OP(OP_TRYCATCH) {
FL(stack)[ipd] = (uintptr_t)ip;
value_t v = do_trycatch();
POPN(1);
FL(stack)[FL(sp)-1] = v;
NEXT_OP;
}
OP(OP_ADD) {
n = *ip++;
if(n == 2)
goto LABEL(do_add2);
LABEL(apply_add):
FL(stack)[ipd] = (uintptr_t)ip;
value_t v = fl_add_any(&FL(stack)[FL(sp)-n], n);
POPN(n);
PUSH(v);
NEXT_OP;
}
OP(OP_LOADAL)
assert(nargs > 0);
PUSH(FL(stack)[bp+GET_INT32(ip)]);
ip += 4;
NEXT_OP;
OP(OP_EQV) {
value_t v;
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_nil;
else
v = fl_compare(FL(stack)[FL(sp)-2], FL(stack)[FL(sp)-1], true) == 0 ? FL_t : FL_nil;
FL(stack)[FL(sp)-2] = v;
POPN(1);
NEXT_OP;
}
OP(OP_KEYARGS) {
value_t v = fn_vals(FL(stack)[bp-1]);
v = vector_elt(v, 0);
uint32_t i = GET_INT32(ip);
ip += 4;
uint32_t x = GET_INT32(ip);
ip += 4;
fixnum_t s = GET_INT32(ip);
ip += 4;
FL(stack)[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);
FL(stack)[ipd] = (uintptr_t)ip;
uint32_t 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);
value_t v = fl_add_any(&FL(stack)[i], n);
int64_t i64;
FL(stack)[i+1] = isfixnum(v) ? fixnum_neg(v) : fl_neg(v);
FL(stack)[i] = POP();
v = fl_add_any(&FL(stack)[i], 2);
POPN(n);
PUSH(v);
NEXT_OP;
}
OP(OP_BRNL)
ip += POP() == FL_nil ? GET_INT32(ip) : 4;
NEXT_OP;
OP(OP_SETAL)
FL(stack)[bp+GET_INT32(ip)] = FL(stack)[FL(sp)-1];
ip += 4;
NEXT_OP;
OP(OP_BOXL) {
uint32_t i = GET_INT32(ip);
ip += 4;
value_t v = mk_cons();
car_(v) = FL(stack)[bp+i];
cdr_(v) = FL_nil;
FL(stack)[bp+i] = v;
NEXT_OP;
}
OP(OP_FUNCTIONP) {
value_t 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_nil;
NEXT_OP;
}
OP(OP_JMPL)
ip += GET_INT32(ip);
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_LOADCL)
ip += 4;
PUSH(vector_elt(FL(stack)[bp+nargs], GET_INT32(ip)));
ip += 4;
NEXT_OP;
OP(OP_LOADVL) {
value_t v = fn_vals(FL(stack)[bp-1]);
v = vector_elt(v, GET_INT32(ip));
ip += 4;
PUSH(v);
NEXT_OP;
}