Skip to content

Commit cae96e7

Browse files
committed
vm: implement CALL_FUNCTION*, fast locals and make function calling work properly
* Add Localsplus to frame to implement the fastlocals * Implemente LOAD_FAST, DELETE_FAST and STORE_FAST properly * Implement CALL_FUNCTION, CALL_FUNCTION_VAR, CALL_FUNCTION_KW, CALL_FUNCTION_VAR_KW * Rename py.Run* to py.VmRun* - external callers should be calling vm.Run
1 parent 7f90811 commit cae96e7

File tree

9 files changed

+516
-141
lines changed

9 files changed

+516
-141
lines changed

py/frame.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ type Frame struct {
6262
// Executing byte // whether the frame is still executing
6363
Blockstack []TryBlock // for try and loop blocks
6464
Block *TryBlock // pointer to current block or nil
65-
// Localsplus []Object // locals+stack, dynamically sized
65+
Localsplus []Object // LocalVars + CellAndFreeVars
6666
}
6767

6868
var FrameType = NewType("frame", "Represents a stack frame")
@@ -78,10 +78,9 @@ func NewFrame(globals, locals StringDict, code *Code, closure Tuple) *Frame {
7878
ncells := len(code.Cellvars)
7979
nfrees := len(code.Freevars)
8080
varsize := nlocals + ncells + nfrees
81-
size := varsize + int(code.Stacksize)
8281
// Allocate the stack, locals, cells and frees in a contigious block of memory
83-
allocation := make([]Object, varsize, size)
84-
localVars := allocation[0:nlocals]
82+
allocation := make([]Object, varsize)
83+
localVars := allocation[:nlocals]
8584
//cellVars := allocation[nlocals : nlocals+ncells]
8685
//freeVars := allocation[nlocals+ncells : varsize]
8786
cellAndFreeVars := allocation[nlocals:varsize]
@@ -93,6 +92,7 @@ func NewFrame(globals, locals StringDict, code *Code, closure Tuple) *Frame {
9392
LocalVars: localVars,
9493
CellAndFreeVars: cellAndFreeVars,
9594
Builtins: Builtins.Globals,
95+
Localsplus: allocation,
9696
Stack: make([]Object, 0, code.Stacksize),
9797
}
9898
}

py/function.go

+1-44
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,6 @@
1111
// executed so far.
1212
package py
1313

14-
import (
15-
"fmt"
16-
)
17-
1814
// A python Function object
1915
type Function struct {
2016
Code *Code // A code object, the __code__ attribute
@@ -87,48 +83,9 @@ func NewFunction(code *Code, globals StringDict, qualname string) *Function {
8783
}
8884
}
8985

90-
// Setup locals for calling the function with the given arguments
91-
func (f *Function) LocalsForCall(args Tuple) StringDict {
92-
// fmt.Printf("call f %#v with %v\n", f, args)
93-
max := int(f.Code.Argcount)
94-
min := max - len(f.Defaults)
95-
if len(args) > max || len(args) < min {
96-
if min == max {
97-
panic(ExceptionNewf(TypeError, "%s() takes %d positional arguments but %d were given", f.Name, max, len(args)))
98-
} else {
99-
panic(ExceptionNewf(TypeError, "%s() takes from %d to %d positional arguments but %d were given", f.Name, min, max, len(args)))
100-
}
101-
}
102-
103-
// FIXME not sure this is right!
104-
// Copy the args into the local variables
105-
locals := NewStringDict()
106-
for i := range args {
107-
locals[f.Code.Varnames[i]] = args[i]
108-
}
109-
for i := len(args); i < max; i++ {
110-
locals[f.Code.Varnames[i]] = f.Defaults[i-min]
111-
}
112-
// fmt.Printf("locals = %v\n", locals)
113-
return locals
114-
}
115-
116-
// Call the function with the given arguments
117-
func (f *Function) LocalsForCallWithKeywords(args Tuple, kwargs StringDict) StringDict {
118-
locals := NewStringDict()
119-
fmt.Printf("FIXME LocalsForCallWithKeywords NOT IMPLEMENTED\n")
120-
return locals
121-
}
122-
12386
// Call a function
12487
func (f *Function) M__call__(args Tuple, kwargs StringDict) Object {
125-
var locals StringDict
126-
if kwargs != nil {
127-
locals = f.LocalsForCallWithKeywords(args, kwargs)
128-
} else {
129-
locals = f.LocalsForCall(args)
130-
}
131-
result, err := Run(f.Globals, locals, f.Code, f.Closure)
88+
result, err := VmEvalCodeEx(f.Code, f.Globals, NewStringDict(), args, kwargs, f.Defaults, f.KwDefaults, f.Closure)
13289
if err != nil {
13390
// Propagate the error
13491
panic(err)

py/generator.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ func (it *Generator) Send(arg Object) Object {
8989
it.Frame.Stack = append(it.Frame.Stack, arg)
9090
}
9191
it.Running = true
92-
res, err := RunFrame(it.Frame)
92+
res, err := VmRunFrame(it.Frame)
9393
it.Running = false
9494
if err != nil {
9595
// Propagate the error

py/import.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ func ImportModuleLevelObject(name string, globals, locals StringDict, fromlist T
116116
panic(ExceptionNewf(ImportError, "Compile didn't return code object"))
117117
}
118118
module := NewModule(name, "", nil, nil)
119-
_, err = Run(module.Globals, module.Globals, code, nil)
119+
_, err = VmRun(module.Globals, module.Globals, code, nil)
120120
if err != nil {
121121
panic(err)
122122
}

py/py.go

+5-3
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,11 @@ type IGetDict interface {
1313

1414
// Some well known objects
1515
var (
16-
// See vm/eval.go - set to avoid circular import
17-
Run func(globals, locals StringDict, code *Code, closure Tuple) (res Object, err error)
18-
RunFrame func(frame *Frame) (res Object, err error)
16+
// Set in vm/eval.go - to avoid circular import
17+
VmRun func(globals, locals StringDict, code *Code, closure Tuple) (res Object, err error)
18+
VmRunFrame func(frame *Frame) (res Object, err error)
19+
VmEvalCodeEx func(co *Code, globals, locals StringDict, args []Object, kws StringDict, defs []Object, kwdefs StringDict, closure Tuple) (retval Object, err error)
20+
1921
// See compile/compile.go - set to avoid circular import
2022
Compile func(str, filename, mode string, flags int, dont_inherit bool) (Object, error)
2123
)

0 commit comments

Comments
 (0)