void CloneObjectsTest::testCloneMethod() { VMSymbol* methodSymbol = GetUniverse()->NewSymbol("myMethod"); VMMethod* orig = GetUniverse()->NewMethod(methodSymbol, 0, 0); VMMethod* clone = orig->Clone(); CPPUNIT_ASSERT((intptr_t)orig != (intptr_t)clone); CPPUNIT_ASSERT_EQUAL_MESSAGE("class differs!!", orig->clazz, clone->clazz); CPPUNIT_ASSERT_EQUAL_MESSAGE("objectSize differs!!", orig->objectSize, clone->objectSize); CPPUNIT_ASSERT_EQUAL_MESSAGE("numberOfFields differs!!", orig->numberOfFields, clone->numberOfFields); CPPUNIT_ASSERT_EQUAL_MESSAGE("numberOfLocals differs!!", INT_VAL(load_ptr(orig->numberOfLocals)), INT_VAL(load_ptr(clone->numberOfLocals))); CPPUNIT_ASSERT_EQUAL_MESSAGE("bcLength differs!!", INT_VAL(load_ptr(orig->bcLength)), INT_VAL(load_ptr(clone->bcLength))); CPPUNIT_ASSERT_EQUAL_MESSAGE("maximumNumberOfStackElements differs!!", INT_VAL(load_ptr(orig->maximumNumberOfStackElements)), INT_VAL(load_ptr(clone->maximumNumberOfStackElements))); CPPUNIT_ASSERT_EQUAL_MESSAGE("numberOfArguments differs!!", INT_VAL(load_ptr(orig->numberOfArguments)), INT_VAL(load_ptr(clone->numberOfArguments))); CPPUNIT_ASSERT_EQUAL_MESSAGE("numberOfConstants differs!!", INT_VAL(load_ptr(orig->numberOfConstants)), INT_VAL(load_ptr(clone->numberOfConstants))); CPPUNIT_ASSERT_EQUAL_MESSAGE("GetHolder() differs!!", orig->GetHolder(), clone->GetHolder()); CPPUNIT_ASSERT_EQUAL_MESSAGE("GetSignature() differs!!", orig->GetSignature(), clone->GetSignature()); }
void _System::Exit_(Interpreter*, VMFrame* frame) { vm_oop_t err = frame->Pop(); long err_no = INT_VAL(err); if (err_no != ERR_SUCCESS) frame->PrintStackTrace(); GetUniverse()->Quit(err_no); }
// Recursive print function - updates buf_index as appropriate // during its traversal of c static int print(cell c) { switch (TYPE(c)) { case PAIR: if (TYPE(car(c)) == PAIR) { catf("("); print(car(c)); catf(")"); } else print(car(c)); if (!cdr(c)) return 0; catf(" "); if (TYPE(cdr(c)) != PAIR) catf(". "); return print(cdr(c)); case S64: case S32: return catf("%ld", INT_VAL(c)); case SYMBOL: return catf("%s", SYM_STR(c)); case NATIVE_FN: case NATIVE_FN_TCO: case NATIVE_MACRO: return catf("NATIVE_FUNCTION<%p>", PTR(c)); case FFI_SYM: return catf("FFI_SYM<%p>", PTR(c)); case FFI_FN: return catf("FFI_FN<%p>", PTR(c)); case FFI_LIBRARY: return catf("FFI_LIBRARY<%p>", PTR(c)); case MACRO: catf("(macro ("); goto print_args_body; case FN: catf("(lambda ("); print_args_body: print(((fn_t*)PTR(c))->args); catf(") "); print(((fn_t*)PTR(c))->body); return catf(")"); case CONS: return catf("CONS"); case NIL: return catf("()"); default: return catf("UNKNOWN<%p>", c); } }
sexpr_t* eval(sexpr_t* sexpr, sexpr_t** env, sexpr_list_t* roots, error_t** error) { if(sexpr == NULL) { return interp.nil_sym; } /* printf("[eval]\n"); */ /* print_sexpr(sexpr); */ /* printf("\n"); */ roots = cons_to_roots_list(roots, sexpr); gc_collect(roots); if(ATOM(sexpr)) { if(SYM(sexpr)) { if(interp.t_sym == sexpr) { return interp.t_sym; } if(interp.nil_sym == sexpr) { return interp.nil_sym; } sexpr_t* val = assoc(sexpr, *env); if(val == NULL) { *error = mk_error("Undefined symbol", SYM_VAL(sexpr)); } return val; } if(INT(sexpr)) { return sexpr; } } else if(ATOM(CAR(sexpr))) { if(SYM(CAR(sexpr))) { // quote if(interp.quote_sym == CAR(sexpr)) { if(CDR(sexpr) == NULL) { *error = mk_error("Missing quote argument", ""); return NULL; } if(CDR(CDR(sexpr)) != NULL) { *error = mk_error("Too many arguments for quote", ""); return NULL; } return CAR(CDR(sexpr)); } // atom if(interp.atom_sym == CAR(sexpr)) { if(ATOM(eval(CAR(CDR(sexpr)), env, roots, error))) { return interp.t_sym; } return interp.nil_sym; } // eq if(interp.eq_sym == CAR(sexpr)) { // TODO check nb args sexpr_t* e1 = eval(CAR(CDR(sexpr)), env, roots, error); if(*error != NULL) { return NULL; } roots = cons_to_roots_list(roots, e1); sexpr_t* e2 = eval(CAR(CDR(CDR(sexpr))), env, roots, error); if(*error != NULL) { return NULL; } if(INT(e1) && INT(e2)) { if(INT_VAL(e1) == INT_VAL(e2)) { return interp.t_sym; } return interp.nil_sym; } if(e1 == e2) { return interp.t_sym; } return interp.nil_sym; } // if if(interp.if_sym == CAR(sexpr)) { sexpr_t* e1 = eval(CAR(CDR(sexpr)), env, roots, error); if(*error != NULL) { return NULL; } if(e1 == interp.nil_sym) { return eval(CAR(CDR(CDR(CDR(sexpr)))), env, roots, error); } else { return eval(CAR(CDR(CDR(sexpr))), env, roots, error); } } // car if(interp.car_sym == CAR(sexpr)) { sexpr_t* e1 = eval(CAR(CDR(sexpr)), env, roots, error); if(*error != NULL) { return NULL; } if(e1 == interp.nil_sym) { return interp.nil_sym; } return CAR(e1); } // cdr if(interp.cdr_sym == CAR(sexpr)) { sexpr_t* e1 = eval(CAR(CDR(sexpr)), env, roots, error); if(*error != NULL) { return NULL; } if(e1 == interp.nil_sym) { return interp.nil_sym; } sexpr_t *res = CDR(e1); if(res == NULL) { return interp.nil_sym; } return res; } // + if(interp.plus_sym == CAR(sexpr)) { sexpr_t* e1 = eval(CAR(CDR(sexpr)), env, roots, error); if(*error != NULL) { return NULL; } roots = cons_to_roots_list(roots, e1); sexpr_t* e2 = eval(CAR(CDR(CDR(sexpr))), env, roots, error); if(*error != NULL) { return NULL; } if(INT(e1) && INT(e2)) { return mk_int(INT_VAL(e1) + INT_VAL(e2)); } *error = mk_error("Arguments for '+' are not integers", ""); return NULL; } // - if(interp.minus_sym == CAR(sexpr)) { sexpr_t* e1 = eval(CAR(CDR(sexpr)), env, roots, error); if(*error != NULL) { return NULL; } roots = cons_to_roots_list(roots, e1); sexpr_t* e2 = eval(CAR(CDR(CDR(sexpr))), env, roots, error); if(*error != NULL) { return NULL; } if(INT(e1) && INT(e2)) { return mk_int(INT_VAL(e1) - INT_VAL(e2)); } *error = mk_error("Arguments for '-' are not integers", ""); return NULL; } if(interp.mul_sym == CAR(sexpr)) { sexpr_t* e1 = eval(CAR(CDR(sexpr)), env, roots, error); if(*error != NULL) { return NULL; } roots = cons_to_roots_list(roots, sexpr); sexpr_t* e2 = eval(CAR(CDR(CDR(sexpr))), env, roots, error); if(*error != NULL) { return NULL; } if(INT(e1) && INT(e2)) { return mk_int(INT_VAL(e1) * INT_VAL(e2)); } *error = mk_error("Arguments for '*' are not integers", ""); return NULL; } // cons if(interp.cons_sym == CAR(sexpr)) { sexpr_t* e1 = eval(CAR(CDR(sexpr)), env, roots, error); if(*error != NULL) { return NULL; } roots = cons_to_roots_list(roots, e1); sexpr_t* e2 = eval(CAR(CDR(CDR(sexpr))), env, roots, error); if(*error != NULL) { return NULL; } return mk_cons(e1 == interp.nil_sym ? NULL : e1, e2 == interp.nil_sym ? NULL : e2); } // def if(interp.def_sym == CAR(sexpr)) { sexpr_t* arg = CAR(CDR(CDR(sexpr))); roots = cons_to_roots_list(roots, arg); sexpr_t* val = eval(arg, env, roots, error); if(*error != NULL) { return NULL; } *env = mk_cons(mk_cons(intern(SYM_VAL(CAR(CDR(sexpr)))), val), *env); return val; } // print if(interp.print_sym == CAR(sexpr)) { sexpr_t* e1 = eval(CAR(CDR(sexpr)), env, roots, error); if(*error != NULL) { return NULL; } print_sexpr(e1); printf("\n"); return e1; } // fn if(interp.fn_sym == CAR(sexpr)) { return mk_fn(sexpr, *env); } // macro if(interp.macro_sym == CAR(sexpr)) { return mk_macro(sexpr); } //eval if(interp.eval_sym == CAR(sexpr)) { sexpr_t* e1 = eval(CAR(CDR(sexpr)), env, roots, error); if(*error != NULL) { return NULL; } roots = cons_to_roots_list(roots, e1); return eval(e1, env, roots, error); } // else resolves first variable sexpr_t* fn = eval(CAR(sexpr), env, roots, error); if(*error != NULL) { return NULL; } // eval fn if(FN(fn)) { sexpr_t* fn_code = CAR(CDR(CDR(CAR(fn)))); sexpr_t* captured_env = CDR(fn); sexpr_t* arguments = eval_list(CDR(sexpr), env, roots, error); if(*error != NULL) { return NULL; } sexpr_t* pairs = pair(CAR(CDR(CAR(fn))), arguments); sexpr_t* eval_env = append(pairs, captured_env); // append the function itself to the env, roots, for recursive calls eval_env = mk_cons(mk_cons(CAR(sexpr), fn), eval_env); /* printf("fn code=\n"); */ /* print_sexpr(fn_code); */ /* printf("\n"); */ roots = cons_to_roots_list(roots, eval_env); return eval(fn_code, &eval_env, roots, error); } // eval macro if(MACRO(fn)) { sexpr_t* macro_code = CAR(CDR(CDR(CAR(fn)))); sexpr_t* pairs = pair(CAR(CDR(CAR(fn))), CDR(sexpr)); sexpr_t* eval_env = append(pairs, *env); roots = cons_to_roots_list(roots, eval_env); sexpr_t* transformed_code = eval(macro_code, &eval_env, roots, error); if(*error != NULL) { return NULL; } return eval(transformed_code, env, roots, error); } // else primitives sexpr_t* arguments = eval_list(CDR(sexpr), env, roots, error); if(*error != NULL) { return NULL; } sexpr_t* to_eval = mk_cons(fn, arguments); return eval(to_eval, env, roots, error); } } else if(CAR(CAR(sexpr)) == interp.fn_sym) { // executes an anonymous function sexpr_t* fn = CAR(sexpr); sexpr_t* fn_code = CAR(CDR(CDR(fn))); sexpr_t* arguments = eval_list(CDR(sexpr), env, roots, error); if(*error != NULL) { return NULL; } sexpr_t* l = pair(CAR(CDR(fn)), arguments); l = append(l, *env); roots = cons_to_roots_list(roots, l); return eval(fn_code, &l, roots, error); } print_sexpr(sexpr); printf("\n"); *error = mk_error("Invalid expression", ""); return NULL; }
static void integer_number(void) { uint64_t number = parse_uint64(parser.previous.start, parser.previous.length); emit_constant(INT_VAL((int64_t)number)); }
long VMMethod::GetNumberOfBytecodes() const { return INT_VAL(load_ptr(bcLength)); }
long VMMethod::GetMaximumNumberOfStackElements() const { return INT_VAL(load_ptr(maximumNumberOfStackElements)); }
object call_c(int func, object proc_ad, object arg_list) /* Call a WIN32 or Linux C function in a DLL or shared library. Alternatively, call a machine-code routine at a given address. */ { volatile unsigned long arg; // !!!! magic var to push values on the stack volatile int argsize; // !!!! number of bytes to pop s1_ptr arg_list_ptr, arg_size_ptr; object_ptr next_arg_ptr, next_size_ptr; object next_arg, next_size; int iresult, i; double dbl_arg, dresult; float flt_arg, fresult; unsigned long size; int proc_index; int cdecl_call; int (*int_proc_address)(); unsigned return_type; char NameBuff[100]; // Setup and Check for Errors proc_index = get_pos_int("c_proc/c_func", proc_ad); if ((unsigned)proc_index >= c_routine_next) { sprintf(TempBuff, "c_proc/c_func: bad routine number (%d)", proc_index); RTFatal(TempBuff); } int_proc_address = c_routine[proc_index].address; #if defined(EWINDOWS) && !defined(EWATCOM) cdecl_call = c_routine[proc_index].convention; #endif if (IS_ATOM(arg_list)) { RTFatal("c_proc/c_func: argument list must be a sequence"); } arg_list_ptr = SEQ_PTR(arg_list); next_arg_ptr = arg_list_ptr->base + arg_list_ptr->length; // only look at length of arg size sequence for now arg_size_ptr = c_routine[proc_index].arg_size; next_size_ptr = arg_size_ptr->base + arg_size_ptr->length; return_type = c_routine[proc_index].return_size; // will be INT if (func && return_type == 0 || !func && return_type != 0) { if (c_routine[proc_index].name->length < 100) MakeCString(NameBuff, MAKE_SEQ(c_routine[proc_index].name)); else NameBuff[0] = '\0'; sprintf(TempBuff, func ? "%s does not return a value" : "%s returns a value", NameBuff); RTFatal(TempBuff); } if (arg_list_ptr->length != arg_size_ptr->length) { if (c_routine[proc_index].name->length < 100) MakeCString(NameBuff, MAKE_SEQ(c_routine[proc_index].name)); else NameBuff[0] = '\0'; sprintf(TempBuff, "C routine %s() needs %d argument%s, not %d", NameBuff, arg_size_ptr->length, (arg_size_ptr->length == 1) ? "" : "s", arg_list_ptr->length); RTFatal(TempBuff); } argsize = arg_list_ptr->length << 2; // Push the Arguments for (i = 1; i <= arg_list_ptr->length; i++) { next_arg = *next_arg_ptr--; next_size = *next_size_ptr--; if (IS_ATOM_INT(next_size)) size = INT_VAL(next_size); else if (IS_ATOM(next_size)) size = (unsigned long)DBL_PTR(next_size)->dbl; else RTFatal("This C routine was defined using an invalid argument type"); if (size == C_DOUBLE || size == C_FLOAT) { /* push 8-byte double or 4-byte float */ if (IS_ATOM_INT(next_arg)) dbl_arg = (double)next_arg; else if (IS_ATOM(next_arg)) dbl_arg = DBL_PTR(next_arg)->dbl; else { arg = arg+argsize+9999; // 9999 = 270f hex - just a marker for asm code RTFatal("arguments to C routines must be atoms"); } if (size == C_DOUBLE) { arg = *(1+(unsigned long *)&dbl_arg); push(); // push high-order half first argsize += 4; arg = *(unsigned long *)&dbl_arg; push(); // don't combine this with the push() below - Lcc bug } else { /* C_FLOAT */ flt_arg = (float)dbl_arg; arg = *(unsigned long *)&flt_arg; push(); } } else { /* push 4-byte integer */ if (size >= E_INTEGER) { if (IS_ATOM_INT(next_arg)) { if (size == E_SEQUENCE) RTFatal("passing an integer where a sequence is required"); } else { if (IS_SEQUENCE(next_arg)) { if (size != E_SEQUENCE && size != E_OBJECT) RTFatal("passing a sequence where an atom is required"); } else { if (size == E_SEQUENCE) RTFatal("passing an atom where a sequence is required"); } RefDS(next_arg); } arg = next_arg; push(); } else if (IS_ATOM_INT(next_arg)) { arg = next_arg; push(); } else if (IS_ATOM(next_arg)) { // atoms are rounded to integers arg = (unsigned long)DBL_PTR(next_arg)->dbl; //correct // if it's a -ve f.p. number, Watcom converts it to int and // then to unsigned int. This is exactly what we want. // Works with the others too. push(); } else { arg = arg+argsize+9999; // just a marker for asm code RTFatal("arguments to C routines must be atoms"); } } } // Make the Call - The C compiler thinks it's a 0-argument call // might be VOID C routine, but shouldn't crash if (return_type == C_DOUBLE) { // expect double to be returned from C routine #if defined(EWINDOWS) && !defined(EWATCOM) if (cdecl_call) { dresult = (*((double ( __cdecl *)())int_proc_address))(); pop(); } else #endif dresult = (*((double (__stdcall *)())int_proc_address))(); #ifdef ELINUX pop(); #endif return NewDouble(dresult); } else if (return_type == C_FLOAT) { // expect float to be returned from C routine #if defined(EWINDOWS) && !defined(EWATCOM) if (cdecl_call) { fresult = (*((float ( __cdecl *)())int_proc_address))(); pop(); } else #endif fresult = (*((float (__stdcall *)())int_proc_address))(); #ifdef ELINUX pop(); #endif return NewDouble((double)fresult); } else { // expect integer to be returned #if defined(EWINDOWS) && !defined(EWATCOM) if (cdecl_call) { iresult = (*((int ( __cdecl *)())int_proc_address))(); pop(); } else #endif iresult = (*((int (__stdcall *)())int_proc_address))(); #ifdef ELINUX pop(); #endif if ((return_type & 0x000000FF) == 04) { /* 4-byte integer - usual case */ // check if unsigned result is required if ((return_type & C_TYPE) == 0x02000000) { // unsigned integer result if ((unsigned)iresult <= (unsigned)MAXINT) { return iresult; } else return NewDouble((double)(unsigned)iresult); } else { // signed integer result if (return_type >= E_INTEGER || (iresult >= MININT && iresult <= MAXINT)) { return iresult; } else return NewDouble((double)iresult); } } else if (return_type == 0) { return 0; /* void - procedure */ } /* less common cases */ else if (return_type == C_UCHAR) { return (unsigned char)iresult; } else if (return_type == C_CHAR) { return (signed char)iresult; } else if (return_type == C_USHORT) { return (unsigned short)iresult; } else if (return_type == C_SHORT) { return (short)iresult; } else return 0; // unknown function return type } }
/* this function is not thread safe */ char *kek_obj_print(kek_obj_t *kek_obj) { static char str[1024]; if (kek_obj == (kek_obj_t *) 0xffffffffffffffff) { (void) snprintf(str, 1024, "kek_obj == 0xffffffffffffffff"); assert(0); goto out; } if (kek_obj == NULL) { (void) snprintf(str, 1024, "kek_obj == NULL"); goto out; } /* vm_debug(DBG_STACK | DBG_STACK_FULL, "kek_obj = %p\n", kek_obj); */ if (!IS_PTR(kek_obj)) { if (IS_CHAR(kek_obj)) { (void) snprintf(str, 1024, "char -%c-", CHAR_VAL(kek_obj)); } else if (IS_INT(kek_obj)) { (void) snprintf(str, 1024, "int -%d-", INT_VAL(kek_obj)); } } else { vm_assert(TYPE_CHECK(kek_obj->h.t), // "kek_obj=%p, "// "type=%d, "// "state=%d, "// "is_const=%d, "// "fromspace=%d, "// "tospace=%d\n",// kek_obj,// kek_obj->h.t,// kek_obj->h.state,// vm_is_const(kek_obj),// gc_cheney_ptr_in_from_space(kek_obj, 1),// gc_cheney_ptr_in_to_space(kek_obj, 1)); switch (kek_obj->h.t) { case KEK_INT: (void) snprintf(str, 1024, "int -%d-", INT_VAL(kek_obj)); break; case KEK_STR: (void) snprintf(str, 1024, "str -%s-", ((kek_string_t *) kek_obj)->string); break; case KEK_ARR: (void) snprintf(str, 1024, "arr -%p-", (void*) kek_obj); break; case KEK_SYM: (void) snprintf(str, 1024, "sym -%s-", ((kek_symbol_t *) kek_obj)->symbol); break; case KEK_NIL: (void) snprintf(str, 1024, "nil"); break; case KEK_UDO: (void) snprintf(str, 1024, "udo"); break; case KEK_ARR_OBJS: (void) snprintf(str, 1024, "arr_objs"); break; case KEK_EXINFO: (void) snprintf(str, 1024, "exinfo"); break; case KEK_EXPT: (void) snprintf(str, 1024, "expt"); break; case KEK_FILE: (void) snprintf(str, 1024, "file"); break; case KEK_TERM: (void) snprintf(str, 1024, "term"); break; case KEK_CLASS: (void) snprintf(str, 1024, "class"); break; case KEK_STACK: (void) snprintf(str, 1024, "stack"); break; case KEK_COPIED: (void) snprintf(str, 1024, "COPIED!"); break; default: assert(0); break; } } out: /* */ return ((char *) (&str)); }
static inline kek_obj_t * bc_bop(op_t o, kek_obj_t *a, kek_obj_t *b) { char * str_a, *str_b; char chr_a[2], chr_b[2]; chr_a[1] = chr_b[1] = '\0'; if (IS_INT(a) && IS_INT(b)) { kek_int_t *res = NULL; vm_debug(DBG_BC, " - %d, %d\n", INT_VAL(a), INT_VAL(b)); switch (o) { case Plus: res = make_integer(INT_VAL(a) + INT_VAL(b)); break; case Minus: res = make_integer(INT_VAL(a) - INT_VAL(b)); break; case Times: res = make_integer(INT_VAL(a) * INT_VAL(b)); break; case Divide: res = make_integer(INT_VAL(a) / INT_VAL(b)); break; case Modulo: res = make_integer(INT_VAL(a) % INT_VAL(b)); break; case Eq: res = make_integer(INT_VAL(a) == INT_VAL(b)); break; case NotEq: res = make_integer(INT_VAL(a) != INT_VAL(b)); break; case Less: res = make_integer(INT_VAL(a) < INT_VAL(b)); break; case Greater: res = make_integer(INT_VAL(a) > INT_VAL(b)); break; case LessOrEq: res = make_integer(INT_VAL(a) <= INT_VAL(b)); break; case GreaterOrEq: res = make_integer(INT_VAL(a) >= INT_VAL(b)); break; case LogOr: res = make_integer(INT_VAL(a) || INT_VAL(b)); break; case LogAnd: res = make_integer(INT_VAL(a) && INT_VAL(b)); break; case BitOr: res = make_integer(INT_VAL(a) | INT_VAL(b)); break; case BitAnd: res = make_integer(INT_VAL(a) & INT_VAL(b)); break; case Xor: res = make_integer(INT_VAL(a) ^ INT_VAL(b)); break; case Lsh: res = make_integer(INT_VAL(a) << INT_VAL(b)); break; case Rsh: res = make_integer(INT_VAL(a) >> INT_VAL(b)); break; default: vm_error("bc_bop: unsupported bop %d on integers\n", o); break; } vm_debug(DBG_BC, " = %d\n", INT_VAL((kek_obj_t* )res)); return (kek_obj_t*) res; } else if (( // This is intentionally complicated :D