@@ -105,7 +105,8 @@ type SymTable struct {
105
105
// col_offset int // offset of first line of block
106
106
// opt_lineno int // lineno of last exec or import *
107
107
// opt_col_offset int // offset of last exec or import *
108
- TmpName int // counter for listcomp temp vars
108
+ TmpName int // counter for listcomp temp vars
109
+ Private string // name of current class or ""
109
110
110
111
Symbols Symbols
111
112
Global * SymTable // symbol table entry for module
@@ -154,15 +155,32 @@ func newSymTableBlock(Ast ast.Ast, Type BlockType, Name string, parent *SymTable
154
155
return stNew
155
156
}
156
157
158
+ // Add arguments to the symbol table
159
+ func (st * SymTable ) addArgumentsToSymbolTable (node * ast.Arguments ) {
160
+ if node .Args == nil {
161
+ return
162
+ }
163
+ // skip default arguments inside function block
164
+ // XXX should ast be different?
165
+ for _ , arg := range node .Args {
166
+ st .AddDef (arg .Arg , defParam )
167
+ }
168
+ for _ , arg := range node .Kwonlyargs {
169
+ st .AddDef (arg .Arg , defParam )
170
+ }
171
+ if node .Vararg != nil {
172
+ st .AddDef (node .Vararg .Arg , defParam )
173
+ st .Varargs = true
174
+ }
175
+ if node .Kwarg != nil {
176
+ st .AddDef (node .Kwarg .Arg , defParam )
177
+ st .Varkeywords = true
178
+ }
179
+ }
180
+
157
181
// Parse the ast into the symbol table
158
182
func (st * SymTable ) Parse (Ast ast.Ast ) {
159
183
ast .Walk (Ast , func (Ast ast.Ast ) bool {
160
- // New symbol tables needed at these points
161
- // FunctionDef
162
- // ClassDef
163
- // Lambda
164
- // Comprehension (all types of comprehension in py3)
165
-
166
184
switch node := Ast .(type ) {
167
185
case * ast.Nonlocal :
168
186
for _ , name := range node .Names {
@@ -211,19 +229,22 @@ func (st *SymTable) Parse(Ast ast.Ast) {
211
229
st .AddDef (node .Name , defLocal )
212
230
name := string (node .Name )
213
231
214
- // Make a new symtable
215
- stNew := newSymTableBlock ( Ast , FunctionBlock , name , st )
216
-
217
- // Walk the Decorators and Returns in this Symtable
232
+ // Walk these things in original symbol table
233
+ if node . Args != nil {
234
+ st . Parse ( node . Args )
235
+ }
218
236
for _ , expr := range node .DecoratorList {
219
237
st .Parse (expr )
220
238
}
221
239
st .Parse (node .Returns )
222
240
223
- // Walk the Args and Body in the new symtable
224
- if node .Args != nil {
225
- stNew .Parse (node .Args )
226
- }
241
+ // Make a new symtable
242
+ stNew := newSymTableBlock (Ast , FunctionBlock , name , st )
243
+
244
+ // Add the arguments to the new symbol table
245
+ stNew .addArgumentsToSymbolTable (node .Args )
246
+
247
+ // Walk the Body in the new symtable
227
248
for _ , stmt := range node .Body {
228
249
stNew .Parse (stmt )
229
250
}
@@ -232,9 +253,49 @@ func (st *SymTable) Parse(Ast ast.Ast) {
232
253
return false
233
254
case * ast.ClassDef :
234
255
st .AddDef (node .Name , defLocal )
256
+ name := string (node .Name )
257
+ // Parse in the original symtable
258
+ for _ , expr := range node .Bases {
259
+ st .Parse (expr )
260
+ }
261
+ for _ , keyword := range node .Keywords {
262
+ st .Parse (keyword )
263
+ }
264
+ if node .Starargs != nil {
265
+ st .Parse (node .Starargs )
266
+ }
267
+ if node .Kwargs != nil {
268
+ st .Parse (node .Kwargs )
269
+ }
270
+ for _ , expr := range node .DecoratorList {
271
+ st .Parse (expr )
272
+ }
273
+ // Make a new symtable
274
+ stNew := newSymTableBlock (Ast , ClassBlock , name , st )
275
+ stNew .Private = name // set name of class
276
+ // Parse body in new symtable
277
+ for _ , stmt := range node .Body {
278
+ stNew .Parse (stmt )
279
+ }
280
+ // return false to stop the parse
281
+ return false
235
282
case * ast.Lambda :
283
+ // Parse in the original symtable
284
+ if node .Args != nil {
285
+ st .Parse (node .Args )
286
+ }
287
+
288
+ // Make a new symtable
289
+ stNew := newSymTableBlock (Ast , FunctionBlock , "lambda" , st )
236
290
237
- // Comprehensions
291
+ // Add the arguments to the new symbol table
292
+ stNew .addArgumentsToSymbolTable (node .Args )
293
+
294
+ // Walk the Body in the new symtable
295
+ stNew .Parse (node .Body )
296
+
297
+ // return false to stop the parse
298
+ return false
238
299
case * ast.ListComp :
239
300
st .parseComprehension (Ast , "listcomp" , node .Generators , node .Elt , nil )
240
301
return false
@@ -247,30 +308,10 @@ func (st *SymTable) Parse(Ast ast.Ast) {
247
308
case * ast.GeneratorExp :
248
309
st .parseComprehension (Ast , "genexpr" , node .Generators , node .Elt , nil )
249
310
return false
250
-
251
- case * ast.Arguments :
252
- // skip default arguments inside function block
253
- // XXX should ast be different?
254
- for _ , arg := range node .Args {
255
- st .AddDef (arg .Arg , defParam )
256
- }
257
- for _ , arg := range node .Kwonlyargs {
258
- st .AddDef (arg .Arg , defParam )
259
- }
260
- if node .Vararg != nil {
261
- st .AddDef (node .Vararg .Arg , defParam )
262
- st .Varargs = true
263
- }
264
- if node .Kwarg != nil {
265
- st .AddDef (node .Kwarg .Arg , defParam )
266
- st .Varkeywords = true
267
- }
268
-
269
311
case * ast.ExceptHandler :
270
312
if node .Name != "" {
271
313
st .AddDef (node .Name , defLocal )
272
314
}
273
-
274
315
case * ast.Alias :
275
316
// Compute store_name, the name actually bound by the import
276
317
// operation. It is different than node.name when node.name is a
@@ -282,7 +323,7 @@ func (st *SymTable) Parse(Ast ast.Ast) {
282
323
dot := strings .LastIndex (string (name ), "." )
283
324
store_name := name
284
325
if dot >= 0 {
285
- store_name = name [dot + 1 : ]
326
+ store_name = name [: dot ]
286
327
}
287
328
if name != "*" {
288
329
st .AddDef (store_name , defImport )
@@ -292,7 +333,6 @@ func (st *SymTable) Parse(Ast ast.Ast) {
292
333
}
293
334
st .Unoptimized |= optImportStar
294
335
}
295
-
296
336
case * ast.Return :
297
337
if node .Value != nil {
298
338
st .ReturnsValue = true
@@ -342,18 +382,16 @@ func (st *SymTable) parseComprehension(Ast ast.Ast, scopeName string, generators
342
382
stNew .Parse (elt )
343
383
}
344
384
345
- const duplicateArgument = "duplicate argument %q in function definition"
346
-
347
385
// Add a symbol into the symble table
348
386
func (st * SymTable ) AddDef (name ast.Identifier , flags DefUse ) {
349
- // FIXME mangled := _Py_Mangle(st.st_private , name)
387
+ // FIXME mangled := _Py_Mangle(st.Private , name)
350
388
mangled := string (name )
351
389
352
390
// Add or update the symbol in the Symbols
353
391
if sym , ok := st .Symbols [mangled ]; ok {
354
392
if (flags & defParam ) != 0 && (sym .Flags & defParam ) != 0 {
355
393
// Is it better to use 'mangled' or 'name' here?
356
- panic (py .ExceptionNewf (py .SyntaxError , duplicateArgument , name ))
394
+ panic (py .ExceptionNewf (py .SyntaxError , "duplicate argument '%s' in function definition" , name ))
357
395
// FIXME
358
396
// PyErr_SyntaxLocationObject(st.st_filename,
359
397
// st.st_cur.ste_lineno,
@@ -574,6 +612,14 @@ func (st *SymTable) CheckUnoptimized() {
574
612
return
575
613
}
576
614
615
+ // FIXME Acording to this
616
+ // https://docs.python.org/3/whatsnew/3.0.html#removed-syntax
617
+ //
618
+ // The from module import * syntax is only allowed at the
619
+ // module level, no longer inside functions.
620
+ //
621
+ // So I think this is dead code
622
+
577
623
trailer := "contains a nested function with free variables"
578
624
if ! st .ChildFree {
579
625
trailer = "is a nested function"
@@ -588,7 +634,7 @@ func (st *SymTable) CheckUnoptimized() {
588
634
}
589
635
}
590
636
591
- /* Enter the final scope information into the ste_symbols dict.
637
+ /* Enter the final scope information into the st.Symbols dict.
592
638
*
593
639
* All arguments are dicts. Modifies symbols, others are read-only.
594
640
*/
@@ -601,6 +647,9 @@ func (symbols Symbols) Update(scopes Scopes, bound, free StringSet, classflag bo
601
647
602
648
/* Record not yet resolved free variables from children (if any) */
603
649
for name := range free {
650
+ // FIXME haven't managed to find a test case for this code
651
+ // suspect a problem!
652
+
604
653
/* Handle symbol that already exists in this scope */
605
654
if symbol , ok := symbols [name ]; ok {
606
655
/* Handle a free variable in a method of
@@ -643,12 +692,6 @@ func (symbols Symbols) Update(scopes Scopes, bound, free StringSet, classflag bo
643
692
propagate back to a parent block.
644
693
*/
645
694
func (st * SymTable ) AnalyzeBlock (bound , free , global StringSet ) {
646
- // PyObject *name, *v, *local = nil, *scopes = nil, *newbound = nil;
647
- // PyObject *newglobal = nil, *newfree = nil, *allfree = nil;
648
- // PyObject *temp;
649
- // int i, success = 0;
650
- // Py_ssize_t pos = 0;
651
-
652
695
local := make (StringSet ) // collect new names bound in block
653
696
scopes := make (Scopes ) // collect scopes defined for each name
654
697
0 commit comments