From a397776d6bf1a9d0b07d7138b289cd661c5e1b99 Mon Sep 17 00:00:00 2001 From: Damien Date: Wed, 9 Oct 2013 23:10:10 +0100 Subject: [PATCH] Implement basic class/object functionality in runtime. --- py/emit.h | 2 +- py/emitbc.c | 12 +- py/emitcpy.c | 16 +-- py/emitnative.c | 14 ++- py/main.c | 2 +- py/runtime.c | 291 +++++++++++++++++++++++++++++++++++++----------- py/runtime.h | 5 +- py/vm.c | 26 +++-- py/vm.h | 5 +- 9 files changed, 273 insertions(+), 100 deletions(-) diff --git a/py/emit.h b/py/emit.h index 93c7298d37..a8bc1fca24 100644 --- a/py/emit.h +++ b/py/emit.h @@ -57,8 +57,8 @@ typedef struct _emit_method_table_t { void (*store_global)(emit_t *emit, qstr qstr); void (*store_deref)(emit_t *emit, qstr qstr); void (*store_attr)(emit_t *emit, qstr qstr); - void (*store_locals)(emit_t *emit); void (*store_subscr)(emit_t *emit); + void (*store_locals)(emit_t *emit); void (*delete_fast)(emit_t *emit, qstr qstr, int local_num); void (*delete_name)(emit_t *emit, qstr qstr); void (*delete_global)(emit_t *emit, qstr qstr); diff --git a/py/emitbc.c b/py/emitbc.c index 81b059d1cb..d1ac74f0e9 100644 --- a/py/emitbc.c +++ b/py/emitbc.c @@ -348,16 +348,16 @@ static void emit_bc_store_attr(emit_t *emit, qstr qstr) { emit_write_byte_1_qstr(emit, PYBC_STORE_ATTR, qstr); } -static void emit_bc_store_locals(emit_t *emit) { - emit_pre(emit, -1); - emit_write_byte_1(emit, PYBC_STORE_LOCALS); -} - static void emit_bc_store_subscr(emit_t *emit) { emit_pre(emit, -3); emit_write_byte_1(emit, PYBC_STORE_SUBSCR); } +static void emit_bc_store_locals(emit_t *emit) { + // not needed for byte code + emit_pre(emit, -1); +} + static void emit_bc_delete_fast(emit_t *emit, qstr qstr, int local_num) { assert(local_num >= 0); emit_pre(emit, 0); @@ -718,8 +718,8 @@ const emit_method_table_t emit_bc_method_table = { emit_bc_store_global, emit_bc_store_deref, emit_bc_store_attr, - emit_bc_store_locals, emit_bc_store_subscr, + emit_bc_store_locals, emit_bc_delete_fast, emit_bc_delete_name, emit_bc_delete_global, diff --git a/py/emitcpy.c b/py/emitcpy.c index 203fce70a1..7c9615c09a 100644 --- a/py/emitcpy.c +++ b/py/emitcpy.c @@ -352,13 +352,6 @@ static void emit_cpy_store_attr(emit_t *emit, qstr qstr) { } } -static void emit_cpy_store_locals(emit_t *emit) { - emit_pre(emit, -1, 1); - if (emit->pass == PASS_3) { - printf("STORE_LOCALS\n"); - } -} - static void emit_cpy_store_subscr(emit_t *emit) { emit_pre(emit, -3, 1); if (emit->pass == PASS_3) { @@ -366,6 +359,13 @@ static void emit_cpy_store_subscr(emit_t *emit) { } } +static void emit_cpy_store_locals(emit_t *emit) { + emit_pre(emit, -1, 1); + if (emit->pass == PASS_3) { + printf("STORE_LOCALS\n"); + } +} + static void emit_cpy_delete_fast(emit_t *emit, qstr qstr, int local_num) { emit_pre(emit, 0, 3); if (emit->pass == PASS_3) { @@ -870,8 +870,8 @@ const emit_method_table_t emit_cpython_method_table = { emit_cpy_store_global, emit_cpy_store_deref, emit_cpy_store_attr, - emit_cpy_store_locals, emit_cpy_store_subscr, + emit_cpy_store_locals, emit_cpy_delete_fast, emit_cpy_delete_name, emit_cpy_delete_global, diff --git a/py/emitnative.c b/py/emitnative.c index 69022e142c..4c2f941e03 100644 --- a/py/emitnative.c +++ b/py/emitnative.c @@ -731,11 +731,6 @@ static void emit_native_store_attr(emit_t *emit, qstr qstr) { assert(0); } -static void emit_native_store_locals(emit_t *emit) { - // not supported - assert(0); -} - static void emit_native_store_subscr(emit_t *emit) { // depends on type of subject: // - integer, function, pointer to structure: error @@ -749,6 +744,13 @@ static void emit_native_store_subscr(emit_t *emit) { emit_call(emit, RT_F_STORE_SUBSCR, rt_store_subscr); } +static void emit_native_store_locals(emit_t *emit) { + // not needed + vtype_kind_t vtype; + emit_pre_pop_reg(emit, &vtype, REG_TEMP0); + emit_post(emit); +} + static void emit_native_delete_fast(emit_t *emit, qstr qstr, int local_num) { // not implemented // could support for Python types, just set to None (so GC can reclaim it) @@ -1146,8 +1148,8 @@ const emit_method_table_t EXPORT_FUN(method_table) = { emit_native_store_global, emit_native_store_deref, emit_native_store_attr, - emit_native_store_locals, emit_native_store_subscr, + emit_native_store_locals, emit_native_delete_fast, emit_native_delete_name, emit_native_delete_global, diff --git a/py/main.c b/py/main.c index cca52c4e73..2059a8fc48 100644 --- a/py/main.c +++ b/py/main.c @@ -33,7 +33,7 @@ int main(int argc, char **argv) { py_parse_node_t pn = py_parse(lex, 0); if (pn != PY_PARSE_NODE_NULL) { //printf("----------------\n"); - parse_node_show(pn, 0); + //parse_node_show(pn, 0); //printf("----------------\n"); py_compile(pn); //printf("----------------\n"); diff --git a/py/runtime.c b/py/runtime.c index 8403a75272..7e7164d4f0 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -9,8 +9,8 @@ #include "runtime.h" #include "vm.h" -//#define DEBUG_printf(args...) (void)0 -#define DEBUG_printf(args...) printf(args) +#define DEBUG_printf(args...) (void)0 +//#define DEBUG_printf(args...) printf(args) #define DEBUG_OP_printf(args...) (void)0 //#define DEBUG_OP_printf(args...) printf(args) @@ -46,6 +46,7 @@ typedef enum { O_SET, O_MAP, O_CLASS, + O_OBJ, } py_obj_kind_t; typedef enum { @@ -59,13 +60,15 @@ typedef struct _py_map_elem_t { } py_map_elem_t; typedef struct _py_map_t { - py_map_kind_t kind; + py_map_kind_t kind; // TODO merge this 1-bit field into alloc or used machine_uint_t alloc; machine_uint_t used; py_map_elem_t *table; } py_map_t; -typedef struct _py_obj_base_t { +typedef struct _py_obj_base_t py_obj_base_t; + +struct _py_obj_base_t { py_obj_kind_t kind; union { const char *id; @@ -101,24 +104,22 @@ typedef struct _py_obj_base_t { py_obj_t *table; } u_set; py_map_t u_map; // for O_MAP - /* - struct { // for O_MAP - int alloc; - int used; - py_map_elem_t *table; - } u_map; - */ struct { // for O_CLASS - py_map_t *map; + py_map_t *locals; } u_class; + struct { // for O_OBJ + py_obj_base_t *class; // points to a O_CLASS object + py_map_t *members; + } u_obj; }; -} py_obj_base_t; +}; py_obj_t py_const_none; py_obj_t py_const_false; py_obj_t py_const_true; -py_map_t map_name; +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}] @@ -334,10 +335,22 @@ py_obj_t py_builtin_len(py_obj_t o_in) { return TO_SMALL_INT(len); } -py_obj_t py_builtin___build_class__(py_obj_t o1, py_obj_t o2) { +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 *class_locals = py_map_new(MAP_QSTR, 0); + map_locals = *class_locals; + + // call the class code + rt_call_function_1(o_class_fun, (py_obj_t)0xdeadbeef); + + // restore old __locals__ object + map_locals = old_locals; + + // create and return the new class py_obj_base_t *o = m_new(py_obj_base_t, 1); o->kind = O_CLASS; - o->u_class.map = py_map_new(MAP_QSTR, 0); + o->u_class.locals = class_locals; return o; } @@ -353,7 +366,10 @@ void rt_init() { py_const_false = py_obj_new_const("False"); py_const_true = py_obj_new_const("True"); - py_map_init(&map_name, MAP_QSTR, 0); + 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__")); 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); @@ -446,6 +462,25 @@ void rt_assign_inline_asm_code(int unique_code_id, py_fun_t fun, uint len, int n } } +bool py_obj_is_callable(py_obj_t o_in) { + if (IS_SMALL_INT(o_in)) { + return false; + } else { + py_obj_base_t *o = o_in; + switch (o->kind) { + case O_FUN_0: + case O_FUN_1: + case O_FUN_2: + case O_FUN_N: + case O_FUN_BC: + case O_FUN_ASM: + return true; + default: + return false; + } + } +} + const char *py_obj_get_type_str(py_obj_t o_in) { if (IS_SMALL_INT(o_in)) { return "int"; @@ -476,6 +511,13 @@ const char *py_obj_get_type_str(py_obj_t o_in) { return "set"; case O_MAP: return "dict"; + case O_OBJ: + { + py_map_elem_t *qn = py_qstr_map_lookup(o->u_obj.class->u_class.locals, qstr_from_str_static("__qualname__"), false); + assert(qn != NULL); + assert(IS_O(qn->value, O_STR)); + return qstr_str(((py_obj_base_t*)qn->value)->u_str); + } default: assert(0); return "UnknownType"; @@ -546,6 +588,7 @@ void py_obj_print(py_obj_t o_in) { break; } default: + printf("", o->kind); assert(0); } } @@ -587,8 +630,25 @@ 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 %s\n", qstr_str(qstr)); - py_map_elem_t *elem = py_qstr_map_lookup(&map_name, qstr, false); + DEBUG_OP_printf("load name %s\n", qstr_str(qstr)); + 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); + if (elem == NULL) { + elem = py_qstr_map_lookup(&map_builtins, qstr, false); + if (elem == NULL) { + printf("name doesn't exist: %s\n", qstr_str(qstr)); + assert(0); + } + } + } + return elem->value; +} + +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); if (elem == NULL) { elem = py_qstr_map_lookup(&map_builtins, qstr, false); if (elem == NULL) { @@ -599,10 +659,6 @@ py_obj_t rt_load_name(qstr qstr) { return elem->value; } -py_obj_t rt_load_global(qstr qstr) { - return rt_load_name(qstr); // TODO -} - py_obj_t rt_load_build_class() { DEBUG_OP_printf("load_build_class\n"); py_map_elem_t *elem = py_qstr_map_lookup(&map_builtins, q___build_class__, false); @@ -614,8 +670,13 @@ py_obj_t rt_load_build_class() { } void rt_store_name(qstr qstr, py_obj_t obj) { - DEBUG_OP_printf("store %s <- %p\n", qstr_str(qstr), obj); - py_qstr_map_lookup(&map_name, qstr, true)->value = obj; + DEBUG_OP_printf("store name %s <- %p\n", qstr_str(qstr), 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_obj_t rt_unary_op(int op, py_obj_t arg) { @@ -803,6 +864,18 @@ py_obj_t rt_call_function_0(py_obj_t 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)()); + } 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); + } else if (IS_O(fun, O_CLASS)) { + // instantiate an instance of a class + 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); @@ -817,7 +890,10 @@ py_obj_t rt_call_function_1(py_obj_t fun, py_obj_t arg) { return ((py_fun_1_t)o->u_fun.fun)(arg); } else if (IS_O(fun, O_FUN_BC)) { py_obj_base_t *o = fun; - assert(o->u_fun_bc.n_args == 1); + 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)) { @@ -845,8 +921,8 @@ py_obj_t rt_call_function_2(py_obj_t fun, py_obj_t arg1, py_obj_t arg2) { 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[0] = arg1; - args[1] = arg2; + 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; @@ -859,6 +935,19 @@ py_obj_t rt_call_function_2(py_obj_t fun, py_obj_t arg1, py_obj_t arg2) { } } +// 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_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 %p\n", fun, self); if (self == NULL) { @@ -877,6 +966,13 @@ py_obj_t rt_call_method_2(py_obj_t fun, py_obj_t self, py_obj_t arg) { } } +// args contains: arg(n_args-1) arg(n_args-2) ... arg(0) self/NULL fun +// if n_args==0 then there are only self/NULL and fun +py_obj_t rt_call_method_n(int n_args, const py_obj_t *args) { + DEBUG_OP_printf("call method %p %p %d args\n", args[n_args + 1], args[n_args] , n_args); + return rt_call_function_n(args[n_args + 1], n_args + ((args[n_args] == NULL) ? 0 : 1), args); +} + // items are in reverse order py_obj_t rt_build_list(int n_args, py_obj_t *items) { py_obj_base_t *o = m_new(py_obj_base_t, 1); @@ -964,6 +1060,107 @@ py_obj_t rt_store_map(py_obj_t map, py_obj_t key, py_obj_t value) { return map; } +py_obj_t build_bound_method(py_obj_t self, py_obj_t meth) { + py_obj_base_t *o = m_new(py_obj_base_t, 1); + o->kind = O_BOUND_METH; + o->u_bound_meth.meth = meth; + o->u_bound_meth.self = self; + return o; +} + +py_obj_t rt_load_attr(py_obj_t base, qstr attr) { + DEBUG_OP_printf("load attr %s\n", qstr_str(attr)); + if (IS_O(base, O_LIST) && attr == q_append) { + return build_bound_method(base, fun_list_append); + } else if (IS_O(base, O_CLASS)) { + py_obj_base_t *o = base; + py_map_elem_t *elem = py_qstr_map_lookup(o->u_class.locals, attr, false); + if (elem == NULL) { + goto no_attr; + } + return elem->value; + } else if (IS_O(base, O_OBJ)) { + // logic: look in obj members then class locals (TODO check this against CPython) + py_obj_base_t *o = base; + py_map_elem_t *elem = py_qstr_map_lookup(o->u_obj.members, attr, false); + if (elem != NULL) { + // object member, always treated as a value + return elem->value; + } + elem = py_qstr_map_lookup(o->u_obj.class->u_class.locals, attr, false); + if (elem != NULL) { + if (py_obj_is_callable(elem->value)) { + // class member is callable so build a bound method + return build_bound_method(base, elem->value); + } else { + // class member is a value, so just return that value + return elem->value; + } + } + goto no_attr; + } + +no_attr: + printf("AttributeError: '%s' object has no attribute '%s'\n", py_obj_get_type_str(base), qstr_str(attr)); + assert(0); + return py_const_none; +} + +void rt_load_method(py_obj_t base, qstr attr, py_obj_t *dest) { + DEBUG_OP_printf("load method %s\n", qstr_str(attr)); + if (IS_O(base, O_LIST) && attr == q_append) { + dest[1] = fun_list_append; + dest[0] = base; + return; + } else if (IS_O(base, O_OBJ)) { + // logic: look in obj members then class locals (TODO check this against CPython) + py_obj_base_t *o = base; + py_map_elem_t *elem = py_qstr_map_lookup(o->u_obj.members, attr, false); + if (elem != NULL) { + // object member, always treated as a value + dest[1] = elem->value; + dest[0] = NULL; + return; + } + elem = py_qstr_map_lookup(o->u_obj.class->u_class.locals, attr, false); + if (elem != NULL) { + if (py_obj_is_callable(elem->value)) { + // class member is callable so build a bound method + dest[1] = elem->value; + dest[0] = base; + return; + } else { + // class member is a value, so just return that value + dest[1] = elem->value; + dest[0] = NULL; + return; + } + } + goto no_attr; + } + +no_attr: + dest[1] = rt_load_attr(base, attr); + dest[0] = NULL; +} + +void rt_store_attr(py_obj_t base, qstr attr, py_obj_t val) { + DEBUG_OP_printf("store attr %p.%s <- %p\n", base, qstr_str(attr), val); + if (IS_O(base, O_OBJ)) { + // logic: look in class locals (no add) then obj members (add) (TODO check this against CPython) + py_obj_base_t *o = base; + py_map_elem_t *elem = py_qstr_map_lookup(o->u_obj.class->u_class.locals, attr, false); + if (elem != NULL) { + elem->value = val; + } else { + elem = py_qstr_map_lookup(o->u_obj.class->u_class.locals, attr, true)->value = val; + } + } else { + printf("?AttributeError: '%s' object has no attribute '%s'\n", py_obj_get_type_str(base), qstr_str(attr)); + assert(0); + } +} + void rt_store_subscr(py_obj_t base, py_obj_t index, py_obj_t value) { if (IS_O(base, O_LIST) && IS_SMALL_INT(index)) { // list store @@ -985,44 +1182,6 @@ void rt_store_subscr(py_obj_t base, py_obj_t index, py_obj_t value) { } } -py_obj_t build_bound_method(py_obj_t self, py_obj_t meth) { - py_obj_base_t *o = m_new(py_obj_base_t, 1); - o->kind = O_BOUND_METH; - o->u_bound_meth.meth = meth; - o->u_bound_meth.self = self; - return o; -} - -py_obj_t rt_load_attr(py_obj_t base, qstr attr) { - DEBUG_OP_printf("load %s\n", qstr_str(attr)); - if (IS_O(base, O_LIST) && attr == q_append) { - return build_bound_method(base, fun_list_append); - } else if (IS_O(base, O_CLASS)) { - py_obj_base_t *o = base; - py_map_elem_t *elem = py_qstr_map_lookup(o->u_class.map, attr, false); - if (elem == NULL) { - printf("Nope! %s\n", qstr_str(attr)); - assert(0); - } - return elem->value; - } else { - printf("AttributeError: '%s' object has no attribute '%s'\n", py_obj_get_type_str(base), qstr_str(attr)); - assert(0); - return py_const_none; - } -} - -void rt_load_method(py_obj_t base, qstr attr, py_obj_t *dest) { - DEBUG_OP_printf("load method %s\n", qstr_str(attr)); - if (IS_O(base, O_LIST) && attr == q_append) { - dest[1] = fun_list_append; - dest[0] = base; - } else { - dest[1] = rt_load_attr(base, attr); - dest[0] = NULL; - } -} - void *rt_fun_table[RT_F_NUMBER_OF] = { rt_load_const_str, rt_load_name, diff --git a/py/runtime.h b/py/runtime.h index 72d589231c..d72182cb39 100644 --- a/py/runtime.h +++ b/py/runtime.h @@ -100,6 +100,7 @@ py_obj_t rt_load_name(qstr qstr); py_obj_t rt_load_global(qstr qstr); py_obj_t rt_load_build_class(); void rt_store_name(qstr qstr, py_obj_t obj); +void rt_store_global(qstr qstr, py_obj_t obj); py_obj_t rt_unary_op(int op, py_obj_t arg); py_obj_t rt_binary_op(int op, py_obj_t lhs, py_obj_t rhs); py_obj_t rt_compare_op(int op, py_obj_t lhs, py_obj_t rhs); @@ -113,10 +114,12 @@ py_obj_t rt_call_function_1(py_obj_t fun, py_obj_t arg); py_obj_t rt_call_function_2(py_obj_t fun, py_obj_t arg1, py_obj_t arg2); py_obj_t rt_call_method_1(py_obj_t fun, py_obj_t self); py_obj_t rt_call_method_2(py_obj_t fun, py_obj_t self, py_obj_t arg); +py_obj_t rt_call_method_n(int n_args, const py_obj_t *args); py_obj_t rt_build_list(int n_args, py_obj_t *items); py_obj_t rt_build_map(int n_args); py_obj_t rt_store_map(py_obj_t map, py_obj_t key, py_obj_t value); py_obj_t rt_build_set(int n_args, py_obj_t *items); -void rt_store_subscr(py_obj_t base, py_obj_t index, py_obj_t val); py_obj_t rt_load_attr(py_obj_t base, qstr attr); void rt_load_method(py_obj_t base, qstr attr, py_obj_t *dest); +void rt_store_attr(py_obj_t base, qstr attr, py_obj_t val); +void rt_store_subscr(py_obj_t base, py_obj_t index, py_obj_t val); diff --git a/py/vm.c b/py/vm.c index 63a478fcf3..ac76089a16 100644 --- a/py/vm.c +++ b/py/vm.c @@ -14,8 +14,9 @@ #define PUSH(val) *--sp = (val) #define POP() (*sp++) -py_obj_t py_execute_byte_code(byte *code, uint len, py_obj_t *args, uint n_args) { - byte *ip = code; +// args are in reverse order in array +py_obj_t py_execute_byte_code(const byte *code, uint len, const py_obj_t *args, uint n_args) { + const byte *ip = code; py_obj_t stack[10]; py_obj_t *sp = &stack[10]; // stack grows down, sp points to top of stack machine_uint_t unum; @@ -27,14 +28,14 @@ py_obj_t py_execute_byte_code(byte *code, uint len, py_obj_t *args, uint n_args) // init args for (int i = 0; i < n_args; i++) { if (i == 0) { - fast0 = args[0]; + fast0 = args[n_args - 1]; } else if (i == 1) { - fast1 = args[1]; + fast1 = args[n_args - 2]; } else if (i == 2) { - fast2 = args[2]; + fast2 = args[n_args - 3]; } else { assert(i - 3 < 4); - fastn[i - 3] = args[i]; + fastn[i - 3] = args[n_args - 1 - i]; } } @@ -137,6 +138,12 @@ py_obj_t py_execute_byte_code(byte *code, uint len, py_obj_t *args, uint n_args) rt_store_name(qstr, POP()); break; + case PYBC_STORE_ATTR: + DECODE_QSTR; + rt_store_attr(sp[0], qstr, sp[1]); + sp += 2; + break; + case PYBC_STORE_SUBSCR: rt_store_subscr(sp[1], sp[0], sp[2]); sp += 3; @@ -254,9 +261,12 @@ py_obj_t py_execute_byte_code(byte *code, uint len, py_obj_t *args, uint n_args) } else if ((unum & 0xff) == 1) { obj2 = *sp++; // the first argument obj1 = *sp++; // the self object (or NULL) - *sp = rt_call_function_2(*sp, obj1, obj2); + *sp = rt_call_method_2(*sp, obj1, obj2); } else { - assert(0); + unum = unum & 0xff; + obj1 = rt_call_method_n(unum, sp); + sp += unum + 1; + *sp = obj1; } break; diff --git a/py/vm.h b/py/vm.h index f09843a960..1a5bcd9b35 100644 --- a/py/vm.h +++ b/py/vm.h @@ -25,8 +25,7 @@ #define PYBC_STORE_NAME (0x34) // qstr #define PYBC_STORE_GLOBAL (0x35) // qstr #define PYBC_STORE_ATTR (0x36) // qstr -#define PYBC_STORE_LOCALS (0x37) -#define PYBC_STORE_SUBSCR (0x38) +#define PYBC_STORE_SUBSCR (0x37) #define PYBC_DELETE_FAST_N (0x39) // uint #define PYBC_DELETE_NAME (0x3a) // qstr @@ -94,4 +93,4 @@ #define PYBC_IMPORT_FROM (0xe1) #define PYBC_IMPORT_STAR (0xe2) -py_obj_t py_execute_byte_code(byte *code, uint len, py_obj_t *args, uint n_args); +py_obj_t py_execute_byte_code(const byte *code, uint len, const py_obj_t *args, uint n_args);