@@ -1005,21 +1005,45 @@ func do_DELETE_FAST(vm *Vm, var_num int32) {
1005
1005
}
1006
1006
}
1007
1007
1008
+ // Name of slot for LOAD_CLOSURE / LOAD_DEREF / etc
1009
+ //
1010
+ // Returns name of variable and bool, true for free var, false for
1011
+ // cell var
1012
+ func _var_name (vm * Vm , i int32 ) (string , bool ) {
1013
+ cellvars := vm .frame .Code .Cellvars
1014
+ if int (i ) < len (cellvars ) {
1015
+ return cellvars [i ], false
1016
+ }
1017
+ return vm .frame .Code .Freevars [int (i )- len (cellvars )], true
1018
+ }
1019
+
1008
1020
// Pushes a reference to the cell contained in slot i of the cell and
1009
1021
// free variable storage. The name of the variable is co_cellvars[i]
1010
1022
// if i is less than the length of co_cellvars. Otherwise it is
1011
1023
// co_freevars[i - len(co_cellvars)].
1012
1024
func do_LOAD_CLOSURE (vm * Vm , i int32 ) {
1013
1025
defer vm .CheckException ()
1014
- vm .NotImplemented ("LOAD_CLOSURE" , i )
1026
+ varname , _ := _var_name (vm , i )
1027
+ // FIXME this is making a new cell each time rather than
1028
+ // returning a reference to an old one
1029
+ vm .PUSH (py .NewCell (vm .frame .Locals [varname ]))
1015
1030
}
1016
1031
1017
1032
// Loads the cell contained in slot i of the cell and free variable
1018
1033
// storage. Pushes a reference to the object the cell contains on the
1019
1034
// stack.
1020
1035
func do_LOAD_DEREF (vm * Vm , i int32 ) {
1021
1036
defer vm .CheckException ()
1022
- vm .NotImplemented ("LOAD_DEREF" , i )
1037
+ res := vm .frame .Closure [i ].(* py.Cell ).Get ()
1038
+ if res == nil {
1039
+ varname , free := _var_name (vm , i )
1040
+ if free {
1041
+ vm .SetException (py .ExceptionNewf (py .UnboundLocalError , unboundFreeErrorMsg , varname ))
1042
+ } else {
1043
+ vm .SetException (py .ExceptionNewf (py .UnboundLocalError , unboundLocalErrorMsg , varname ))
1044
+ }
1045
+ }
1046
+ vm .PUSH (res )
1023
1047
}
1024
1048
1025
1049
// Much like LOAD_DEREF but first checks the locals dictionary before
@@ -1111,24 +1135,18 @@ func do_CALL_FUNCTION(vm *Vm, argc int32) {
1111
1135
vm .Call (fn , args , kwargs )
1112
1136
}
1113
1137
1114
- // Pushes a new function object on the stack. TOS is the code
1115
- // associated with the function. The function object is defined to
1116
- // have argc default parameters, which are found below TOS.
1117
- //
1118
- // FIXME these docs are slightly wrong.
1119
- func do_MAKE_FUNCTION (vm * Vm , argc int32 ) {
1120
- defer vm .CheckException ()
1138
+ // Implementation for MAKE_FUNCTION and MAKE_CLOSURE
1139
+ func _make_function (vm * Vm , argc int32 , opcode byte ) {
1121
1140
posdefaults := argc & 0xff
1122
1141
kwdefaults := (argc >> 8 ) & 0xff
1123
1142
num_annotations := (argc >> 16 ) & 0x7fff
1124
1143
qualname := vm .POP ()
1125
1144
code := vm .POP ()
1126
1145
function := py .NewFunction (code .(* py.Code ), vm .frame .Globals , string (qualname .(py.String )))
1127
1146
1128
- // FIXME share code with MAKE_CLOSURE
1129
- // if opcode == MAKE_CLOSURE {
1130
- // function.Closure = vm.POP();
1131
- // }
1147
+ if opcode == MAKE_CLOSURE {
1148
+ function .Closure = vm .POP ().(py.Tuple )
1149
+ }
1132
1150
1133
1151
if num_annotations > 0 {
1134
1152
names := vm .POP ().(py.Tuple ) // names of args with annotations
@@ -1167,15 +1185,24 @@ func do_MAKE_FUNCTION(vm *Vm, argc int32) {
1167
1185
vm .PUSH (function )
1168
1186
}
1169
1187
1188
+ // Pushes a new function object on the stack. TOS is the code
1189
+ // associated with the function. The function object is defined to
1190
+ // have argc default parameters, which are found below TOS.
1191
+ //
1192
+ // FIXME these docs are slightly wrong.
1193
+ func do_MAKE_FUNCTION (vm * Vm , argc int32 ) {
1194
+ defer vm .CheckException ()
1195
+ _make_function (vm , argc , MAKE_FUNCTION )
1196
+ }
1197
+
1170
1198
// Creates a new function object, sets its func_closure slot, and
1171
1199
// pushes it on the stack. TOS is the code associated with the
1172
1200
// function, TOS1 the tuple containing cells for the closure’s free
1173
1201
// variables. The function also has argc default parameters, which are
1174
1202
// found below the cells.
1175
1203
func do_MAKE_CLOSURE (vm * Vm , argc int32 ) {
1176
1204
defer vm .CheckException ()
1177
- vm .NotImplemented ("MAKE_CLOSURE" , argc )
1178
- // see MAKE_FUNCTION
1205
+ _make_function (vm , argc , MAKE_CLOSURE )
1179
1206
}
1180
1207
1181
1208
// Pushes a slice object on the stack. argc must be 2 or 3. If it is
@@ -1278,6 +1305,8 @@ func (vm *Vm) UnwindExceptHandler(frame *py.Frame, block *py.TryBlock) {
1278
1305
// FIXME figure out how we are going to signal exceptions!
1279
1306
//
1280
1307
// Returns an Object and an error. The error will be a py.ExceptionInfo
1308
+ //
1309
+ // This is the equivalent of PyEval_EvalFrame
1281
1310
func RunFrame (frame * py.Frame ) (res py.Object , err error ) {
1282
1311
vm := NewVm (frame )
1283
1312
// defer func() {
@@ -1412,8 +1441,10 @@ func RunFrame(frame *py.Frame) (res py.Object, err error) {
1412
1441
// Any parameters are expected to have been decoded into locals
1413
1442
//
1414
1443
// Returns an Object and an error. The error will be a py.ExceptionInfo
1415
- func Run (globals , locals py.StringDict , code * py.Code ) (res py.Object , err error ) {
1416
- frame := py .NewFrame (globals , locals , code )
1444
+ //
1445
+ // This is the equivalent of PyEval_EvalCode with closure support
1446
+ func Run (globals , locals py.StringDict , code * py.Code , closure py.Tuple ) (res py.Object , err error ) {
1447
+ frame := py .NewFrame (globals , locals , code , closure )
1417
1448
1418
1449
// If this is a generator then make a generator object from
1419
1450
// the frame and return that instead
0 commit comments