Skip to content

Commit 5d621d0

Browse files
committed
compiler: fill out symtable machinery
* Implement opt and scopes * Make functions and nested functions work * Stringer symbols for flags to aid debugging
1 parent 39eaaff commit 5d621d0

File tree

5 files changed

+904
-93
lines changed

5 files changed

+904
-93
lines changed

compile/make_symtable_test.py

Lines changed: 45 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,16 @@
1313

1414
inp = [
1515
('''1''', "eval"),
16-
#('''a*b*c''', "eval"),
17-
#('''def fn(): pass''', "exec"),
18-
#('''def fn(a,b):\n e=1\n return a*b*c*d*e''', "exec"),
19-
#('''def fn(a,b):\n def nested(c,d):\n return a*b*c*d*e''', "exec"),
20-
# ('''def fn(a,b,c): pass''', "exec"),
21-
# ('''def fn(a,b=1,c=2): pass''', "exec"),
22-
# ('''def fn(a,*arg,b=1,c=2): pass''', "exec"),
23-
# ('''def fn(a,*arg,b=1,c=2,**kwargs): pass''', "exec"),
24-
# ('''def fn(a:"a",*arg:"arg",b:"b"=1,c:"c"=2,**kwargs:"kw") -> "ret": pass''', "exec"),
25-
# ('''def fn(): a+b''', "exec"),
16+
('''a*b*c''', "eval"),
17+
('''def fn(): pass''', "exec"),
18+
('''def fn(a,b):\n e=1\n return a*b*c*d*e''', "exec"),
19+
('''def fn(a,b):\n def nested(c,d):\n return a*b*c*d*e''', "exec"),
20+
('''\
21+
def fn(a:"a",*arg:"arg",b:"b"=1,c:"c"=2,**kwargs:"kw") -> "ret":
22+
def fn(A,b):
23+
e=1
24+
return a*arg*b*c*kwargs*A*e*glob''', "exec"),
25+
# FIXME need with x as y
2626
]
2727

2828
def dump_bool(b):
@@ -52,29 +52,57 @@ def dump_strings(ss):
5252
("defImport", 2<<6), # assignment occurred via import
5353
)
5454

55+
#opt flags flags to names (from symtable.h)
56+
OPT_FLAGS = (
57+
("optImportStar", 1),
58+
("optTopLevel", 2),
59+
)
60+
5561
BLOCK_TYPES = {
5662
"function": "FunctionBlock",
5763
"class": "ClassBlock",
5864
"module": "ModuleBlock",
5965
}
6066

67+
def dump_flags(flag_bits, flags_dict):
68+
"""Dump the bits in flag_bits using the flags_dict"""
69+
flags = []
70+
for name, mask in flags_dict:
71+
if (flag_bits & mask) != 0:
72+
flags.append(name)
73+
if not flags:
74+
flags = ["0"]
75+
return "|".join(flags)
76+
6177
def dump_symtable(st):
6278
"""Dump the symtable"""
6379
out = "&SymTable{\n"
6480
out += 'Type:%s,\n' % BLOCK_TYPES[st.get_type()] # Return the type of the symbol table. Possible values are 'class', 'module', and 'function'.
6581
out += 'Name:"%s",\n' % st.get_name() # Return the table’s name. This is the name of the class if the table is for a class, the name of the function if the table is for a function, or 'top' if the table is global (get_type() returns 'module').
6682

6783
out += 'Lineno:%s,\n' % st.get_lineno() # Return the number of the first line in the block this table represents.
68-
out += 'Optimized:%s,\n' % dump_bool(st.is_optimized()) # Return True if the locals in this table can be optimized.
84+
out += 'Unoptimized:%s,\n' % dump_flags(st._table.optimized, OPT_FLAGS) # Return False if the locals in this table can be optimized.
6985
out += 'Nested:%s,\n' % dump_bool(st.is_nested()) # Return True if the block is a nested class or function.
70-
out += 'Exec:%s,\n' % dump_bool(st.has_exec()) # Return True if the block uses exec.
71-
out += 'ImportStar:%s,\n' % dump_bool(st.has_import_star()) # Return True if the block uses a starred from-import.
86+
#out += 'Exec:%s,\n' % dump_bool(st.has_exec()) # Return True if the block uses exec.
87+
#out += 'ImportStar:%s,\n' % dump_bool(st.has_import_star()) # Return True if the block uses a starred from-import.
88+
out += 'Varnames:%s,\n' % dump_strings(st._table.varnames)
7289
out += 'Symbols: Symbols{\n'
90+
children = dict()
7391
for name in st.get_identifiers():
74-
value = st.lookup(name)
75-
out += '"%s":%s,\n' % (name, dump_symbol(value))
92+
s = st.lookup(name)
93+
out += '"%s":%s,\n' % (name, dump_symbol(s))
94+
ns = s.get_namespaces()
95+
if len(ns) == 0:
96+
pass
97+
elif len(ns) == 1:
98+
children[name] = ns[0]
99+
else:
100+
raise AssertionError("More than one namespace")
101+
out += '},\n'
102+
out += 'Children:map[string]*SymTable{\n'
103+
for name, symtable in children.items():
104+
out += '"%s":%s,\n' % (name, dump_symtable(symtable))
76105
out += '},\n'
77-
# out += 'children:"%s",\n' % st.get_children() # Return a list of the nested symbol tables.
78106
out += "}"
79107
return out
80108

@@ -83,27 +111,9 @@ def dump_symbol(s):
83111
#class symtable.Symbol
84112
# An entry in a SymbolTable corresponding to an identifier in the source. The constructor is not public.
85113
out = "Symbol{\n"
86-
out += 'Name:"%s",\n' % s.get_name() # Return the symbol’s name.
87-
flags = []
88-
flag_bits = s._Symbol__flags
89-
for name, mask in DEF_FLAGS:
90-
if (flag_bits & mask) != 0:
91-
flags.append(name)
92-
if not flags:
93-
flags = ["0"]
94-
out += 'Flags:%s,\n' % "|".join(flags)
95-
114+
out += 'Flags:%s,\n' % dump_flags(s._Symbol__flags, DEF_FLAGS)
96115
scope = SCOPES.get(s._Symbol__scope, "scopeUnknown")
97116
out += 'Scope:%s,\n' % scope
98-
99-
# Return a namespace bound to this name.
100-
ns = s.get_namespaces()
101-
if len(ns) == 0:
102-
pass
103-
elif len(ns) == 1:
104-
out += 'Namespace:%s,\n' % dump_symtable(ns[0])
105-
else:
106-
raise AssertionError("More than one namespace")
107117
out += "}"
108118
return out
109119

compile/stringer.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// generated by stringer -type=Scope,BlockType -output stringer.go; DO NOT EDIT
2+
3+
package compile
4+
5+
import "fmt"
6+
7+
const _Scope_name = "scopeInvalidscopeLocalscopeGlobalExplicitscopeGlobalImplicitscopeFreescopeCell"
8+
9+
var _Scope_index = [...]uint8{0, 12, 22, 41, 60, 69, 78}
10+
11+
func (i Scope) String() string {
12+
if i+1 >= Scope(len(_Scope_index)) {
13+
return fmt.Sprintf("Scope(%d)", i)
14+
}
15+
return _Scope_name[_Scope_index[i]:_Scope_index[i+1]]
16+
}
17+
18+
const _BlockType_name = "FunctionBlockClassBlockModuleBlock"
19+
20+
var _BlockType_index = [...]uint8{0, 13, 23, 34}
21+
22+
func (i BlockType) String() string {
23+
if i+1 >= BlockType(len(_BlockType_index)) {
24+
return fmt.Sprintf("BlockType(%d)", i)
25+
}
26+
return _BlockType_name[_BlockType_index[i]:_BlockType_index[i+1]]
27+
}

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