diff options
Diffstat (limited to 'starlark/interp.go')
-rw-r--r-- | starlark/interp.go | 30 |
1 files changed, 21 insertions, 9 deletions
diff --git a/starlark/interp.go b/starlark/interp.go index f00382c..642d8f5 100644 --- a/starlark/interp.go +++ b/starlark/interp.go @@ -547,11 +547,9 @@ loop: locals[arg] = stack[sp-1] sp-- - case compile.SETCELL: - x := stack[sp-2] - y := stack[sp-1] - sp -= 2 - y.(*cell).v = x + case compile.SETLOCALCELL: + locals[arg].(*cell).v = stack[sp-1] + sp-- case compile.SETGLOBAL: fn.module.globals[arg] = stack[sp-1] @@ -570,9 +568,23 @@ loop: stack[sp] = fn.freevars[arg] sp++ - case compile.CELL: - x := stack[sp-1] - stack[sp-1] = x.(*cell).v + case compile.LOCALCELL: + v := locals[arg].(*cell).v + if v == nil { + err = fmt.Errorf("local variable %s referenced before assignment", f.Locals[arg].Name) + break loop + } + stack[sp] = v + sp++ + + case compile.FREECELL: + v := fn.freevars[arg].(*cell).v + if v == nil { + err = fmt.Errorf("local variable %s referenced before assignment", f.Freevars[arg].Name) + break loop + } + stack[sp] = v + sp++ case compile.GLOBAL: x := fn.module.globals[arg] @@ -641,7 +653,7 @@ func (mandatory) Hash() (uint32, error) { return 0, nil } // A cell is a box containing a Value. // Local variables marked as cells hold their value indirectly // so that they may be shared by outer and inner nested functions. -// Cells are always accessed using indirect CELL/SETCELL instructions. +// Cells are always accessed using indirect {FREE,LOCAL,SETLOCAL}CELL instructions. // The FreeVars tuple contains only cells. // The FREE instruction always yields a cell. type cell struct{ v Value } |