1010package compile
1111
1212import (
13+ "fmt"
1314 "log"
1415 "strings"
1516
@@ -84,9 +85,9 @@ type Symbol struct {
8485
8586type Symbols map [string ]Symbol
8687
87- func NewSymbols () Symbols {
88- return make ( Symbols )
89- }
88+ type Children [] * SymTable
89+
90+ type LookupChild map [ast. Ast ] * SymTable
9091
9192type SymTable struct {
9293 Type BlockType // 'class', 'module', and 'function'
@@ -104,13 +105,14 @@ type SymTable struct {
104105 // col_offset int // offset of first line of block
105106 // opt_lineno int // lineno of last exec or import *
106107 // opt_col_offset int // offset of last exec or import *
107- // tmpname int // counter for listcomp temp vars
108-
109- Symbols Symbols
110- Global * SymTable // symbol table entry for module
111- Parent * SymTable
112- Varnames []string // list of function parameters
113- Children map [string ]* SymTable // Child SymTables keyed by symbol name
108+ TmpName int // counter for listcomp temp vars
109+
110+ Symbols Symbols
111+ Global * SymTable // symbol table entry for module
112+ Parent * SymTable
113+ Varnames []string // list of function parameters
114+ Children Children // Child SymTables
115+ LookupChild LookupChild // Child symtables keyed by ast
114116}
115117
116118// Make a new top symbol table from the ast supplied
@@ -127,11 +129,12 @@ func NewSymTable(Ast ast.Ast) *SymTable {
127129// Make a new symbol table from the ast supplied of the given type
128130func newSymTable (Type BlockType , Name string , parent * SymTable ) * SymTable {
129131 st := & SymTable {
130- Type : Type ,
131- Name : Name ,
132- Parent : parent ,
133- Symbols : NewSymbols (),
134- Children : make (map [string ]* SymTable ),
132+ Type : Type ,
133+ Name : Name ,
134+ Parent : parent ,
135+ Symbols : make (Symbols ),
136+ Children : make (Children , 0 ),
137+ LookupChild : make (LookupChild ),
135138 }
136139 if parent == nil {
137140 st .Global = st
@@ -142,6 +145,15 @@ func newSymTable(Type BlockType, Name string, parent *SymTable) *SymTable {
142145 return st
143146}
144147
148+ // Make a new symtable and add it to parent
149+ func newSymTableBlock (Ast ast.Ast , Type BlockType , Name string , parent * SymTable ) * SymTable {
150+ stNew := newSymTable (Type , Name , parent )
151+ parent .Children = append (parent .Children , stNew )
152+ parent .LookupChild [Ast ] = stNew
153+ // FIXME set stNew.Lineno
154+ return stNew
155+ }
156+
145157// Parse the ast into the symbol table
146158func (st * SymTable ) Parse (Ast ast.Ast ) {
147159 ast .Walk (Ast , func (Ast ast.Ast ) bool {
@@ -199,10 +211,8 @@ func (st *SymTable) Parse(Ast ast.Ast) {
199211 st .AddDef (node .Name , defLocal )
200212 name := string (node .Name )
201213
202- // Make a new symtable and add it to parent
203- stNew := newSymTable (FunctionBlock , name , st )
204- st .Children [name ] = stNew
205- // FIXME set stNew.Lineno
214+ // Make a new symtable
215+ stNew := newSymTableBlock (Ast , FunctionBlock , name , st )
206216
207217 // Walk the Decorators and Returns in this Symtable
208218 for _ , expr := range node .DecoratorList {
@@ -292,34 +302,44 @@ func (st *SymTable) Parse(Ast ast.Ast) {
292302 })
293303}
294304
295- func (st * SymTable ) parseComprehension (Ast ast.Ast , scope_name ast.Identifier , generators []ast.Comprehension , elt ast.Expr , value ast.Expr ) {
296- /* FIXME
297- _, is_generator := Ast.(*ast.GeneratorExp)
298- needs_tmp := !is_generator
305+ // make a new temporary name
306+ func (st * SymTable ) newTmpName () {
307+ st .TmpName ++
308+ id := ast .Identifier (fmt .Sprintf ("_[%d]" , st .TmpName ))
309+ st .AddDef (id , defLocal )
310+ }
311+
312+ func (st * SymTable ) parseComprehension (Ast ast.Ast , scopeName string , generators []ast.Comprehension , elt ast.Expr , value ast.Expr ) {
313+ _ , isGenerator := Ast .(* ast.GeneratorExp )
314+ needsTmp := ! isGenerator
299315 outermost := generators [0 ]
300316 // Outermost iterator is evaluated in current scope
301317 st .Parse (outermost .Iter )
302318 // Create comprehension scope for the rest
303- if scope_name == "" || !symtable_enter_block(st, scope_name, FunctionBlock, e, e.lineno, e.col_offset) {
304- return 0
305- }
306- st.st_cur.ste_generator = is_generator
319+ stNew := newSymTableBlock (Ast , FunctionBlock , scopeName , st )
320+ stNew .Generator = isGenerator
307321 // Outermost iter is received as an argument
308- id := ast.Identifier(fmt.Sprintf(".%d", pos ))
309- st .AddDef(id, defParam)
322+ id := ast .Identifier (fmt .Sprintf (".%d" , 0 ))
323+ stNew .AddDef (id , defParam )
310324 // Allocate temporary name if needed
311- if needs_tmp {
312- symtable_new_tmpname(st )
325+ if needsTmp {
326+ stNew . newTmpName ( )
313327 }
314- VISIT(st, expr, outermost.target)
315- parseSeq(st, expr, outermost.ifs)
316- parseSeq_tail(st, comprehension, generators, 1)
317- if value {
318- VISIT(st, expr, value)
328+ stNew .Parse (outermost .Target )
329+ for _ , expr := range outermost .Ifs {
330+ stNew .Parse (expr )
319331 }
320- VISIT(st, expr, elt)
321- return symtable_exit_block(st, e)
322- */
332+ for _ , comprehension := range generators [1 :] {
333+ stNew .Parse (comprehension .Target )
334+ stNew .Parse (comprehension .Iter )
335+ for _ , expr := range comprehension .Ifs {
336+ stNew .Parse (expr )
337+ }
338+ }
339+ if value != nil {
340+ stNew .Parse (value )
341+ }
342+ stNew .Parse (elt )
323343}
324344
325345const duplicateArgument = "duplicate argument %q in function definition"
0 commit comments