From a5190a7dac7a73e676d6d649035f846ea92d2d2d Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 15 Aug 2014 22:39:08 +0100 Subject: [PATCH] py: Fix typing of viper locals; allow default types in annotation. --- py/compile.c | 25 ++++++++++++++----------- py/emitnative.c | 16 +++++++++++----- tests/micropython/viper.py | 23 ++++++++++++++++++++++- tests/micropython/viper.py.exp | 3 +++ 4 files changed, 50 insertions(+), 17 deletions(-) diff --git a/py/compile.c b/py/compile.c index eb9cf9a948..10bfb1f3cd 100644 --- a/py/compile.c +++ b/py/compile.c @@ -3017,7 +3017,7 @@ STATIC void compile_scope_func_annotations(compiler_t *comp, mp_parse_node_t pn) qstr arg_type = MP_PARSE_NODE_LEAF_ARG(pn_annotation); EMIT_ARG(set_native_type, MP_EMIT_NATIVE_TYPE_ARG, id_info->local_num, arg_type); } else { - compile_syntax_error(comp, pn_annotation, "annotation must be an identifier"); + compile_syntax_error(comp, pn_annotation, "parameter annotation must be an identifier"); } } #endif // MICROPY_EMIT_NATIVE @@ -3155,17 +3155,20 @@ STATIC void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) { apply_to_single_or_list(comp, pns->nodes[1], PN_typedargslist, compile_scope_func_annotations); // pns->nodes[2] is return/whole function annotation - #if MICROPY_EMIT_NATIVE - if (scope->emit_options == MP_EMIT_OPT_VIPER) { - // nodes[2] can be null or a test-expr - if (MP_PARSE_NODE_IS_ID(pns->nodes[2])) { - qstr ret_type = MP_PARSE_NODE_LEAF_ARG(pns->nodes[2]); - EMIT_ARG(set_native_type, MP_EMIT_NATIVE_TYPE_RETURN, 0, ret_type); - } else { - compile_syntax_error(comp, pns->nodes[2], "annotation must be an identifier"); + mp_parse_node_t pn_annotation = pns->nodes[2]; + if (!MP_PARSE_NODE_IS_NULL(pn_annotation)) { + #if MICROPY_EMIT_NATIVE + if (scope->emit_options == MP_EMIT_OPT_VIPER) { + // nodes[2] can be null or a test-expr + if (MP_PARSE_NODE_IS_ID(pn_annotation)) { + qstr ret_type = MP_PARSE_NODE_LEAF_ARG(pn_annotation); + EMIT_ARG(set_native_type, MP_EMIT_NATIVE_TYPE_RETURN, 0, ret_type); + } else { + compile_syntax_error(comp, pn_annotation, "return annotation must be an identifier"); + } } + #endif // MICROPY_EMIT_NATIVE } - #endif // MICROPY_EMIT_NATIVE } compile_node(comp, pns->nodes[3]); // 3 is function body @@ -3625,7 +3628,7 @@ mp_obj_t mp_compile(mp_parse_node_t pn, qstr source_file, uint emit_opt, bool is comp->emit_method_table = &emit_native_thumb_method_table; #endif comp->emit = emit_native; - comp->emit_method_table->set_native_type(comp->emit, MP_EMIT_NATIVE_TYPE_ENABLE, s->emit_options == MP_EMIT_OPT_VIPER, 0); + EMIT_ARG(set_native_type, MP_EMIT_NATIVE_TYPE_ENABLE, s->emit_options == MP_EMIT_OPT_VIPER, 0); // native emitters need an extra pass to compute stack size compile_scope(comp, s, MP_PASS_STACK_SIZE); diff --git a/py/emitnative.c b/py/emitnative.c index 7f3c73c2e4..eb5b6b1f4b 100644 --- a/py/emitnative.c +++ b/py/emitnative.c @@ -241,12 +241,19 @@ STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop // set default type for return and arguments emit->return_vtype = VTYPE_PYOBJ; - for (int i = 0; i < emit->local_vtype_alloc; i++) { + for (mp_uint_t i = 0; i < emit->scope->num_pos_args; i++) { emit->local_vtype[i] = VTYPE_PYOBJ; } - for (int i = 0; i < emit->stack_info_alloc; i++) { + + // local variables begin unbound, and have unknown type + for (mp_uint_t i = emit->scope->num_pos_args; i < emit->local_vtype_alloc; i++) { + emit->local_vtype[i] = VTYPE_UNBOUND; + } + + // values on stack begin unbound + for (mp_uint_t i = 0; i < emit->stack_info_alloc; i++) { emit->stack_info[i].kind = STACK_VALUE; - emit->stack_info[i].vtype = VTYPE_PYOBJ; + emit->stack_info[i].vtype = VTYPE_UNBOUND; } #if N_X64 @@ -844,7 +851,6 @@ STATIC void emit_native_load_subscr(emit_t *emit) { emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); } else { printf("ViperTypeError: can't do subscr of types %d and %d\n", vtype_lhs, vtype_rhs); - assert(0); } } @@ -1212,7 +1218,7 @@ STATIC void emit_native_binary_op(emit_t *emit, mp_binary_op_t op) { emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); } else { printf("ViperTypeError: can't do binary op between types %d and %d\n", vtype_lhs, vtype_rhs); - assert(0); + emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); } } diff --git a/tests/micropython/viper.py b/tests/micropython/viper.py index e1c04784df..2ed70ade60 100644 --- a/tests/micropython/viper.py +++ b/tests/micropython/viper.py @@ -10,6 +10,25 @@ def f(x:int, y:int) -> int: def g(x:object, y:object) -> object: return x + y +# a local (should have automatic type int) +@micropython.viper +def h(x:int) -> int: + y = 4 + return x + y + +# without type annotation, types should default to object +@micropython.viper +def i(x, y): + return x * y + +# a for loop +@micropython.viper +def viper_sum(a:int, b:int) -> int: + total = 0 + for x in range(a, b): + total += x + return total + # this doesn't work at the moment #@micropython.viper #def g() -> uint: @@ -17,4 +36,6 @@ def g(x:object, y:object) -> object: print(f(1, 2)) print(g(1, 2)) -#print(h()) +print(h(3)) +print(i(4, 5)) +print(viper_sum(10, 10000)) diff --git a/tests/micropython/viper.py.exp b/tests/micropython/viper.py.exp index 7ea2ad9b22..6ee698f66a 100644 --- a/tests/micropython/viper.py.exp +++ b/tests/micropython/viper.py.exp @@ -1,2 +1,5 @@ 6 3 +7 +20 +49994955