Skip to content

Commit 069f460

Browse files
committed
compile: implement yield and yield from
1 parent cc7bc38 commit 069f460

File tree

3 files changed

+135
-3
lines changed

3 files changed

+135
-3
lines changed

compile/compile.go

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1515,10 +1515,24 @@ func (c *compiler) Expr(expr ast.Expr) {
15151515
c.comprehension(expr, node.Generators)
15161516
case *ast.Yield:
15171517
// Value Expr
1518-
panic("FIXME compile: Yield not implemented")
1518+
if c.SymTable.Type != symtable.FunctionBlock {
1519+
panic(py.ExceptionNewf(py.SyntaxError, "'yield' outside function"))
1520+
}
1521+
if node.Value != nil {
1522+
c.Expr(node.Value)
1523+
} else {
1524+
c.LoadConst(py.None)
1525+
}
1526+
c.Op(vm.YIELD_VALUE)
15191527
case *ast.YieldFrom:
15201528
// Value Expr
1521-
panic("FIXME compile: YieldFrom not implemented")
1529+
if c.SymTable.Type != symtable.FunctionBlock {
1530+
panic(py.ExceptionNewf(py.SyntaxError, "'yield' outside function"))
1531+
}
1532+
c.Expr(node.Value)
1533+
c.Op(vm.GET_ITER)
1534+
c.LoadConst(py.None)
1535+
c.Op(vm.YIELD_FROM)
15221536
case *ast.Compare:
15231537
// Left Expr
15241538
// Ops []CmpOp

compile/compile_data_test.go

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3722,4 +3722,106 @@ var compileTestData = []struct {
37223722
Firstlineno: 1,
37233723
Lnotab: "",
37243724
}, nil, ""},
3725+
{"yield", "exec", nil, py.SyntaxError, "'yield' outside function"},
3726+
{"yield potato", "exec", nil, py.SyntaxError, "'yield' outside function"},
3727+
{"def f():\n yield\n ", "exec", &py.Code{
3728+
Argcount: 0,
3729+
Kwonlyargcount: 0,
3730+
Nlocals: 0,
3731+
Stacksize: 2,
3732+
Flags: 64,
3733+
Code: "\x64\x00\x00\x64\x01\x00\x84\x00\x00\x5a\x00\x00\x64\x02\x00\x53",
3734+
Consts: []py.Object{&py.Code{
3735+
Argcount: 0,
3736+
Kwonlyargcount: 0,
3737+
Nlocals: 0,
3738+
Stacksize: 1,
3739+
Flags: 99,
3740+
Code: "\x64\x00\x00\x56\x01\x64\x00\x00\x53",
3741+
Consts: []py.Object{py.None},
3742+
Names: []string{},
3743+
Varnames: []string{},
3744+
Freevars: []string{},
3745+
Cellvars: []string{},
3746+
Filename: "<string>",
3747+
Name: "f",
3748+
Firstlineno: 1,
3749+
Lnotab: "\x00\x01",
3750+
}, py.String("f"), py.None},
3751+
Names: []string{"f"},
3752+
Varnames: []string{},
3753+
Freevars: []string{},
3754+
Cellvars: []string{},
3755+
Filename: "<string>",
3756+
Name: "<module>",
3757+
Firstlineno: 1,
3758+
Lnotab: "",
3759+
}, nil, ""},
3760+
{"def f():\n yield potato\n ", "exec", &py.Code{
3761+
Argcount: 0,
3762+
Kwonlyargcount: 0,
3763+
Nlocals: 0,
3764+
Stacksize: 2,
3765+
Flags: 64,
3766+
Code: "\x64\x00\x00\x64\x01\x00\x84\x00\x00\x5a\x00\x00\x64\x02\x00\x53",
3767+
Consts: []py.Object{&py.Code{
3768+
Argcount: 0,
3769+
Kwonlyargcount: 0,
3770+
Nlocals: 0,
3771+
Stacksize: 1,
3772+
Flags: 99,
3773+
Code: "\x74\x00\x00\x56\x01\x64\x00\x00\x53",
3774+
Consts: []py.Object{py.None},
3775+
Names: []string{"potato"},
3776+
Varnames: []string{},
3777+
Freevars: []string{},
3778+
Cellvars: []string{},
3779+
Filename: "<string>",
3780+
Name: "f",
3781+
Firstlineno: 1,
3782+
Lnotab: "\x00\x01",
3783+
}, py.String("f"), py.None},
3784+
Names: []string{"f"},
3785+
Varnames: []string{},
3786+
Freevars: []string{},
3787+
Cellvars: []string{},
3788+
Filename: "<string>",
3789+
Name: "<module>",
3790+
Firstlineno: 1,
3791+
Lnotab: "",
3792+
}, nil, ""},
3793+
{"yield from range(10)", "exec", nil, py.SyntaxError, "'yield' outside function"},
3794+
{"def f():\n yield from range(10)\n ", "exec", &py.Code{
3795+
Argcount: 0,
3796+
Kwonlyargcount: 0,
3797+
Nlocals: 0,
3798+
Stacksize: 2,
3799+
Flags: 64,
3800+
Code: "\x64\x00\x00\x64\x01\x00\x84\x00\x00\x5a\x00\x00\x64\x02\x00\x53",
3801+
Consts: []py.Object{&py.Code{
3802+
Argcount: 0,
3803+
Kwonlyargcount: 0,
3804+
Nlocals: 0,
3805+
Stacksize: 2,
3806+
Flags: 99,
3807+
Code: "\x74\x00\x00\x64\x01\x00\x83\x01\x00\x44\x64\x00\x00\x48\x01\x64\x00\x00\x53",
3808+
Consts: []py.Object{py.None, py.Int(10)},
3809+
Names: []string{"range"},
3810+
Varnames: []string{},
3811+
Freevars: []string{},
3812+
Cellvars: []string{},
3813+
Filename: "<string>",
3814+
Name: "f",
3815+
Firstlineno: 1,
3816+
Lnotab: "\x00\x01",
3817+
}, py.String("f"), py.None},
3818+
Names: []string{"f"},
3819+
Varnames: []string{},
3820+
Freevars: []string{},
3821+
Cellvars: []string{},
3822+
Filename: "<string>",
3823+
Name: "<module>",
3824+
Firstlineno: 1,
3825+
Lnotab: "",
3826+
}, nil, ""},
37253827
}

compile/make_compile_test.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,23 @@ def method(self, c):
344344
('''from mod import a''', "exec"),
345345
('''from mod1.mod2.mod3 import *''', "exec"),
346346
('''from mod1.mod2.mod3 import a as aa, b as bb, c''', "exec"),
347-
347+
# yield
348+
('''yield''', "exec", SyntaxError),
349+
('''yield potato''', "exec", SyntaxError),
350+
('''\
351+
def f():
352+
yield
353+
''', "exec"),
354+
('''\
355+
def f():
356+
yield potato
357+
''', "exec"),
358+
# yield from
359+
('''yield from range(10)''', "exec", SyntaxError),
360+
('''\
361+
def f():
362+
yield from range(10)
363+
''', "exec"),
348364
]
349365

350366
def string(s):

0 commit comments

Comments
 (0)