func ParseTry(fset *token.FileSet, f *ast.File) { blocks := FilterAst(f, func(n ast.Node) bool { return GetBlock(n) != nil }) for tree := range blocks { parent := ParentFunc(tree) b := GetBlock(tree.Node) var block []ast.Stmt madeTry := false for _, v := range *b { if try := GetTryCall(v); try != nil { madeTry = true block = AppendTryBlock(block, v, BuildTryBlock(parent, try)) } else { block = append(block, v) } } if madeTry { varErr := &ast.ValueSpec{nil, []*ast.Ident{ast.NewIdent("err")}, ast.NewIdent("error"), nil, nil} defineErr := &ast.GenDecl{nil, 0, token.VAR, 0, []ast.Spec{varErr, nil}, 0} stmt := []ast.Stmt{&ast.DeclStmt{defineErr}} block = append(stmt, block...) } *b = block } EnsureNoTry(f) }
func insertIntVar(file *ast.File, name string, value int) { var before, after []ast.Decl if len(file.Decls) > 0 { hasImport := false if genDecl, ok := file.Decls[0].(*ast.GenDecl); ok { hasImport = genDecl.Tok == token.IMPORT } if hasImport { before, after = []ast.Decl{file.Decls[0]}, file.Decls[1:] } else { after = file.Decls } } file.Decls = append(before, &ast.GenDecl{ Tok: token.VAR, Specs: []ast.Spec{ &ast.ValueSpec{ Names: []*ast.Ident{ast.NewIdent(name)}, Type: ast.NewIdent("int"), Values: []ast.Expr{ &ast.BasicLit{ Kind: token.INT, Value: fmt.Sprintf("%d", value), }, }, }, }, }, ) file.Decls = append(file.Decls, after...) }
func AppendTryBlock(block []ast.Stmt, node ast.Node, errBlock []ast.Stmt) []ast.Stmt { var try, call *ast.CallExpr var assign *ast.AssignStmt _err, _nil := ast.NewIdent("err"), ast.NewIdent("nil") // err != nil errNil := &ast.BinaryExpr{_err, 0, token.NEQ, _nil} // if errNil { stmt } ifBlock := &ast.IfStmt{0, nil, errNil, &ast.BlockStmt{0, errBlock, 0}, nil} switch n := node.(type) { case *ast.AssignStmt: assign = n try = n.Rhs[0].(*ast.CallExpr) case *ast.ExprStmt: try = n.X.(*ast.CallExpr) default: log.Fatalf("unhandled try() node type: %T\n", node) } if assign == nil { assign = &ast.AssignStmt{nil, 0, token.ASSIGN, nil} } call = StripTry(try) assign.Rhs = []ast.Expr{call} assign.Lhs = append(assign.Lhs, _err) block = append(block, assign) block = append(block, ifBlock) return block }
func replaceStructLiteralWithIdentifier(statement ast.Node, n *ast.CompositeLit, name string) { ast.Inspect(statement, func(parentNode ast.Node) bool { switch parentNode := parentNode.(type) { case *ast.KeyValueExpr: if parentNode.Value == n { parentNode.Value = ast.NewIdent(name) } case *ast.CallExpr: for i, expr := range parentNode.Args { if expr == n { parentNode.Args[i] = ast.NewIdent(name) } } case *ast.AssignStmt: if parentNode.Rhs[0] == n { parentNode.Rhs[0] = ast.NewIdent(name) } case *ast.ReturnStmt: for i, expr := range parentNode.Results { if expr == n { parentNode.Results[i] = ast.NewIdent(name) } } case *ast.CompositeLit: for i, expr := range parentNode.Elts { if expr == n { parentNode.Elts[i] = ast.NewIdent(name) } } } return true }) }
func (t *GeneratorModel) resolveMutexType() *ast.SelectorExpr { alias := t.AddImport("sync", "sync") return &ast.SelectorExpr{ X: ast.NewIdent(alias), Sel: ast.NewIdent("RWMutex"), } }
func insertHello(file *ast.File) { ast.Inspect(file, func(node ast.Node) bool { if ifStmt, ok := node.(*ast.IfStmt); ok { ifStmt.Body.List = append( []ast.Stmt{ &ast.ExprStmt{ X: &ast.CallExpr{ Fun: &ast.SelectorExpr{ X: ast.NewIdent("fmt"), Sel: ast.NewIdent("Printf"), }, Args: []ast.Expr{ &ast.BasicLit{ Kind: token.STRING, Value: "\"hello\"", }, }, }, }, }, ifStmt.Body.List..., ) } return true }) }
func (m *FileBuilder) Build() *ast.File { file := &ast.File{ Name: ast.NewIdent(m.filePackageName), } if len(m.aliasToImport) > 0 { importDeclaration := &ast.GenDecl{ Tok: token.IMPORT, Lparen: token.Pos(1), Specs: []ast.Spec{}, } for alias, location := range m.aliasToImport { importDeclaration.Specs = append(importDeclaration.Specs, &ast.ImportSpec{ Name: ast.NewIdent(alias), Path: &ast.BasicLit{ Kind: token.STRING, Value: fmt.Sprintf("\"%s\"", location), }, }) } file.Decls = append(file.Decls, importDeclaration) } for _, builder := range m.generalDeclarationBuilders { file.Decls = append(file.Decls, builder.Build()) } return file }
// playExampleFile takes a whole file example and synthesizes a new *ast.File // such that the example is function main in package main. func playExampleFile(file *ast.File) *ast.File { // Strip copyright comment if present. comments := file.Comments if len(comments) > 0 && strings.HasPrefix(comments[0].Text(), "Copyright") { comments = comments[1:] } // Copy declaration slice, rewriting the ExampleX function to main. var decls []ast.Decl for _, d := range file.Decls { if f, ok := d.(*ast.FuncDecl); ok && isTest(f.Name.Name, "Example") { // Copy the FuncDecl, as it may be used elsewhere. newF := *f newF.Name = ast.NewIdent("main") newF.Body, comments = stripOutputComment(f.Body, comments) d = &newF } decls = append(decls, d) } // Copy the File, as it may be used elsewhere. f := *file f.Name = ast.NewIdent("main") f.Decls = decls f.Comments = comments return &f }
func (m *MethodBuilder) Build() ast.Decl { statements := make([]ast.Stmt, len(m.statementBuilders)) for i, builder := range m.statementBuilders { statements[i] = builder.Build() } return &ast.FuncDecl{ Recv: &ast.FieldList{ List: []*ast.Field{ { Names: []*ast.Ident{ ast.NewIdent(m.receiverName), }, Type: &ast.StarExpr{ X: ast.NewIdent(m.receiverType), }, }, }, }, Name: ast.NewIdent(m.name), Type: m.funcType, Body: &ast.BlockStmt{ List: statements, }, } }
func (gen CodeGenerator) methodCallCountGetter(method *ast.Field) *ast.FuncDecl { return &ast.FuncDecl{ Name: ast.NewIdent(callCountMethodName(method)), Type: &ast.FuncType{ Results: &ast.FieldList{List: []*ast.Field{ &ast.Field{ Type: ast.NewIdent("int"), }, }}, }, Recv: gen.receiverFieldList(), Body: &ast.BlockStmt{List: []ast.Stmt{ callMutex(method, "RLock"), deferMutex(method, "RUnlock"), &ast.ReturnStmt{ Results: []ast.Expr{ &ast.CallExpr{ Fun: ast.NewIdent("len"), Args: []ast.Expr{ &ast.SelectorExpr{ X: receiverIdent(), Sel: ast.NewIdent(callArgsFieldName(method)), }, }, }, }, }, }}, } }
func hmacnew(f *ast.File) (fixed bool) { if !imports(f, "crypto/hmac") { return } walk(f, func(n interface{}) { ce, ok := n.(*ast.CallExpr) if !ok { return } var pkg string switch { case isPkgDot(ce.Fun, "hmac", "NewMD5"): pkg = "md5" case isPkgDot(ce.Fun, "hmac", "NewSHA1"): pkg = "sha1" case isPkgDot(ce.Fun, "hmac", "NewSHA256"): pkg = "sha256" default: return } addImport(f, "crypto/"+pkg) ce.Fun = ast.NewIdent("hmac.New") ce.Args = append([]ast.Expr{ast.NewIdent(pkg + ".New")}, ce.Args...) fixed = true }) return }
func makeLoop(node *parser.CallNode) *ast.CallExpr { returnIdent := generateIdent() loopIdent := generateIdent() fnBody := h.EmptyS() bindingsVector := node.Args[0].(*parser.VectorNode) addRecurLabelAndBindings(parser.NewIdentNode(loopIdent.String()), bindingsVector.Copy().(*parser.VectorNode), node.Args[1:]) bindings := makeBindings(bindingsVector, token.DEFINE) returnIdentValueSpec := makeValueSpec(h.I(returnIdent), nil, anyType) returnIdentDecl := makeDeclStmt(makeGeneralDecl(token.VAR, []ast.Spec{returnIdentValueSpec})) fnBody = append(fnBody, bindings...) fnBody = append(fnBody, returnIdentDecl) init := makeAssignStmt(h.E(loopIdent), h.E(ast.NewIdent("true")), token.DEFINE) forBody := h.EmptyS() forBody = append(forBody, makeAssignStmt(h.E(loopIdent), h.E(ast.NewIdent("false")), token.ASSIGN)) forBody = append(forBody, wrapExprsWithStmt(EvalExprs(node.Args[1:len(node.Args)-1]))...) forBody = append(forBody, makeAssignStmt(h.E(returnIdent), h.E(EvalExpr(node.Args[len(node.Args)-1])), token.ASSIGN)) forStmt := makeForStmt(init, nil, loopIdent, makeBlockStmt(forBody)) fnBody = append(fnBody, forStmt) fnBody = append(fnBody, makeReturnStmt(h.E(returnIdent))) results := makeFieldList([]*ast.Field{makeField(nil, anyType)}) fnType := makeFuncType(results, nil) fn := makeFuncLit(fnType, makeBlockStmt(fnBody)) return makeFuncCall(fn, h.EmptyE()) }
func (b *CountMethodBuilder) Build() ast.Decl { mutexLockBuilder := NewMutexActionBuilder() mutexLockBuilder.SetMutexFieldSelector(b.mutexFieldSelector) mutexLockBuilder.SetAction("RLock") mutexUnlockBuilder := NewMutexActionBuilder() mutexUnlockBuilder.SetMutexFieldSelector(b.mutexFieldSelector) mutexUnlockBuilder.SetAction("RUnlock") mutexUnlockBuilder.SetDeferred(true) b.methodBuilder.SetType(&ast.FuncType{ Params: &ast.FieldList{}, Results: &ast.FieldList{ List: []*ast.Field{ { Type: ast.NewIdent("int"), }, }, }, }) b.methodBuilder.AddStatementBuilder(mutexLockBuilder) b.methodBuilder.AddStatementBuilder(mutexUnlockBuilder) b.methodBuilder.AddStatementBuilder(StatementToBuilder(&ast.ReturnStmt{ Results: []ast.Expr{ &ast.CallExpr{ Fun: ast.NewIdent("len"), Args: []ast.Expr{ b.argsFieldSelector, }, }, }, })) return b.methodBuilder.Build() }
// We handle comparisons as a call to some go code, since you can only // compare ints, floats, cmplx, and such, you know... // We handle arithmetic operations as function calls, since all args are evaluated func makeNAryCallableExpr(node *parser.CallNode) *ast.CallExpr { op := node.Callee.(*parser.IdentNode).Ident args := EvalExprs(node.Args) var selector string // TODO: abstract this away into a map!!! switch op { case ">": selector = "GT" case ">=": selector = "GTEQ" case "<": selector = "LT" case "<=": selector = "LTEQ" case "=": selector = "EQ" case "+": selector = "ADD" case "-": selector = "SUB" case "*": selector = "MUL" case "/": selector = "DIV" case "mod": if len(node.Args) > 2 { panic("can't calculate modulo with more than 2 arguments!") } selector = "MOD" } return makeFuncCall(makeSelectorExpr(ast.NewIdent("core"), ast.NewIdent(selector)), args) }
func TestBadAst(t *testing.T) { // typeOfExpr should gracefully handle broken AST structures. Let's // construct some. // Array with bad length descriptor. // [Bad]int32 badArr := ast.ArrayType{ Len: ast.NewIdent("Bad"), Elt: ast.NewIdent("int32"), } typ, err := typeOfExpr(&badArr) assert.Equal(t, typ, nil) assert.Equal(t, err.Error(), "invalid array size expression") // Array with bad length descriptor. // ["How about that!"]int32 badArr = ast.ArrayType{ Len: &ast.BasicLit{Kind: token.STRING, Value: `"How about that!"`}, Elt: ast.NewIdent("int32"), } typ, err = typeOfExpr(&badArr) assert.Equal(t, typ, nil) assert.Equal(t, err.Error(), "invalid array size type") // Array with bad length descriptor. // [10ii0]int32 badArr = ast.ArrayType{ Len: &ast.BasicLit{Kind: token.INT, Value: "10ii0"}, Elt: ast.NewIdent("int32"), } typ, err = typeOfExpr(&badArr) assert.Equal(t, typ, nil) assert.Equal(t, err.Error(), "strconv.ParseInt: parsing \"10ii0\": invalid syntax") }
func constDecl(kind token.Token, args ...string) *ast.GenDecl { decl := ast.GenDecl{Tok: token.CONST} if len(args)%3 != 0 { panic("Number of values passed to ConstString must be a multiple of 3") } for i := 0; i < len(args); i += 3 { name, typ, val := args[i], args[i+1], args[i+2] lit := &ast.BasicLit{Kind: kind} if kind == token.STRING { lit.Value = strconv.Quote(val) } else { lit.Value = val } a := &ast.ValueSpec{ Names: []*ast.Ident{ast.NewIdent(name)}, Values: []ast.Expr{lit}, } if typ != "" { a.Type = ast.NewIdent(typ) } decl.Specs = append(decl.Specs, a) } if len(decl.Specs) > 1 { decl.Lparen = 1 } return &decl }
func (f *File) newCounter(start, end token.Pos, numStmt int) ast.Stmt { cnt := genCounter() if f.blocks != nil { s := f.fset.Position(start) e := f.fset.Position(end) *f.blocks = append(*f.blocks, CoverBlock{cnt, f.shortName, s.Line, s.Column, e.Line, e.Column, numStmt}) } idx := &ast.BasicLit{ Kind: token.INT, Value: strconv.Itoa(cnt), } counter := &ast.IndexExpr{ X: &ast.SelectorExpr{ X: ast.NewIdent(fuzzdepPkg), Sel: ast.NewIdent("CoverTab"), }, Index: idx, } return &ast.IncDecStmt{ X: counter, Tok: token.INC, } }
func genFuncDecl(mockTypeName string, methName string, method *ast.FuncType) *ast.FuncDecl { f := &ast.FuncDecl{ Recv: &ast.FieldList{List: []*ast.Field{ { Names: []*ast.Ident{ast.NewIdent("s")}, Type: &ast.StarExpr{X: ast.NewIdent(mockTypeName)}, }, }}, Name: ast.NewIdent(methName), Type: method, Body: &ast.BlockStmt{List: []ast.Stmt{ &ast.ExprStmt{ &ast.CallExpr{ Fun: &ast.SelectorExpr{ X: ast.NewIdent("s"), Sel: ast.NewIdent(methName + "_"), }, Args: fieldListToIdentList(method.Params), Ellipsis: ellipsisIfNeeded(method.Params), }, }, }}, } if method.Results != nil { f.Body = &ast.BlockStmt{List: []ast.Stmt{ &ast.ReturnStmt{ Results: []ast.Expr{f.Body.List[0].(*ast.ExprStmt).X}, }, }} } return f }
func (t *GeneratorModel) resolveInterfaceType(location, name string) *ast.SelectorExpr { alias := t.AddImport("", location) return &ast.SelectorExpr{ X: ast.NewIdent(alias), Sel: ast.NewIdent(name), } }
func makeCallExpr(name string, params *st.SymbolTable, pointerSymbols map[st.Symbol]int, pos token.Pos, recvSym *st.VariableSymbol, pack *st.Package, filename string) (*ast.CallExpr, int) { var Fun ast.Expr if recvSym != nil { x := ast.NewIdent(recvSym.Name()) x.NamePos = pos Fun = &ast.SelectorExpr{x, ast.NewIdent(name)} } else { x := ast.NewIdent(name) x.NamePos = pos Fun = x } l, _ := utils.GetNodeLength(Fun) l += 2 args, i := make([]ast.Expr, params.Count()), 0 params.ForEachNoLock(func(sym st.Symbol) { args[i] = sym.ToAstExpr(pack, filename) if depth, ok := pointerSymbols[sym]; ok { for depth > 0 { args[i] = &ast.UnaryExpr{token.NoPos, token.AND, args[i]} depth-- } } ll, _ := utils.GetNodeLength(args[i]) l += ll + 2 i++ }) l -= 2 return &ast.CallExpr{Fun, token.NoPos, args, token.NoPos, pos + token.Pos(l-1)}, l }
func makeNamedExpr(s Symbol, pack *Package, filename string) ast.Expr { if s.PackageFrom() != pack { imp := pack.GetImport(filename, s.PackageFrom()) prefix := imp.Name() return &ast.SelectorExpr{ast.NewIdent(prefix), ast.NewIdent(s.Name())} } return ast.NewIdent(s.Name()) }
func (self *PackageFile) processRangeStmt(a *ast.RangeStmt) { if !self.cursorIn(a.Body) { return } savescope := self.scope self.scope = AdvanceScope(self.scope) self.topscope = self.scope if a.Tok == token.DEFINE { var t1, t2 ast.Expr // TODO: deal with typedefed slices/maps here t1, _ = NewDeclVar("tmp", nil, a.X, -1, self.scope).InferType(self.ctx) if t1 != nil { // figure out range Key, Value types switch t := t1.(type) { case *ast.Ident: // string if t.Name() == "string" { t1 = ast.NewIdent("int") t2 = ast.NewIdent("int") } else { t1, t2 = nil, nil } case *ast.ArrayType: t1 = ast.NewIdent("int") t2 = t.Elt case *ast.MapType: t1 = t.Key t2 = t.Value case *ast.ChanType: t1 = t.Value t2 = nil default: t1, t2 = nil, nil } if t, ok := a.Key.(*ast.Ident); ok { d := NewDeclVar(t.Name(), t1, nil, -1, self.scope) if d != nil { self.scope.addNamedDecl(d) } } if a.Value != nil { if t, ok := a.Value.(*ast.Ident); ok { d := NewDeclVar(t.Name(), t2, nil, -1, self.scope) if d != nil { self.scope.addNamedDecl(d) } } } } } self.processBlockStmt(a.Body) self.scope = savescope }
func fixDeclaredNotUsed(nodepath []ast.Node, identName string) bool { // insert "_ = x" to supress "declared but not used" error stmt := &ast.AssignStmt{ Lhs: []ast.Expr{ast.NewIdent("_")}, Tok: token.ASSIGN, Rhs: []ast.Expr{ast.NewIdent(identName)}, } return appendStmt(nodepath, stmt) }
func causeExpr(errgoIdent string, ident string) *ast.CallExpr { return &ast.CallExpr{ Fun: &ast.SelectorExpr{ X: ast.NewIdent(errgoIdent), Sel: ast.NewIdent("Cause"), }, Args: []ast.Expr{ast.NewIdent(ident)}, } }
func (t *Togo) CtxFuncCall(funcName string, args []goast.Expr) *goast.CallExpr { return &goast.CallExpr{ Fun: &goast.SelectorExpr{ X: goast.NewIdent("ctx"), Sel: goast.NewIdent(funcName), }, Args: args, } }
func (self *method_compiler) ret() { stmt := &ast.AssignStmt{ Lhs: []ast.Expr{ast.NewIdent("res")}, Rhs: []ast.Expr{ast.NewIdent("rb" + strconv.Itoa(self.stack_top))}, Tok: token.ASSIGN, } self.append_stmt(stmt) self.append_stmt(&ast.ReturnStmt{}) }
func (gen CodeGenerator) methodReturnsSetter(method *ast.Field) *ast.FuncDecl { methodType := method.Type.(*ast.FuncType) params := []*ast.Field{} structFields := []ast.Expr{} eachMethodResult(methodType, func(name string, t ast.Expr) { params = append(params, &ast.Field{ Names: []*ast.Ident{ast.NewIdent(name)}, Type: t, }) structFields = append(structFields, ast.NewIdent(name)) }) return &ast.FuncDecl{ Name: ast.NewIdent(returnSetterMethodName(method)), Type: &ast.FuncType{ Params: &ast.FieldList{List: params}, }, Recv: gen.receiverFieldList(), Body: &ast.BlockStmt{List: []ast.Stmt{ &ast.AssignStmt{ Tok: token.ASSIGN, Lhs: []ast.Expr{ &ast.SelectorExpr{ X: receiverIdent(), Sel: ast.NewIdent(methodStubFuncName(method)), }, }, Rhs: []ast.Expr{ &ast.BasicLit{ Kind: token.STRING, Value: "nil", }, }, }, &ast.AssignStmt{ Tok: token.ASSIGN, Lhs: []ast.Expr{ &ast.SelectorExpr{ X: receiverIdent(), Sel: ast.NewIdent(returnStructFieldName(method)), }, }, Rhs: []ast.Expr{ &ast.CompositeLit{ Type: returnStructTypeForMethod(methodType), Elts: structFields, }, }, }, }}, } }
// ctx may be nil. func insertContext(f *ast.File, call *ast.CallExpr, ctx *ast.Ident) { if ctx == nil { // context is unknown, so use a plain "ctx". ctx = ast.NewIdent("ctx") } else { // Create a fresh *ast.Ident so we drop the position information. ctx = ast.NewIdent(ctx.Name) } call.Args = append([]ast.Expr{ctx}, call.Args...) }
func (sp *intSpec) generate() []ast.Decl { strLen := strconv.Itoa(sp.size * 8) iType := ast.NewIdent("int" + strLen) iCast := ast.NewIdent("uint" + strLen) iMethod := "Uint" + strLen if !sp.signed { iType, iCast = iCast, iType } // encode encodeMethod := createFuncDecl(sp.encode, iType, ident_i, WRITE) encodeMethod.Body.List = []ast.Stmt{ createBufferInit(sp.size, WRITE), // binary.BigEndian.PutUint16(buf, uint16(i)) &ast.ExprStmt{ X: &ast.CallExpr{ Fun: &ast.SelectorExpr{ X: sel_bigEndian, Sel: ast.NewIdent("Put" + iMethod), }, Args: []ast.Expr{ ident_buf, cast(iCast, ident_i, sp.signed), }, }, }, stmt_writeBuf, stmt_return, } // decode decodeMethod := createFuncDecl(sp.decode, iType, ident_i, READ) decodeMethod.Body.List = []ast.Stmt{ createBufferInit(sp.size, READ), stmt_readFull, stmt_retOnErr, // i = Uint16(binary.BigEndian.Uint16(bs)) &ast.AssignStmt{ Lhs: exprL_ident_i, Tok: token.ASSIGN, Rhs: []ast.Expr{ cast(iType, &ast.CallExpr{ Fun: &ast.SelectorExpr{ X: sel_bigEndian, Sel: ast.NewIdent(iMethod), }, Args: exprL_ident_buf, }, sp.signed), }, }, stmt_return, } return []ast.Decl{encodeMethod, decodeMethod} }
// newCounter creates a new counter expression of the appropriate form. func (f *File) newCounter(start, end token.Pos, numStmt int) ast.Stmt { counter := &ast.IndexExpr{ X: &ast.SelectorExpr{ X: ast.NewIdent(*varVar), Sel: ast.NewIdent("Count"), }, Index: f.index(), } stmt := counterStmt(f, counter) f.blocks = append(f.blocks, Block{start, end, numStmt}) return stmt }