1
1
// compile python code
2
2
package compile
3
3
4
- // FIXME line numbers
5
4
// FIXME name mangling
6
5
// FIXME kill ast.Identifier and turn into string?
7
6
@@ -68,6 +67,7 @@ const (
68
67
// State for the compiler
69
68
type compiler struct {
70
69
Code * py.Code // code being built up
70
+ Filename string
71
71
OpCodes Instructions
72
72
loops loopstack
73
73
SymTable * symtable.SymTable
@@ -104,11 +104,12 @@ func Compile(str, filename, mode string, futureFlags int, dont_inherit bool) (py
104
104
return nil , err
105
105
}
106
106
// Make symbol table
107
- SymTable , err := symtable .NewSymTable (Ast )
107
+ SymTable , err := symtable .NewSymTable (Ast , filename )
108
108
if err != nil {
109
109
return nil , err
110
110
}
111
111
c := newCompiler (nil , compilerScopeModule )
112
+ c .Filename = filename
112
113
err = c .compileAst (Ast , filename , futureFlags , dont_inherit , SymTable )
113
114
if err != nil {
114
115
return nil , err
@@ -131,10 +132,18 @@ func newCompiler(parent *compiler, scopeType compilerScopeType) *compiler {
131
132
}
132
133
if parent != nil {
133
134
c .depth = parent .depth + 1
135
+ c .Filename = parent .Filename
134
136
}
135
137
return c
136
138
}
137
139
140
+ // Panics abount a syntax error on this ast node
141
+ func (c * compiler ) panicSyntaxErrorf (Ast ast.Ast , format string , a ... interface {}) {
142
+ err := py .ExceptionNewf (py .SyntaxError , format , a ... )
143
+ err = py .MakeSyntaxError (err , c .Filename , Ast .GetLineno (), Ast .GetColOffset (), "" )
144
+ panic (err )
145
+ }
146
+
138
147
// Create a new compiler object at Ast, using private for name mangling
139
148
func (c * compiler ) newCompilerScope (compilerScope compilerScopeType , Ast ast.Ast , private string ) (newC * compiler ) {
140
149
newSymTable := c .SymTable .FindChild (Ast )
@@ -791,7 +800,7 @@ func (c *compiler) tryExcept(node *ast.Try) {
791
800
c .Label (except )
792
801
for i , handler := range node .Handlers {
793
802
if handler .ExprType == nil && i < n - 1 {
794
- panic ( py . ExceptionNewf ( py . SyntaxError , "default 'except:' must be last" ) )
803
+ c . panicSyntaxErrorf ( handler , "default 'except:' must be last" )
795
804
}
796
805
// FIXME c.u.u_lineno_set = 0
797
806
// c.u.u_lineno = handler.lineno
@@ -976,7 +985,7 @@ func (c *compiler) Stmt(stmt ast.Stmt) {
976
985
case * ast.Return :
977
986
// Value Expr
978
987
if c .SymTable .Type != symtable .FunctionBlock {
979
- panic ( py . ExceptionNewf ( py . SyntaxError , "'return' outside function" ) )
988
+ c . panicSyntaxErrorf ( node , "'return' outside function" )
980
989
}
981
990
if node .Value != nil {
982
991
c .Expr (node .Value )
@@ -1165,15 +1174,15 @@ func (c *compiler) Stmt(stmt ast.Stmt) {
1165
1174
case * ast.Break :
1166
1175
l := c .loops .Top ()
1167
1176
if l == nil {
1168
- panic ( py . ExceptionNewf ( py . SyntaxError , "'break' outside loop" ) )
1177
+ c . panicSyntaxErrorf ( node , "'break' outside loop" )
1169
1178
}
1170
1179
c .Op (vm .BREAK_LOOP )
1171
1180
case * ast.Continue :
1172
1181
const loopError = "'continue' not properly in loop"
1173
1182
const inFinallyError = "'continue' not supported inside 'finally' clause"
1174
1183
l := c .loops .Top ()
1175
1184
if l == nil {
1176
- panic ( py . ExceptionNewf ( py . SyntaxError , loopError ) )
1185
+ c . panicSyntaxErrorf ( node , loopError )
1177
1186
}
1178
1187
switch l .Type {
1179
1188
case loopLoop :
@@ -1187,15 +1196,15 @@ func (c *compiler) Stmt(stmt ast.Stmt) {
1187
1196
}
1188
1197
// Prevent continue anywhere under a finally even if hidden in a sub-try or except.
1189
1198
if l .Type == finallyEndLoop {
1190
- panic ( py . ExceptionNewf ( py . SyntaxError , inFinallyError ) )
1199
+ c . panicSyntaxErrorf ( node , inFinallyError )
1191
1200
}
1192
1201
}
1193
1202
if i == - 1 {
1194
- panic ( py . ExceptionNewf ( py . SyntaxError , loopError ) )
1203
+ c . panicSyntaxErrorf ( node , loopError )
1195
1204
}
1196
1205
c .Jump (vm .CONTINUE_LOOP , l .Start )
1197
1206
case finallyEndLoop :
1198
- panic ( py . ExceptionNewf ( py . SyntaxError , inFinallyError ) )
1207
+ c . panicSyntaxErrorf ( node , inFinallyError )
1199
1208
default :
1200
1209
panic ("unknown loop type" )
1201
1210
}
@@ -1329,14 +1338,21 @@ func (c *compiler) callHelper(n int, Args []ast.Expr, Keywords []*ast.Keyword, S
1329
1338
}
1330
1339
kwargs := len (Keywords )
1331
1340
duplicateDetector := make (map [ast.Identifier ]struct {}, len (Keywords ))
1341
+ var duplicate * ast.Keyword
1332
1342
for i := range Keywords {
1333
1343
kw := Keywords [i ]
1334
- duplicateDetector [kw .Arg ] = struct {}{}
1344
+ if _ , found := duplicateDetector [kw .Arg ]; found {
1345
+ if duplicate == nil {
1346
+ duplicate = kw
1347
+ }
1348
+ } else {
1349
+ duplicateDetector [kw .Arg ] = struct {}{}
1350
+ }
1335
1351
c .LoadConst (py .String (kw .Arg ))
1336
1352
c .Expr (kw .Value )
1337
1353
}
1338
- if len ( duplicateDetector ) != len ( Keywords ) {
1339
- panic ( py . ExceptionNewf ( py . SyntaxError , "keyword argument repeated" ) )
1354
+ if duplicate != nil {
1355
+ c . panicSyntaxErrorf ( duplicate , "keyword argument repeated" )
1340
1356
}
1341
1357
op := vm .CALL_FUNCTION
1342
1358
if Starargs != nil {
@@ -1447,14 +1463,14 @@ func (c *compiler) tupleOrList(op vm.OpCode, ctx ast.ExprContext, elts []ast.Exp
1447
1463
starred , isStarred := elt .(* ast.Starred )
1448
1464
if isStarred && ! seen_star {
1449
1465
if i >= (1 << 8 ) || n - i - 1 >= (INT_MAX >> 8 ) {
1450
- panic ( py . ExceptionNewf ( py . SyntaxError , "too many expressions in star-unpacking assignment" ) )
1466
+ c . panicSyntaxErrorf ( elt , "too many expressions in star-unpacking assignment" )
1451
1467
}
1452
1468
c .OpArg (vm .UNPACK_EX , uint32 ((i + ((n - i - 1 ) << 8 ))))
1453
1469
seen_star = true
1454
1470
// FIXME Overwrite the starred element
1455
1471
elts [i ] = starred .Value
1456
1472
} else if isStarred {
1457
- panic ( py . ExceptionNewf ( py . SyntaxError , "two starred expressions in assignment" ) )
1473
+ c . panicSyntaxErrorf ( elt , "two starred expressions in assignment" )
1458
1474
}
1459
1475
}
1460
1476
if ! seen_star {
@@ -1692,7 +1708,7 @@ func (c *compiler) Expr(expr ast.Expr) {
1692
1708
case * ast.Yield :
1693
1709
// Value Expr
1694
1710
if c .SymTable .Type != symtable .FunctionBlock {
1695
- panic ( py . ExceptionNewf ( py . SyntaxError , "'yield' outside function" ) )
1711
+ c . panicSyntaxErrorf ( node , "'yield' outside function" )
1696
1712
}
1697
1713
if node .Value != nil {
1698
1714
c .Expr (node .Value )
@@ -1703,7 +1719,7 @@ func (c *compiler) Expr(expr ast.Expr) {
1703
1719
case * ast.YieldFrom :
1704
1720
// Value Expr
1705
1721
if c .SymTable .Type != symtable .FunctionBlock {
1706
- panic ( py . ExceptionNewf ( py . SyntaxError , "'yield' outside function" ) )
1722
+ c . panicSyntaxErrorf ( node , "'yield' outside function" )
1707
1723
}
1708
1724
c .Expr (node .Value )
1709
1725
c .Op (vm .GET_ITER )
@@ -1845,9 +1861,9 @@ func (c *compiler) Expr(expr ast.Expr) {
1845
1861
case ast .Store :
1846
1862
// In all legitimate cases, the Starred node was already replaced
1847
1863
// by tupleOrList: is that okay?
1848
- panic ( py . ExceptionNewf ( py . SyntaxError , "starred assignment target must be in a list or tuple" ) )
1864
+ c . panicSyntaxErrorf ( node , "starred assignment target must be in a list or tuple" )
1849
1865
default :
1850
- panic ( py . ExceptionNewf ( py . SyntaxError , "can use starred expression only as assignment target" ) )
1866
+ c . panicSyntaxErrorf ( node , "can use starred expression only as assignment target" )
1851
1867
}
1852
1868
case * ast.Name :
1853
1869
// Id Identifier
0 commit comments