github.com/jmigpin/editor@v1.6.0/core/godebug/annotator.go (about)

     1  package godebug
     2  
     3  import (
     4  	"fmt"
     5  	"go/ast"
     6  	"go/constant"
     7  	"go/token"
     8  	"go/types"
     9  	"math/big"
    10  	"sort"
    11  	"strconv"
    12  	"strings"
    13  
    14  	"github.com/jmigpin/editor/util/astut"
    15  	"github.com/jmigpin/editor/util/reflectutil"
    16  )
    17  
    18  type Annotator struct {
    19  	fset *token.FileSet
    20  
    21  	typesInfo    *types.Info
    22  	nodeAnnTypes map[ast.Node]AnnotationType
    23  
    24  	fileIndex          int
    25  	debugPkgName       string
    26  	debugVarPrefix     string // will have integer appended
    27  	debugVarNameIndex  int
    28  	debugLastIndex     int  // n indexes were used
    29  	builtDebugLineStmt bool // at least one debug stmt inserted
    30  
    31  	simpleTestMode bool // just testing annotator (no types)
    32  }
    33  
    34  func NewAnnotator(fset *token.FileSet) *Annotator {
    35  	ann := &Annotator{fset: fset}
    36  	// defaults for tests; used values are in annotatorset
    37  	ann.debugPkgName = "Σ"
    38  	ann.debugVarPrefix = "Σ"
    39  	return ann
    40  }
    41  
    42  //----------
    43  
    44  func (ann *Annotator) AnnotateAstFile(astFile *ast.File) {
    45  	ctx := &Ctx{}
    46  	ctx = ctx.withDebugIndex(0)
    47  
    48  	ann.vis(ctx, astFile)
    49  
    50  	// commented: setting astfile.comments to nil seems to fix things for the ast printer.
    51  	//ann.removeInnerFuncComments(astFile)
    52  	astFile.Comments = nil
    53  
    54  	ann.debugLastIndex = ann.correctDebugIndexes(astFile)
    55  
    56  	//fmt.Println("result----")
    57  	//ann.printNode(astFile)
    58  }
    59  
    60  //----------
    61  
    62  func (ann *Annotator) log(args ...interface{}) {
    63  	//log.Print(args...)
    64  	s := fmt.Sprint(args...)
    65  	s = strings.TrimRight(s, "\n") + "\n"
    66  	fmt.Print(s)
    67  }
    68  func (ann *Annotator) logf(f string, args ...interface{}) {
    69  	ann.log(fmt.Sprintf(f, args...))
    70  }
    71  
    72  //----------
    73  
    74  func (ann *Annotator) vis(ctx *Ctx, v interface{}) {
    75  	switch t := v.(type) {
    76  	case nil: // nothing todo
    77  	case ast.Node:
    78  		ann.vis2(ctx, t)
    79  	case *[]ast.Stmt:
    80  		ann.visStmts(ctx, t)
    81  	default:
    82  		panic(fmt.Sprintf("todo: %T", t))
    83  	}
    84  }
    85  
    86  // Should only be called throught vis()
    87  func (ann *Annotator) vis2(ctx *Ctx, node ast.Node) {
    88  	//ann.logf("vis2 %T\n", node)
    89  	//ann.logf("vis2 %T (%v)\n", node, ann.sprintNode(node))
    90  
    91  	// handle here for top level directives (ex: func decl)
    92  	ctx = ann.annotationBlockCtx(ctx, node)
    93  	if ctx.boolean(ctxIdNoAnnotations) {
    94  		ann.visNoAnnotations(ctx, node)
    95  		return
    96  	}
    97  
    98  	// build name: visit node if there is a function defined for it
    99  	name, err := reflectutil.TypeNameBase(node)
   100  	if err != nil {
   101  		return
   102  	}
   103  	res, err := reflectutil.InvokeByName(ann, "Vis"+name, ctx, node)
   104  	if err != nil {
   105  		ann.logf("todo: vis2: %v", err)
   106  		return
   107  	}
   108  	if len(res) != 0 {
   109  		panic(fmt.Sprintf("len of res not zero: %v", len(res)))
   110  	}
   111  }
   112  
   113  //----------
   114  
   115  func (ann *Annotator) visNoAnnotations(ctx *Ctx, n1 ast.Node) {
   116  	ast.Inspect(n1, func(n2 ast.Node) bool {
   117  		if n2 != n1 {
   118  			ctx2 := ann.annotationBlockCtx(ctx, n2)
   119  			if !ctx2.boolean(ctxIdNoAnnotations) {
   120  				ann.vis(ctx2, n2)
   121  				return false // done with noannotations
   122  			}
   123  		}
   124  
   125  		// special handling of a few nodes to setup the ctx in case annotations become enabled
   126  		switch t2 := n2.(type) {
   127  		case *ast.BlockStmt:
   128  			ann.vis(ctx, &t2.List)
   129  			return false
   130  		case *ast.CaseClause:
   131  			ann.vis(ctx, &t2.Body) // not a blockstmt
   132  			return false
   133  		case *ast.CommClause:
   134  			ann.vis(ctx, &t2.Body) // not a blockstmt
   135  			return false
   136  
   137  		case *ast.FuncDecl:
   138  			ctx2 := ctx.withFuncType(t2.Type)
   139  			ann.vis(ctx2, t2.Body)
   140  			return false
   141  		case *ast.FuncLit:
   142  			ctx2 := ctx.withFuncType(t2.Type)
   143  			ann.vis(ctx2, t2.Body)
   144  			return false
   145  
   146  		case *ast.DeclStmt:
   147  			ann.VisDeclStmt(ctx, t2) // sets ctx boolean
   148  			return false
   149  
   150  		// TODO: godebug directive in "else if" between "else" and "if"?
   151  
   152  		default:
   153  			return true // visit childs
   154  		}
   155  	})
   156  }
   157  
   158  //----------
   159  
   160  // the resulting (res) "debug" expr for the given expr
   161  func (ann *Annotator) resExpr(ctx *Ctx, e *ast.Expr) ast.Expr {
   162  	ctx = ctx.withExpr(e)
   163  	node := *e
   164  
   165  	//ann.logf("resExpr %T\n", node)
   166  	//ann.logf("resExpr %T (%v)\n", *e, ann.sprintNode2(node))
   167  
   168  	// buildname: visit node if there is a function defined for it
   169  	name, err := reflectutil.TypeNameBase(node)
   170  	if err != nil {
   171  		return nilIdent()
   172  	}
   173  	res, err := reflectutil.InvokeByName(ann, "Res"+name, ctx, node)
   174  	if err != nil {
   175  		ann.logf("todo: resExpr: %v", err)
   176  		return nilIdent()
   177  	}
   178  	result := res[0].Interface().(ast.Expr) // must succeed
   179  	if result == nil {
   180  		return nilIdent()
   181  	}
   182  	return result
   183  }
   184  
   185  func (ann *Annotator) resExprs(ctx *Ctx, es *[]ast.Expr) ast.Expr {
   186  	ctx = ctx.withExprs(es)
   187  	w := []ast.Expr{}
   188  	for i := range *es {
   189  		ctx2 := ctx
   190  		e1 := &(*es)[i]
   191  		res := (ast.Expr)(nil)
   192  		if i == 0 && ctx2.boolean(ctxIdFirstArgIsType) {
   193  			ctx2 = ctx2.withBoolean(ctxIdInTypeArg, true)
   194  		}
   195  		res = ann.resExpr(ctx2, e1)
   196  		if res == nil {
   197  			res = nilIdent()
   198  		}
   199  		w = append(w, res)
   200  	}
   201  	if len(w) == 0 {
   202  		return nilIdent()
   203  	}
   204  	return ann.newDebugI(ctx, "IL", w...)
   205  }
   206  
   207  func (ann *Annotator) resFieldList(ctx *Ctx, fl *ast.FieldList) ast.Expr {
   208  	w := []ast.Expr{}
   209  	for _, f := range fl.List {
   210  		// set field name if it has no names (otherwise it won't output)
   211  		if len(f.Names) == 0 {
   212  			f.Names = append(f.Names, ann.newIdent(ctx))
   213  		}
   214  
   215  		for i := range f.Names {
   216  			e1 := ast.Expr(f.Names[i])
   217  			e := ann.resExpr(ctx, &e1) // e1 won't be replaceable (local var)
   218  			w = append(w, e)
   219  		}
   220  	}
   221  	if len(w) == 0 {
   222  		return nilIdent()
   223  	}
   224  	return ann.newDebugI(ctx, "IL", w...)
   225  }
   226  
   227  //----------
   228  //----------
   229  //----------
   230  
   231  func (ann *Annotator) VisFile(ctx *Ctx, file *ast.File) {
   232  	for _, d := range file.Decls {
   233  		ann.vis(ctx, d)
   234  	}
   235  }
   236  
   237  func (ann *Annotator) VisGenDecl(ctx *Ctx, gd *ast.GenDecl) {
   238  	switch gd.Tok {
   239  	case token.CONST:
   240  		// TODO: handle iota
   241  	case token.VAR:
   242  		// annotate only if inside decl stmt
   243  		// TODO: top level var decls that have a func lit assigned?
   244  		if !ctx.boolean(ctxIdInDeclStmt) {
   245  			break
   246  		}
   247  
   248  		if len(gd.Specs) >= 2 {
   249  			ann.splitGenDecl(ctx, gd)
   250  		}
   251  		for _, spec := range gd.Specs {
   252  			ann.vis(ctx, spec)
   253  		}
   254  	}
   255  }
   256  
   257  func (ann *Annotator) VisImportSpec(ctx *Ctx, is *ast.ImportSpec) {
   258  }
   259  
   260  func (ann *Annotator) VisDeclStmt(ctx *Ctx, ds *ast.DeclStmt) {
   261  	// DeclStmt is a decl in a stmt list => gendecl is only const/type/var
   262  	ctx = ctx.withBoolean(ctxIdInDeclStmt, true)
   263  	ann.vis(ctx, ds.Decl)
   264  }
   265  
   266  func (ann *Annotator) VisFuncDecl(ctx *Ctx, fd *ast.FuncDecl) {
   267  	// body can be nil (external func decls, only the header declared)
   268  	if fd.Body == nil {
   269  		return
   270  	}
   271  
   272  	//// don't annotate these functions to avoid endless loop recursion
   273  	//if fd.Recv != nil && fd.Body != nil && fd.Name.Name == "String" && len(fd.Type.Params.List) == 0 {
   274  	//	return
   275  	//}
   276  	//if fd.Recv != nil && fd.Body != nil && fd.Name.Name == "Error" && len(fd.Type.Params.List) == 0 {
   277  	//	return
   278  	//}
   279  
   280  	// visit body first to avoid annotating params insertions
   281  	ctx2 := ctx.withFuncType(fd.Type)
   282  	ann.vis(ctx2, fd.Body)
   283  
   284  	// visit params
   285  	ann.visFieldList(ctx, fd.Type.Params, fd.Body)
   286  }
   287  
   288  func (ann *Annotator) VisBlockStmt(ctx *Ctx, bs *ast.BlockStmt) {
   289  	ann.vis(ctx, &bs.List)
   290  }
   291  
   292  func (ann *Annotator) VisExprStmt(ctx *Ctx, es *ast.ExprStmt) {
   293  	ctx = ctx.withFixedDebugIndex()
   294  	xPos := es.X.Pos()
   295  	e := ann.resExpr(ctx, &es.X)
   296  	ctx3 := ctx.withInsertStmtAfter(true)
   297  	ann.insertDebugLine(ctx3, xPos, e)
   298  }
   299  
   300  func (ann *Annotator) VisAssignStmt(ctx *Ctx, as *ast.AssignStmt) {
   301  	ctx = ctx.withFixedDebugIndex()
   302  
   303  	asPos := as.Pos()
   304  	asTok := as.Tok
   305  
   306  	// right hand side
   307  	ctx3 := ctx
   308  	if len(as.Rhs) == 1 {
   309  		// ex: a:=b
   310  		// ex: a,ok:= m[b]
   311  		// ex: a,b,c:=f()
   312  		ctx3 = ctx3.withNResults(len(as.Lhs))
   313  	} else {
   314  		// ex: a,b,c:=d,e,f // each of {d,e,f} return only 1 result
   315  		ctx3 = ctx3.withNResults(1)
   316  	}
   317  	rhs := ann.resExprs(ctx3, &as.Rhs)
   318  
   319  	// assign right hand side to a var before the main assign stmt
   320  	ctx5 := ctx.withInsertStmtAfter(false)
   321  	rhs2 := ann.assignToNewIdent(ctx5, rhs)
   322  
   323  	// simplify (don't show lhs since it's similar to rhs)
   324  	allSimple := false // ex: a++, a+=1
   325  	switch asTok {
   326  	case token.DEFINE, token.ASSIGN:
   327  		allSimple = true
   328  		if len(as.Rhs) == 1 {
   329  			if _, ok := as.Rhs[0].(*ast.TypeAssertExpr); ok {
   330  				allSimple = false
   331  			}
   332  		}
   333  	}
   334  	if allSimple {
   335  		for _, e := range as.Lhs {
   336  			if !isIdentOrSelectorOfIdents(e) {
   337  				allSimple = false
   338  				break
   339  			}
   340  		}
   341  	}
   342  	if allSimple {
   343  		ann.insertDebugLine(ctx, asPos, rhs2)
   344  		return
   345  	}
   346  
   347  	// left hand side
   348  	// ex: a[i] // returns 1 result
   349  	// ex: a,b,c:= // each expr returns 1 result to be debugged
   350  	ctx4 := ctx
   351  	ctx4 = ctx.withInsertStmtAfter(true)
   352  	ctx4 = ctx4.withNResults(1)
   353  	ctx4 = ctx4.withBoolean(ctxIdExprInLhs, true)
   354  	lhs := ann.resExprs(ctx4, &as.Lhs)
   355  
   356  	ctx = ctx.withInsertStmtAfter(true)
   357  	opbl := basicLitInt(int(asTok))
   358  	ce3 := ann.newDebugI(ctx, "IA", lhs, opbl, rhs2)
   359  	ann.insertDebugLine(ctx, asPos, ce3)
   360  }
   361  
   362  func (ann *Annotator) VisReturnStmt(ctx *Ctx, rs *ast.ReturnStmt) {
   363  	ft, ok := ctx.funcType()
   364  	if !ok {
   365  		return
   366  	}
   367  
   368  	// functype number of results to return
   369  	nres := ft.Results.NumFields()
   370  	if nres == 0 {
   371  		// show debug step
   372  		ce := ann.newDebugI(ctx, "ISt")
   373  		ann.insertDebugLine(ctx, rs.Pos(), ce)
   374  		return
   375  	}
   376  
   377  	// naked return (have nres>0), use results ids
   378  	if len(rs.Results) == 0 {
   379  		var w []ast.Expr
   380  		for _, f := range ft.Results.List {
   381  			for _, id := range f.Names {
   382  				w = append(w, id)
   383  			}
   384  		}
   385  		rs.Results = w
   386  	}
   387  
   388  	// visit results
   389  	pos := rs.Pos()
   390  	ctx2 := ctx
   391  	ctx2 = ctx2.withFixedDebugIndex()
   392  	if len(rs.Results) > 1 { // each return expr returns 1 result
   393  		ctx2 = ctx2.withNResults(1)
   394  	} else {
   395  		ctx2 = ctx2.withNResults(nres)
   396  	}
   397  	e2 := ann.resExprs(ctx2, &rs.Results)
   398  
   399  	ann.insertDebugLine(ctx2, pos, e2)
   400  }
   401  
   402  func (ann *Annotator) VisTypeSwitchStmt(ctx *Ctx, tss *ast.TypeSwitchStmt) {
   403  	ctx = ctx.withFixedDebugIndex()
   404  	if ok := ann.wrapInitInBlockAndVisit(ctx, tss, &tss.Init); ok {
   405  		return
   406  	}
   407  
   408  	// visiting tss.assign stmt would enter into the stmt exprstmt that always inserts the stmt after; this case needs the stmt insert before
   409  	e2 := (*ast.Expr)(nil)
   410  	switch t := tss.Assign.(type) {
   411  	case *ast.ExprStmt:
   412  		e2 = &t.X
   413  	case *ast.AssignStmt:
   414  		if len(t.Rhs) == 1 {
   415  			e2 = &t.Rhs[0]
   416  		}
   417  	}
   418  	if e2 != nil {
   419  		pos := (*e2).Pos()
   420  		ctx2 := ctx
   421  		ctx2 = ctx2.withFixedDebugIndex()
   422  		ctx2 = ctx2.withInsertStmtAfter(false)
   423  		e := ann.resExpr(ctx2, e2)
   424  		ann.insertDebugLine(ctx2, pos, e)
   425  	}
   426  
   427  	ctx3 := ctx.withNilFixedDebugIndex()
   428  	ann.vis(ctx3, tss.Body)
   429  }
   430  
   431  func (ann *Annotator) VisSwitchStmt(ctx *Ctx, ss *ast.SwitchStmt) {
   432  	ctx = ctx.withFixedDebugIndex()
   433  	if ok := ann.wrapInitInBlockAndVisit(ctx, ss, &ss.Init); ok {
   434  		return
   435  	}
   436  
   437  	if ss.Tag != nil {
   438  		tagPos := ss.Tag.Pos()
   439  		ctx3 := ctx
   440  		ctx3 = ctx3.withNResults(1) // ex: switch f1() // f1 has 1 result
   441  		e := ann.resExpr(ctx3, &ss.Tag)
   442  		ann.insertDebugLine(ctx3, tagPos, e)
   443  	}
   444  
   445  	// reset fixed debug index to visit the body since it has several stmts
   446  	ctx2 := ctx.withNilFixedDebugIndex()
   447  	ann.vis(ctx2, ss.Body)
   448  }
   449  
   450  func (ann *Annotator) VisIfStmt(ctx *Ctx, is *ast.IfStmt) {
   451  	ctx = ctx.withFixedDebugIndex()
   452  	if ok := ann.wrapInitInBlockAndVisit(ctx, is, &is.Init); ok {
   453  		return
   454  	}
   455  
   456  	// condition
   457  	isPos := is.Cond.Pos()
   458  	ctx2 := ctx
   459  	ctx2 = ctx2.withNResults(1)
   460  	ctx2 = ctx2.withInsertStmtAfter(false)
   461  	e := ann.resExpr(ctx2, &is.Cond)
   462  	ann.insertDebugLine(ctx2, isPos, e)
   463  
   464  	// reset fixed debug index to visit the body since it has several stmts
   465  	ctx3 := ctx.withNilFixedDebugIndex()
   466  	ann.vis(ctx3, is.Body)
   467  
   468  	switch is.Else.(type) {
   469  	case *ast.IfStmt: // "else if ..."
   470  		// wrap in block stmt to visit "if" stmt
   471  		bs := &ast.BlockStmt{List: []ast.Stmt{is.Else}}
   472  		is.Else = bs
   473  	}
   474  	ann.vis(ctx3, is.Else)
   475  }
   476  
   477  func (ann *Annotator) VisForStmt(ctx *Ctx, fs *ast.ForStmt) {
   478  	ctx = ctx.withFixedDebugIndex()
   479  	if ok := ann.wrapInitInBlockAndVisit(ctx, fs, &fs.Init); ok {
   480  		return
   481  	}
   482  
   483  	// visit the body first to avoid annotating inserted stmts of cond/post later
   484  	ctx7 := ctx.withNilFixedDebugIndex()
   485  	ann.vis(ctx7, fs.Body)
   486  
   487  	if fs.Cond != nil {
   488  		fsBodyCtx := ctx.withStmts(&fs.Body.List)
   489  		condPos := fs.Cond.Pos()
   490  
   491  		e := ann.resExpr(fsBodyCtx, &fs.Cond)
   492  		ann.insertDebugLine(fsBodyCtx, condPos, e)
   493  
   494  		// create ifstmt to break the loop
   495  		ue := &ast.UnaryExpr{Op: token.NOT, X: fs.Cond} // negate
   496  		is := &ast.IfStmt{If: fs.Pos(), Cond: ue, Body: &ast.BlockStmt{}}
   497  		fs.Cond = nil // clear forstmt condition
   498  		fsBodyCtx.insertStmt(is)
   499  		isBodyCtx := ctx.withStmts(&is.Body.List)
   500  
   501  		// insert break inside ifstmt
   502  		brk := &ast.BranchStmt{Tok: token.BREAK}
   503  		isBodyCtx.insertStmt(brk)
   504  	}
   505  
   506  	if fs.Post != nil {
   507  		fsBodyCtx := ctx.withStmts(&fs.Body.List) // TODO: review
   508  
   509  		// init flag var to run post stmt
   510  		flagVar := ann.newIdent(ctx)
   511  		as4 := ann.newAssignStmt11(flagVar, &ast.Ident{Name: "false"})
   512  		ctx.insertStmt(as4)
   513  
   514  		// inside the forloop: ifstmt to know if the post stmt can run
   515  		is := &ast.IfStmt{Body: &ast.BlockStmt{}}
   516  		is.Cond = flagVar
   517  		fsBodyCtx.insertStmt(is)
   518  		isBodyCtx := ctx.withStmts(&is.Body.List)
   519  
   520  		// move fs.Post to inside the ifstmt
   521  		isBodyCtx.insertStmt(fs.Post)
   522  		fs.Post = nil
   523  
   524  		// visit ifstmt body that now contains the post stmt
   525  		ann.vis(ctx, is.Body)
   526  
   527  		// insert stmt that sets the flag to true
   528  		as5 := ann.newAssignStmt11(flagVar, &ast.Ident{Name: "true"})
   529  		as5.Tok = token.ASSIGN
   530  		fsBodyCtx.insertStmt(as5)
   531  	}
   532  }
   533  
   534  func (ann *Annotator) VisRangeStmt(ctx *Ctx, rs *ast.RangeStmt) {
   535  	ctx = ctx.withFixedDebugIndex()
   536  
   537  	xPos := rs.X.Pos()
   538  	rsTok := rs.Tok
   539  
   540  	// range stmt
   541  	ctx3 := ctx.withNResults(1)
   542  	x := ann.resExpr(ctx3, &rs.X)
   543  	//ann.insertDebugLine(ctx3, xPos, x)
   544  
   545  	// length of x (insert before for stmt)
   546  	e5 := &ast.CallExpr{Fun: ast.NewIdent("len"), Args: []ast.Expr{rs.X}}
   547  	e6 := ann.newDebugI(ctx, "IVr", e5)
   548  	e7 := ann.assignToNewIdent(ctx, e6) // var is of type item
   549  
   550  	// first debug line (entering the loop)
   551  	e11 := ann.newDebugIL(ctx, e7, x)
   552  	ann.insertDebugLine(ctx, xPos, e11)
   553  
   554  	// visit the body first to avoid annotating inserted stmts
   555  	ctx6 := ctx.withNilFixedDebugIndex()
   556  	ann.vis(ctx6, rs.Body)
   557  
   558  	// key and value
   559  	kvPos := token.Pos(0)
   560  	rsBodyCtx := ctx.withStmts(&rs.Body.List)
   561  	kves := []ast.Expr{}
   562  	if rs.Key != nil {
   563  		kvPos = rs.Key.Pos()
   564  		e2 := ann.resExpr(rsBodyCtx, &rs.Key)
   565  		kves = append(kves, e2)
   566  	}
   567  	if rs.Value != nil {
   568  		if kvPos == 0 {
   569  			kvPos = rs.Value.Pos()
   570  		}
   571  		e2 := ann.resExpr(rsBodyCtx, &rs.Value)
   572  		kves = append(kves, e2)
   573  	}
   574  
   575  	if len(kves) > 0 {
   576  		ctx5 := rsBodyCtx
   577  		opbl := basicLitInt(int(rsTok))
   578  		rhs := ann.newDebugI(ctx5, "IL", []ast.Expr{e7}...)
   579  		lhs := ann.newDebugI(ctx5, "IL", kves...)
   580  		e9 := ann.newDebugI(ctx5, "IA", lhs, opbl, rhs)
   581  		ann.insertDebugLine(ctx5, kvPos, e9)
   582  	}
   583  }
   584  
   585  func (ann *Annotator) VisIncDecStmt(ctx *Ctx, ids *ast.IncDecStmt) {
   586  	ctx = ctx.withFixedDebugIndex()
   587  	idsPos := ids.X.Pos()
   588  	idsTok := ids.Tok
   589  
   590  	// value before
   591  	e1 := ann.resExpr(ctx, &ids.X)
   592  	l1 := ann.newDebugI(ctx, "IL", e1)
   593  	ctx3 := ctx.withInsertStmtAfter(false)
   594  	l1before := ann.assignToNewIdent(ctx3, l1)
   595  
   596  	// value after
   597  	ctx2 := ctx.withInsertStmtAfter(true)
   598  	e2 := ann.resExpr(ctx2, &ids.X)
   599  	l2 := ann.newDebugI(ctx, "IL", e2)
   600  
   601  	opbl := basicLitInt(int(idsTok))
   602  	ce3 := ann.newDebugI(ctx2, "IA", l2, opbl, l1before)
   603  	ann.insertDebugLine(ctx2, idsPos, ce3)
   604  }
   605  
   606  func (ann *Annotator) VisLabeledStmt(ctx *Ctx, ls *ast.LabeledStmt) {
   607  	// Problem:
   608  	// -	label1: ; // inserting empty stmt breaks compilation
   609  	// 	for { break label1 } // compile error: invalid break label
   610  	// -	using block stmts won't work
   611  	// 	label1:
   612  	// 	{ for { break label1} } // compile error
   613  	// No way to insert debug stmts between the label and the stmt.
   614  	// Just make a debug step with "label" where a warning can be shown.
   615  
   616  	if ls.Stmt == nil {
   617  		return
   618  	}
   619  
   620  	switch ls.Stmt.(type) {
   621  	case *ast.ForStmt, *ast.RangeStmt, *ast.SwitchStmt, *ast.TypeSwitchStmt:
   622  		// can't insert stmts between the label and the stmt (alters program)
   623  
   624  		ctx = ctx.withLabeledStmt(ls)
   625  		ann.vis(ctx, ls.Stmt)
   626  	default:
   627  		// use empty stmt to insert stmts between label and stmt
   628  		stmt := ls.Stmt
   629  		ls.Stmt = &ast.EmptyStmt{}
   630  
   631  		// insert stmt before, consider stmt done
   632  		ctx3 := ctx.withInsertStmtAfter(false)
   633  		ctx3.insertStmt(ls)
   634  
   635  		// replace stmt and continue visit
   636  		ctx.replaceStmt(stmt)
   637  		ann.vis(ctx, stmt)
   638  	}
   639  }
   640  
   641  func (ann *Annotator) VisBranchStmt(ctx *Ctx, bs *ast.BranchStmt) {
   642  	ce := ann.newDebugI(ctx, "IBr")
   643  	ann.insertDebugLine(ctx, bs.Pos(), ce)
   644  }
   645  
   646  func (ann *Annotator) VisDeferStmt(ctx *Ctx, ds *ast.DeferStmt) {
   647  	ann.visDeferStmt2(ctx, &ds.Call)
   648  }
   649  func (ann *Annotator) VisGoStmt(ctx *Ctx, gs *ast.GoStmt) {
   650  	ann.visDeferStmt2(ctx, &gs.Call)
   651  }
   652  func (ann *Annotator) visDeferStmt2(ctx *Ctx, cep **ast.CallExpr) {
   653  	ctx = ctx.withCallExpr(cep)
   654  	ce := *cep
   655  
   656  	funPos := ce.Fun.Pos()
   657  
   658  	// assign arguments to tmp variables
   659  	if len(ce.Args) > 0 {
   660  		//args2 := make([]ast.Expr, len(ce.Args))
   661  		//copy(args2, ce.Args)
   662  		//ids := ann.assignToNewIdents2(ctx, len(ce.Args), args2...)
   663  		for i, e := range ce.Args {
   664  			if ann.canAssignToVar(ctx, e) {
   665  				id := ann.assignToNewIdent(ctx, e)
   666  				ce.Args[i] = id
   667  			}
   668  			//else {
   669  			//ce.Args[i] = ids[i]
   670  			//}
   671  		}
   672  	}
   673  
   674  	ctx = ctx.withFixedDebugIndex()
   675  
   676  	// handle funclit
   677  	ceFunIsFuncLit := false
   678  	switch ce.Fun.(type) {
   679  	case *ast.FuncLit:
   680  		ceFunIsFuncLit = true
   681  		ctx3 := ctx.withNResults(1)
   682  		fun := ann.resExpr(ctx3, &ce.Fun)
   683  		ann.insertDebugLine(ctx, funPos, fun)
   684  	}
   685  
   686  	// replace func call with wrapped function
   687  	fl2 := &ast.FuncLit{
   688  		Type: &ast.FuncType{
   689  			Params: &ast.FieldList{},
   690  		},
   691  		Body: &ast.BlockStmt{
   692  			List: []ast.Stmt{&ast.ExprStmt{X: ce}},
   693  		},
   694  	}
   695  	ce2 := &ast.CallExpr{Fun: fl2}
   696  	ctx.replaceCallExpr(ce2)
   697  
   698  	// temporary switch names for better debug line
   699  	if ceFunIsFuncLit {
   700  		if id, ok := ce.Fun.(*ast.Ident); ok {
   701  			name := id.Name
   702  			id.Name = "f"
   703  			defer func() { id.Name = name }()
   704  		}
   705  	}
   706  
   707  	// visit block with the func call to insert debug stmts inside
   708  	ann.vis(ctx, fl2.Body)
   709  }
   710  
   711  func (ann *Annotator) VisValueSpec(ctx *Ctx, vs *ast.ValueSpec) {
   712  	// ex: var a, b int = 1, 2
   713  	// ex: var a, b = f()
   714  	if len(vs.Values) > 0 {
   715  		pos := vs.Pos()
   716  		nres := len(vs.Names)
   717  		if len(vs.Values) >= 2 {
   718  			nres = 1
   719  		}
   720  		ctx2 := ctx
   721  		ctx2 = ctx2.withFixedDebugIndex()
   722  		ctx2 = ctx2.withNResults(nres)
   723  		e := ann.resExprs(ctx2, &vs.Values)
   724  		ann.insertDebugLine(ctx2, pos, e)
   725  	}
   726  }
   727  
   728  func (ann *Annotator) VisSelectStmt(ctx *Ctx, ss *ast.SelectStmt) {
   729  	// debug step to show it has entered the select statement
   730  	e1 := ann.newDebugI(ctx, "ISt")
   731  	ann.insertDebugLine(ctx, ss.Pos(), e1)
   732  
   733  	ann.vis(ctx, ss.Body)
   734  }
   735  
   736  func (ann *Annotator) VisCaseClause(ctx *Ctx, cc *ast.CaseClause) {
   737  	// visit body
   738  	ann.vis(ctx, &cc.Body)
   739  
   740  	// debug step showing the case was entered
   741  	ctx2 := ctx.withStmts(&cc.Body)
   742  	ce := ann.newDebugI(ctx2, "ISt")
   743  	ann.insertDebugLine(ctx2, cc.Case, ce)
   744  }
   745  
   746  func (ann *Annotator) VisCommClause(ctx *Ctx, cc *ast.CommClause) {
   747  	// visit body first to avoid annotating inserted stmts
   748  	ann.vis(ctx, &cc.Body)
   749  
   750  	// debug step showing the case was entered
   751  	ctx2 := ctx.withStmts(&cc.Body)
   752  	e1 := ann.newDebugI(ctx2, "ISt")
   753  	ann.insertDebugLine(ctx2, cc.Case, e1)
   754  }
   755  
   756  func (ann *Annotator) VisSendStmt(ctx *Ctx, ss *ast.SendStmt) {
   757  	pos := ss.Pos()
   758  
   759  	ctx2 := ctx.withNResults(1)
   760  	val := ann.resExpr(ctx2, &ss.Value)
   761  
   762  	ctx3 := ctx.withInsertStmtAfter(true)
   763  	ch := ann.resExpr(ctx3, &ss.Chan)
   764  
   765  	ce := ann.newDebugI(ctx, "IS", ch, val)
   766  	ann.insertDebugLine(ctx3, pos, ce)
   767  }
   768  
   769  //----------
   770  
   771  func (ann *Annotator) visStmts(ctx *Ctx, stmts *[]ast.Stmt) {
   772  	ctx2 := ctx.withStmts(stmts)
   773  	for stmt := ctx2.curStmt(); stmt != nil; stmt = ctx2.nextStmt() {
   774  		// handle here to enabled/disable next stmts in this list
   775  		ctx2 = ann.annotationBlockCtx(ctx2, stmt)
   776  
   777  		ann.vis(ctx2, stmt)
   778  	}
   779  }
   780  
   781  // NOTE: mostly used for params (fixed debug index)
   782  func (ann *Annotator) visFieldList(ctx *Ctx, fl *ast.FieldList, body *ast.BlockStmt) {
   783  	if len(fl.List) == 0 {
   784  		return
   785  	}
   786  	ctx2 := ctx
   787  	ctx2 = ctx2.withStmts(&body.List)
   788  	ctx2 = ctx2.withFixedDebugIndex()
   789  	e1 := ann.resFieldList(ctx2, fl)
   790  	ann.insertDebugLine(ctx2, fl.Opening, e1)
   791  }
   792  
   793  //----------
   794  //----------
   795  //----------
   796  
   797  func (ann *Annotator) ResCallExpr(ctx *Ctx, ce *ast.CallExpr) ast.Expr {
   798  	cePos := ce.Pos()
   799  
   800  	// handle fun expr
   801  	isFuncLit := false
   802  	isPanic := false
   803  	isFirstArgType := false
   804  	switch t := ce.Fun.(type) {
   805  	case *ast.Ident:
   806  		// handle builtin funcs
   807  		switch t.Name {
   808  		case "panic":
   809  			if ann.isBuiltin(t) {
   810  				isPanic = true
   811  			}
   812  		case "new", "make":
   813  			if ann.isBuiltin(t) {
   814  				isFirstArgType = true
   815  			}
   816  		}
   817  	case *ast.FuncLit:
   818  		isFuncLit = true
   819  	}
   820  
   821  	// visit fun expr
   822  	ctx5 := ctx.withNResults(1)
   823  	ctx5 = ctx5.withBoolean(ctxIdNameInsteadOfValue, true)
   824  	fx := ann.resExpr(ctx5, &ce.Fun)
   825  	if isFuncLit {
   826  		ann.insertDebugLine(ctx, cePos, fx) // show step
   827  		fx = ann.newDebugIVsBl(ctx, "f")    // continue with simple name
   828  	}
   829  
   830  	// visit args
   831  	ctx2 := ctx
   832  	ctx2 = ctx2.withNResults(1) // each arg returns 1 result
   833  	ctx2 = ctx2.withBoolean(ctxIdFirstArgIsType, isFirstArgType)
   834  	args := ann.resExprs(ctx2, &ce.Args)
   835  
   836  	// show stepping in (insert before func call)
   837  	args2 := append([]ast.Expr{fx}, args)
   838  	e4 := ann.newDebugI(ctx, "ICe", args2...)
   839  	ann.insertDebugLine(ctx, cePos, e4)
   840  
   841  	// avoid "line unreachable" compiler errors
   842  	if isPanic {
   843  		return afterPanicIdent()
   844  	}
   845  
   846  	result := ann.solveNResults(ctx, ce)
   847  	//if ctx.boolean(ctxIdNameInsteadOfValue) {
   848  	//	result = nilIdent()
   849  	//}
   850  
   851  	return ann.newDebugI(ctx, "IC", e4, result)
   852  }
   853  
   854  func (ann *Annotator) ResBasicLit(ctx *Ctx, bl *ast.BasicLit) ast.Expr {
   855  	return ann.newDebugIVi(ctx, bl)
   856  }
   857  
   858  func (ann *Annotator) ResIdent(ctx *Ctx, id *ast.Ident) ast.Expr {
   859  	if id.Name == "_" {
   860  		return ann.newDebugI(ctx, "IAn")
   861  	}
   862  	if ctx.boolean(ctxIdInTypeArg) {
   863  		return ann.resType(ctx, id)
   864  	}
   865  	if ctx.boolean(ctxIdNameInsteadOfValue) {
   866  		return ann.newDebugIVsBl(ctx, id.Name)
   867  	}
   868  	return ann.newDebugIVi(ctx, id)
   869  }
   870  
   871  func (ann *Annotator) ResUnaryExpr(ctx *Ctx, ue *ast.UnaryExpr) ast.Expr {
   872  	xPos := ue.X.Pos()
   873  
   874  	ctx2 := ctx
   875  	if ue.Op == token.AND {
   876  		ctx2 = ctx2.withTakingVarAddress(ue.X)
   877  	}
   878  	x := ann.resExpr(ctx2, &ue.X)
   879  
   880  	opbl := basicLitInt(int(ue.Op))
   881  	e4 := ann.newDebugI(ctx, "IUe", opbl, x)
   882  	if ue.Op == token.ARROW {
   883  		ann.insertDebugLine(ctx, xPos, e4)
   884  	}
   885  
   886  	result := ann.solveNResults(ctx, ue)
   887  
   888  	return ann.newDebugI(ctx, "IU", e4, result)
   889  }
   890  
   891  func (ann *Annotator) ResFuncLit(ctx *Ctx, fl *ast.FuncLit) ast.Expr {
   892  	ctx0 := ctx // for the last return
   893  	ctx = ctx.withResetForFuncLit()
   894  
   895  	// visit body first to avoid annotating params insertions
   896  	ctx3 := ctx
   897  	ctx3 = ctx3.withFuncType(fl.Type)
   898  	ann.vis(ctx3, fl.Body)
   899  
   900  	// visit params
   901  	ann.visFieldList(ctx, fl.Type.Params, fl.Body)
   902  
   903  	return ann.solveNResults(ctx0, fl)
   904  }
   905  
   906  func (ann *Annotator) ResSelectorExpr(ctx *Ctx, se *ast.SelectorExpr) ast.Expr {
   907  	if ctx.boolean(ctxIdInTypeArg) {
   908  		return ann.resType(ctx, se)
   909  	}
   910  
   911  	// simplify
   912  	if isIdentOrSelectorOfIdents(se) {
   913  		if ctx.boolean(ctxIdNameInsteadOfValue) {
   914  			return ann.newDebugIVsBl(ctx, se.Sel.Name)
   915  		}
   916  		return ann.newDebugIVi(ctx, se)
   917  	}
   918  
   919  	//xPos := se.X.Pos()
   920  	ctx4 := ctx.withNResults(1) //.withNameInsteadOfValue(false)
   921  	x := ann.resExpr(ctx4, &se.X)
   922  	//ann.insertDebugLine(ctx4, xPos, x)
   923  
   924  	sel := ast.Expr(nil)
   925  	if ctx.boolean(ctxIdNameInsteadOfValue) {
   926  		sel = ann.newDebugIVsBl(ctx, se.Sel.Name)
   927  	} else {
   928  		sel = ann.newDebugIVi(ctx, se)
   929  	}
   930  	return ann.newDebugI(ctx, "ISel", x, sel)
   931  
   932  	//ctx3 := ctx.withExpr(&se.X).withNResults(1)
   933  	//result := ann.solveNResults(ctx3, se.X)
   934  
   935  	//return ann.newDebugItem(ctx, "ISel", result, sel)
   936  }
   937  
   938  func (ann *Annotator) ResCompositeLit(ctx *Ctx, cl *ast.CompositeLit) ast.Expr {
   939  	// NOTE: not doing cl.Type
   940  	e := ann.resExprs(ctx, &cl.Elts)
   941  	return ann.newDebugI(ctx, "ILit", e)
   942  }
   943  
   944  func (ann *Annotator) ResKeyValueExpr(ctx *Ctx, kv *ast.KeyValueExpr) ast.Expr {
   945  	k := ast.Expr(nil)
   946  	if id, ok := kv.Key.(*ast.Ident); ok {
   947  		bl := basicLitStringQ(id.Name)
   948  		k = ann.newDebugI(ctx, "IVs", bl)
   949  	} else {
   950  		k = ann.resExpr(ctx, &kv.Key)
   951  	}
   952  	v := ann.resExpr(ctx, &kv.Value)
   953  	return ann.newDebugI(ctx, "IKV", k, v)
   954  }
   955  
   956  func (ann *Annotator) ResTypeAssertExpr(ctx *Ctx, tae *ast.TypeAssertExpr) ast.Expr {
   957  	// tae.Type!=nil is "t,ok:=X.(<type>)"
   958  	// tae.Type==nil is "switch X.(type)"
   959  	isSwitch := tae.Type == nil
   960  
   961  	ctx2 := ctx
   962  	ctx2 = ctx2.withNResults(1) // ex: f().(type) // f() returns 1 result
   963  	x := ann.resExpr(ctx2, &tae.X)
   964  
   965  	// simplify
   966  	if !isSwitch {
   967  		return x
   968  	}
   969  
   970  	xt := ann.newDebugI(ctx, "IVt", tae.X)
   971  	return ann.newDebugI(ctx, "ITA", x, xt)
   972  }
   973  
   974  func (ann *Annotator) ResParenExpr(ctx *Ctx, pe *ast.ParenExpr) ast.Expr {
   975  	x := ann.resExpr(ctx, &pe.X)
   976  	return ann.newDebugI(ctx, "IP", x)
   977  }
   978  
   979  func (ann *Annotator) ResIndexExpr(ctx *Ctx, ie *ast.IndexExpr) ast.Expr {
   980  	// ex: a,b=c[i],d[j]
   981  	// ex: a,ok:=m[f1()] // map access, more then 1 result
   982  
   983  	isSimple := isIdentOrSelectorOfIdents(ie.X)
   984  
   985  	ctx2 := ctx.withBoolean(ctxIdNameInsteadOfValue, true)
   986  	x := ann.resExpr(ctx2, &ie.X)
   987  
   988  	// wrap in parenthesis
   989  	if !isSimple {
   990  		x = ann.newDebugIP(ctx, x)
   991  	}
   992  
   993  	// Index expr
   994  	ctx3 := ctx
   995  	ctx3 = ctx3.withNResults(1)                    // ex: a[f()] // f() returns 1 result
   996  	ctx3 = ctx3.withInsertStmtAfter(false)         // ex: a[f()] // f() must be before
   997  	ctx3 = ctx3.withBoolean(ctxIdExprInLhs, false) // ex: a[f()] // allow to replace f()
   998  	ix := ann.resExpr(ctx3, &ie.Index)
   999  
  1000  	result := ann.solveNResults(ctx, ie)
  1001  
  1002  	return ann.newDebugI(ctx, "II", x, ix, result)
  1003  }
  1004  
  1005  func (ann *Annotator) ResSliceExpr(ctx *Ctx, se *ast.SliceExpr) ast.Expr {
  1006  	isSimple := isIdentOrSelectorOfIdents(se.X)
  1007  
  1008  	ctx2 := ctx.withBoolean(ctxIdNameInsteadOfValue, true)
  1009  	x := ann.resExpr(ctx2, &se.X)
  1010  
  1011  	// wrap in parenthesis
  1012  	if !isSimple {
  1013  		x = ann.newDebugIP(ctx, x)
  1014  	}
  1015  
  1016  	// index expr
  1017  	ix := []ast.Expr{}
  1018  	for _, e := range []*ast.Expr{&se.Low, &se.High, &se.Max} {
  1019  		r := ann.resExpr(ctx, e)
  1020  		ix = append(ix, r)
  1021  	}
  1022  
  1023  	result := ann.solveNResults(ctx, se)
  1024  
  1025  	// slice3: 2 colons present
  1026  	s := "false"
  1027  	if se.Slice3 {
  1028  		s = "true"
  1029  	}
  1030  	slice3Bl := basicLitString(s)
  1031  
  1032  	return ann.newDebugI(ctx, "II2", x, ix[0], ix[1], ix[2], slice3Bl, result)
  1033  }
  1034  
  1035  func (ann *Annotator) ResStarExpr(ctx *Ctx, se *ast.StarExpr) ast.Expr {
  1036  	if ann.isType(se) {
  1037  		return ann.resType(ctx, se)
  1038  	}
  1039  
  1040  	// ex: *a=1
  1041  	ctx = ctx.withNResults(1)
  1042  
  1043  	x := ann.resExpr(ctx, &se.X)
  1044  	//return x
  1045  
  1046  	result := ann.solveNResults(ctx, se)
  1047  
  1048  	opbl := basicLitInt(int(token.MUL))
  1049  	e2 := ann.newDebugI(ctx, "IUe", opbl, x)
  1050  	return ann.newDebugI(ctx, "IU", e2, result)
  1051  }
  1052  
  1053  func (ann *Annotator) ResMapType(ctx *Ctx, mt *ast.MapType) ast.Expr {
  1054  	return ann.resType(ctx, mt)
  1055  }
  1056  func (ann *Annotator) ResChanType(ctx *Ctx, ct *ast.ChanType) ast.Expr {
  1057  	return ann.resType(ctx, ct)
  1058  }
  1059  func (ann *Annotator) ResArrayType(ctx *Ctx, at *ast.ArrayType) ast.Expr {
  1060  	return ann.resType(ctx, at)
  1061  }
  1062  func (ann *Annotator) ResInterfaceType(ctx *Ctx, it *ast.InterfaceType) ast.Expr {
  1063  	return ann.resType(ctx, it)
  1064  }
  1065  
  1066  //----------
  1067  
  1068  func (ann *Annotator) ResBinaryExpr(ctx *Ctx, be *ast.BinaryExpr) ast.Expr {
  1069  	ctx = ctx.withNResults(1)
  1070  	switch be.Op {
  1071  	case token.LAND, token.LOR:
  1072  		return ann.resBinaryExprAndOr(ctx, be)
  1073  	default:
  1074  		return ann.resBinaryExpr2(ctx, be)
  1075  	}
  1076  }
  1077  func (ann *Annotator) resBinaryExpr2(ctx *Ctx, be *ast.BinaryExpr) ast.Expr {
  1078  	x := ann.resExpr(ctx, &be.X)
  1079  	y := ann.resExpr(ctx, &be.Y)
  1080  	result := ann.solveNResults(ctx, be)
  1081  	opbl := basicLitInt(int(be.Op))
  1082  	return ann.newDebugI(ctx, "IB", x, opbl, y, result)
  1083  }
  1084  func (ann *Annotator) resBinaryExprAndOr(ctx *Ctx, be *ast.BinaryExpr) ast.Expr {
  1085  	// ex: f1() || f2() // f2 should not be called if f1 is true
  1086  	// ex: f1() && f2() // f2 should not be called if f1 is false
  1087  
  1088  	x := ann.resExpr(ctx, &be.X)
  1089  
  1090  	// init result var with be.X
  1091  	resVar := ast.Expr(ann.newIdent(ctx))
  1092  	as4 := ann.newAssignStmt11(resVar, be.X)
  1093  	as4.Tok = token.DEFINE
  1094  	ctx.insertStmt(as4)
  1095  	// replace expr with result var
  1096  	ctx.replaceExpr(resVar)
  1097  
  1098  	// init y result var (in case be.Y doesn't run)
  1099  	ybl := ann.newDebugIVsBl(ctx, "?")
  1100  	yRes := ann.assignToNewIdent(ctx, ybl)
  1101  
  1102  	// x condition based on being "&&" or "||"
  1103  	xCond := resVar
  1104  	if be.Op == token.LOR {
  1105  		xCond = &ast.UnaryExpr{Op: token.NOT, X: xCond}
  1106  	}
  1107  
  1108  	// ifstmt to test x result to decide whether to run y
  1109  	is := &ast.IfStmt{If: be.Pos(), Body: &ast.BlockStmt{}}
  1110  	is.Cond = xCond
  1111  	ctx.insertStmt(is)
  1112  	isBodyCtx := ctx.withStmts(&is.Body.List)
  1113  
  1114  	y := ann.resExpr(isBodyCtx, &be.Y)
  1115  
  1116  	// (inside ifstmt) assign debug result to y
  1117  	as3 := ann.newAssignStmt11(yRes, y)
  1118  	as3.Tok = token.ASSIGN
  1119  	isBodyCtx.insertStmt(as3)
  1120  
  1121  	// inside ifstmt: assign be.Y to result var
  1122  	as2 := ann.newAssignStmt11(resVar, be.Y)
  1123  	as2.Tok = token.ASSIGN
  1124  	isBodyCtx.insertStmt(as2)
  1125  
  1126  	opbl := basicLitInt(int(be.Op))
  1127  	resVar2 := ann.newDebugIVi(ctx, resVar)
  1128  	return ann.newDebugI(ctx, "IB", x, opbl, yRes, resVar2)
  1129  }
  1130  
  1131  //----------
  1132  //----------
  1133  //----------
  1134  
  1135  // Mostly gets the expression into a var(s) to be able to use the result without calculating it twice. Ex: don't double call f().
  1136  func (ann *Annotator) solveNResults(ctx *Ctx, e ast.Expr) ast.Expr {
  1137  	// ex: a, b = c[i], d[j] // 1 result for each expr
  1138  	// ex: a, ok := c[f1()] // map access, more then 1 result
  1139  	// ex: a[i]=b // can't replace a[i]
  1140  	// ex: a:=&b[i] -> d0:=b[i];a:=&d0 // d0 wrong address
  1141  
  1142  	nres := ctx.nResults()
  1143  	if nres == 0 {
  1144  		return nilIdent() // ex: f1() // with no return value
  1145  	}
  1146  
  1147  	if !ann.canAssignToVar(ctx, e) {
  1148  		return ann.newDebugIVi(ctx, e)
  1149  	}
  1150  
  1151  	if ce, ok := e.(*ast.CallExpr); ok {
  1152  		if typ, ok := ann.typev(ce); ok {
  1153  			switch t := typ.Type.(type) {
  1154  			case *types.Tuple:
  1155  				nres = t.Len()
  1156  			}
  1157  		}
  1158  	}
  1159  
  1160  	if nres >= 2 {
  1161  		ids := ann.assignToNewIdents2(ctx, nres, e)
  1162  		ctx.replaceExprs(ids)
  1163  		ids2 := ann.wrapInIVi(ctx, ids...)
  1164  		return ann.newDebugIL(ctx, ids2...)
  1165  	}
  1166  
  1167  	ctx = ctx.withInsertStmtAfter(false)
  1168  
  1169  	// TODO: review
  1170  	//if ctx.exprOnLhs() {
  1171  	//	// get address of the expression to replace
  1172  	//	ue := &ast.UnaryExpr{Op: token.AND, X: e}
  1173  	//	e2 := ann.assignToNewIdent2(ctx, ue)
  1174  	//	se := &ast.StarExpr{X: e2}
  1175  	//	ctx.replaceExpr(se)
  1176  	//	return ann.newDebugItem(ctx, "IVi", e2)
  1177  	//}
  1178  
  1179  	e2 := ann.assignToNewIdent(ctx, e)
  1180  	ctx.replaceExpr(e2)
  1181  	return ann.newDebugIVi(ctx, e2)
  1182  }
  1183  
  1184  //----------
  1185  
  1186  func (ann *Annotator) newDebugIVi(ctx *Ctx, e ast.Expr) ast.Expr {
  1187  	if s, ok := ann.isBigConst(e); ok {
  1188  		return ann.newDebugIVsBl(ctx, s)
  1189  	}
  1190  	return ann.newDebugI(ctx, "IVi", e)
  1191  }
  1192  func (ann *Annotator) newDebugIVsBl(ctx *Ctx, s string) ast.Expr {
  1193  	return ann.newDebugI(ctx, "IVs", basicLitStringQ(s))
  1194  }
  1195  func (ann *Annotator) newDebugIL(ctx *Ctx, es ...ast.Expr) ast.Expr {
  1196  	return ann.newDebugI(ctx, "IL", es...)
  1197  }
  1198  func (ann *Annotator) newDebugIP(ctx *Ctx, e ast.Expr) ast.Expr {
  1199  	return ann.newDebugI(ctx, "IP", e)
  1200  }
  1201  
  1202  func (ann *Annotator) wrapInIVi(ctx *Ctx, es ...ast.Expr) []ast.Expr {
  1203  	ivs := []ast.Expr{}
  1204  	for _, e := range es {
  1205  		e2 := ann.newDebugIVi(ctx, e)
  1206  		ivs = append(ivs, e2)
  1207  	}
  1208  	return ivs
  1209  }
  1210  
  1211  func (ann *Annotator) newDebugI(ctx *Ctx, fname string, es ...ast.Expr) ast.Expr {
  1212  	se := &ast.SelectorExpr{
  1213  		X:   ast.NewIdent(ann.debugPkgName),
  1214  		Sel: ast.NewIdent(fname),
  1215  	}
  1216  	ce := &ast.CallExpr{Fun: se, Args: es}
  1217  
  1218  	// TODO: handle this where they are called?
  1219  	// assign to var because these are called more then once
  1220  	assign := false
  1221  	switch fname {
  1222  	case "ICe", "IUe":
  1223  		assign = true
  1224  	}
  1225  	if assign {
  1226  		return ann.assignToNewIdent(ctx, ce)
  1227  	}
  1228  
  1229  	return ce
  1230  }
  1231  
  1232  //----------
  1233  
  1234  func (ann *Annotator) insertDebugLine(ctx *Ctx, pos token.Pos, expr ast.Expr) {
  1235  	if isAfterPanicIdent(expr) {
  1236  		return
  1237  	}
  1238  	stmt := ann.newDebugLine(ctx, pos, expr)
  1239  	ctx.insertStmt(stmt)
  1240  }
  1241  func (ann *Annotator) newDebugLine(ctx *Ctx, pos token.Pos, expr ast.Expr) ast.Stmt {
  1242  	se := &ast.SelectorExpr{
  1243  		X:   ast.NewIdent(ann.debugPkgName),
  1244  		Sel: ast.NewIdent("Line"),
  1245  	}
  1246  	args := []ast.Expr{
  1247  		basicLitInt(ann.fileIndex),
  1248  		basicLitInt(ctx.nextDebugIndex()),
  1249  		basicLitInt(ann.fset.Position(pos).Offset),
  1250  		expr,
  1251  	}
  1252  	es := &ast.ExprStmt{X: &ast.CallExpr{Fun: se, Args: args}}
  1253  	ann.builtDebugLineStmt = true
  1254  	return es
  1255  }
  1256  
  1257  //----------
  1258  
  1259  func (ann *Annotator) assignToNewIdent(ctx *Ctx, expr ast.Expr) ast.Expr {
  1260  	return ann.assignToNewIdents2(ctx, 1, expr)[0]
  1261  }
  1262  func (ann *Annotator) assignToNewIdents2(ctx *Ctx, nIds int, exprs ...ast.Expr) []ast.Expr {
  1263  	ids := []ast.Expr{}
  1264  	for i := 0; i < nIds; i++ {
  1265  		id := ann.newIdent(ctx)
  1266  
  1267  		// have id use expr position
  1268  		k := i
  1269  		if len(exprs) == 1 {
  1270  			k = 0
  1271  		}
  1272  		id.NamePos = exprs[k].Pos()
  1273  
  1274  		ids = append(ids, id)
  1275  	}
  1276  	as := ann.newAssignStmt(ids, exprs)
  1277  	ctx.insertStmt(as)
  1278  	return ids
  1279  }
  1280  
  1281  //----------
  1282  
  1283  func (ann *Annotator) newAssignStmt11(lhs, rhs ast.Expr) *ast.AssignStmt {
  1284  	return ann.newAssignStmt([]ast.Expr{lhs}, []ast.Expr{rhs})
  1285  }
  1286  func (ann *Annotator) newAssignStmt(lhs, rhs []ast.Expr) *ast.AssignStmt {
  1287  	return &ast.AssignStmt{Tok: token.DEFINE, Lhs: lhs, Rhs: rhs}
  1288  }
  1289  
  1290  //----------
  1291  
  1292  func (ann *Annotator) newIdent(ctx *Ctx) *ast.Ident {
  1293  	return &ast.Ident{Name: ann.newVarName(ctx)}
  1294  }
  1295  func (ann *Annotator) newVarName(ctx *Ctx) string {
  1296  	s := fmt.Sprintf("%s%d", ann.debugVarPrefix, ann.debugVarNameIndex)
  1297  	ann.debugVarNameIndex++
  1298  	return s
  1299  }
  1300  
  1301  //----------
  1302  
  1303  // assigning the expr to a var could create a var of different type,
  1304  // if the expr is on the left-hand-side, it could alter program behavior if the original destination doesn't get the value
  1305  func (ann *Annotator) canAssignToVar(ctx *Ctx, e ast.Expr) bool {
  1306  	if ann.isType(e) {
  1307  		return false
  1308  	}
  1309  	if ann.isConst(e) {
  1310  		return false
  1311  	}
  1312  	if isNilIdent(e) {
  1313  		return false
  1314  	}
  1315  
  1316  	// TODO: review
  1317  	if e2, ok := ctx.takingVarAddress(); ok {
  1318  		if e2 == e {
  1319  			return false
  1320  		}
  1321  	}
  1322  
  1323  	switch t := e.(type) {
  1324  	case *ast.BasicLit:
  1325  		return false
  1326  	case *ast.CallExpr:
  1327  		return true
  1328  	case *ast.FuncLit:
  1329  		return true
  1330  	case *ast.TypeAssertExpr:
  1331  		return true
  1332  	case *ast.ParenExpr:
  1333  		return ann.canAssignToVar(ctx, t.X)
  1334  	case *ast.StarExpr:
  1335  		return !ctx.boolean(ctxIdExprInLhs) && !ann.isType(t.X)
  1336  	case *ast.SelectorExpr:
  1337  		// could be a const in a pkg (pkg.const1)
  1338  		//return !ann.isType(t.Sel) && !ann.isConst(t.Sel)
  1339  		return ann.canAssignToVar(ctx, t.Sel)
  1340  	case *ast.Ident:
  1341  		//return !ann.isType(t) && !ann.isConst(t)
  1342  		return true
  1343  	case *ast.IndexExpr, *ast.SliceExpr:
  1344  		// ex: a[i]=b // can't replace a[i] // TODO: it could with an address but that can't be done here
  1345  		return !ctx.boolean(ctxIdExprInLhs)
  1346  
  1347  	case *ast.BinaryExpr:
  1348  		switch t.Op {
  1349  		// depend on one being assignable (both could be consts)
  1350  		case
  1351  			token.ADD, // +
  1352  			token.SUB, // -
  1353  			token.MUL, // *
  1354  			token.QUO, // /
  1355  			token.REM, // %
  1356  
  1357  			token.AND, // &
  1358  			token.OR,  // |
  1359  			token.XOR, // ^
  1360  			//token.SHL,     // << // depend on left arg only
  1361  			//token.SHR,     // >> // depend on left arg only
  1362  			token.AND_NOT: // &^
  1363  			return ann.canAssignToVar(ctx, t.X) || ann.canAssignToVar(ctx, t.Y)
  1364  
  1365  		// depend on the left arg
  1366  		case token.SHL, // <<
  1367  			token.SHR: // >>
  1368  			return ann.canAssignToVar(ctx, t.X)
  1369  
  1370  		default:
  1371  			// ex: a>b
  1372  			return true
  1373  		}
  1374  
  1375  	case *ast.UnaryExpr:
  1376  		switch t.Op {
  1377  		case token.AND, // ex: &a
  1378  			token.ARROW: // ex: <-a
  1379  			return true
  1380  		case token.ADD, // ex: 1+(+2)
  1381  			token.SUB, // ex: 1+(-2)
  1382  			token.XOR, // ex: ^a
  1383  			token.NOT: // ex: !a
  1384  			return ann.canAssignToVar(ctx, t.X) // can be a const
  1385  		}
  1386  
  1387  	default:
  1388  		fmt.Printf("todo: canassigntovar: %T", e)
  1389  	}
  1390  	return false
  1391  }
  1392  
  1393  //----------
  1394  
  1395  func (ann *Annotator) wrapInitInBlockAndVisit(ctx *Ctx, stmt ast.Stmt, initStmt *ast.Stmt) bool {
  1396  	if *initStmt == nil {
  1397  		return false
  1398  	}
  1399  
  1400  	if _, ok := ctx.labeledStmt(); ok {
  1401  		// setup debug msg
  1402  		bls := basicLitStringQ("init not annotated due to label stmt")
  1403  		ce := ann.newDebugI(ctx, "ILa", bls)
  1404  		ann.insertDebugLine(ctx, stmt.Pos(), ce)
  1405  		return false
  1406  	}
  1407  
  1408  	// wrap in blockstmt to have vars that belong only to init
  1409  	bs := &ast.BlockStmt{}
  1410  	bs.List = append(bs.List, *initStmt, stmt)
  1411  	//ctx.nilifyStmt(initStmt)
  1412  	*initStmt = nil
  1413  	ctx.replaceStmt(bs)
  1414  
  1415  	ann.vis(ctx, bs)
  1416  
  1417  	return true
  1418  }
  1419  
  1420  //func (ann *Annotator) wrapInBlockIfInit(ctx *Ctx, stmt ast.Stmt, initStmt *ast.Stmt) (*Ctx, bool) {
  1421  //	if *initStmt == nil {
  1422  //		return nil, false
  1423  //	}
  1424  
  1425  //	//if _, ok := ctx.labeledStmt(); ok {
  1426  //	//	// setup debug msg
  1427  //	//	bls := basicLitStringQ("init not annotated due to label stmt")
  1428  //	//	ce := ann.newDebugItem(ctx, "ILa", bls)
  1429  //	//	ann.insertDebugLine(ctx, stmt.Pos(), ce)
  1430  //	//	return false
  1431  //	//}
  1432  
  1433  //	// wrap in blockstmt to have vars that belong only to init
  1434  //	bs := &ast.BlockStmt{}
  1435  //	bs.List = append(bs.List, *initStmt, stmt)
  1436  //	*initStmt = nil
  1437  //	ctx.replaceStmt(bs)
  1438  
  1439  //	ctx2 := ctx.withStmts(&bs.List)
  1440  //	ann.vis(ctx2, bs)
  1441  
  1442  //	return true
  1443  //}
  1444  
  1445  //----------
  1446  
  1447  //func (ann *Annotator) castStringToItem(ctx *Ctx, v string) ast.Expr {
  1448  //	se := &ast.SelectorExpr{
  1449  //		X:   ast.NewIdent(ann.debugPkgName),
  1450  //		Sel: ast.NewIdent("Item"),
  1451  //	}
  1452  //	bl := basicLitStringQ(v)
  1453  //	return &ast.CallExpr{Fun: se, Args: []ast.Expr{bl}}
  1454  //}
  1455  
  1456  func (ann *Annotator) resType(ctx *Ctx, e ast.Expr) ast.Expr {
  1457  	//str := "type"
  1458  	//switch t := e.(type) {
  1459  	//case *ast.InterfaceType:
  1460  	//case *ast.MapType:
  1461  	//	str = "map"
  1462  	//case *ast.ArrayType:
  1463  	//	str = "array"
  1464  	//	if t.Len == nil {
  1465  	//		str = "slice"
  1466  	//	}
  1467  	//case *ast.SelectorExpr:
  1468  	//	str = "type"
  1469  	//}
  1470  
  1471  	return ann.newDebugIVsBl(ctx, "T")
  1472  }
  1473  
  1474  //----------
  1475  
  1476  func (ann *Annotator) splitGenDecl(ctx *Ctx, gd *ast.GenDecl) {
  1477  	// keep to reset later
  1478  	si := ctx.stmtsIter()
  1479  	after := si.after
  1480  
  1481  	ctx2 := ctx.withInsertStmtAfter(true)
  1482  	for _, spec := range gd.Specs {
  1483  		gd2 := &ast.GenDecl{Tok: gd.Tok, Specs: []ast.Spec{spec}}
  1484  		stmt := &ast.DeclStmt{Decl: gd2}
  1485  		ctx2.insertStmt(stmt)
  1486  	}
  1487  	// reset counter to have the other specs be visited
  1488  	si.after = after
  1489  	// clear gd stmt, will output as "var ()"
  1490  	gd.Specs = nil
  1491  }
  1492  
  1493  //----------
  1494  
  1495  func (ann *Annotator) annotationBlockCtx(ctx *Ctx, n ast.Node) *Ctx {
  1496  	// TODO: catches "godebug" directives surrounded with blank lines?
  1497  
  1498  	// catch "godebug" directive at the top of this node
  1499  	on, ok := ann.annotationBlockOn(n)
  1500  
  1501  	// if annotating only blocks, start with no annotations
  1502  	// TODO: confusing? there is no other way having only a block being annotated and don't annotate the rest
  1503  	if ok && on {
  1504  		if _, ok2 := n.(*ast.File); ok2 {
  1505  			on = false
  1506  		}
  1507  	}
  1508  
  1509  	if ok && ctx.boolean(ctxIdNoAnnotations) != !on {
  1510  		return ctx.withBoolean(ctxIdNoAnnotations, !on)
  1511  	}
  1512  	return ctx
  1513  }
  1514  
  1515  // Returns (on/off, ok)
  1516  func (ann *Annotator) annotationBlockOn(n ast.Node) (bool, bool) {
  1517  	if ann.nodeAnnTypes == nil {
  1518  		return false, false
  1519  	}
  1520  	at, ok := ann.nodeAnnTypes[n]
  1521  	if !ok {
  1522  		return false, false
  1523  	}
  1524  	switch at {
  1525  	case AnnotationTypeOff:
  1526  		return false, true
  1527  	case AnnotationTypeBlock:
  1528  		return true, true
  1529  	default:
  1530  		return false, false
  1531  	}
  1532  }
  1533  
  1534  //----------
  1535  
  1536  func (ann *Annotator) isType(e ast.Expr) bool {
  1537  	if ann.simpleTestMode {
  1538  		return false
  1539  	}
  1540  	tv, ok := ann.typev(e)
  1541  	return ok && tv.IsType()
  1542  }
  1543  
  1544  func (ann *Annotator) isBuiltin(e ast.Expr) bool {
  1545  	if ann.simpleTestMode {
  1546  		return true
  1547  	}
  1548  	tv, ok := ann.typev(e)
  1549  	return ok && tv.IsBuiltin()
  1550  }
  1551  
  1552  //// ex: fn() is not addressable (can't do "&fn()", only a:=fn(); &a)
  1553  //func (ann *Annotator) isAddressable(e ast.Expr) bool {
  1554  //	tv, ok := ann.typev(e)
  1555  //	return ok && tv.Addressable()
  1556  //}
  1557  
  1558  func (ann *Annotator) isConst(e ast.Expr) bool {
  1559  	if ann.simpleTestMode {
  1560  		//if id, ok := e.(*ast.Ident); ok {
  1561  		//	isVar := strings.HasPrefix(id.Name, ann.debugVarPrefix)
  1562  		//	return !isVar
  1563  		//}
  1564  		return false
  1565  	}
  1566  
  1567  	tv, ok := ann.typev(e)
  1568  	return ok && tv.Value != nil
  1569  
  1570  	//if !ok || tv.Value == nil {
  1571  	//	return false
  1572  	//}
  1573  	//switch tv.Value.Kind() {
  1574  	//case constant.Int, constant.Float, constant.Complex:
  1575  	//	return true
  1576  	//default:
  1577  	//	return false
  1578  	//}
  1579  }
  1580  
  1581  func (ann *Annotator) isBigConst(e ast.Expr) (string, bool) {
  1582  	// handles big constants:
  1583  	// _=uint64(1<<64 - 1)
  1584  	// _=uint64(math.MaxUint64)
  1585  	// the annotator would generate IV(1<<64), which will give a compile error since "1<<64" overflows an int (consts are assigned to int by default)
  1586  
  1587  	tv, ok := ann.typev(e)
  1588  	if !ok || tv.Value == nil {
  1589  		return "", false
  1590  	}
  1591  	u := constant.Val(tv.Value)
  1592  	switch t := u.(type) {
  1593  	case *big.Int, *big.Float, *big.Rat:
  1594  		return fmt.Sprintf("%s", t), true
  1595  	}
  1596  	return "", false
  1597  }
  1598  
  1599  func (ann *Annotator) typev(e ast.Expr) (types.TypeAndValue, bool) {
  1600  	if ann.typesInfo == nil {
  1601  		return types.TypeAndValue{}, false
  1602  	}
  1603  	tv, ok := ann.typesInfo.Types[e]
  1604  	return tv, ok
  1605  }
  1606  
  1607  //----------
  1608  
  1609  // Correct debugindexes to have the numbers attributed in order at compile time. Allows assuming an ordered slice (debugindex/textindex) in the editor.
  1610  func (ann *Annotator) correctDebugIndexes(n ast.Node) int {
  1611  
  1612  	type lineInfo struct {
  1613  		lineCE        *ast.CallExpr
  1614  		oldDebugIndex int
  1615  		byteIndex     int // fset position offset (for sort)
  1616  		seenCount     int
  1617  	}
  1618  	seenCount := 0
  1619  	lines := []*lineInfo{}
  1620  
  1621  	// collect all calls to debug.Line()
  1622  	ast.Inspect(n, func(n2 ast.Node) bool {
  1623  		// find line callexpr
  1624  		ce := (*ast.CallExpr)(nil)
  1625  		switch t2 := n2.(type) {
  1626  		case *ast.CallExpr:
  1627  			ce2 := t2
  1628  			if se, ok := ce2.Fun.(*ast.SelectorExpr); ok {
  1629  				if id, ok := se.X.(*ast.Ident); ok {
  1630  					if id.Name == ann.debugPkgName && se.Sel.Name == "Line" {
  1631  						ce = ce2
  1632  					}
  1633  				}
  1634  			}
  1635  		}
  1636  		if ce == nil {
  1637  			return true // continue
  1638  		}
  1639  
  1640  		// debugindex
  1641  		di, err := strconv.Atoi(ce.Args[1].(*ast.BasicLit).Value)
  1642  		if err != nil {
  1643  			panic(err)
  1644  		}
  1645  		// fset offset position (byteindex)
  1646  		byteIndex, err := strconv.Atoi(ce.Args[2].(*ast.BasicLit).Value)
  1647  		if err != nil {
  1648  			panic(err)
  1649  		}
  1650  		// keep
  1651  		li := &lineInfo{
  1652  			lineCE:        ce,
  1653  			oldDebugIndex: di,
  1654  			byteIndex:     byteIndex,
  1655  			seenCount:     seenCount,
  1656  		}
  1657  		seenCount++
  1658  
  1659  		lines = append(lines, li)
  1660  
  1661  		return true
  1662  	})
  1663  
  1664  	// sort debug lines by byteindex (fset offset)
  1665  	sort.Slice(lines, func(a, b int) bool {
  1666  		va, vb := lines[a], lines[b]
  1667  		if va.byteIndex == vb.byteIndex {
  1668  			// the one seen first while visiting the ast
  1669  			return va.seenCount < vb.seenCount
  1670  		}
  1671  		return va.byteIndex < vb.byteIndex
  1672  	})
  1673  
  1674  	// setup new debug indexes
  1675  	di := 0
  1676  	m := map[int]int{}         // [textIndex]debugIndex
  1677  	for _, li := range lines { // visited by byteindex order
  1678  		di2 := di
  1679  		// check if this debugIndex was already seen
  1680  		if di3, ok := m[li.oldDebugIndex]; ok {
  1681  			di2 = di3
  1682  		} else {
  1683  			// assign new debug index
  1684  			di2 = di
  1685  			m[li.oldDebugIndex] = di
  1686  			di++
  1687  		}
  1688  
  1689  		// assign final debug index
  1690  		li.lineCE.Args[1] = basicLitInt(di2)
  1691  	}
  1692  
  1693  	return di
  1694  }
  1695  
  1696  //----------
  1697  
  1698  func (ann *Annotator) removeInnerFuncComments(astFile *ast.File) {
  1699  	// ensure comments are not in between stmts in the middle of declarations inside functions (solves test100)
  1700  	// Other comments stay in place since they might be needed (build comments, "c" package comments, ...)
  1701  	u := astFile.Comments[:0]             // use already allocated mem
  1702  	for _, cg := range astFile.Comments { // all comments
  1703  		keep := true
  1704  
  1705  		// check if inside func decl
  1706  		for _, d := range astFile.Decls {
  1707  			if _, ok := d.(*ast.FuncDecl); !ok {
  1708  				continue
  1709  			}
  1710  			if d.Pos() > cg.End() { // passed comment
  1711  				break
  1712  			}
  1713  			in := cg.Pos() >= d.Pos() && cg.Pos() < d.End()
  1714  			if in {
  1715  				keep = false
  1716  				break
  1717  			}
  1718  		}
  1719  
  1720  		if keep {
  1721  			u = append(u, cg)
  1722  		}
  1723  	}
  1724  	astFile.Comments = u
  1725  }
  1726  
  1727  //----------
  1728  
  1729  func (ann *Annotator) sprintNode(n ast.Node) string {
  1730  	return astut.SprintNode(ann.fset, n)
  1731  }
  1732  func (ann *Annotator) printNode(n ast.Node) {
  1733  	fmt.Println(ann.sprintNode(n))
  1734  }
  1735  
  1736  //----------
  1737  
  1738  //func (ann *Annotator) wrapInParenIfNotSimple(ctx *Ctx, e ast.Expr) ast.Expr {
  1739  //	if !isSimple(e) {
  1740  //		return ann.newDebugIP(ctx, e)
  1741  //	}
  1742  //	return e
  1743  //}
  1744  
  1745  //----------
  1746  //----------
  1747  //----------
  1748  
  1749  //func isSimple(e ast.Expr) bool {
  1750  //	return isIdentOrSelectorOfIdents(e)
  1751  //}
  1752  
  1753  func isIdentOrSelectorOfIdents(e ast.Expr) bool {
  1754  	switch t := e.(type) {
  1755  	case *ast.Ident:
  1756  		return true
  1757  	case *ast.SelectorExpr:
  1758  		return isIdentOrSelectorOfIdents(t.X)
  1759  	}
  1760  	// ex: (a+b).Fn()
  1761  	return false
  1762  }
  1763  
  1764  //----------
  1765  
  1766  var _emptyExpr = &ast.Ident{Name: "*emptyExpr*"}
  1767  
  1768  func emptyExpr() ast.Expr { return _emptyExpr }
  1769  
  1770  //----------
  1771  
  1772  func nilIdent() *ast.Ident {
  1773  	return &ast.Ident{Name: "nil"}
  1774  }
  1775  func isNilIdent(e ast.Expr) bool {
  1776  	return isIdentWithName(e, "nil")
  1777  }
  1778  
  1779  func anonIdent() *ast.Ident {
  1780  	return &ast.Ident{Name: "_"}
  1781  }
  1782  func isAnonIdent(e ast.Expr) bool {
  1783  	return isIdentWithName(e, "_")
  1784  }
  1785  
  1786  func afterPanicIdent() *ast.Ident {
  1787  	return &ast.Ident{Name: "after panic"}
  1788  }
  1789  func isAfterPanicIdent(e ast.Expr) bool {
  1790  	return isIdentWithName(e, "after panic")
  1791  }
  1792  
  1793  func isIdentWithName(e ast.Expr, name string) bool {
  1794  	id, ok := e.(*ast.Ident)
  1795  	return ok && id.Name == name
  1796  }
  1797  
  1798  //----------
  1799  
  1800  func basicLitString(v string) *ast.BasicLit {
  1801  	s := strings.ReplaceAll(v, "%", "%%")
  1802  	return &ast.BasicLit{Kind: token.STRING, Value: s}
  1803  }
  1804  func basicLitStringQ(v string) *ast.BasicLit { // quoted
  1805  	s := strings.ReplaceAll(v, "%", "%%")
  1806  	return &ast.BasicLit{Kind: token.STRING, Value: fmt.Sprintf("%q", s)}
  1807  }
  1808  func basicLitInt(v int) *ast.BasicLit {
  1809  	return &ast.BasicLit{Kind: token.INT, Value: fmt.Sprintf("%d", v)}
  1810  }