summaryrefslogtreecommitdiffstatshomepage
path: root/py/vm.c
diff options
context:
space:
mode:
authorDamien George <damien.p.george@gmail.com>2014-04-09 15:26:46 +0100
committerDamien George <damien.p.george@gmail.com>2014-04-09 15:26:46 +0100
commit2bf7c092225645d8c5b15e536afdce39e3593e42 (patch)
treee257514a3008411367ea5e62eaea4b101ccac257 /py/vm.c
parent11d8cd54c992eee55f27d3779738626bdc095c03 (diff)
downloadmicropython-2bf7c092225645d8c5b15e536afdce39e3593e42.tar.gz
micropython-2bf7c092225645d8c5b15e536afdce39e3593e42.zip
py: Properly implement deletion of locals and derefs, and detect errors.
Needed to reinstate 2 delete opcodes, to specifically check that a local is not deleted twice.
Diffstat (limited to 'py/vm.c')
-rw-r--r--py/vm.c32
1 files changed, 31 insertions, 1 deletions
diff --git a/py/vm.c b/py/vm.c
index 170104467c..f8b60acd22 100644
--- a/py/vm.c
+++ b/py/vm.c
@@ -241,9 +241,23 @@ dispatch_loop:
PUSH(fastn[-unum]);
break;
+ case MP_BC_LOAD_FAST_CHECKED:
+ DECODE_UINT;
+ obj1 = fastn[-unum];
+ if (obj1 == MP_OBJ_NULL) {
+ local_name_error:
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_NameError, "local variable referenced before assignment"));
+ }
+ PUSH(obj1);
+ break;
+
case MP_BC_LOAD_DEREF:
DECODE_UINT;
- PUSH(mp_obj_cell_get(fastn[-unum]));
+ obj1 = mp_obj_cell_get(fastn[-unum]);
+ if (obj1 == MP_OBJ_NULL) {
+ goto local_name_error;
+ }
+ PUSH(obj1);
break;
case MP_BC_LOAD_NAME:
@@ -314,6 +328,22 @@ dispatch_loop:
sp -= 3;
break;
+ case MP_BC_DELETE_FAST:
+ DECODE_UINT;
+ if (fastn[-unum] == MP_OBJ_NULL) {
+ goto local_name_error;
+ }
+ fastn[-unum] = MP_OBJ_NULL;
+ break;
+
+ case MP_BC_DELETE_DEREF:
+ DECODE_UINT;
+ if (mp_obj_cell_get(fastn[-unum]) == MP_OBJ_NULL) {
+ goto local_name_error;
+ }
+ mp_obj_cell_set(fastn[-unum], MP_OBJ_NULL);
+ break;
+
case MP_BC_DELETE_NAME:
DECODE_QSTR;
mp_delete_name(qst);