8000 compile: fix kwonlyargs and raise SyntaxError on duplicated keywords · go-python/gpython@7f90811 · GitHub
[go: up one dir, main page]

Skip to content

Commit 7f90811

Browse files
committed
compile: fix kwonlyargs and raise SyntaxError on duplicated keywords
1 parent e4ed532 commit 7f90811

File tree

3 files changed

+43
-2
lines changed

3 files changed

+43
-2
lines changed

compile/compile.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -528,8 +528,8 @@ func (c *compiler) compileFunc(compilerScope compilerScopeType, Ast ast.Ast, Arg
528528
c.Exprs(Args.Defaults)
8000
529529

530530
// KwDefaults
531-
if len(Args.Kwonlyargs) != len(Args.KwDefaults) {
532-
panic("differing number of Kwonlyargs to KwDefaults")
531+
if len(Args.KwDefaults) > len(Args.Kwonlyargs) {
532+
panic("compile: more KwDefaults than Kwonlyargs")
533533
}
534534
for i := range Args.KwDefaults {
535535
c.LoadConst(py.String(Args.Kwonlyargs[i].Arg))
@@ -1322,11 +1322,16 @@ func (c *compiler) callHelper(n int, Args []ast.Expr, Keywords []*ast.Keyword, S
13221322
c.Expr(Args[i])
13231323
}
13241324
kwargs := len(Keywords)
1325+
duplicateDetector := make(map[ast.Identifier]struct{}, len(Keywords))
13251326
for i := range Keywords {
13261327
kw := Keywords[i]
1328+
duplicateDetector[kw.Arg] = struct{}{}
13271329
c.LoadConst(py.String(kw.Arg))
13281330
c.Expr(kw.Value)
13291331
}
1332+
if len(duplicateDetector) != len(Keywords) {
1333+
panic(py.ExceptionNewf(py.SyntaxError, "keyword argument repeated"))
1334+
}
13301335
op := vm.CALL_FUNCTION
13311336
if Starargs != nil {
13321337
c.Expr(Starargs)

compile/compile_data_test.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2254,6 +2254,7 @@ var compileTestData = []struct {
22542254
Firstlineno: 1,
22552255
Lnotab: "",
22562256
}, nil, ""},
2257+
{"f(a=1,a=2)", "eval", nil, py.SyntaxError, "keyword argument repeated"},
22572258
{"return", "exec", nil, py.SyntaxError, "'return' outside function"},
22582259
{"def fn(): pass", "exec" 8000 , &py.Code{
22592260
Argcount: 0,
@@ -2552,6 +2553,39 @@ var compileTestData = []struct {
25522553
Firstlineno: 1,
25532554
Lnotab: "",
25542555
}, nil, ""},
2556+
{"def fn(x,*,a,b): x+a+b", "exec", &py.Code{
2557+
Argcount: 0,
2558+
Kwonlyargcount: 0,
2559+
Nlocals: 0,
2560+
Stacksize: 2,
2561+
Flags: 64,
2562+
Code: "\x64\x00\x00\x64\x01\x00\x84\x00\x00\x5a\x00\x00\x64\x02\x00\x53",
2563+
Consts: []py.Object{&py.Code{
2564+
Argcount: 1,
2565+
Kwonlyargcount: 2,
2566+
Nlocals: 3,
2567+
Stacksize: 2,
2568+
Flags: 67,
2569+
Code: "\x7c\x00\x00\x7c\x01\x00\x17\x7c\x02\x00\x17\x01\x64\x00\x00\x53",
2570+
Consts: []py.Object{py.None},
2571+
Names: []string{},
2572+
Varnames: []string{"x", "a", "b"},
2573+
Freevars: []string{},
2574+
Cellvars: []string{},
2575+
Filename: "<string>",
2576+
Name: "fn",
2577+
Firstlineno: 1,
2578+
Lnotab: "",
2579+
}, py.String("fn"), py.None},
2580+
Names: []string{"fn"},
2581+
Varnames: []string{},
2582+
Freevars: []string{},
2583+
Cellvars: []string{},
2584+
Filename: "<string>",
2585+
Name: "<module>",
2586+
Firstlineno: 1,
2587+
Lnotab: "",
2588+
}, nil, ""},
25552589
{"def fn(a):\n global b\n b = a", "exec", &py.Code{
25562590
Argcount: 0,
25572591
Kwonlyargcount: 0,

compile/make_compile_test.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ def nested(d):
176176
('''f(a, b, *args)''', "eval"),
177177
('''f(a, b, *args, d=e, **kwargs)''', "eval"),
178178
('''f(a, d=e, **kwargs)''', "eval"),
179+
('''f(a=1,a=2)''', "eval", SyntaxError),
179180
# return
180181
('''return''', "exec", SyntaxError),
181182
# def
@@ -188,6 +189,7 @@ def nested(d):
188189
('''def fn(a:"a",*arg:"arg",b:"b"=1,c:"c"=2,**kwargs:"kw") -> "ret": pass''', "exec"),
189190
('''def fn(): a+b''', "exec"),
190191
('''def fn(a,b): a+b+c+d''', "exec"),
192+
('''def fn(x,*,a,b): x+a+b''', "exec"),
191193
('''\
192194
def fn(a):
193195
global b

0 commit comments

Comments
 (0)
0