// mark closure static inline void _gc_mark_closure(struct a2_gc* gc_p, struct a2_gcobj* gcobj, enum gc_mark m){ assert(gcobj->type == A2_TCLOSURE); if(mask(gcobj->mark) == mask(m)) return; gcobj->mark = m; size_t i; struct a2_closure* cls = a2_gcobj2closure(gcobj); // mark upvalue for(i=0; i<cls->uv_size; i++){ if(cls->uv_chain[i].type == uv_gc){ cls->uv_chain[i].v.uv_obj->mark = m; assert(cls->uv_chain[i].v.uv_obj->type == _A2_TUPVALUE); a2_gc_markit(gc_p, cls->uv_chain[i].v.uv_obj->value.uv, m); } } // mark const varable for(i=0; i<cls->xcls_p->c_stack.top; i++){ if(obj_t(&(cls->xcls_p->c_stack.stk_p[i])) == A2_TSTRING){ obj_vX(&(cls->xcls_p->c_stack.stk_p[i]), obj)->mark = m; } } }
inline char* obj2str(struct a2_obj* obj, char* buf, size_t len){ assert(obj); switch(obj_t(obj)){ case A2_TNUMBER: snprintf(buf, len, "%.14g", obj_vNum(obj)); return buf; case A2_TSTRING: return a2_gcobj2string(obj_vX(obj, obj)); case A2_TBOOL: snprintf(buf, len, "%s", (obj_vX(obj, uinteger))?("true"):("false")); return buf; case A2_TNIL: return "nil"; case _A2_TADDR: _sf(buf, len, "[%zd]", obj_vX(obj, addr)); return buf; case A2_TCLOSURE: snprintf(buf, len, "closure:%p", a2_gcobj2closure(obj_vX(obj, obj))); return buf; case A2_TARRAY: snprintf(buf, len, "array:%p", a2_gcobj2array(obj_vX(obj, obj))); return buf; case A2_TMAP: snprintf(buf, len, "map:%p", a2_gcobj2map(obj_vX(obj, obj))); return buf; default: assert(0); } return NULL; }
// call a2 function static inline void __vm_call_function(struct a2_vm* vm_p, struct a2_obj* _func){ assert(obj_t(_func)==A2_TCLOSURE); struct a2_obj* _obj = NULL; int i, j, params = a2_closure_params(a2_gcobj2closure(obj_vX(_func, obj))); struct a2_array* _args = NULL; struct vm_callinfo* _ci = curr_ci; ir _ir = curr_ir; // new call info int b = ir_ga(curr_ir), n=ir_gc(curr_ir); callinfo_new(vm_p, a2_gcobj2closure(obj_vX(_func, obj)), b, n); // jump call _ci->pc++; // if is mutableargs if(params<0){ params = -1 - params; _obj = callinfo_sfreg(curr_ci, params); if(ir_gb(_ir)>params){ // set _args list _args = a2_array_new(); struct a2_gcobj* _array_gcobj = a2_array2gcobj(_args); a2_gcadd(vm_p->env_p, _array_gcobj); obj_setX(_obj, A2_TARRAY, obj, _array_gcobj); }else{ obj_setX(_obj, A2_TNIL, point, NULL); } } // set params for(i=ir_ga(_ir)+1, j=0; i<=ir_ga(_ir)+ir_gb(_ir) && j<params; j++, i++){ _obj = callinfo_sfreg(curr_ci, j); *_obj = *callinfo_sfreg(_ci, i); } // set clear params for( ;j<params; j++){ _obj = callinfo_sfreg(curr_ci, j); obj_setX(_obj, A2_TNIL, point, NULL); } // if mutable args for(j=0; i<=ir_ga(_ir)+ir_gb(_ir) && _args; i++, j++){ a2_array_add(_args, callinfo_sfreg(_ci, i)); } }
A2_API inline void* a2_topoint(struct a2_state* state, int idx){ struct a2_obj* obj = a2_getcstack(state->env_p, idx); switch(obj_t(obj)){ case A2_TARRAY: return a2_gcobj2array(obj_vX(obj, obj)); case A2_TMAP: return a2_gcobj2map(obj_vX(obj, obj)); case A2_TCLOSURE: return a2_gcobj2closure(obj_vX(obj, obj)); default: return NULL; } }
int a2_vm_pcall(struct a2_vm* vm_p, struct a2_obj* cls_obj, struct a2_obj* args_obj, int args){ assert(obj_t(cls_obj) == A2_TCLOSURE); struct a2_closure* cls = a2_gcobj2closure(obj_vX(cls_obj, obj)); callinfo_new(vm_p, NULL, 0, 0); callinfo_new(vm_p, cls, 0, 0); // set arg int i, j; for(i=0, j=0; i<args && j<curr_ci->reg_stack.len; j++, i++){ *callinfo_sfreg(curr_ci, j) = args_obj[i]; } // set clear for(; j<curr_ci->reg_stack.len; j++){ *callinfo_sfreg(curr_ci, j) = a2_nil2obj(); } int ret = _vm_prun(vm_p); callinfo_free(vm_p); return ret; }