Skip to content

Commit 44e6f63

Browse files
committed
compile: symtable: global and nonlocal
1 parent 5d621d0 commit 44e6f63

File tree

4 files changed

+215
-40
lines changed

4 files changed

+215
-40
lines changed

compile/make_symtable_test.py

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,26 @@ def fn(a:"a",*arg:"arg",b:"b"=1,c:"c"=2,**kwargs:"kw") -> "ret":
2222
def fn(A,b):
2323
e=1
2424
return a*arg*b*c*kwargs*A*e*glob''', "exec"),
25+
('''\
26+
def fn(a):
27+
global b
28+
b = a''', "exec"),
29+
('''\
30+
def fn(a):
31+
b = 6
32+
global b
33+
b = a''', "exec"),
34+
('''\
35+
def outer():
36+
x = 1
37+
def inner():
38+
nonlocal x
39+
x = 2''', "exec"),
40+
('''\
41+
def outer():
42+
def inner():
43+
nonlocal x
44+
x = 2''', "exec", SyntaxError),
2545
# FIXME need with x as y
2646
]
2747

@@ -149,14 +169,15 @@ def main():
149169
error = e.msg
150170
else:
151171
raise ValueError("Expecting exception %s" % exc)
152-
table = "nil"
172+
dumped_symtable = "nil"
153173
gostring = "nil"
154174
exc_name = "py.%s" % exc.__name__
155175
else:
156176
table = symtable(source, "<string>", mode)
157177
exc_name = "nil"
158178
error = ""
159-
out.append('{"%s", "%s", %s, %s, "%s"},' % (escape(source), mode, dump_symtable(table), exc_name, escape(error)))
179+
dumped_symtable = dump_symtable(table)
180+
out.append('{"%s", "%s", %s, %s, "%s"},' % (escape(source), mode, dumped_symtable, exc_name, escape(error)))
160181
out.append("}\n")
161182
print("Writing %s" % path)
162183
with open(path, "w") as f:

compile/symtable.go

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
package compile
1111

1212
import (
13+
"log"
1314
"strings"
1415

1516
"github.com/ncw/gpython/ast"
@@ -153,10 +154,34 @@ func (st *SymTable) Parse(Ast ast.Ast) {
153154
switch node := Ast.(type) {
154155
case *ast.Nonlocal:
155156
for _, name := range node.Names {
157+
cur, ok := st.Symbols[string(name)]
158+
if ok {
159+
if (cur.Flags & defLocal) != 0 {
160+
// FIXME this should be a warning
161+
log.Printf("name '%s' is assigned to before nonlocal declaration", name)
162+
163+
}
164+
if (cur.Flags & defUse) != 0 {
165+
// FIXME this should be a warning
166+
log.Printf("name '%s' is used prior to nonlocal declaration", name)
167+
}
168+
}
156169
st.AddDef(name, defNonlocal)
157170
}
158171
case *ast.Global:
159172
for _, name := range node.Names {
173+
cur, ok := st.Symbols[string(name)]
174+
if ok {
175+
if (cur.Flags & defLocal) != 0 {
176+
// FIXME this should be a warning
177+
log.Printf("name '%s' is assigned to before global declaration", name)
178+
179+
}
180+
if (cur.Flags & defUse) != 0 {
181+
// FIXME this should be a warning
182+
log.Printf("name '%s' is used prior to global declaration", name)
183+
}
184+
}
160185
st.AddDef(name, defGlobal)
161186
}
162187
case *ast.Name:
@@ -449,7 +474,7 @@ func (st *SymTable) AnalyzeName(scopes Scopes, name string, flags DefUse, bound,
449474
if bound == nil {
450475
panic(py.ExceptionNewf(py.SyntaxError, "nonlocal declaration not allowed at module level"))
451476
}
452-
if bound.Contains(name) {
477+
if !bound.Contains(name) {
453478
panic(py.ExceptionNewf(py.SyntaxError, "no binding for nonlocal '%s' found", name))
454479
}
455480
scopes[name] = scopeFree

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy