From b636996daa8b067dcf7d14ebeefcc461bf362613 Mon Sep 17 00:00:00 2001 From: xushiwei Date: Tue, 24 Oct 2023 23:58:48 +0800 Subject: [PATCH 1/3] cb.startBlockStmt: set start/end --- codebuild.go | 49 +++++++++++++++++++++++++++++-------------------- func.go | 4 ++-- package_test.go | 2 +- stmt.go | 28 ++++++++++++++-------------- 4 files changed, 46 insertions(+), 37 deletions(-) diff --git a/codebuild.go b/codebuild.go index c186006c..249eebb2 100644 --- a/codebuild.go +++ b/codebuild.go @@ -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()) @@ -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 } @@ -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 { @@ -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 } @@ -2208,17 +2212,17 @@ 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") } @@ -2226,7 +2230,7 @@ func (p *CodeBuilder) Then() *CodeBuilder { 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") @@ -2260,12 +2264,12 @@ func (p *CodeBuilder) Else() *CodeBuilder { // // end // -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 } @@ -2345,12 +2349,12 @@ func (p *CodeBuilder) TypeCase(n int) *CodeBuilder { // n=0 means default case } // 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 } @@ -2370,12 +2374,12 @@ func (p *CodeBuilder) CommCase(n int) *CodeBuilder { } // 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 } @@ -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 } @@ -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 } diff --git a/func.go b/func.go index 4f488221..5be2a1e2 100644 --- a/func.go +++ b/func.go @@ -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 " @@ -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. diff --git a/package_test.go b/package_test.go index 8e626f43..39bed713 100644 --- a/package_test.go +++ b/package_test.go @@ -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() diff --git a/stmt.go b/stmt.go index 78b4be45..2f824bf7 100644 --- a/stmt.go +++ b/stmt.go @@ -23,7 +23,7 @@ import ( ) type controlFlow interface { - Then(cb *CodeBuilder) + Then(cb *CodeBuilder, src ...ast.Node) } // ---------------------------------------------------------------------------- @@ -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") @@ -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") } @@ -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) { @@ -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: @@ -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) @@ -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) { @@ -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) { @@ -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 { @@ -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 @@ -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]) { @@ -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) { From 3d951be5607f974d3ebcdba008e3d7e81b095385 Mon Sep 17 00:00:00 2001 From: xushiwei Date: Wed, 25 Oct 2023 00:32:13 +0800 Subject: [PATCH 2/3] cb.Else(src) --- codebuild.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/codebuild.go b/codebuild.go index 249eebb2..9e0ac004 100644 --- a/codebuild.go +++ b/codebuild.go @@ -2237,12 +2237,12 @@ func (p *CodeBuilder) Then(src ...ast.Node) *CodeBuilder { } // 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") From 27b599506dce88e0f854883b11729e750cbcab05 Mon Sep 17 00:00:00 2001 From: xushiwei Date: Wed, 25 Oct 2023 00:50:51 +0800 Subject: [PATCH 3/3] cb.Ccase: src ...ast.Node --- codebuild.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/codebuild.go b/codebuild.go index 9e0ac004..73cf0ebb 100644 --- a/codebuild.go +++ b/codebuild.go @@ -2337,12 +2337,12 @@ 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") @@ -2359,7 +2359,7 @@ func (p *CodeBuilder) Select(src ...ast.Node) *CodeBuilder { } // 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) } @@ -2367,7 +2367,7 @@ func (p *CodeBuilder) CommCase(n int) *CodeBuilder { 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") @@ -2384,12 +2384,12 @@ func (p *CodeBuilder) Switch(src ...ast.Node) *CodeBuilder { } // 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")