Skip to content

Commit b52ac85

Browse files
committed
Work on getting the python functions running
* Use StringDict instead of Dict for internals * __main__ module * function objects * Callable interface * factor VM into seperate files * Add logging to not implemented opcodes
1 parent dcccf9b commit b52ac85

File tree

13 files changed

+551
-202
lines changed

13 files changed

+551
-202
lines changed

builtin/builtin.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ sep: string inserted between values, default a space.
6767
end: string appended after the last value, default a newline.
6868
flush: whether to forcibly flush the stream.`
6969

70-
func builtin_print(self py.Object, args py.Tuple, kwargs py.Dict) py.Object {
70+
func builtin_print(self py.Object, args py.Tuple, kwargs py.StringDict) py.Object {
7171
fmt.Printf("print %v, %v, %v\n", self, args, kwargs)
7272
return py.None
7373
}

main.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,8 @@ func main() {
6161
log.Fatal(err)
6262
}
6363
code := obj.(*py.Code)
64-
v := vm.NewVm()
65-
err = v.Run(code)
64+
module := py.NewModule("__main__", "", nil)
65+
err = vm.Run(module.Globals, module.Globals, code)
6666
if err != nil {
6767
log.Fatal(err)
6868
}

marshal/marshal.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,8 @@ func ReadObject(r io.Reader) (obj py.Object, err error) {
206206
// FIXME differentiate the types TYPE_TUPLE, TYPE_LIST, TYPE_SET, TYPE_FROZENSET
207207
return py.Tuple(tuple), nil
208208
case TYPE_DICT:
209-
dict := make(py.Dict)
209+
// FIXME should be py.Dict
210+
dict := py.NewStringDict()
210211
var key, value py.Object
211212
for {
212213
key, err = ReadObject(r)
@@ -221,10 +222,11 @@ func ReadObject(r io.Reader) (obj py.Object, err error) {
221222
return
222223
}
223224
if value != nil {
224-
dict[key] = value
225+
// FIXME should be objects as key
226+
dict[string(key.(py.String))] = value
225227
}
226228
}
227-
return py.Dict(dict), nil
229+
return dict, nil
228230
case TYPE_REF:
229231
// Reference to something???
230232
var n int32

py/code.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import (
88

99
// Code object
1010
type Code struct {
11-
// Object_HEAD
1211
Argcount int32 // #arguments, except *args
1312
Kwonlyargcount int32 // #keyword only arguments
1413
Nlocals int32 // #local variables

py/function.go

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
// Function objects
2+
//
3+
// Function objects and code objects should not be confused with each other:
4+
//
5+
// Function objects are created by the execution of the 'def' statement.
6+
// They reference a code object in their __code__ attribute, which is a
7+
// purely syntactic object, i.e. nothing more than a compiled version of some
8+
// source code lines. There is one code object per source code "fragment",
9+
// but each code object can be referenced by zero or many function objects
10+
// depending only on how many times the 'def' statement in the source was
11+
// executed so far.
12+
package py
13+
14+
import (
15+
"fmt"
16+
)
17+
18+
// A python Function object
19+
type Function struct {
20+
Code *Code // A code object, the __code__ attribute
21+
Globals StringDict // A dictionary (other mappings won't do)
22+
Defaults Tuple // NULL or a tuple
23+
KwDefaults StringDict // NULL or a dict
24+
Closure Tuple // NULL or a tuple of cell objects
25+
Doc Object // The __doc__ attribute, can be anything
26+
Name String // The __name__ attribute, a string object
27+
Dict StringDict // The __dict__ attribute, a dict or NULL
28+
Weakreflist List // List of weak references
29+
Module *Module // The __module__ attribute, can be anything
30+
Annotations StringDict // Annotations, a dict or NULL
31+
Qualname String // The qualified name
32+
}
33+
34+
var FunctionType = NewType("function")
35+
36+
// Type of this object
37+
func (o *Function) Type() *Type {
38+
return FunctionType
39+
}
40+
41+
// Define a new function
42+
//
43+
// Return a new function object associated with the code object
44+
// code. globals must be a dictionary with the global variables
45+
// accessible to the function.
46+
//
47+
// The function’s docstring, name and __module__ are retrieved from
48+
// the code object, the argument defaults and closure are set to NULL.
49+
//
50+
// Allows to set the function object’s __qualname__
51+
// attribute. qualname should be a unicode object or ""; if "", the
52+
// __qualname__ attribute is set to the same value as its __name__
53+
// attribute.
54+
func NewFunction(code *Code, globals StringDict, qualname String) *Function {
55+
var doc Object
56+
var module *Module
57+
if len(code.Consts) >= 1 {
58+
doc = code.Consts[0]
59+
if _, ok := doc.(String); !ok {
60+
doc = None
61+
}
62+
} else {
63+
doc = None
64+
}
65+
66+
// __module__: If module name is in globals, use it. Otherwise, use None.
67+
68+
if moduleobj, ok := globals["__name__"]; ok {
69+
module = (moduleobj).(*Module)
70+
}
71+
72+
if qualname == "" {
73+
qualname = code.Name
74+
}
75+
76+
return &Function{
77+
Code: code,
78+
Qualname: qualname,
79+
Globals: globals,
80+
Name: code.Name,
81+
Doc: doc,
82+
Module: module,
83+
}
84+
}
85+
86+
// Call the function with the given arguments
87+
func (f *Function) Call(self Object, args Tuple) Object {
88+
fmt.Printf("call f %#v with %v and %v\n", f, self, args)
89+
if len(f.Code.Varnames) < len(args) {
90+
panic("Too many args!")
91+
// FIXME don't know how to deal with default args
92+
}
93+
// FIXME not sure this is right!
94+
// Copy the args into the local variables
95+
locals := NewStringDict()
96+
for i := range args {
97+
locals[string(f.Code.Varnames[i].(String))] = args[i]
98+
}
99+
fmt.Printf("locals = %v\n", locals)
100+
// FIXME return vm.Run(f.Globals, locals, f.Code)
101+
return None
102+
}
103+
104+
// Call the function with the given arguments
105+
func (f *Function) CallWithKeywords(self Object, args Tuple, kwargs StringDict) Object {
106+
return None
107+
}
108+
109+
// Check it implements the interface
110+
var _ Callable = (*Function)(nil)

py/method.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ package py
77

88
// Types for methods
99
type PyCFunction func(Object, Tuple) Object
10-
type PyCFunctionWithKeywords func(Object, Tuple, Dict) Object
10+
type PyCFunctionWithKeywords func(Object, Tuple, StringDict) Object
1111

1212
const (
1313

@@ -124,13 +124,16 @@ func (m *Method) Call(self Object, args Tuple) Object {
124124
return m.method(self, args)
125125
}
126126
// FIXME or call with empty dict?
127-
return m.methodWithKeywords(self, args, NewDict())
127+
return m.methodWithKeywords(self, args, NewStringDict())
128128
}
129129

130130
// Call the method with the given arguments
131-
func (m *Method) CallWithKeywords(self Object, args Tuple, kwargs Dict) Object {
131+
func (m *Method) CallWithKeywords(self Object, args Tuple, kwargs StringDict) Object {
132132
if m.method != nil {
133133
panic("Can't call method with kwargs")
134134
}
135135
return m.methodWithKeywords(self, args, kwargs)
136136
}
137+
138+
// Check it implements the interface
139+
var _ Callable = (*Method)(nil)

py/module.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ var (
1717
type Module struct {
1818
Name string
1919
Doc string
20-
Methods map[string]*Method
20+
Globals StringDict
2121
// dict Dict
2222
}
2323

@@ -33,11 +33,11 @@ func NewModule(name, doc string, methods []*Method) *Module {
3333
m := &Module{
3434
Name: name,
3535
Doc: doc,
36-
Methods: make(map[string]*Method),
36+
Globals: NewStringDict(),
3737
}
3838
// Insert the methods into the module dictionary
3939
for _, method := range methods {
40-
m.Methods[method.Name] = method
40+
m.Globals[method.Name] = method
4141
}
4242
// Register the module
4343
modules[name] = m

py/py.go

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -72,18 +72,21 @@ func (o Complex64) Type() *Type {
7272
return Complex64Type
7373
}
7474

75-
var DictType = NewType("dict")
75+
var StringDictType = NewType("dict")
7676

77-
type Dict map[Object]Object
77+
// String to object dictionary
78+
//
79+
// Used for variables etc where the keys can only be strings
80+
type StringDict map[string]Object
7881

79-
// Type of this Dict object
80-
func (o Dict) Type() *Type {
81-
return DictType
82+
// Type of this StringDict object
83+
func (o StringDict) Type() *Type {
84+
return StringDictType
8285
}
8386

8487
// Make a new dictionary
85-
func NewDict() Dict {
86-
return make(Dict)
88+
func NewStringDict() StringDict {
89+
return make(StringDict)
8790
}
8891

8992
var SetType = NewType("set")
@@ -106,3 +109,12 @@ func (o *BigInt) Type() *Type {
106109

107110
// Make sure it satisfies the interface
108111
var _ Object = (*BigInt)(nil)
112+
113+
// Interfaces satisfied by a subset of Objects
114+
type Callable interface {
115+
// Call the method with the args
116+
Call(self Object, args Tuple) Object
117+
118+
// Call the method with the args and kwargs
119+
CallWithKeywords(self Object, args Tuple, kwargs StringDict) Object
120+
}

py/type.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
package py
44

55
type Type struct {
6-
name string // For printing, in format "<module>.<name>"
6+
Name string // For printing, in format "<module>.<name>"
77
/*
88
Py_ssize_t tp_basicsize, tp_itemsize; // For allocation
99
@@ -94,7 +94,7 @@ func (o *Type) Type() *Type {
9494
// Make a new type from a name
9595
func NewType(name string) *Type {
9696
return &Type{
97-
name: name,
97+
Name: name,
9898
}
9999
}
100100

0 commit comments

Comments
 (0)