Skip to content

Commit

Permalink
Merge pull request #294 from xushiwei/q
Browse files Browse the repository at this point in the history
cb.startBlockStmt: set start/end
  • Loading branch information
xushiwei authored Oct 24, 2023
2 parents 3d1b2e0 + 27b5995 commit 08fb252
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 45 deletions.
65 changes: 37 additions & 28 deletions codebuild.go
Original file line number Diff line number Diff line change
Expand Up @@ -237,10 +237,10 @@ func (p *CodeBuilder) Pkg() *Package {
return p.pkg
}

func (p *CodeBuilder) startFuncBody(fn *Func, old *funcBodyCtx) *CodeBuilder {
func (p *CodeBuilder) startFuncBody(fn *Func, src []ast.Node, old *funcBodyCtx) *CodeBuilder {
p.current.fn, old.fn = fn, p.current.fn
p.current.labels, old.labels = nil, p.current.labels
p.startBlockStmt(fn, "func "+fn.Name(), &old.codeBlockCtx)
p.startBlockStmt(fn, src, "func "+fn.Name(), &old.codeBlockCtx)
scope := p.current.scope
sig := fn.Type().(*types.Signature)
insertParams(scope, sig.Params())
Expand Down Expand Up @@ -268,8 +268,12 @@ func (p *CodeBuilder) endFuncBody(old funcBodyCtx) []ast.Stmt {
return stmts
}

func (p *CodeBuilder) startBlockStmt(current codeBlock, comment string, old *codeBlockCtx) *CodeBuilder {
scope := types.NewScope(p.current.scope, token.NoPos, token.NoPos, comment)
func (p *CodeBuilder) startBlockStmt(current codeBlock, src []ast.Node, comment string, old *codeBlockCtx) *CodeBuilder {
var start, end token.Pos
if src != nil {
start, end = src[0].Pos(), src[0].End()
}
scope := types.NewScope(p.current.scope, start, end, comment)
p.current.codeBlockCtx, *old = codeBlockCtx{current, scope, p.stk.Len(), nil, nil, 0}, p.current.codeBlockCtx
return p
}
Expand Down Expand Up @@ -537,7 +541,7 @@ func (p *CodeBuilder) CallInlineClosureStart(sig *types.Signature, arity int, el
for i, n := 0, results.Len(); i < n; i++ {
p.emitVar(pkg, closure, results.At(i), false)
}
p.startFuncBody(closure, &closure.old)
p.startFuncBody(closure, nil, &closure.old)
args := p.stk.GetArgs(arity)
var flags InstrFlags
if ellipsis {
Expand Down Expand Up @@ -2182,12 +2186,12 @@ func (p *CodeBuilder) Go() *CodeBuilder {
}

// Block starts a block statement.
func (p *CodeBuilder) Block() *CodeBuilder {
func (p *CodeBuilder) Block(src ...ast.Node) *CodeBuilder {
if debugInstr {
log.Println("Block")
}
stmt := &blockStmt{}
p.startBlockStmt(stmt, "block statement", &stmt.old)
p.startBlockStmt(stmt, src, "block statement", &stmt.old)
return p
}

Expand All @@ -2208,37 +2212,37 @@ func (p *CodeBuilder) InVBlock() bool {
}

// Block starts a if statement.
func (p *CodeBuilder) If() *CodeBuilder {
func (p *CodeBuilder) If(src ...ast.Node) *CodeBuilder {
if debugInstr {
log.Println("If")
}
stmt := &ifStmt{}
p.startBlockStmt(stmt, "if statement", &stmt.old)
p.startBlockStmt(stmt, src, "if statement", &stmt.old)
return p
}

// Then starts body of a if/switch/for statement.
func (p *CodeBuilder) Then() *CodeBuilder {
func (p *CodeBuilder) Then(src ...ast.Node) *CodeBuilder {
if debugInstr {
log.Println("Then")
}
if p.stk.Len() == p.current.base {
panic("use None() for empty expr")
}
if flow, ok := p.current.codeBlock.(controlFlow); ok {
flow.Then(p)
flow.Then(p, src...)
return p
}
panic("use if..then or switch..then or for..then please")
}

// Else starts else body of a if..else statement.
func (p *CodeBuilder) Else() *CodeBuilder {
func (p *CodeBuilder) Else(src ...ast.Node) *CodeBuilder {
if debugInstr {
log.Println("Else")
}
if flow, ok := p.current.codeBlock.(*ifStmt); ok {
flow.Else(p)
flow.Else(p, src...)
return p
}
panic("use if..else please")
Expand All @@ -2260,12 +2264,12 @@ func (p *CodeBuilder) Else() *CodeBuilder {
//
// end
// </pre>
func (p *CodeBuilder) TypeSwitch(name string) *CodeBuilder {
func (p *CodeBuilder) TypeSwitch(name string, src ...ast.Node) *CodeBuilder {
if debugInstr {
log.Println("TypeSwitch")
}
stmt := &typeSwitchStmt{name: name}
p.startBlockStmt(stmt, "type switch statement", &stmt.old)
p.startBlockStmt(stmt, src, "type switch statement", &stmt.old)
return p
}

Expand Down Expand Up @@ -2333,59 +2337,59 @@ func (p *CodeBuilder) TypeAssertThen() *CodeBuilder {
}

// TypeCase starts case body of a type switch statement.
func (p *CodeBuilder) TypeCase(n int) *CodeBuilder { // n=0 means default case
func (p *CodeBuilder) TypeCase(n int, src ...ast.Node) *CodeBuilder { // n=0 means default case
if debugInstr {
log.Println("TypeCase", n)
}
if flow, ok := p.current.codeBlock.(*typeSwitchStmt); ok {
flow.TypeCase(p, n)
flow.TypeCase(p, n, src...)
return p
}
panic("use switch x.(type) .. case please")
}

// Select starts a select statement.
func (p *CodeBuilder) Select() *CodeBuilder {
func (p *CodeBuilder) Select(src ...ast.Node) *CodeBuilder {
if debugInstr {
log.Println("Select")
}
stmt := &selectStmt{}
p.startBlockStmt(stmt, "select statement", &stmt.old)
p.startBlockStmt(stmt, src, "select statement", &stmt.old)
return p
}

// CommCase starts case body of a select..case statement.
func (p *CodeBuilder) CommCase(n int) *CodeBuilder {
func (p *CodeBuilder) CommCase(n int, src ...ast.Node) *CodeBuilder {
if debugInstr {
log.Println("CommCase", n)
}
if n > 1 {
panic("TODO: multi commStmt in select..case?")
}
if flow, ok := p.current.codeBlock.(*selectStmt); ok {
flow.CommCase(p, n)
flow.CommCase(p, n, src...)
return p
}
panic("use select..case please")
}

// Switch starts a switch statement.
func (p *CodeBuilder) Switch() *CodeBuilder {
func (p *CodeBuilder) Switch(src ...ast.Node) *CodeBuilder {
if debugInstr {
log.Println("Switch")
}
stmt := &switchStmt{}
p.startBlockStmt(stmt, "switch statement", &stmt.old)
p.startBlockStmt(stmt, src, "switch statement", &stmt.old)
return p
}

// Case starts case body of a switch..case statement.
func (p *CodeBuilder) Case(n int) *CodeBuilder { // n=0 means default case
func (p *CodeBuilder) Case(n int, src ...ast.Node) *CodeBuilder { // n=0 means default case
if debugInstr {
log.Println("Case", n)
}
if flow, ok := p.current.codeBlock.(*switchStmt); ok {
flow.Case(p, n)
flow.Case(p, n, src...)
return p
}
panic("use switch..case please")
Expand Down Expand Up @@ -2483,12 +2487,12 @@ func (p *CodeBuilder) Fallthrough() *CodeBuilder {
}

// For func
func (p *CodeBuilder) For() *CodeBuilder {
func (p *CodeBuilder) For(src ...ast.Node) *CodeBuilder {
if debugInstr {
log.Println("For")
}
stmt := &forStmt{}
p.startBlockStmt(stmt, "for statement", &stmt.old)
p.startBlockStmt(stmt, src, "for statement", &stmt.old)
return p
}

Expand All @@ -2506,11 +2510,16 @@ func (p *CodeBuilder) Post() *CodeBuilder {

// ForRange func
func (p *CodeBuilder) ForRange(names ...string) *CodeBuilder {
return p.ForRangeEx(names)
}

// ForRangeEx func
func (p *CodeBuilder) ForRangeEx(names []string, src ...ast.Node) *CodeBuilder {
if debugInstr {
log.Println("ForRange", names)
}
stmt := &forRangeStmt{names: names}
p.startBlockStmt(stmt, "for range statement", &stmt.old)
p.startBlockStmt(stmt, src, "for range statement", &stmt.old)
return p
}

Expand Down
4 changes: 2 additions & 2 deletions func.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ func (p *Func) Ancestor() *Func {
}

// BodyStart func
func (p *Func) BodyStart(pkg *Package) *CodeBuilder {
func (p *Func) BodyStart(pkg *Package, src ...ast.Node) *CodeBuilder {
if debugInstr {
var recv string
tag := "NewFunc "
Expand All @@ -111,7 +111,7 @@ func (p *Func) BodyStart(pkg *Package) *CodeBuilder {
}
log.Printf("%v%v%v %v\n", tag, name, recv, sig)
}
return pkg.cb.startFuncBody(p, &p.old)
return pkg.cb.startFuncBody(p, src, &p.old)
}

// End is for internal use.
Expand Down
2 changes: 1 addition & 1 deletion package_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -840,7 +840,7 @@ func main() {
func TestTypeAssert(t *testing.T) {
pkg := newMainPackage()
params := types.NewTuple(pkg.NewParam(token.NoPos, "v", gox.TyEmptyInterface))
pkg.NewFunc(nil, "foo", params, nil, false).BodyStart(pkg).
pkg.NewFunc(nil, "foo", params, nil, false).BodyStart(pkg, source("{}", 1, 5)).
DefineVarStart(0, "x").VarVal("v").TypeAssert(types.Typ[types.Int], false).EndInit(1).
DefineVarStart(0, "y", "ok").VarVal("v").TypeAssert(types.Typ[types.String], true).EndInit(1).
End()
Expand Down
28 changes: 14 additions & 14 deletions stmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import (
)

type controlFlow interface {
Then(cb *CodeBuilder)
Then(cb *CodeBuilder, src ...ast.Node)
}

// ----------------------------------------------------------------------------
Expand Down Expand Up @@ -77,7 +77,7 @@ type ifStmt struct {
old2 codeBlockCtx
}

func (p *ifStmt) Then(cb *CodeBuilder) {
func (p *ifStmt) Then(cb *CodeBuilder, src ...ast.Node) {
cond := cb.stk.Pop()
if !types.AssignableTo(cond.Type, types.Typ[types.Bool]) {
panic("TODO: if statement condition is not a boolean expr")
Expand All @@ -91,10 +91,10 @@ func (p *ifStmt) Then(cb *CodeBuilder) {
default:
panic("TODO: if statement has too many init statements")
}
cb.startBlockStmt(p, "if body", &p.old2)
cb.startBlockStmt(p, src, "if body", &p.old2)
}

func (p *ifStmt) Else(cb *CodeBuilder) {
func (p *ifStmt) Else(cb *CodeBuilder, src ...ast.Node) {
if p.body != nil {
panic("TODO: else statement already exists")
}
Expand All @@ -103,7 +103,7 @@ func (p *ifStmt) Else(cb *CodeBuilder) {
cb.current.flows |= flows

p.body = &ast.BlockStmt{List: stmts}
cb.startBlockStmt(p, "else body", &p.old2)
cb.startBlockStmt(p, src, "else body", &p.old2)
}

func (p *ifStmt) End(cb *CodeBuilder, src ast.Node) {
Expand Down Expand Up @@ -144,7 +144,7 @@ type switchStmt struct {
old codeBlockCtx
}

func (p *switchStmt) Then(cb *CodeBuilder) {
func (p *switchStmt) Then(cb *CodeBuilder, src ...ast.Node) {
p.tag = cb.stk.Pop()
switch stmts := cb.clearBlockStmt(); len(stmts) {
case 0:
Expand All @@ -156,7 +156,7 @@ func (p *switchStmt) Then(cb *CodeBuilder) {
}
}

func (p *switchStmt) Case(cb *CodeBuilder, n int) {
func (p *switchStmt) Case(cb *CodeBuilder, n int, src ...ast.Node) {
var list []ast.Expr
if n > 0 {
list = make([]ast.Expr, n)
Expand All @@ -178,7 +178,7 @@ func (p *switchStmt) Case(cb *CodeBuilder, n int) {
cb.stk.PopN(n)
}
stmt := &caseStmt{list: list}
cb.startBlockStmt(stmt, "case statement", &stmt.old)
cb.startBlockStmt(stmt, src, "case statement", &stmt.old)
}

func (p *switchStmt) End(cb *CodeBuilder, src ast.Node) {
Expand Down Expand Up @@ -225,13 +225,13 @@ type selectStmt struct {
old codeBlockCtx
}

func (p *selectStmt) CommCase(cb *CodeBuilder, n int) {
func (p *selectStmt) CommCase(cb *CodeBuilder, n int, src ...ast.Node) {
var comm ast.Stmt
if n == 1 {
comm = cb.popStmt()
}
stmt := &commCase{comm: comm}
cb.startBlockStmt(stmt, "comm case statement", &stmt.old)
cb.startBlockStmt(stmt, src, "comm case statement", &stmt.old)
}

func (p *selectStmt) End(cb *CodeBuilder, src ast.Node) {
Expand Down Expand Up @@ -291,7 +291,7 @@ func (p *typeSwitchStmt) TypeAssertThen(cb *CodeBuilder) {
p.x, p.xSrc, p.xType = x.Val, x.Src, xType
}

func (p *typeSwitchStmt) TypeCase(cb *CodeBuilder, n int) {
func (p *typeSwitchStmt) TypeCase(cb *CodeBuilder, n int, src ...ast.Node) {
var list []ast.Expr
var typ types.Type
if n > 0 {
Expand All @@ -318,7 +318,7 @@ func (p *typeSwitchStmt) TypeCase(cb *CodeBuilder, n int) {
}

stmt := &typeCaseStmt{list: list}
cb.startBlockStmt(stmt, "type case statement", &stmt.old)
cb.startBlockStmt(stmt, src, "type case statement", &stmt.old)

if p.name != "" {
if n != 1 { // default, or case with multi expr
Expand Down Expand Up @@ -400,7 +400,7 @@ type forStmt struct {
loopBodyHandler
}

func (p *forStmt) Then(cb *CodeBuilder) {
func (p *forStmt) Then(cb *CodeBuilder, src ...ast.Node) {
cond := cb.stk.Pop()
if cond.Val != nil {
if !types.AssignableTo(cond.Type, types.Typ[types.Bool]) {
Expand All @@ -416,7 +416,7 @@ func (p *forStmt) Then(cb *CodeBuilder) {
default:
panic("TODO: for condition has too many init statements")
}
cb.startBlockStmt(p, "for body", &p.old2)
cb.startBlockStmt(p, src, "for body", &p.old2)
}

func (p *forStmt) Post(cb *CodeBuilder) {
Expand Down

0 comments on commit 08fb252

Please sign in to comment.