Skip to content

Commit 9d45873

Browse files
committed
vm, builtin, py: locals(), globals() and builtin fixes
* builtin: Implement locals(), globals() and fix __import__() * builtin: Fix ord() * builtin: Tests * py: frame: add FastToLocals and LocalsToFast * vm: Use the above in IMPORT_STAR * vm: Implementation for locals(), globals() and call for __import__
1 parent 4f76837 commit 9d45873

File tree

9 files changed

+382
-29
lines changed

9 files changed

+382
-29
lines changed

‎builtin/builtin.go‎

Lines changed: 16 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ Noteworthy: None is the 'nil' object; Ellipsis represents '...' in slices.`
1818
funcinit(){
1919
methods:= []*py.Method{
2020
py.NewMethod("__build_class__", builtin___build_class__, 0, build_class_doc),
21-
py.NewMethod("__import__", builtin___import__, 0, import_doc),
21+
py.NewMethod("__import__", py.InternalMethodImport, 0, import_doc),
2222
py.NewMethod("abs", builtin_abs, 0, abs_doc),
2323
// py.NewMethod("all", builtin_all, 0, all_doc),
2424
// py.NewMethod("any", builtin_any, 0, any_doc),
@@ -34,7 +34,7 @@ func init(){
3434
// py.NewMethod("exec", builtin_exec, 0, exec_doc),
3535
// py.NewMethod("format", builtin_format, 0, format_doc),
3636
py.NewMethod("getattr", builtin_getattr, 0, getattr_doc),
37-
// py.NewMethod("globals", builtin_globals, py.METH_NOARGS, globals_doc),
37+
py.NewMethod("globals", py.InternalMethodGlobals, 0, globals_doc),
3838
py.NewMethod("hasattr", builtin_hasattr, 0, hasattr_doc),
3939
// py.NewMethod("hash", builtin_hash, 0, hash_doc),
4040
// py.NewMethod("hex", builtin_hex, 0, hex_doc),
@@ -44,7 +44,7 @@ func init(){
4444
// py.NewMethod("issubclass", builtin_issubclass, 0, issubclass_doc),
4545
// py.NewMethod("iter", builtin_iter, 0, iter_doc),
4646
py.NewMethod("len", builtin_len, 0, len_doc),
47-
// py.NewMethod("locals", builtin_locals, py.METH_NOARGS, locals_doc),
47+
py.NewMethod("locals", py.InternalMethodLocals, 0, locals_doc),
4848
// py.NewMethod("max", builtin_max, 0, max_doc),
4949
// py.NewMethod("min", builtin_min, 0, min_doc),
5050
py.NewMethod("next", builtin_next, 0, next_doc),
@@ -351,21 +351,6 @@ fromlist is not empty. Level is used to determine whether to perform
351351
absolute or relative imports. 0 is absolute while a positive number
352352
is the number of parent directories to search relative to the current module.`
353353

354-
funcbuiltin___import__(self py.Object, args py.Tuple, kwargs py.StringDict) py.Object{
355-
kwlist:= []string{"name", "globals", "locals", "fromlist", "level"}
356-
varname py.Object
357-
varglobals py.Object=py.NewStringDict()
358-
varlocals py.Object=py.NewStringDict()
359-
varfromlist py.Object= py.Tuple{}
360-
varlevel py.Object=py.Int(0)
361-
362-
py.ParseTupleAndKeywords(args, kwargs, "U|OOOi:__import__", kwlist, &name, &globals, &locals, &fromlist, &level)
363-
iffromlist==py.None{
364-
fromlist= py.Tuple{}
365-
}
366-
returnpy.ImportModuleLevelObject(string(name.(py.String)), globals.(py.StringDict), locals.(py.StringDict), fromlist.(py.Tuple), int(level.(py.Int)))
367-
}
368-
369354
constord_doc=`ord(c) -> integer
370355
371356
Return the integer ordinal of a one-character string.`
@@ -375,13 +360,13 @@ func builtin_ord(self, obj py.Object) py.Object{
375360
switchx:=obj.(type){
376361
case py.Bytes:
377362
size=len(x)
378-
iflen(x)==1{
363+
ifsize==1{
379364
returnpy.Int(x[0])
380365
}
381366
case py.String:
382-
varrunerune
383-
rune, size=utf8.DecodeRuneInString(string(x))
384-
iflen(x)==size&&rune!=utf8.RuneError{
367+
size=len(x)
368+
rune, runeSize:=utf8.DecodeRuneInString(string(x))
369+
ifsize==runeSize&&rune!=utf8.RuneError{
385370
returnpy.Int(rune)
386371
}
387372
//case py.ByteArray:
@@ -396,7 +381,7 @@ func builtin_ord(self, obj py.Object) py.Object{
396381
panic(py.ExceptionNewf(py.TypeError, "ord() expected string of length 1, but %s found", obj.Type().Name))
397382
}
398383

399-
panic(py.ExceptionNewf(py.TypeError, "ord() expected a character, but string of length %zd found", size))
384+
panic(py.ExceptionNewf(py.TypeError, "ord() expected a character, but string of length %d found", size))
400385
}
401386

402387
constgetattr_doc=`getattr(object, name[, default]) -> value
@@ -575,3 +560,11 @@ func builtin_chr(self py.Object, args py.Tuple) py.Object{
575560
n:=utf8.EncodeRune(buf, rune(x))
576561
returnpy.String(buf[:n])
577562
}
563+
564+
constlocals_doc=`locals() -> dictionary
565+
566+
Update and return a dictionary containing the current scope's local variables.`
567+
568+
constglobals_doc=`globals() -> dictionary
569+
570+
Return the dictionary containing the current scope's global variables.`

‎builtin/builtin_test.go‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package builtin_test
2+
3+
import (
4+
"testing"
5+
6+
"github.com/ncw/gpython/pytest"
7+
)
8+
9+
funcTestVm(t*testing.T){
10+
pytest.RunTests(t, "tests")
11+
}

‎builtin/tests/builtin.py‎

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
doc="abs"
2+
assertabs(0) ==0
3+
assertabs(10) ==10
4+
assertabs(-10) ==10
5+
6+
doc="chr"
7+
assertchr(65) =="A"
8+
assertchr(163) =="£"
9+
assertchr(0x263A) =="☺"
10+
11+
doc="compile"
12+
code=compile("pass", "<string>", "exec")
13+
# FIXME
14+
15+
doc="getattr"
16+
classC:
17+
def__init__(self):
18+
self.potato=42
19+
c=C()
20+
assertgetattr(c, "potato") ==42
21+
assertgetattr(c, "potato", 43) ==42
22+
assertgetattr(c, "sausage", 43) ==43
23+
24+
doc="globals"
25+
a=1
26+
assertglobals()["a"] ==1
27+
28+
doc="hasattr"
29+
asserthasattr(c, "potato")
30+
assertnothasattr(c, "sausage")
31+
32+
doc="len"
33+
assertlen(()) ==0
34+
assertlen((1,2,3)) ==3
35+
assertlen("hello") ==5
36+
assertlen("£☺") ==2
37+
38+
doc="locals"
39+
deffn(x):
40+
print(locals())
41+
assertlocals()["x"] ==1
42+
fn(1)
43+
44+
doc="next no default"
45+
defgen():
46+
yield1
47+
yield2
48+
g=gen()
49+
assertnext(g) ==1
50+
assertnext(g) ==2
51+
ok=False
52+
try:
53+
next(g)
54+
exceptStopIteration:
55+
ok=True
56+
assertok, "StopIteration not raised"
57+
58+
doc="next with default"
59+
g=gen()
60+
assertnext(g, 42) ==1
61+
assertnext(g, 42) ==2
62+
assertnext(g, 42) ==42
63+
assertnext(g, 42) ==42
64+
65+
doc="next no default with exception"
66+
defgen2():
67+
yield1
68+
raiseValueError("potato")
69+
g=gen2()
70+
assertnext(g) ==1
71+
ok=False
72+
try:
73+
next(g)
74+
exceptValueError:
75+
ok=True
76+
assertok, "ValueError not raised"
77+
78+
doc="next with default and exception"
79+
g=gen2()
80+
assertnext(g, 42) ==1
81+
ok=False
82+
try:
83+
next(g)
84+
exceptValueError:
85+
ok=True
86+
assertok, "ValueError not raised"
87+
88+
doc="ord"
89+
assert65==ord("A")
90+
assert163==ord("£")
91+
assert0x263A==ord("☺")
92+
assert65==ord(b"A")
93+
ok=False
94+
try:
95+
ord("AA")
96+
exceptTypeErrorase:
97+
ife.args[0] !="ord() expected a character, but string of length 2 found":
98+
raise
99+
ok=True
100+
assertok, "TypeError not raised"
101+
try:
102+
ord(None)
103+
exceptTypeErrorase:
104+
ife.args[0] !="ord() expected string of length 1, but NoneType found":
105+
raise
106+
ok=True
107+
assertok, "TypeError not raised"
108+
109+
doc="pow"
110+
assertpow(2, 10) ==1024
111+
# FIXME assert pow(2, 10, 17) == 4
112+
113+
doc="print"
114+
# FIXME
115+
116+
doc="round"
117+
assertround(1.1) ==1.0
118+
119+
doc="setattr"
120+
classC: pass
121+
c=C()
122+
assertnothasattr(c, "potato")
123+
setattr(c, "potato", "spud")
124+
assertgetattr(c, "potato") =="spud"
125+
assertc.potato=="spud"
126+
127+
doc="__import__"
128+
lib=__import__("lib")
129+
assertlib.libfn() ==42
130+
assertlib.libvar==43
131+
assertlib.libclass().method() ==44
132+
133+
doc="finished"

‎builtin/tests/lib.py‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Some targets to be imported
2+
3+
deflibfn():
4+
return42
5+
6+
libvar=43
7+
8+
classlibclass:
9+
defmethod(self):
10+
return44
11+
12+
_libprivate=45

‎notes.txt‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,15 @@ Make a gpython-minimal with no built in stdlib
1616

1717
Bytecode compile the standard library and embed into go files - can then make a gpython with no external files.
1818

19+
NB Would probably be a lot quicker to define
20+
21+
Arg struct{
22+
Name string
23+
Value Object
24+
}
25+
26+
And pass args using []Arg instead of StringDict
27+
1928
Testing
2029
=======
2130

0 commit comments

Comments
(0)