From 3b8d74b979a5f5b12cc4ae3e47e40d2fccbd2ff5 Mon Sep 17 00:00:00 2001 From: bloeys Date: Sat, 5 Nov 2022 01:26:20 +0400 Subject: [PATCH] Implement YieldNone+ comments --- cogo/cogo.go | 10 +++++++ cogo/{sleeper.go => helper_yielders.go} | 0 demo.cogo.go | 11 +++++++ demo.go | 4 +++ main.go | 39 +++++++++++++++++++++++++ 5 files changed, 64 insertions(+) rename cogo/{sleeper.go => helper_yielders.go} (100%) diff --git a/cogo/cogo.go b/cogo/cogo.go index 36a1a8e..4cb1449 100755 --- a/cogo/cogo.go +++ b/cogo/cogo.go @@ -48,14 +48,24 @@ func (c *Coroutine[InT, OutT]) Tick() (done bool) { return c.State == -1 } +// Yield yields and sets the Out variable to the passed variable func (c *Coroutine[InT, OutT]) Yield(out OutT) { panic(fmt.Sprintf("Yield got called at runtime, which means the code generator was not run, you used cogo incorrectly, or cogo has a bug. Yield should NOT get called at runtime. coroutine: %+v;;; yield value: %+v;;;", c, out)) } +// YieldTo gives control to a Yielder object and immediately executes one Tick on it. +// Future 'Tick' calls on the original coroutine will run 'Tick' on passed Yielder. +// +// The original coroutine will only resume execution once this yielder reports that its done func (c *Coroutine[InT, OutT]) YieldTo(y Yielder) { panic(fmt.Sprintf("YieldTo got called at runtime, which means the code generator was not run, you used cogo incorrectly, or cogo has a bug. Yield should NOT get called at runtime. coroutine: %+v;;; yielder value: %+v;;;", c, y)) } +// YieldNone yields without updating the Out variable +func (c *Coroutine[InT, OutT]) YieldNone() { + panic(fmt.Sprintf("YieldNone got called at runtime, which means the code generator was not run, you used cogo incorrectly, or cogo has a bug. Yield should NOT get called at runtime. coroutine: %+v;;;", c)) +} + func HasGen() bool { return true } diff --git a/cogo/sleeper.go b/cogo/helper_yielders.go similarity index 100% rename from cogo/sleeper.go rename to cogo/helper_yielders.go diff --git a/demo.cogo.go b/demo.cogo.go index 5134d05..6aed80c 100755 --- a/demo.cogo.go +++ b/demo.cogo.go @@ -84,8 +84,19 @@ func test2_cogo(c *cogo.Coroutine[int, int]) { switch c.SubState { default: } + + println("test2222 before yield none") + c.State++ + c.SubState = -1 + return + case 3: + switch c.SubState { + default: + } c.State = -1 c.SubState = -1 + + println("test2222 after yield none") default: c.State = -1 c.SubState = -1 diff --git a/demo.go b/demo.go index 6361091..215033c 100755 --- a/demo.go +++ b/demo.go @@ -54,4 +54,8 @@ func test2(c *cogo.Coroutine[int, int]) { println("test2222 yield:", 2) c.Yield(2) + + println("test2222 before yield none") + c.YieldNone() + println("test2222 after yield none") } diff --git a/main.go b/main.go index 7579010..8a46cd0 100755 --- a/main.go +++ b/main.go @@ -371,6 +371,45 @@ func (p *processor) genCogoFuncsNodeProcessor(c *astutil.Cursor) bool { ), ) + lastCaseEndBodyListIndex = i + } else if cogoFuncSelExpr.Sel.Name == "YieldNone" { + + // Add everything from the last begin/yield until this yield into a case + stmtsSinceLastCogo := funcDecl.Body.List[lastCaseEndBodyListIndex+1 : i] + + caseStmts := make([]ast.Stmt, 0, len(stmtsSinceLastCogo)+5) + + caseStmts = append(caseStmts, subSwitchStmt) + subSwitchStmt = &ast.SwitchStmt{ + Tag: ast.NewIdent(coroutineParamName + ".SubState"), + Body: &ast.BlockStmt{ + List: []ast.Stmt{ + getCaseWithStmts(nil, []ast.Stmt{}), + }, + }, + } + + caseStmts = append(caseStmts, stmtsSinceLastCogo...) + caseStmts = append(caseStmts, + &ast.IncDecStmt{ + Tok: token.INC, + X: ast.NewIdent(coroutineParamName + ".State"), + }, + &ast.AssignStmt{ + Lhs: []ast.Expr{ast.NewIdent(coroutineParamName + ".SubState")}, + Tok: token.ASSIGN, + Rhs: []ast.Expr{ast.NewIdent("-1")}, + }, + &ast.ReturnStmt{}, + ) + + switchStmt.Body.List = append(switchStmt.Body.List, + getCaseWithStmts( + []ast.Expr{ast.NewIdent(fmt.Sprint(len(switchStmt.Body.List)))}, + caseStmts, + ), + ) + lastCaseEndBodyListIndex = i } }