diff options
Diffstat (limited to 'py/runtime.c')
-rw-r--r-- | py/runtime.c | 236 |
1 files changed, 116 insertions, 120 deletions
diff --git a/py/runtime.c b/py/runtime.c index e9a8614389..81487c2b68 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -7,7 +7,7 @@ #include "misc.h" #include "machine.h" #include "runtime.h" -#include "vm.h" +#include "bc.h" #if 0 // print debugging info #define DEBUG_printf(args...) printf(args) @@ -120,8 +120,9 @@ py_obj_t py_const_none; py_obj_t py_const_false; py_obj_t py_const_true; -py_map_t map_locals; -py_map_t map_globals; +// locals and globals need to be pointers because they can be the same in outer module scope +py_map_t *map_locals; +py_map_t *map_globals; py_map_t map_builtins; // approximatelly doubling primes; made with Mathematica command: Table[Prime[Floor[(1.7)^n]], {n, 3, 24}] @@ -339,9 +340,9 @@ py_obj_t py_builtin_len(py_obj_t o_in) { py_obj_t py_builtin___build_class__(py_obj_t o_class_fun, py_obj_t o_class_name) { // we differ from CPython: we set the new __locals__ object here - py_map_t old_locals = map_locals; + py_map_t *old_locals = map_locals; py_map_t *class_locals = py_map_new(MAP_QSTR, 0); - map_locals = *class_locals; + map_locals = class_locals; // call the class code rt_call_function_1(o_class_fun, (py_obj_t)0xdeadbeef); @@ -368,10 +369,9 @@ void rt_init() { py_const_false = py_obj_new_const("False"); py_const_true = py_obj_new_const("True"); - py_map_init(&map_locals, MAP_QSTR, 0); - - py_map_init(&map_globals, MAP_QSTR, 1); - py_qstr_map_lookup(&map_globals, qstr_from_str_static("__name__"), true)->value = py_obj_new_str(qstr_from_str_static("__main__")); + // locals = globals for outer module (see Objects/frameobject.c/PyFrame_New()) + map_locals = map_globals = py_map_new(MAP_QSTR, 1); + py_qstr_map_lookup(map_globals, qstr_from_str_static("__name__"), true)->value = py_obj_new_str(qstr_from_str_static("__main__")); py_map_init(&map_builtins, MAP_QSTR, 3); py_qstr_map_lookup(&map_builtins, q_print, true)->value = rt_make_function_1(py_builtin_print); @@ -476,6 +476,7 @@ bool py_obj_is_callable(py_obj_t o_in) { case O_FUN_N: case O_FUN_BC: case O_FUN_ASM: + // what about O_CLASS, and an O_OBJ that has a __call__ method? return true; default: return false; @@ -633,9 +634,9 @@ py_obj_t rt_load_const_str(qstr qstr) { py_obj_t rt_load_name(qstr qstr) { // logic: search locals, globals, builtins DEBUG_OP_printf("load name %s\n", qstr_str(qstr)); - py_map_elem_t *elem = py_qstr_map_lookup(&map_locals, qstr, false); + py_map_elem_t *elem = py_qstr_map_lookup(map_locals, qstr, false); if (elem == NULL) { - elem = py_qstr_map_lookup(&map_globals, qstr, false); + elem = py_qstr_map_lookup(map_globals, qstr, false); if (elem == NULL) { elem = py_qstr_map_lookup(&map_builtins, qstr, false); if (elem == NULL) { @@ -650,7 +651,7 @@ py_obj_t rt_load_name(qstr qstr) { py_obj_t rt_load_global(qstr qstr) { // logic: search globals, builtins DEBUG_OP_printf("load global %s\n", qstr_str(qstr)); - py_map_elem_t *elem = py_qstr_map_lookup(&map_globals, qstr, false); + py_map_elem_t *elem = py_qstr_map_lookup(map_globals, qstr, false); if (elem == NULL) { elem = py_qstr_map_lookup(&map_builtins, qstr, false); if (elem == NULL) { @@ -673,12 +674,12 @@ py_obj_t rt_load_build_class() { void rt_store_name(qstr qstr, py_obj_t obj) { DEBUG_OP_printf("store name %s <- %p\n", qstr_str(qstr), obj); - py_qstr_map_lookup(&map_locals, qstr, true)->value = obj; + py_qstr_map_lookup(map_locals, qstr, true)->value = obj; } void rt_store_global(qstr qstr, py_obj_t obj) { DEBUG_OP_printf("store global %s <- %p\n", qstr_str(qstr), obj); - py_qstr_map_lookup(&map_globals, qstr, true)->value = obj; + py_qstr_map_lookup(map_globals, qstr, true)->value = obj; } py_obj_t rt_unary_op(int op, py_obj_t arg) { @@ -809,6 +810,26 @@ py_obj_t rt_make_function(int n_args, py_fun_t code) { return o; } +py_obj_t rt_call_function_0(py_obj_t fun) { + return rt_call_function_n(fun, 0, NULL); +} + +py_obj_t rt_call_function_1(py_obj_t fun, py_obj_t arg) { + return rt_call_function_n(fun, 1, &arg); +} + +py_obj_t rt_call_function_2(py_obj_t fun, py_obj_t arg1, py_obj_t arg2) { + py_obj_t args[2]; + args[1] = arg1; + args[0] = arg2; + return rt_call_function_n(fun, 2, args); +} + +typedef machine_uint_t (*inline_asm_fun_0_t)(); +typedef machine_uint_t (*inline_asm_fun_1_t)(machine_uint_t); +typedef machine_uint_t (*inline_asm_fun_2_t)(machine_uint_t, machine_uint_t); +typedef machine_uint_t (*inline_asm_fun_3_t)(machine_uint_t, machine_uint_t, machine_uint_t); + // convert a Python object to a sensible value for inline asm machine_uint_t rt_convert_obj_for_inline_asm(py_obj_t obj) { // TODO for byte_array, pass pointer to the array @@ -847,130 +868,109 @@ py_obj_t rt_convert_val_from_inline_asm(machine_uint_t val) { return TO_SMALL_INT(val); } -typedef machine_uint_t (*inline_asm_fun_0_t)(); -typedef machine_uint_t (*inline_asm_fun_1_t)(machine_uint_t); -typedef machine_uint_t (*inline_asm_fun_2_t)(machine_uint_t, machine_uint_t); - -py_obj_t rt_call_function_0(py_obj_t fun) { +// args are in reverse order in the array +py_obj_t rt_call_function_n(py_obj_t fun, int n_args, const py_obj_t *args) { + int n_args_fun = 0; if (IS_O(fun, O_FUN_0)) { py_obj_base_t *o = fun; - DEBUG_OP_printf("calling native %p with no args\n", o->u_fun.fun); + if (n_args != 0) { + n_args_fun = 0; + goto bad_n_args; + } + DEBUG_OP_printf("calling native %p()\n", o->u_fun.fun); return ((py_fun_0_t)o->u_fun.fun)(); + + } else if (IS_O(fun, O_FUN_1)) { + py_obj_base_t *o = fun; + if (n_args != 1) { + n_args_fun = 1; + goto bad_n_args; + } + DEBUG_OP_printf("calling native %p(%p)\n", o->u_fun.fun, args[0]); + return ((py_fun_1_t)o->u_fun.fun)(args[0]); + + } else if (IS_O(fun, O_FUN_2)) { + py_obj_base_t *o = fun; + if (n_args != 2) { + n_args_fun = 2; + goto bad_n_args; + } + DEBUG_OP_printf("calling native %p(%p, %p)\n", o->u_fun.fun, args[1], args[0]); + return ((py_fun_2_t)o->u_fun.fun)(args[1], args[0]); + + // TODO O_FUN_N + } else if (IS_O(fun, O_FUN_BC)) { py_obj_base_t *o = fun; - assert(o->u_fun_bc.n_args == 0); - DEBUG_OP_printf("calling byte code %p with no args\n", o->u_fun_bc.code); - return py_execute_byte_code(o->u_fun_bc.code, o->u_fun_bc.len, NULL, 0); + if (n_args != o->u_fun_bc.n_args) { + n_args_fun = o->u_fun_bc.n_args; + goto bad_n_args; + } + DEBUG_OP_printf("calling byte code %p(n_args=%d)\n", o->u_fun_bc.code, n_args); + return py_execute_byte_code(o->u_fun_bc.code, o->u_fun_bc.len, args, n_args); + } else if (IS_O(fun, O_FUN_ASM)) { py_obj_base_t *o = fun; - assert(o->u_fun_asm.n_args == 0); - DEBUG_OP_printf("calling inline asm %p with no args\n", o->u_fun_asm.fun); - return rt_convert_val_from_inline_asm(((inline_asm_fun_0_t)o->u_fun_asm.fun)()); + if (n_args != o->u_fun_asm.n_args) { + n_args_fun = o->u_fun_asm.n_args; + goto bad_n_args; + } + DEBUG_OP_printf("calling inline asm %p(n_args=%d)\n", o->u_fun_asm.fun, n_args); + machine_uint_t ret; + if (n_args == 0) { + ret = ((inline_asm_fun_0_t)o->u_fun_asm.fun)(); + } else if (n_args == 1) { + ret = ((inline_asm_fun_1_t)o->u_fun_asm.fun)(rt_convert_obj_for_inline_asm(args[0])); + } else if (n_args == 2) { + ret = ((inline_asm_fun_2_t)o->u_fun_asm.fun)(rt_convert_obj_for_inline_asm(args[1]), rt_convert_obj_for_inline_asm(args[0])); + } else if (n_args == 3) { + ret = ((inline_asm_fun_3_t)o->u_fun_asm.fun)(rt_convert_obj_for_inline_asm(args[2]), rt_convert_obj_for_inline_asm(args[1]), rt_convert_obj_for_inline_asm(args[0])); + } else { + assert(0); + ret = 0; + } + return rt_convert_val_from_inline_asm(ret); + } else if (IS_O(fun, O_BOUND_METH)) { py_obj_base_t *o = fun; - DEBUG_OP_printf("calling bound method %p with self and no args\n", o->u_bound_meth.meth); - return rt_call_function_1(o->u_bound_meth.meth, o->u_bound_meth.self); + DEBUG_OP_printf("calling bound method %p(self=%p, n_args=%d)\n", o->u_bound_meth.meth, o->u_bound_meth.self, n_args); + if (n_args == 0) { + return rt_call_function_n(o->u_bound_meth.meth, 1, &o->u_bound_meth.self); + } else if (n_args == 1) { + py_obj_t args2[2]; + args2[1] = o->u_bound_meth.self; + args2[0] = args[0]; + return rt_call_function_n(o->u_bound_meth.meth, 2, args2); + } else { + // TODO not implemented + assert(0); + return py_const_none; + //return rt_call_function_2(o->u_bound_meth.meth, n_args + 1, o->u_bound_meth.self + args); + } + } else if (IS_O(fun, O_CLASS)) { // instantiate an instance of a class + if (n_args != 0) { + n_args_fun = 0; + goto bad_n_args; + } DEBUG_OP_printf("instantiate object of class %p with no args\n", fun); py_obj_base_t *o = m_new(py_obj_base_t, 1); o->kind = O_OBJ; o->u_obj.class = fun; o->u_obj.members = py_map_new(MAP_QSTR, 0); return o; - } else { - printf("fun0:%p\n", fun); - assert(0); - return py_const_none; - } -} -py_obj_t rt_call_function_1(py_obj_t fun, py_obj_t arg) { - if (IS_O(fun, O_FUN_1)) { - py_obj_base_t *o = fun; - DEBUG_OP_printf("calling native %p with 1 arg\n", o->u_fun.fun); - return ((py_fun_1_t)o->u_fun.fun)(arg); - } else if (IS_O(fun, O_FUN_BC)) { - py_obj_base_t *o = fun; - if (o->u_fun_bc.n_args != 1) { - printf("rt_call_function_1: trying to pass 1 argument to a function that takes %d arguments\n", o->u_fun_bc.n_args); - assert(0); - } - DEBUG_OP_printf("calling byte code %p with 1 arg\n", o->u_fun_bc.code); - return py_execute_byte_code(o->u_fun_bc.code, o->u_fun_bc.len, &arg, 1); - } else if (IS_O(fun, O_FUN_ASM)) { - py_obj_base_t *o = fun; - assert(o->u_fun_asm.n_args == 1); - DEBUG_OP_printf("calling inline asm %p with 1 arg\n", o->u_fun_asm.fun); - return rt_convert_val_from_inline_asm(((inline_asm_fun_1_t)o->u_fun_asm.fun)(rt_convert_obj_for_inline_asm(arg))); - } else if (IS_O(fun, O_BOUND_METH)) { - py_obj_base_t *o = fun; - return rt_call_function_2(o->u_bound_meth.meth, o->u_bound_meth.self, arg); } else { - printf("fun1:%p\n", fun); + printf("fun %p %d\n", fun, ((py_obj_base_t*)fun)->kind); assert(0); return py_const_none; } -} -py_obj_t rt_call_function_2(py_obj_t fun, py_obj_t arg1, py_obj_t arg2) { - if (IS_O(fun, O_FUN_2)) { - py_obj_base_t *o = fun; - DEBUG_OP_printf("calling native %p(%p, %p)\n", o->u_fun.fun, arg1, arg2); - return ((py_fun_2_t)o->u_fun.fun)(arg1, arg2); - } else if (IS_O(fun, O_FUN_BC)) { - py_obj_base_t *o = fun; - assert(o->u_fun_bc.n_args == 2); - DEBUG_OP_printf("calling byte code %p with 2 args\n", o->u_fun_bc.code); - py_obj_t args[2]; - args[1] = arg1; - args[0] = arg2; - return py_execute_byte_code(o->u_fun_bc.code, o->u_fun_bc.len, &args[0], 2); - } else if (IS_O(fun, O_FUN_ASM)) { - py_obj_base_t *o = fun; - assert(o->u_fun_asm.n_args == 2); - DEBUG_OP_printf("calling inline asm %p with 2 args\n", o->u_fun_asm.fun); - return rt_convert_val_from_inline_asm(((inline_asm_fun_2_t)o->u_fun_asm.fun)(rt_convert_obj_for_inline_asm(arg1), rt_convert_obj_for_inline_asm(arg2))); - } else { - assert(0); - return py_const_none; - } -} - -// args are in reverse order in the array -py_obj_t rt_call_function_n(py_obj_t fun, int n_args, const py_obj_t *args) { - if (IS_O(fun, O_FUN_2)) { - assert(n_args == 2); - py_obj_base_t *o = fun; - DEBUG_OP_printf("calling native %p(%p, %p)\n", o->u_fun.fun, args[1], args[0]); - return ((py_fun_2_t)o->u_fun.fun)(args[1], args[0]); - } else if (IS_O(fun, O_FUN_BC)) { - py_obj_base_t *o = fun; - assert(o->u_fun_bc.n_args == n_args); - DEBUG_OP_printf("calling byte code %p with %d args\n", o->u_fun_bc.code, n_args); - return py_execute_byte_code(o->u_fun_bc.code, o->u_fun_bc.len, args, n_args); - } else { - assert(0); - return py_const_none; - } -} - -py_obj_t rt_call_method_1(py_obj_t fun, py_obj_t self) { - DEBUG_OP_printf("call method %p(self=%p)\n", fun, self); - if (self == NULL) { - return rt_call_function_0(fun); - } else { - return rt_call_function_1(fun, self); - } -} - -py_obj_t rt_call_method_2(py_obj_t fun, py_obj_t self, py_obj_t arg) { - DEBUG_OP_printf("call method %p(self=%p, %p)\n", fun, self, arg); - if (self == NULL) { - return rt_call_function_1(fun, arg); - } else { - return rt_call_function_2(fun, self, arg); - } +bad_n_args: + printf("TypeError: function takes %d positional arguments but %d were given\n", n_args_fun, n_args); + assert(0); + return py_const_none; } // args contains: arg(n_args-1) arg(n_args-2) ... arg(0) self/NULL fun @@ -1206,11 +1206,7 @@ void *rt_fun_table[RT_F_NUMBER_OF] = { rt_store_map, rt_build_set, rt_make_function_from_id, - rt_call_function_0, - rt_call_function_1, - rt_call_function_2, - rt_call_method_1, - rt_call_method_2, + rt_call_function_n, rt_call_method_n, rt_binary_op, rt_compare_op, |