summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorDamien George <damien.p.george@gmail.com>2014-08-15 22:39:08 +0100
committerDamien George <damien.p.george@gmail.com>2014-08-15 22:39:08 +0100
commita5190a7dac7a73e676d6d649035f846ea92d2d2d (patch)
tree92d64dc58f1515327ae484129a66847f669c6757
parent2ac4af6946543ae96cf3659468e1b8cabb057f85 (diff)
downloadmicropython-a5190a7dac7a73e676d6d649035f846ea92d2d2d.tar.gz
micropython-a5190a7dac7a73e676d6d649035f846ea92d2d2d.zip
py: Fix typing of viper locals; allow default types in annotation.
-rw-r--r--py/compile.c25
-rw-r--r--py/emitnative.c16
-rw-r--r--tests/micropython/viper.py23
-rw-r--r--tests/micropython/viper.py.exp3
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