forked from flosch/GoPy
-
Notifications
You must be signed in to change notification settings - Fork 0
/
pyfunc.go
134 lines (114 loc) · 2.64 KB
/
pyfunc.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
package vm
import (
"fmt"
"log"
"time"
)
const (
PyFuncExternal = iota
PyFuncInternal
)
type PyFunc struct {
PyObjectData
// Internal func
module *Module
name *string
mfunc ModuleFunc
// External func
codeobj PyObject
// Meta
functype int
closure PyObject // nil or tuple of cell objects
_doc PyObject // __doc__ attribute | not used yet
_name PyObject // __name__ attribute | not used yet
}
func (pf *PyFunc) setClosure(c PyObject) {
pf.closure = c
}
func (pf *PyFunc) getValue() interface{} {
return pf.codeobj
}
func (pf *PyFunc) isTrue() bool {
return true
}
func (pf *PyFunc) isExternal() bool {
return pf.functype == PyFuncExternal
}
func (pf *PyFunc) asString() *string {
var str string
switch pf.functype {
case PyFuncInternal:
str = fmt.Sprintf("<internal function %s>", *pf.name)
case PyFuncExternal:
str = fmt.Sprintf("<external function %s>", *pf.codeobj.asString())
default:
panic("unknown func type")
}
return &str
}
func (pf *PyFunc) log(msg string) {
var ident string
switch pf.functype {
case PyFuncInternal:
ident = fmt.Sprintf("%s.%s", pf.module.name, *pf.name)
case PyFuncExternal:
ident = fmt.Sprintf("%s/%s", *pf.codeobj.(*PyCode).filename, *pf.codeobj.(*PyCode).name)
default:
panic("unknown func type")
}
log.Println(fmt.Sprintf("[%s] %s", ident, msg))
}
func (pf *PyFunc) run(args *PyArgs) PyObject {
// Create frame for run
frame := NewPyFrame(1000) // TODO change stack size to a better value?
starttime := time.Now()
defer func() {
if debugMode {
pf.log(fmt.Sprintf("Execution took %s.", time.Since(starttime)))
}
}()
switch pf.functype {
case PyFuncInternal:
return pf.mfunc(args)
case PyFuncExternal:
if args != nil {
for i, value := range args.positional {
// Iterate reverse! Therefore:
idx := len(args.positional) - 1 - i
name := pf.codeobj.(*PyCode).varnames.(*PyTuple).items[idx]
frame.names[*name.asString()] = value
//fmt.Printf("\n --- Setting %v -> %v...\n", *name.asString(), *value.asString())
}
if len(args.keyword) > 0 {
panic("Not implemented")
}
}
if debugMode {
pf.log("Called")
}
res, err := pf.codeobj.(*PyCode).eval(frame)
if err != nil {
pf.codeobj.(*PyCode).runtimeError(err.Error())
}
return res
default:
panic("unknown func type")
}
panic("unreachable")
}
func NewPyFuncInternal(module *Module, fn ModuleFunc, name *string) PyObject {
return &PyFunc{
module: module,
name: name,
functype: PyFuncInternal,
mfunc: fn,
}
}
func NewPyFuncExternal(codeobj PyObject) PyObject {
pf := &PyFunc{
codeobj: codeobj,
functype: PyFuncExternal,
}
pf.pyObjInit()
return pf
}