diff --git a/builtin_test.go b/builtin_test.go index 3cae63a4..9b6b1a0f 100644 --- a/builtin_test.go +++ b/builtin_test.go @@ -569,7 +569,7 @@ func TestVarDeclEnd(t *testing.T) { t.Fatal("TestVarDeclEnd failed: no error?") } }() - decl.End(nil) + decl.End(nil, nil) } func TestCheckParenExpr(t *testing.T) { @@ -935,7 +935,7 @@ func TestForRangeStmtPanic(t *testing.T) { } }() var s forRangeStmt - s.End(nil) + s.End(nil, nil) } func TestNewFuncDeclPanic(t *testing.T) { @@ -969,7 +969,7 @@ func TestSwitchStmtPanic(t *testing.T) { } }() var s switchStmt - s.End(nil) + s.End(nil, nil) } func TestCallIncDec(t *testing.T) { diff --git a/codebuild.go b/codebuild.go index 8474a5c3..c8a5d02f 100644 --- a/codebuild.go +++ b/codebuild.go @@ -40,7 +40,7 @@ func getSrc(node []ast.Node) ast.Node { // ---------------------------------------------------------------------------- type codeBlock interface { - End(cb *CodeBuilder) + End(cb *CodeBuilder, src ast.Node) } type vblockCtx struct { @@ -314,9 +314,10 @@ func (p *CodeBuilder) startStmtAt(stmt ast.Stmt) int { } // Usage: -// idx := cb.startStmtAt(stmt) -// ... -// cb.commitStmt(idx) +// +// idx := cb.startStmtAt(stmt) +// ... +// cb.commitStmt(idx) func (p *CodeBuilder) commitStmt(idx int) { stmts := p.current.stmts n := len(stmts) - 1 @@ -751,7 +752,7 @@ retry: } // MapLit func -func (p *CodeBuilder) MapLit(typ types.Type, arity int) *CodeBuilder { +func (p *CodeBuilder) MapLit(typ types.Type, arity int, src ...ast.Node) *CodeBuilder { if debugInstr { log.Println("MapLit", typ, arity) } @@ -777,7 +778,7 @@ func (p *CodeBuilder) MapLit(typ types.Type, arity int) *CodeBuilder { typExpr = toMapType(pkg, t) } ret := &ast.CompositeLit{Type: typExpr} - p.stk.Push(&internal.Elem{Type: typ, Val: ret}) + p.stk.Push(&internal.Elem{Type: typ, Val: ret, Src: getSrc(src)}) return p } if (arity & 1) != 0 { @@ -810,7 +811,9 @@ func (p *CodeBuilder) MapLit(typ types.Type, arity int) *CodeBuilder { } } } - p.stk.Ret(arity, &internal.Elem{Type: typ, Val: &ast.CompositeLit{Type: typExpr, Elts: elts}}) + p.stk.Ret(arity, &internal.Elem{ + Type: typ, Val: &ast.CompositeLit{Type: typExpr, Elts: elts}, Src: getSrc(src), + }) return p } @@ -860,10 +863,15 @@ func (p *CodeBuilder) indexElemExpr(args []*internal.Elem, i int) ast.Expr { // SliceLit func func (p *CodeBuilder) SliceLit(typ types.Type, arity int, keyVal ...bool) *CodeBuilder { - var elts []ast.Expr var keyValMode = (keyVal != nil && keyVal[0]) + return p.SliceLitEx(typ, arity, keyValMode) +} + +// SliceLitEx func +func (p *CodeBuilder) SliceLitEx(typ types.Type, arity int, keyVal bool, src ...ast.Node) *CodeBuilder { + var elts []ast.Expr if debugInstr { - log.Println("SliceLit", typ, arity, keyValMode) + log.Println("SliceLit", typ, arity, keyVal) } var t *types.Slice var typExpr ast.Expr @@ -880,7 +888,7 @@ func (p *CodeBuilder) SliceLit(typ types.Type, arity int, keyVal ...bool) *CodeB log.Panicln("SliceLit: typ isn't a slice type -", reflect.TypeOf(typ)) } } - if keyValMode { // in keyVal mode + if keyVal { // in keyVal mode if (arity & 1) != 0 { log.Panicln("SliceLit: invalid arity, can't be odd in keyVal mode -", arity) } @@ -904,7 +912,9 @@ func (p *CodeBuilder) SliceLit(typ types.Type, arity int, keyVal ...bool) *CodeB typ = t typExpr = toSliceType(pkg, t) } - p.stk.Push(&internal.Elem{Type: typ, Val: &ast.CompositeLit{Type: typExpr}}) + p.stk.Push(&internal.Elem{ + Type: typ, Val: &ast.CompositeLit{Type: typExpr}, Src: getSrc(src), + }) return p } var val types.Type @@ -930,16 +940,23 @@ func (p *CodeBuilder) SliceLit(typ types.Type, arity int, keyVal ...bool) *CodeB } } } - p.stk.Ret(arity, &internal.Elem{Type: typ, Val: &ast.CompositeLit{Type: typExpr, Elts: elts}}) + p.stk.Ret(arity, &internal.Elem{ + Type: typ, Val: &ast.CompositeLit{Type: typExpr, Elts: elts}, Src: getSrc(src), + }) return p } // ArrayLit func func (p *CodeBuilder) ArrayLit(typ types.Type, arity int, keyVal ...bool) *CodeBuilder { - var elts []ast.Expr var keyValMode = (keyVal != nil && keyVal[0]) + return p.ArrayLitEx(typ, arity, keyValMode) +} + +// ArrayLitEx func +func (p *CodeBuilder) ArrayLitEx(typ types.Type, arity int, keyVal bool, src ...ast.Node) *CodeBuilder { + var elts []ast.Expr if debugInstr { - log.Println("ArrayLit", typ, arity, keyValMode) + log.Println("ArrayLit", typ, arity, keyVal) } var t *types.Array var typExpr ast.Expr @@ -954,7 +971,7 @@ func (p *CodeBuilder) ArrayLit(typ types.Type, arity int, keyVal ...bool) *CodeB default: log.Panicln("ArrayLit: typ isn't a array type -", reflect.TypeOf(typ)) } - if keyValMode { // in keyVal mode + if keyVal { // in keyVal mode if (arity & 1) != 0 { log.Panicln("ArrayLit: invalid arity, can't be odd in keyVal mode -", arity) } @@ -995,12 +1012,14 @@ func (p *CodeBuilder) ArrayLit(typ types.Type, arity int, keyVal ...bool) *CodeB } } } - p.stk.Ret(arity, &internal.Elem{Type: typ, Val: &ast.CompositeLit{Type: typExpr, Elts: elts}}) + p.stk.Ret(arity, &internal.Elem{ + Type: typ, Val: &ast.CompositeLit{Type: typExpr, Elts: elts}, Src: getSrc(src), + }) return p } // StructLit func -func (p *CodeBuilder) StructLit(typ types.Type, arity int, keyVal bool) *CodeBuilder { +func (p *CodeBuilder) StructLit(typ types.Type, arity int, keyVal bool, src ...ast.Node) *CodeBuilder { if debugInstr { log.Println("StructLit", typ, arity, keyVal) } @@ -1062,7 +1081,9 @@ func (p *CodeBuilder) StructLit(typ types.Type, arity int, keyVal bool) *CodeBui } } } - p.stk.Ret(arity, &internal.Elem{Type: typ, Val: &ast.CompositeLit{Type: typExpr, Elts: elts}}) + p.stk.Ret(arity, &internal.Elem{ + Type: typ, Val: &ast.CompositeLit{Type: typExpr, Elts: elts}, Src: getSrc(src), + }) return p } @@ -2059,9 +2080,9 @@ func (p *CodeBuilder) CompareNil(op token.Token, src ...ast.Node) *CodeBuilder { } // UnaryOp: -// - cb.UnaryOp(op token.Token) -// - cb.UnaryOp(op token.Token, twoValue bool) -// - cb.UnaryOp(op token.Token, twoValue bool, src ast.Node) +// - cb.UnaryOp(op token.Token) +// - cb.UnaryOp(op token.Token, twoValue bool) +// - cb.UnaryOp(op token.Token, twoValue bool, src ast.Node) func (p *CodeBuilder) UnaryOp(op token.Token, params ...interface{}) *CodeBuilder { var src ast.Node var flags InstrFlags @@ -2194,14 +2215,17 @@ func (p *CodeBuilder) Else() *CodeBuilder { //
 // typeSwitch(name) init; expr typeAssertThen
 // type1, type2, ... typeN typeCase(N)
-//    ...
-//    end
+//
+//	...
+//	end
+//
 // type1, type2, ... typeM typeCase(M)
-//    ...
-//    end
+//
+//	...
+//	end
+//
 // end
 // 
-// func (p *CodeBuilder) TypeSwitch(name string) *CodeBuilder { if debugInstr { log.Println("TypeSwitch") @@ -2491,7 +2515,7 @@ func (p *CodeBuilder) EndStmt() *CodeBuilder { } // End func -func (p *CodeBuilder) End() *CodeBuilder { +func (p *CodeBuilder) End(src ...ast.Node) *CodeBuilder { if debugInstr { typ := reflect.TypeOf(p.current.codeBlock) if typ.Kind() == reflect.Ptr { @@ -2503,7 +2527,7 @@ func (p *CodeBuilder) End() *CodeBuilder { panic("forget to call EndStmt()?") } } - p.current.End(p) + p.current.End(p, getSrc(src)) return p } diff --git a/func.go b/func.go index 85ab050d..3928d75e 100644 --- a/func.go +++ b/func.go @@ -102,7 +102,7 @@ func (p *Func) BodyStart(pkg *Package) *CodeBuilder { } // End is for internal use. -func (p *Func) End(cb *CodeBuilder) { +func (p *Func) End(cb *CodeBuilder, src ast.Node) { if p.isInline() { p.inlineClosureEnd(cb) return @@ -112,7 +112,7 @@ func (p *Func) End(cb *CodeBuilder) { t, _ := toNormalizeSignature(nil, p.Type().(*types.Signature)) if fn := p.decl; fn == nil { // is closure expr := &ast.FuncLit{Type: toFuncType(pkg, t), Body: body} - cb.stk.Push(&internal.Elem{Val: expr, Type: t}) + cb.stk.Push(&internal.Elem{Val: expr, Type: t, Src: src}) } else { fn.Name, fn.Type, fn.Body = ident(p.Name()), toFuncType(pkg, t), body if recv := t.Recv(); IsMethodRecv(recv) { diff --git a/stmt.go b/stmt.go index 15704daf..78b4be45 100644 --- a/stmt.go +++ b/stmt.go @@ -29,14 +29,15 @@ type controlFlow interface { // ---------------------------------------------------------------------------- // // block -// ... -// end // +// ... +// +// end type blockStmt struct { old codeBlockCtx } -func (p *blockStmt) End(cb *CodeBuilder) { +func (p *blockStmt) End(cb *CodeBuilder, src ast.Node) { stmts, flows := cb.endBlockStmt(&p.old) cb.current.flows |= flows cb.emitStmt(&ast.BlockStmt{List: stmts}) @@ -45,25 +46,29 @@ func (p *blockStmt) End(cb *CodeBuilder) { // ---------------------------------------------------------------------------- // // vblock -// ... -// end // +// ... +// +// end type vblockStmt struct { old vblockCtx } -func (p *vblockStmt) End(cb *CodeBuilder) { +func (p *vblockStmt) End(cb *CodeBuilder, src ast.Node) { cb.endVBlockStmt(&p.old) } // ---------------------------------------------------------------------------- // // if init; cond then -// ... +// +// ... +// // else -// ... -// end // +// ... +// +// end type ifStmt struct { init ast.Stmt cond ast.Expr @@ -101,7 +106,7 @@ func (p *ifStmt) Else(cb *CodeBuilder) { cb.startBlockStmt(p, "else body", &p.old2) } -func (p *ifStmt) End(cb *CodeBuilder) { +func (p *ifStmt) End(cb *CodeBuilder, src ast.Node) { stmts, flows := cb.endBlockStmt(&p.old2) cb.current.flows |= flows @@ -124,14 +129,15 @@ func (p *ifStmt) End(cb *CodeBuilder) { // ---------------------------------------------------------------------------- // // switch init; tag then -// expr1, expr2, ..., exprN case(N) -// ... -// end -// expr1, expr2, ..., exprM case(M) -// ... -// end -// end // +// expr1, expr2, ..., exprN case(N) +// ... +// end +// expr1, expr2, ..., exprM case(M) +// ... +// end +// +// end type switchStmt struct { init ast.Stmt tag *internal.Elem @@ -175,7 +181,7 @@ func (p *switchStmt) Case(cb *CodeBuilder, n int) { cb.startBlockStmt(stmt, "case statement", &stmt.old) } -func (p *switchStmt) End(cb *CodeBuilder) { +func (p *switchStmt) End(cb *CodeBuilder, src ast.Node) { if p.tag == nil { return } @@ -195,7 +201,7 @@ func (p *caseStmt) Fallthrough(cb *CodeBuilder) { cb.emitStmt(&ast.BranchStmt{Tok: token.FALLTHROUGH}) } -func (p *caseStmt) End(cb *CodeBuilder) { +func (p *caseStmt) End(cb *CodeBuilder, src ast.Node) { body, flows := cb.endBlockStmt(&p.old) cb.current.flows |= flows cb.emitStmt(&ast.CaseClause{List: p.list, Body: body}) @@ -205,11 +211,15 @@ func (p *caseStmt) End(cb *CodeBuilder) { // // select // commStmt1 commCase() -// ... -// end +// +// ... +// end +// // commStmt2 commCase() -// ... -// end +// +// ... +// end +// // end type selectStmt struct { old codeBlockCtx @@ -224,7 +234,7 @@ func (p *selectStmt) CommCase(cb *CodeBuilder, n int) { cb.startBlockStmt(stmt, "comm case statement", &stmt.old) } -func (p *selectStmt) End(cb *CodeBuilder) { +func (p *selectStmt) End(cb *CodeBuilder, src ast.Node) { stmts, flows := cb.endBlockStmt(&p.old) cb.current.flows |= (flows &^ flowFlagBreak) cb.emitStmt(&ast.SelectStmt{Body: &ast.BlockStmt{List: stmts}}) @@ -235,7 +245,7 @@ type commCase struct { old codeBlockCtx } -func (p *commCase) End(cb *CodeBuilder) { +func (p *commCase) End(cb *CodeBuilder, src ast.Node) { body, flows := cb.endBlockStmt(&p.old) cb.current.flows |= flows cb.emitStmt(&ast.CommClause{Comm: p.comm, Body: body}) @@ -245,13 +255,16 @@ func (p *commCase) End(cb *CodeBuilder) { // // typeSwitch(name) init; expr typeAssertThen // type1, type2, ... typeN typeCase(N) -// ... -// end +// +// ... +// end +// // type1, type2, ... typeM typeCase(M) -// ... -// end -// end // +// ... +// end +// +// end type typeSwitchStmt struct { init ast.Stmt name string @@ -316,7 +329,7 @@ func (p *typeSwitchStmt) TypeCase(cb *CodeBuilder, n int) { } } -func (p *typeSwitchStmt) End(cb *CodeBuilder) { +func (p *typeSwitchStmt) End(cb *CodeBuilder, src ast.Node) { stmts, flows := cb.endBlockStmt(&p.old) cb.current.flows |= (flows &^ flowFlagBreak) @@ -340,7 +353,7 @@ type typeCaseStmt struct { old codeBlockCtx } -func (p *typeCaseStmt) End(cb *CodeBuilder) { +func (p *typeCaseStmt) End(cb *CodeBuilder, src ast.Node) { body, flows := cb.endBlockStmt(&p.old) cb.current.flows |= flows cb.emitStmt(&ast.CaseClause{List: p.list, Body: body}) @@ -373,10 +386,11 @@ func InsertStmtFront(body *ast.BlockStmt, stmt ast.Stmt) { // ---------------------------------------------------------------------------- // // for init; cond then -// body -// post -// end // +// body +// post +// +// end type forStmt struct { init ast.Stmt cond ast.Expr @@ -411,7 +425,7 @@ func (p *forStmt) Post(cb *CodeBuilder) { p.body = &ast.BlockStmt{List: stmts} } -func (p *forStmt) End(cb *CodeBuilder) { +func (p *forStmt) End(cb *CodeBuilder, src ast.Node) { var post ast.Stmt if p.body != nil { // has post stmt stmts, _ := cb.endBlockStmt(&p.old) @@ -433,13 +447,16 @@ func (p *forStmt) End(cb *CodeBuilder) { // ---------------------------------------------------------------------------- // // forRange names... exprX rangeAssignThen -// ... +// +// ... +// // end // // forRange exprKey exprVal exprX rangeAssignThen -// ... -// end // +// ... +// +// end type forRangeStmt struct { names []string stmt *ast.RangeStmt @@ -640,7 +657,7 @@ const ( cantUseFlows = "can't use return/continue/break/goto in for range of udt.Gop_Enum(callback)" ) -func (p *forRangeStmt) End(cb *CodeBuilder) { +func (p *forRangeStmt) End(cb *CodeBuilder, src ast.Node) { if p.stmt == nil { return } diff --git a/type_var_and_const.go b/type_var_and_const.go index f9a5b33a..987f15e8 100644 --- a/type_var_and_const.go +++ b/type_var_and_const.go @@ -194,7 +194,7 @@ func (p *ValueDecl) Ref(name string) Ref { // End is provided for internal usage. // Don't call it at any time. Please use (*CodeBuilder).EndInit instead. -func (p *ValueDecl) End(cb *CodeBuilder) { +func (p *ValueDecl) End(cb *CodeBuilder, src ast.Node) { fatal("don't call End(), please use EndInit() instead") }