11// compile python code
22package compile
33
4- // FIXME line numbers
54// FIXME name mangling
65// FIXME kill ast.Identifier and turn into string?
76
@@ -68,6 +67,7 @@ const (
6867// State for the compiler
6968type compiler struct {
7069 Code * py.Code // code being built up
70+ Filename string
7171 OpCodes Instructions
7272 loops loopstack
7373 SymTable * symtable.SymTable
@@ -104,11 +104,12 @@ func Compile(str, filename, mode string, futureFlags int, dont_inherit bool) (py
104104 return nil , err
105105 }
106106 // Make symbol table
107- SymTable , err := symtable .NewSymTable (Ast )
107+ SymTable , err := symtable .NewSymTable (Ast , filename )
108108 if err != nil {
109109 return nil , err
110110 }
111111 c := newCompiler (nil , compilerScopeModule )
112+ c .Filename = filename
112113 err = c .compileAst (Ast , filename , futureFlags , dont_inherit , SymTable )
113114 if err != nil {
114115 return nil , err
@@ -131,10 +132,18 @@ func newCompiler(parent *compiler, scopeType compilerScopeType) *compiler {
131132 }
132133 if parent != nil {
133134 c .depth = parent .depth + 1
135+ c .Filename = parent .Filename
134136 }
135137 return c
136138}
137139
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+
138147// Create a new compiler object at Ast, using private for name mangling
139148func (c * compiler ) newCompilerScope (compilerScope compilerScopeType , Ast ast.Ast , private string ) (newC * compiler ) {
140149 newSymTable := c .SymTable .FindChild (Ast )
@@ -791,7 +800,7 @@ func (c *compiler) tryExcept(node *ast.Try) {
791800 c .Label (except )
792801 for i , handler := range node .Handlers {
793802 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" )
795804 }
796805 // FIXME c.u.u_lineno_set = 0
797806 // c.u.u_lineno = handler.lineno
@@ -976,7 +985,7 @@ func (c *compiler) Stmt(stmt ast.Stmt) {
976985 case * ast.Return :
977986 // Value Expr
978987 if c .SymTable .Type != symtable .FunctionBlock {
979- panic ( py . ExceptionNewf ( py . SyntaxError , "'return' outside function" ) )
988+ c . panicSyntaxErrorf ( node , "'return' outside function" )
980989 }
981990 if node .Value != nil {
982991 c .Expr (node .Value )
@@ -1165,15 +1174,15 @@ func (c *compiler) Stmt(stmt ast.Stmt) {
11651174 case * ast.Break :
11661175 l := c .loops .Top ()
11671176 if l == nil {
1168- panic ( py . ExceptionNewf ( py . SyntaxError , "'break' outside loop" ) )
1177+ c . panicSyntaxErrorf ( node , "'break' outside loop" )
11691178 }
11701179 c .Op (vm .BREAK_LOOP )
11711180 case * ast.Continue :
11721181 const loopError = "'continue' not properly in loop"
11731182 const inFinallyError = "'continue' not supported inside 'finally' clause"
11741183 l := c .loops .Top ()
11751184 if l == nil {
1176- panic ( py . ExceptionNewf ( py . SyntaxError , loopError ) )
1185+ c . panicSyntaxErrorf ( node , loopError )
11771186 }
11781187 switch l .Type {
11791188 case loopLoop :
@@ -1187,15 +1196,15 @@ func (c *compiler) Stmt(stmt ast.Stmt) {
11871196 }
11881197 // Prevent continue anywhere under a finally even if hidden in a sub-try or except.
11891198 if l .Type == finallyEndLoop {
1190- panic ( py . ExceptionNewf ( py . SyntaxError , inFinallyError ) )
1199+ c . panicSyntaxErrorf ( node , inFinallyError )
11911200 }
11921201 }
11931202 if i == - 1 {
1194- panic ( py . ExceptionNewf ( py . SyntaxError , loopError ) )
1203+ c . panicSyntaxErrorf ( node , loopError )
11951204 }
11961205 c .Jump (vm .CONTINUE_LOOP , l .Start )
11971206 case finallyEndLoop :
1198- panic ( py . ExceptionNewf ( py . SyntaxError , inFinallyError ) )
1207+ c . panicSyntaxErrorf ( node , inFinallyError )
11991208 default :
12001209 panic ("unknown loop type" )
12011210 }
@@ -1329,14 +1338,21 @@ func (c *compiler) callHelper(n int, Args []ast.Expr, Keywords []*ast.Keyword, S
13291338 }
13301339 kwargs := len (Keywords )
13311340 duplicateDetector := make (map [ast.Identifier ]struct {}, len (Keywords ))
1341+ var duplicate * ast.Keyword
13321342 for i := range Keywords {
13331343 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+ }
13351351 c .LoadConst (py .String (kw .Arg ))
13361352 c .Expr (kw .Value )
13371353 }
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" )
13401356 }
13411357 op := vm .CALL_FUNCTION
13421358 if Starargs != nil {
@@ -1447,14 +1463,14 @@ func (c *compiler) tupleOrList(op vm.OpCode, ctx ast.ExprContext, elts []ast.Exp
14471463 starred , isStarred := elt .(* ast.Starred )
14481464 if isStarred && ! seen_star {
14491465 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" )
14511467 }
14521468 c .OpArg (vm .UNPACK_EX , uint32 ((i + ((n - i - 1 ) << 8 ))))
14531469 seen_star = true
14541470 // FIXME Overwrite the starred element
14551471 elts [i ] = starred .Value
14561472 } else if isStarred {
1457- panic ( py . ExceptionNewf ( py . SyntaxError , "two starred expressions in assignment" ) )
1473+ c . panicSyntaxErrorf ( elt , "two starred expressions in assignment" )
14581474 }
14591475 }
14601476 if ! seen_star {
@@ -1692,7 +1708,7 @@ func (c *compiler) Expr(expr ast.Expr) {
16921708 case * ast.Yield :
16931709 // Value Expr
16941710 if c .SymTable .Type != symtable .FunctionBlock {
1695- panic ( py . ExceptionNewf ( py . SyntaxError , "'yield' outside function" ) )
1711+ c . panicSyntaxErrorf ( node , "'yield' outside function" )
16961712 }
16971713 if node .Value != nil {
16981714 c .Expr (node .Value )
@@ -1703,7 +1719,7 @@ func (c *compiler) Expr(expr ast.Expr) {
17031719 case * ast.YieldFrom :
17041720 // Value Expr
17051721 if c .SymTable .Type != symtable .FunctionBlock {
1706- panic ( py . ExceptionNewf ( py . SyntaxError , "'yield' outside function" ) )
1722+ c . panicSyntaxErrorf ( node , "'yield' outside function" )
17071723 }
17081724 c .Expr (node .Value )
17091725 c .Op (vm .GET_ITER )
@@ -1845,9 +1861,9 @@ func (c *compiler) Expr(expr ast.Expr) {
18451861 case ast .Store :
18461862 // In all legitimate cases, the Starred node was already replaced
18471863 // 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" )
18491865 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" )
18511867 }
18521868 case * ast.Name :
18531869 // Id Identifier
0 commit comments