TmFrame* push_frame(Object fnc) { /* make extra space for self in method call */ Object *top = tm->frame->top + 2; tm->frame ++ ; TmFrame* f = tm->frame; /* check oprand stack */ if (top >= tm->stack + STACK_SIZE) { pop_frame(); tm_raise("tm_eval: stack overflow"); } /* check frame stack*/ if (tm->frame >= tm->frames + FRAMES_COUNT-1) { pop_frame(); tm_raise("tm_eval: frame overflow"); } f->pc = GET_FUNCTION(fnc)->code; f->locals = top; f->maxlocals = get_function_max_locals(GET_FUNCTION(fnc)); f->stack = f->locals + f->maxlocals; f->top = f->stack; f->fnc = fnc; // clear local variables int i;for(i = 0; i < f->maxlocals; i++) { f->locals[i] = NONE_OBJECT; } *(f->top) = NONE_OBJECT; f->jmp = NULL; return f; }
int obj_equals(Object a, Object b){ if(TM_TYPE(a) != TM_TYPE(b)) return 0; switch(TM_TYPE(a)){ case TYPE_NUM:return GET_NUM(a) == GET_NUM(b); case TYPE_STR: { String* s1 = GET_STR_OBJ(a); String* s2 = GET_STR_OBJ(b); return s1->value == s2->value || (s1->len == s2->len && strncmp(s1->value, s2->value, s1->len) == 0); } case TYPE_LIST: { if(GET_LIST(a) == GET_LIST(b)) return 1; int i; int len = GET_LIST(a)->len; Object* nodes1 = GET_LIST(a)->nodes; Object* nodes2 = GET_LIST(b)->nodes; for(i = 0; i < len; i++){ if(!obj_equals(nodes1[i], nodes2[i]) ){ return 0; } } return 1; } case TYPE_NONE:return 1; case TYPE_DICT:return GET_DICT(a) == GET_DICT(b); case TYPE_FUNCTION: return GET_FUNCTION(a) == GET_FUNCTION(b); default: { const char* ltype = tm_type(a.type); const char* rtype = tm_type(b.type); tm_raise("equals(): not supported type %d:%s and %d:%s", TM_TYPE(a), ltype, TM_TYPE(b), rtype); } } return 0; }
/** * @since 2016-11-20 */ Object tm_load_module(Object file, Object code, Object name) { Object mod = module_new(file, name, code); Object fnc = func_new(mod, NONE_OBJECT, NULL); GET_FUNCTION(fnc)->code = (unsigned char*) GET_STR(code); GET_FUNCTION(fnc)->name = string_new("#main"); call_function(fnc); return GET_MODULE(mod)->globals; }
Object call_function(Object func) { Object ret; if (IS_FUNC(func)) { resolve_method_self(func); /* call native */ if (GET_FUNCTION(func)->native != NULL) { return GET_FUNCTION(func)->native(); } else { TmFrame* f = push_frame(func); /* if (GET_FUNCTION(func)->modifier == 0) { return tm_eval(f); }*/ L_recall: if (setjmp(f->buf)==0) { return tm_eval(f); } else { f = tm->frame; /* handle exception in this frame */ if (f->jmp != NULL) { f->pc = f->jmp; f->jmp = NULL; goto L_recall; /* there is no handler, throw to last frame */ } else { push_exception(f); tm->frame--; longjmp(tm->frame->buf, 1); } } } } else if (IS_DICT(func)) { ret = class_new(func); Object *_fnc = dict_get_by_str(ret, "__init__"); if (_fnc != NULL) { call_function(*_fnc); } return ret; } tm_raise("File %o, line=%d: call_function:invalid object %o", GET_FUNCTION_FILE(tm->frame->fnc), tm->frame->lineno, func); return NONE_OBJECT; }
Object obj_get(Object self, Object k) { Object v; switch (TM_TYPE(self)) { case TYPE_STR: { DictNode* node; if (TM_TYPE(k) == TYPE_NUM) { double d = GET_NUM(k); int n = d; if (n < 0) { n += GET_STR_LEN(self); } if (n >= GET_STR_LEN(self) || n < 0) tm_raise("String_get: index overflow ,len=%d,index=%d, str=%o", GET_STR_LEN(self), n, self); return string_chr(0xff & GET_STR(self)[n]); } else if ((node = dict_get_node(GET_DICT(tm->str_proto), k)) != NULL) { return method_new(node->val, self); } break; } case TYPE_LIST:{ DictNode* node; if (TM_TYPE(k) == TYPE_NUM) { return list_get(GET_LIST(self), GET_NUM(k)); } else if ((node = dict_get_node(GET_DICT(tm->list_proto), k))!=NULL) { return method_new(node->val, self); } break; } case TYPE_DICT:{ DictNode* node; node = dict_get_node(GET_DICT(self), k); if (node != NULL) { return node->val; } else if ((node = dict_get_node(GET_DICT(tm->dict_proto), k))!=NULL) { return method_new(node->val, self); } break; } case TYPE_FUNCTION: return get_func_attr(GET_FUNCTION(self), k); case TYPE_DATA: return GET_DATA(self)->get(GET_DATA(self), k); } tm_raise("keyError %o", k); return NONE_OBJECT; }
bool ExternalReader::m_libload(void) { bool r = false; if (!m_hLib) { #if defined(WIN32) #if defined(_DEBUG) || defined(DEBUG) m_hLib = LOAD_LIBRARY("externalReaderd.dll"); #else m_hLib = LOAD_LIBRARY("externalReader.dll"); #endif #elif defined(__APPLE__) m_hLib = LOAD_LIBRARY("libexternalReader.dylib"); #else m_hLib = LOAD_LIBRARY("libexternalReader.so"); #endif if (m_hLib) { m_hOpen = (CardReaderOpen_t) GET_FUNCTION(m_hLib, CardReaderOpen); m_hSend = (CardReaderSend_t) GET_FUNCTION(m_hLib, CardReaderSend); m_hGetATR = (CardReaderGetATR_t) GET_FUNCTION(m_hLib, CardReaderGetATR); m_hSupportsPACE = (CardReaderSupportsPACE_t) GET_FUNCTION(m_hLib, CardReaderSupportsPACE); m_hDoPACE = (CardReaderDoPACE_t) GET_FUNCTION(m_hLib, CardReaderDoPACE); m_hClose = (CardReaderClose_t) GET_FUNCTION(m_hLib, CardReaderClose); } else { eCardCore_warn(DEBUG_LEVEL_CARD, "could not load external reader library"); } } if (!m_hLib || !m_hOpen || !m_hSend || !m_hGetATR || !m_hSupportsPACE || !m_hDoPACE || !m_hClose) { eCardCore_warn(DEBUG_LEVEL_CARD, "could not load external reader library functions"); m_libcleanup(); } else { r = true; } return r; }
BOOL get_real_driver_functions(PSplitterContext ctx) { BOOL result; result = FALSE; do { GET_FUNCTION(ctx, COM_Init, TRUE); GET_FUNCTION(ctx, COM_PreDeinit, FALSE); GET_FUNCTION(ctx, COM_Deinit, TRUE); GET_FUNCTION(ctx, COM_Open, TRUE); GET_FUNCTION(ctx, COM_Close, TRUE); GET_FUNCTION(ctx, COM_Read, TRUE); GET_FUNCTION(ctx, COM_Write, TRUE); GET_FUNCTION(ctx, COM_Seek, FALSE); GET_FUNCTION(ctx, COM_PowerUp, TRUE); GET_FUNCTION(ctx, COM_PowerDown, TRUE); GET_FUNCTION(ctx, COM_IOControl, TRUE); result = TRUE; } while (0); return result; }
/** ** evaluate byte code. ** @param f: Frame ** @return evaluated value. */ Object tm_eval(TmFrame* f) { Object* locals = f->locals; Object* top = f->stack; Object cur_fnc = f->fnc; Object globals = get_globals(cur_fnc); // TODO use code cache to replace unsigned char* unsigned char* pc = f->pc; const char* func_name_sz = get_func_name_sz(cur_fnc); Object x, k, v; Object ret = NONE_OBJECT; int i; #if INTERP_DB printf("File \"%s\": enter function %s\n",get_func_file_sz(cur_fnc), get_func_name_sz(cur_fnc)); #endif while (1) { i = (pc[1] << 8) | pc[2]; #if INTERP_DB printf("%30s%2d: %d frame = %d, top = %d\n","", pc[0], i, tm->cur, (int) (top - f->stack)); #endif switch (pc[0]) { case OP_NUMBER: { double d = atof((char*)pc + 3); pc += i; v = tm_number(d); /* obj_append(tm->constants,v);*/ dict_set(tm->constants, v, NONE_OBJECT); break; } case OP_STRING: { v = string_alloc((char*)pc + 3, i); pc += i; /* obj_append(tm->constants,v); */ dict_set(tm->constants, v, NONE_OBJECT); break; } case OP_IMPORT: { // TODO // tm_import(globals) Object import_func = tm_get_global(globals, "_import"); arg_start(); arg_push(globals); Object modname, attr; if (i == 1) { modname = TM_POP(); arg_push(modname); // arg1 } else { attr = TM_POP(); modname = TM_POP(); arg_push(modname); arg_push(attr); } call_function(import_func); break; } case OP_CONSTANT: { TM_PUSH(GET_CONST(i)); break; } case OP_NONE: { TM_PUSH(NONE_OBJECT); break; } case OP_LOAD_LOCAL: { TM_PUSH(locals[i]); break; } case OP_STORE_LOCAL: locals[i] = TM_POP(); break; case OP_LOAD_GLOBAL: { /* tm_printf("load global %o\n", GET_CONST(i)); */ int idx = dict_get_attr(GET_DICT(globals), i); if (idx == -1) { idx = dict_get_attr(GET_DICT(tm->builtins), i); if (idx == -1) { tm_raise("NameError: name %o is not defined", GET_CONST(i)); } else { Object value = GET_DICT(tm->builtins)->nodes[idx].val; // OPTIMIZE // set the builtin to `globals()` obj_set(globals, GET_CONST(i), value); idx = dict_get_attr(GET_DICT(globals), i); pc[0] = OP_FAST_LD_GLO; code16(pc+1, idx); // OPTIMIZE END TM_PUSH(value); } } else { TM_PUSH(GET_DICT(globals)->nodes[idx].val); pc[0] = OP_FAST_LD_GLO; code16(pc+1, idx); } break; } case OP_STORE_GLOBAL: { x = TM_POP(); int idx = dict_set_attr(GET_DICT(globals), i, x); pc[0] = OP_FAST_ST_GLO; code16(pc+1, idx); break; } case OP_FAST_LD_GLO: { TM_PUSH(GET_DICT(globals)->nodes[i].val); break; } case OP_FAST_ST_GLO: { GET_DICT(globals)->nodes[i].val = TM_POP(); break; } case OP_LIST: { TM_PUSH(list_new(2)); FRAME_CHECK_GC(); break; } case OP_APPEND: v = TM_POP(); x = TM_TOP(); tm_assert(IS_LIST(x), "tm_eval: OP_APPEND require list"); list_append(GET_LIST(x), v); break; case OP_DICT_SET: v = TM_POP(); k = TM_POP(); x = TM_TOP(); tm_assert(IS_DICT(x), "tm_eval: OP_DICT_SET require dict"); obj_set(x, k, v); break; case OP_DICT: { TM_PUSH(dict_new()); FRAME_CHECK_GC(); break; } TM_OP(OP_ADD, obj_add) TM_OP(OP_SUB, obj_sub) TM_OP(OP_MUL, obj_mul) TM_OP(OP_DIV, obj_div) TM_OP(OP_MOD, obj_mod) TM_OP(OP_GET, obj_get) case OP_SLICE: { Object second = TM_POP(); Object first = TM_POP(); *top = obj_slice(*top, first, second); break; } case OP_EQEQ: { *(top-1) = tm_number(obj_equals(*(top-1), *top)); top--; break; } case OP_NOTEQ: { *(top-1) = tm_number(!obj_equals(*(top-1), *top)); top--; break; } case OP_LT: { *(top-1) = tm_number(obj_cmp(*(top-1), *top)<0); top--; break; } case OP_LTEQ: { *(top-1) = tm_number(obj_cmp(*(top-1), *top)<=0); top--; break; } case OP_GT: { *(top-1) = tm_number(obj_cmp(*(top-1), *top)>0); top--; break; } case OP_GTEQ: { *(top-1) = tm_number(obj_cmp(*(top-1), *top)>=0); top--; break; } case OP_IN: { *(top-1) = tm_number(obj_in(*(top-1), *top)); top--; break; } case OP_AND: { *(top-1) = tm_number(is_true_obj(*(top-1)) && is_true_obj(*top)); top--; break; } case OP_OR: { *(top-1) = tm_number(is_true_obj(*(top-1)) || is_true_obj(*top)); top--; break; } case OP_NOT:{ *top = tm_number(!is_true_obj(*top)); break; } case OP_SET: k = TM_POP(); x = TM_POP(); v = TM_POP(); #if INTERP_DB tm_printf("Self %o, Key %o, Val %o\n", x, k, v); #endif obj_set(x, k, v); break; case OP_POP: { top--; break; } case OP_NEG: TM_TOP() = obj_neg(TM_TOP()); break; case OP_CALL: { f->top = top; top -= i; arg_set_arguments(top + 1, i); Object func = TM_POP(); TM_PUSH(call_function(func)); // TM_PUSH(call_function(func)); tm->frame = f; FRAME_CHECK_GC(); break; } case OP_APPLY: { f->top = top; Object args = TM_POP(); tm_assert_type(args, TYPE_LIST, "tm_eval: OP_APPLY"); arg_set_arguments(LIST_NODES(args), LIST_LEN(args)); Object func = TM_POP(); x = call_function(func); TM_PUSH(x); tm->frame = f; FRAME_CHECK_GC(); break; } case OP_LOAD_PARAMS: { int parg = pc[1]; int varg = pc[2]; if (tm->arg_cnt < parg || tm->arg_cnt > parg + varg) { tm_raise("ArgError,parg=%d,varg=%d,given=%d", parg, varg, tm->arg_cnt); } for(i = 0; i < tm->arg_cnt; i++){ locals[i] = tm->arguments[i]; } break; } case OP_LOAD_PARG: { int parg = i; for (i = 0; i < parg; i++) { locals[i] = arg_take_obj(func_name_sz); } break; } case OP_LOAD_NARG: { int arg_index = i; Object list = list_new(tm->arg_cnt); while (arg_remains() > 0) { obj_append(list, arg_take_obj(func_name_sz)); } locals[arg_index] = list; break; } case OP_ITER: { *top = iter_new(*top); break; } case OP_NEXT: { Object *next = next_ptr(*top); if (next != NULL) { TM_PUSH(*next); break; } else { pc += i * 3; continue; } break; } case OP_DEF: { Object mod = GET_FUNCTION(cur_fnc)->mod; Object fnc = func_new(mod, NONE_OBJECT, NULL); pc = func_resolve(GET_FUNCTION(fnc), pc); GET_FUNCTION_NAME(fnc) = GET_CONST(i); TM_PUSH(fnc); continue; } case OP_RETURN: { ret = TM_POP(); goto end; } case OP_ROT: { int half = i / 2; int j; for (j = 0; j < half; j++) { Object temp = *(top - j); *(top-j) = *(top - i + j + 1); *(top-i+j+1) = temp; } break; } case OP_UNPACK: { x = TM_POP(); tm_assert_type(x, TYPE_LIST, "tm_eval:UNPACK"); int j; for(j = LIST_LEN(x)-1; j >= 0; j--) { TM_PUSH(LIST_GET(x, j)); } break; } case OP_DEL: { k = TM_POP(); x = TM_POP(); obj_del(x, k); break; } case OP_POP_JUMP_ON_FALSE: { if (!is_true_obj(TM_POP())) { pc += i * 3; continue; } break; } case OP_JUMP_ON_TRUE: { if (is_true_obj(TM_TOP())) { pc += i * 3; continue; } break; } case OP_JUMP_ON_FALSE: { if (!is_true_obj(TM_TOP())) { pc += i * 3; continue; } break; } case OP_UP_JUMP: pc -= i * 3; continue; case OP_JUMP: pc += i * 3; continue; case OP_EOP: case OP_EOF: { ret = NONE_OBJECT; goto end; } case OP_LOAD_EX: { top = f->last_top; TM_PUSH(tm->ex); break; } case OP_SETJUMP: { f->last_top = top; f->jmp = pc + i * 3; break; } case OP_CLR_JUMP: { f->jmp = NULL; break;} case OP_LINE: { f->lineno = i; break;} case OP_DEBUG: { #if 0 Object fdebug = tm_get_global(globals, "__debug__"); f->top = top; tm_call(0, fdebug, 1, tm_number(tm->frame - tm->frames)); break; #endif } case OP_FILE: { // module name here. break; } default: tm_raise("BAD INSTRUCTION, %d\n globals() = \n%o", pc[0], GET_FUNCTION_GLOBALS(f->fnc)); goto end; } pc += 3; } end: /* if (top != f->stack) { tm_raise("tm_eval: operand stack overflow"); }*/ pop_frame(); return ret; }