8000 First commit - work in progress only · go-python/gpython@4c48b1f · GitHub
[go: up one dir, main page]

Skip to content
Sign in

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 4c48b1f

Browse files
committed
First commit - work in progress only
0 parents  commit 4c48b1f

File tree

5 files changed

+1324
-0
lines changed

5 files changed

+1324
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
*~

marshal/marshal.go

Lines changed: 319 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,319 @@
1+
// Implement unmarshal and marshal
2+
package marshal
3+
4+
import (
5+
"encoding/binary"
6+
"errors"
7+
"github.com/ncw/gpython/py"
8+
"io"
9+
"strconv"
10+
"fmt"
11+
)
12+
13+
const (
14+
TYPE_NULL = '0'
15+
TYPE_NONE = 'N'
16+
TYPE_FALSE = 'F'
17+
TYPE_TRUE = 'T'
18+
TYPE_STOPITER = 'S'
19+
TYPE_ELLIPSIS = '.'
20+
TYPE_INT = 'i'
21+
TYPE_FLOAT = 'f'
22+
TYPE_BINARY_FLOAT = 'g'
23+
TYPE_COMPLEX = 'x'
24+
TYPE_BINARY_COMPLEX = 'y'
25+
TYPE_LONG = 'l'
26+
TYPE_STRING = 's'
27+
TYPE_INTERNED = 't'
28+
TYPE_REF = 'r'
29+
TYPE_TUPLE = '('
30+
TYPE_LIST = '['
31+
TYPE_DICT = '{'
32+
TYPE_CODE = 'c'
33+
TYPE_UNICODE = 'u'
34+
TYPE_UNKNOWN = '?'
35+
TYPE_SET = '<'
36+
TYPE_FROZENSET = '>'
37+
FLAG_REF = 0x80 // with a type, add obj to index
38+
SIZE32_MAX = 0x7FFFFFFF
39+
40+
// We assume that Python ints are stored internally in base some power of
41+
// 2**15; for the sake of portability we'll always read and write them in base
42+
// exactly 2**15.
43+
44+
PyLong_MARSHAL_SHIFT = 15
45+
PyLong_MARSHAL_BASE = (1 << PyLong_MARSHAL_SHIFT)
46+
PyLong_MARSHAL_MASK = (PyLong_MARSHAL_BASE - 1)
47+
)
48+
49+
// Reads an object from the input
50+
func ReadObject(r io.Reader) (obj py.Object, err error) {
51+
var code byte
52+
err = binary.Read(r, binary.LittleEndian, &code)
53+
if err != nil {
54+
return
55+
}
56+
57+
//flag := code & FLAG_REF
58+
Type := code &^ FLAG_REF
59+
60+
switch Type {
61+
case TYPE_NULL:
62+
// A null object
63+
return nil, nil
64+
case TYPE_NONE:
65+
// The Python None object
66+
return py.None, nil
67+
case TYPE_FALSE:
68+
// The python False object
69+
return py.False, nil
70+
case TYPE_TRUE:
71+
// The python True object
72+
return py.True, nil
73+
case TYPE_STOPITER:
74+
// The python StopIteration Exception
75+
return py.StopIteration, nil
76+
case TYPE_ELLIPSIS:
77+
// The python elipsis object
78+
return py.Elipsis, nil
79+
case TYPE_INT:
80+
// 4 bytes of signed integer
81+
va F438 r n int32
82+
err = binary.Read(r, binary.LittleEndian, &n)
83+
if err != nil {
84+
return n, nil
85+
}
86+
case TYPE_FLOAT:
87+
// Floating point number as a string
88+
var length uint8
89+
err = binary.Read(r, binary.LittleEndian, &length)
90+
if err != nil {
91+
return
92+
}
93+
buf := make([]byte, int(length))
94+
_, err = io.ReadFull(r, buf)
95+
if err != nil {
96+
return
97+
}
98+
var f float64
99+
f, err = strconv.ParseFloat(string(buf), 64)
100+
if err != nil {
101+
return
102+
}
103+
return f, nil
104+
case TYPE_BINARY_FLOAT:
105+
var f float64
106+
err = binary.Read(r, binary.LittleEndian, &f)
107+
if err != nil {
108+
return
109+
}
110+
return f, nil
111+
case TYPE_COMPLEX:
112+
// Complex number as a string
113+
// FIXME this is using Go conversion not Python conversion which may differ
114+
var length uint8
115+
err = binary.Read(r, binary.LittleEndian, &length)
116+
if err != nil {
117+
return
118+
}
119+
buf := make([]byte, int(length))
120+
_, err = io.ReadFull(r, buf)
121+
if err != nil {
122+
return
123+
}
124+
var c complex64
125+
// FIXME c, err = strconv.ParseComplex(string(buf), 64)
126+
if err != nil {
127+
return
128+
}
129+
return c, nil
130+
case TYPE_BINARY_COMPLEX:
131+
var c complex64
132+
err = binary.Read(r, binary.LittleEndian, &c)
133+
if err != nil {
134+
return
135+
}
136+
return c, nil
137+
case TYPE_LONG:
138+
var size int32
139+
err = binary.Read(r, binary.LittleEndian, &size)
140+
if err != nil {
141+
return
142+
}
143+
// FIXME negative := false
144+
if size < 0 {
145+
// FIXME negative = true
146+
size = -size
147+
}
148+
if size < 0 || size > SIZE32_MAX {
149+
return nil, errors.New("bad marshal data (long size out of range)")
150+
}
151+
// FIXME not sure what -ve size means!
152+
// Now read shorts which hav 55F e 15 bits of the number in
153+
digits := make([]int16, size)
154+
err = binary.Read(r, binary.LittleEndian, &size)
155+
if err != nil {
156+
return
157+
}
158+
if digits[0] == 0 {
159+
// FIXME should be ValueError
160+
return nil, errors.New("bad marshal data (digit out of range in long)")
161+
}
162+
// FIXME actually convert into something...
163+
return digits, nil
164+
case TYPE_STRING, TYPE_INTERNED, TYPE_UNICODE:
165+
var size int32
166+
err = binary.Read(r, binary.LittleEndian, &size)
167+
if err != nil {
168+
return
169+
}
170+
if size < 0 || size > SIZE32_MAX {
171+
return nil, errors.New("bad marshal data (string size out of range)")
172+
}
173+
buf := make([]byte, int(size))
174+
_, err = io.ReadFull(r, buf)
175+
if err != nil {
176+
return
177+
}
178+
// FIXME do something different for unicode & interned?
179+
return string(buf), nil
180+
case TYPE_TUPLE, TYPE_LIST, TYPE_SET, TYPE_FROZENSET:
181+
var size int32
182+
err = binary.Read(r, binary.LittleEndian, &size)
183+
if err != nil {
184+
return
185+
}
186+
if size < 0 || size > SIZE32_MAX {
187+
return nil, errors.New("bad marshal data (tuple size out of range)")
188+
}
189+
tuple := make([]py.Object, int(size))
190+
for i := range tuple {
191+
tuple[i], err = ReadObject(r)
192+
if err != nil {
193+
return
194+
}
195+
}
196+
// FIXME differentiate the types TYPE_TUPLE, TYPE_LIST, TYPE_SET, TYPE_FROZENSET
197+
return tuple, nil
198+
case TYPE_DICT:
199+
dict := make(map[py.Object]py.Object)
200+
var key, value py.Object
201+
for {
202+
key, err = ReadObject(r)
203+
if err != nil {
204+
return
205+
}
206+
if key == nil {
207+
break
208+
}
209+
value, err = ReadObject(r)
210+
if err != nil {
211+
return
212+
}
213+
if value != nil {
214+
dict[key] = value
215+
}
216+
}
217+
return dict, nil
218+
case TYPE_REF:
219+
// Reference to something???
220+
var n int32
221+
err = binary.Read(r, binary.LittleEndian, &n)
222+
if err != nil {
223+
return
224+
}
225+
// FIXME
226+
case TYPE_CODE:
227+
var argcount int32
228+
var kwonlyargcount int32
229+
var nlocals int32
230+
var stacksize int32
231+
var flags int32
232+
var code py.Object
233+
var consts py.Object
234+
var names py.Object
235+
var varnames py.Object
236+
var freevars py.Object
237+
var cellvars py.Object
238+
var filename py.Object
239+
var name py.Object
240+
var firstlineno int32
241+
var lnotab py.Object
242+
243+
if err = binary.Read(r, binary.LittleEndian, &argcount); err != nil {
244+
return
245+
}
246+
if err = binary.Read(r, binary.LittleEndian, &kwonlyargcount); err != nil {
247+
return
248+
}
249+
if err = binary.Read(r, binary.LittleEndian, &nlocals); err != nil {
250+
return
251+
}
252+
if err = binary.Read(r, binary.LittleEndian, &stacksize); err != nil {
253+
return
254+
}
255+
if err = binary.Read(r, binary.LittleEndian, &flags); err != nil {
256+
return
257+
}
258+
if code, err = ReadObject(r); err != nil {
259+
return
260+
}
261+
if consts, err = ReadObject(r); err != nil {
262+
return
263+
}
264+
if names, err = ReadObject(r); err != nil {
265+
return
266+
}
267+
if varnames, err = ReadObject(r); err != nil {
268+
return
269+
}
270+
if freevars, err = ReadObject(r); err != nil {
271+
return
272+
}
273+
if cellvars, err = ReadObject(r); err != nil {
274+
return
275+
}
276+
if filename, err = ReadObject(r); err != nil {
277+
return
278+
}
279+
if name, err = ReadObject(r); err != nil {
280+
return
281+
}
282+
if err = binary.Read(r, binary.LittleEndian, &firstlineno); err != nil {
283+
return
284+
}
285+
if lnotab, err = ReadObject(r); err != nil {
286+
return
287+
}
288+
289+
fmt.Printf("argcount = %v\n", argcount)
290+
fmt.Printf("kwonlyargcount = %v\n", kwonlyargcount)
291+
fmt.Printf("nlocals = %v\n", nlocals)
292+
fmt.Printf("stacksize = %v\n", stacksize)
293+
fmt.Printf("flags = %v\n", flags)
294+
fmt.Printf("code = %v\n", code)
295+
fmt.Printf("consts = %v\n", consts)
296+
fmt.Printf("names = %v\n", names)
297+
fmt.Printf("varnames = %v\n", varnames)
298+
fmt.Printf("freevars = %v\n", freevars)
299+
fmt.Printf("cellvars = %v\n", cellvars)
300+
fmt.Printf("filename = %v\n", filename)
301+
fmt.Printf("name = %v\n", name)
302+
fmt.Printf("firstlineno = %v\n", firstlineno)
303+
fmt.Printf("lnotab = %v\n", lnotab)
304+
305+
/*
306+
v = (PyObject *) PyCode_New(
307+
argcount, kwonlyargcount,
308+
nlocals, stacksize, flags,
309+
code, consts, names, varnames,
310+
freevars, cellvars, filename, name,
311+
firstlineno, lnotab);
312+
*/
313+
return code, nil // FIXME
314+
default:
315+
return nil, errors.New("bad marshal data (unknown type code)")
316+
}
317+
318+
return
319+
}

py/py.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// Python global definitions
2+
package py
3+
4+
// A python object
5+
type Object interface{}
6+
7+
// Some well known objects
8+
var (
9+
None, False, True, StopIteration, Elipsis Object
10+
)

0 commit comments

Comments
 (0)
0