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; }
// foreachloop static inline void _vm_foreachloop(struct a2_vm* vm_p){ struct a2_obj* _k = callinfo_sfreg(curr_ci, ir_ga(curr_ir)); struct a2_obj* _v = callinfo_sfreg(curr_ci, ir_ga(curr_ir)+1); struct a2_obj* _c = callinfo_sfreg(curr_ci, ir_ga(curr_ir)+2); struct a2_obj* __v = NULL; if(obj_t(_c)!=A2_TMAP && obj_t(_c)!=A2_TARRAY) vm_error("the varable is not map or array."); // dump next switch(obj_t(_c)){ case A2_TMAP: __v = a2_map_next(a2_gcobj2map(obj_vX(_c, obj)), _k); if(__v==NULL) curr_pc++; else{ *_v = *__v; jump(ir_gbx(curr_ir)); } break; case A2_TARRAY: __v = a2_array_next(a2_gcobj2array(obj_vX(_c, obj)), _k); if(__v==NULL) // dump is end curr_pc++; else{ *_v = *__v; jump(ir_gbx(curr_ir)); } break; default: assert(0); } }
// set value static inline void _vm_setvalue(struct a2_vm* vm_p){ struct a2_obj* _c = callinfo_sfreg(curr_ci, ir_ga(curr_ir)); struct a2_obj* _k = _getvalue(vm_p, ir_gb(curr_ir)); struct a2_obj* _v = _getvalue(vm_p, ir_gc(curr_ir)); struct a2_obj* __d = NULL; switch(obj_t(_c)){ case A2_TARRAY: if(obj_t(_k)!=A2_TNUMBER) vm_error("the key is must number at set array."); __d = a2_array_get(a2_gcobj2array(obj_vX(_c, obj)), _k); if(!__d) goto SVALUE_ERROR; *__d = *_v; break; case A2_TMAP: if(obj_t(_k)!=A2_TNUMBER && obj_t(_k)!=A2_TSTRING) vm_error("the key is must number or string at set map."); __d = a2_map_query(a2_gcobj2map(obj_vX(_c, obj)), _k); if(!__d) goto SVALUE_ERROR; *__d = *_v; break; default: vm_error("the varable is not map or array."); } curr_pc++; return; SVALUE_ERROR: vm_error("the key is overfllow."); }
// del key/value A2_API inline void a2_delmap(struct a2_state* state){ int top = a2_top(state)-1; struct a2_obj* k = a2_getcstack(state->env_p, top); struct a2_obj* map = a2_getcstack(state->env_p, top-1); check_map(map); check_key(k); a2_map_del(a2_gcobj2map(obj_vX(map, obj)), k); a2_pop(state, 1); }
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; } }
// get map A2_API inline void a2_getmap(struct a2_state* state){ int top = a2_top(state)-1; struct a2_obj* k = a2_getcstack(state->env_p, top); struct a2_obj* map = a2_getcstack(state->env_p, top-1); struct a2_obj* v = NULL; check_map(map); check_key(k); v = a2_map_query(a2_gcobj2map(obj_vX(map, obj)), k); if(v==NULL) obj_setX(map, A2_TNIL, point, NULL); else *map = *v; }
// mark map static inline void _gc_mark_map(struct a2_gc* gc_p, struct a2_gcobj* gcobj, enum gc_mark m){ assert(gcobj->type == A2_TMAP); if(mask(gcobj->mark) == mask(m)) return; gcobj->mark = m; struct a2_obj k = a2_nil2obj(); struct a2_obj* vp = NULL; struct a2_map* map_p = a2_gcobj2map(gcobj); while(NULL != (vp = a2_map_next(map_p, &k))){ if(obj_t(&k)==A2_TSTRING){ gcobj->mark = m; } a2_gc_markit(gc_p, vp, m); } }
//set map static inline void _vm_setmap(struct a2_vm* vm_p){ int i, end=ir_gb(curr_ir)+2*ir_gc(curr_ir); struct a2_obj* _d = callinfo_sfreg(curr_ci, ir_ga(curr_ir)); struct a2_obj* _v = NULL; struct a2_map* map = NULL; assert(obj_t(_d)==A2_TMAP); struct a2_kv kv={0}; for(i=ir_gb(curr_ir); i<end; i+=2){ kv.key = callinfo_sfreg(curr_ci, i); kv.vp = callinfo_sfreg(curr_ci, i+1); map = a2_gcobj2map(obj_vX(_d, obj)); if( (_v=a2_map_query(map, kv.key))==NULL ) a2_map_add(map, &kv); else *_v = *kv.vp; } curr_pc++; }
A2_API inline void a2_len(struct a2_state* state, int idx){ struct a2_obj* obj = a2_getcstack(state->env_p, idx); size_t len =0; struct a2_obj len_obj; switch(obj_t(obj)){ case A2_TMAP: len = a2_map_len(a2_gcobj2map(obj_vX(obj, obj))); break; case A2_TARRAY: len = a2_array_len(a2_gcobj2array(obj_vX(obj, obj))); break; case A2_TSTRING: len = a2_string_len(a2_gcobj2string(obj_vX(obj, obj))); break; default: a2_error(state->env_p, e_run_error, "the type is not map or array at len function."); } len_obj = a2_number2obj((a2_number)len); a2_pushstack(state->env_p, &len_obj); }