From e6c0dff9671c493e9a13a22a1b8902dee88da064 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 15 Aug 2014 23:47:59 +0100 Subject: [PATCH] py: Viper can now store to global. --- py/emitnative.c | 20 +++++++++++++++----- py/objfun.c | 30 ++++-------------------------- py/runtime.c | 27 +++++++++++++++++++++++++++ py/runtime.h | 3 +++ py/runtime0.h | 5 ++++- tests/micropython/viper.py | 8 ++++++++ tests/micropython/viper.py.exp | 1 + 7 files changed, 62 insertions(+), 32 deletions(-) diff --git a/py/emitnative.c b/py/emitnative.c index eb5b6b1f4b..4966e37e30 100644 --- a/py/emitnative.c +++ b/py/emitnative.c @@ -903,8 +903,16 @@ STATIC void emit_native_store_name(emit_t *emit, qstr qstr) { } STATIC void emit_native_store_global(emit_t *emit, qstr qstr) { - // not implemented - assert(0); + vtype_kind_t vtype = peek_vtype(emit); + if (vtype == VTYPE_PYOBJ) { + emit_pre_pop_reg(emit, &vtype, REG_ARG_2); + } else { + emit_pre_pop_reg(emit, &vtype, REG_ARG_1); + emit_call_with_imm_arg(emit, MP_F_CONVERT_NATIVE_TO_OBJ, mp_convert_native_to_obj, vtype, REG_ARG_2); // arg2 = type + ASM_MOV_REG_TO_REG(REG_RET, REG_ARG_2); + } + emit_call_with_imm_arg(emit, MP_F_STORE_GLOBAL, mp_store_global, qstr, REG_ARG_1); // arg1 = name + emit_post(emit); } STATIC void emit_native_store_attr(emit_t *emit, qstr qstr) { @@ -1420,12 +1428,14 @@ STATIC void emit_native_call_method(emit_t *emit, int n_positional, int n_keywor STATIC void emit_native_return_value(emit_t *emit) { DEBUG_printf("return_value\n"); - // easy. since we don't know who we return to, just return the raw value. - // runtime needs then to know our type signature, but I think that's possible. vtype_kind_t vtype; emit_pre_pop_reg(emit, &vtype, REG_RET); if (emit->do_viper_types) { - if (vtype != emit->return_vtype) { + if (vtype == VTYPE_PTR_NONE) { + if (emit->return_vtype == VTYPE_PYOBJ) { + ASM_MOV_IMM_TO_REG((mp_uint_t)mp_const_none, REG_RET); + } + } else if (vtype != emit->return_vtype) { printf("ViperTypeError: incompatible return type\n"); } } else { diff --git a/py/objfun.c b/py/objfun.c index 83e5ade5db..63dbd4f15e 100644 --- a/py/objfun.c +++ b/py/objfun.c @@ -517,28 +517,6 @@ typedef mp_uint_t (*viper_fun_1_t)(mp_uint_t); typedef mp_uint_t (*viper_fun_2_t)(mp_uint_t, mp_uint_t); typedef mp_uint_t (*viper_fun_3_t)(mp_uint_t, mp_uint_t, mp_uint_t); -// convert a Micro Python object to a valid value for viper, based on wanted type -STATIC mp_uint_t convert_obj_for_viper(mp_obj_t obj, mp_uint_t type) { - switch (type & 3) { - case MP_NATIVE_TYPE_OBJ: return (mp_uint_t)obj; - case MP_NATIVE_TYPE_BOOL: - case MP_NATIVE_TYPE_INT: - case MP_NATIVE_TYPE_UINT: return mp_obj_get_int(obj); - default: assert(0); return 0; - } -} - -// convert a return value from viper to a Micro Python object based on viper return type -STATIC mp_obj_t convert_val_from_viper(mp_uint_t val, mp_uint_t type) { - switch (type & 3) { - case MP_NATIVE_TYPE_OBJ: return (mp_obj_t)val; - case MP_NATIVE_TYPE_BOOL: return MP_BOOL(val); - case MP_NATIVE_TYPE_INT: return mp_obj_new_int(val); - case MP_NATIVE_TYPE_UINT: return mp_obj_new_int_from_uint(val); - default: assert(0); return mp_const_none; - } -} - STATIC mp_obj_t fun_viper_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *args) { mp_obj_fun_viper_t *self = self_in; @@ -548,17 +526,17 @@ STATIC mp_obj_t fun_viper_call(mp_obj_t self_in, uint n_args, uint n_kw, const m if (n_args == 0) { ret = ((viper_fun_0_t)self->fun)(); } else if (n_args == 1) { - ret = ((viper_fun_1_t)self->fun)(convert_obj_for_viper(args[0], self->type_sig >> 2)); + ret = ((viper_fun_1_t)self->fun)(mp_convert_obj_to_native(args[0], self->type_sig >> 2)); } else if (n_args == 2) { - ret = ((viper_fun_2_t)self->fun)(convert_obj_for_viper(args[0], self->type_sig >> 2), convert_obj_for_viper(args[1], self->type_sig >> 4)); + ret = ((viper_fun_2_t)self->fun)(mp_convert_obj_to_native(args[0], self->type_sig >> 2), mp_convert_obj_to_native(args[1], self->type_sig >> 4)); } else if (n_args == 3) { - ret = ((viper_fun_3_t)self->fun)(convert_obj_for_viper(args[0], self->type_sig >> 2), convert_obj_for_viper(args[1], self->type_sig >> 4), convert_obj_for_viper(args[2], self->type_sig >> 6)); + ret = ((viper_fun_3_t)self->fun)(mp_convert_obj_to_native(args[0], self->type_sig >> 2), mp_convert_obj_to_native(args[1], self->type_sig >> 4), mp_convert_obj_to_native(args[2], self->type_sig >> 6)); } else { assert(0); ret = 0; } - return convert_val_from_viper(ret, self->type_sig); + return mp_convert_native_to_obj(ret, self->type_sig); } STATIC const mp_obj_type_t mp_type_fun_viper = { diff --git a/py/runtime.c b/py/runtime.c index 59e47c7ff7..f233a772c0 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -1163,8 +1163,34 @@ NORETURN void mp_not_implemented(const char *msg) { nlr_raise(mp_obj_new_exception_msg(&mp_type_NotImplementedError, msg)); } +// convert a Micro Python object to a valid native value based on type +mp_uint_t mp_convert_obj_to_native(mp_obj_t obj, mp_uint_t type) { + DEBUG_printf("mp_convert_obj_to_native(%p, " UINT_FMT ")\n", obj, type); + switch (type & 3) { + case MP_NATIVE_TYPE_OBJ: return (mp_uint_t)obj; + case MP_NATIVE_TYPE_BOOL: + case MP_NATIVE_TYPE_INT: + case MP_NATIVE_TYPE_UINT: return mp_obj_get_int(obj); + default: assert(0); return 0; + } +} + +// convert a native value to a Micro Python object based on type +mp_obj_t mp_convert_native_to_obj(mp_uint_t val, mp_uint_t type) { + DEBUG_printf("mp_convert_native_to_obj(" UINT_FMT ", " UINT_FMT ")\n", val, type); + switch (type & 3) { + case MP_NATIVE_TYPE_OBJ: return (mp_obj_t)val; + case MP_NATIVE_TYPE_BOOL: return MP_BOOL(val); + case MP_NATIVE_TYPE_INT: return mp_obj_new_int(val); + case MP_NATIVE_TYPE_UINT: return mp_obj_new_int_from_uint(val); + default: assert(0); return mp_const_none; + } +} + // these must correspond to the respective enum void *const mp_fun_table[MP_F_NUMBER_OF] = { + mp_convert_obj_to_native, + mp_convert_native_to_obj, mp_load_const_int, mp_load_const_dec, mp_load_const_str, @@ -1174,6 +1200,7 @@ void *const mp_fun_table[MP_F_NUMBER_OF] = { mp_load_attr, mp_load_method, mp_store_name, + mp_store_global, mp_store_attr, mp_obj_subscr, mp_obj_is_true, diff --git a/py/runtime.h b/py/runtime.h index 2feb24de97..f908d9d26d 100644 --- a/py/runtime.h +++ b/py/runtime.h @@ -115,6 +115,9 @@ void mp_import_all(mp_obj_t module); // Raise NotImplementedError with given message NORETURN void mp_not_implemented(const char *msg); +mp_uint_t mp_convert_obj_to_native(mp_obj_t obj, mp_uint_t type); +mp_obj_t mp_convert_native_to_obj(mp_uint_t val, mp_uint_t type); + extern struct _mp_obj_list_t mp_sys_path_obj; extern struct _mp_obj_list_t mp_sys_argv_obj; #define mp_sys_path ((mp_obj_t)&mp_sys_path_obj) diff --git a/py/runtime0.h b/py/runtime0.h index 01504f59cf..dfce041b8f 100644 --- a/py/runtime0.h +++ b/py/runtime0.h @@ -102,7 +102,9 @@ typedef enum { } mp_binary_op_t; typedef enum { - MP_F_LOAD_CONST_INT = 0, + MP_F_CONVERT_OBJ_TO_NATIVE = 0, + MP_F_CONVERT_NATIVE_TO_OBJ, + MP_F_LOAD_CONST_INT, MP_F_LOAD_CONST_DEC, MP_F_LOAD_CONST_STR, MP_F_LOAD_NAME, @@ -111,6 +113,7 @@ typedef enum { MP_F_LOAD_ATTR, MP_F_LOAD_METHOD, MP_F_STORE_NAME, + MP_F_STORE_GLOBAL, MP_F_STORE_ATTR, MP_F_OBJ_SUBSCR, MP_F_OBJ_IS_TRUE, diff --git a/tests/micropython/viper.py b/tests/micropython/viper.py index 2ed70ade60..36849abafd 100644 --- a/tests/micropython/viper.py +++ b/tests/micropython/viper.py @@ -29,6 +29,13 @@ def viper_sum(a:int, b:int) -> int: total += x return total +# accessing a global +@micropython.viper +def access_global(): + global gl + gl = 1 + return gl + # this doesn't work at the moment #@micropython.viper #def g() -> uint: @@ -39,3 +46,4 @@ print(g(1, 2)) print(h(3)) print(i(4, 5)) print(viper_sum(10, 10000)) +print(access_global(), gl) diff --git a/tests/micropython/viper.py.exp b/tests/micropython/viper.py.exp index 6ee698f66a..4c308316b2 100644 --- a/tests/micropython/viper.py.exp +++ b/tests/micropython/viper.py.exp @@ -3,3 +3,4 @@ 7 20 49994955 +1 1