10
10
package compile
11
11
12
12
import (
13
+ "fmt"
13
14
"log"
14
15
"strings"
15
16
@@ -84,9 +85,9 @@ type Symbol struct {
84
85
85
86
type Symbols map [string ]Symbol
86
87
87
- func NewSymbols () Symbols {
88
- return make ( Symbols )
89
- }
88
+ type Children [] * SymTable
89
+
90
+ type LookupChild map [ast. Ast ] * SymTable
90
91
91
92
type SymTable struct {
92
93
Type BlockType // 'class', 'module', and 'function'
@@ -104,13 +105,14 @@ type SymTable struct {
104
105
// col_offset int // offset of first line of block
105
106
// opt_lineno int // lineno of last exec or import *
106
107
// 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
114
116
}
115
117
116
118
// Make a new top symbol table from the ast supplied
@@ -127,11 +129,12 @@ func NewSymTable(Ast ast.Ast) *SymTable {
127
129
// Make a new symbol table from the ast supplied of the given type
128
130
func newSymTable (Type BlockType , Name string , parent * SymTable ) * SymTable {
129
131
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 ),
135
138
}
136
139
if parent == nil {
137
140
st .Global = st
@@ -142,6 +145,15 @@ func newSymTable(Type BlockType, Name string, parent *SymTable) *SymTable {
142
145
return st
143
146
}
144
147
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
+
145
157
// Parse the ast into the symbol table
146
158
func (st * SymTable ) Parse (Ast ast.Ast ) {
147
159
ast .Walk (Ast , func (Ast ast.Ast ) bool {
@@ -199,10 +211,8 @@ func (st *SymTable) Parse(Ast ast.Ast) {
199
211
st .AddDef (node .Name , defLocal )
200
212
name := string (node .Name )
201
213
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 )
206
216
207
217
// Walk the Decorators and Returns in this Symtable
208
218
for _ , expr := range node .DecoratorList {
@@ -292,34 +302,44 @@ func (st *SymTable) Parse(Ast ast.Ast) {
292
302
})
293
303
}
294
304
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
299
315
outermost := generators [0 ]
300
316
// Outermost iterator is evaluated in current scope
301
317
st .Parse (outermost .Iter )
302
318
// 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
307
321
// 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 )
310
324
// Allocate temporary name if needed
311
- if needs_tmp {
312
- symtable_new_tmpname(st )
325
+ if needsTmp {
326
+ stNew . newTmpName ( )
313
327
}
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 )
319
331
}
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 )
323
343
}
324
344
325
345
const duplicateArgument = "duplicate argument %q in function definition"
0 commit comments