go/ast: adding a new ast node

834 views
Skip to first unread message

Abhishek Kulkarni

unread,
Aug 4, 2011, 5:56:10 PM8/4/11
to golang-nuts
I couldn't find any examples or any tests/fixes (in gofix) that
do this, but how do I add new nodes to an AST while walking
it?

more specifically, i want to, let's say, change:
   var a Foo
to
   var a Foo
   a = 42

Is it possible to do this?

Thanks,
Abhishek

John Asmuth

unread,
Aug 4, 2011, 6:00:26 PM8/4/11
to golan...@googlegroups.com
It doesn't compile anymore (since I don't maintain it), but https://github.com/skelterjohn/gorf does this kind of thing, and I imagine the relevant bits for your query still make sense. It's a refactoring tool, so it rewrites go code by reading in the ast, manipulating it, and pretty-printing the result.

Evan Shaw

unread,
Aug 4, 2011, 6:16:40 PM8/4/11
to Abhishek Kulkarni, golang-nuts

Yes, you can do this. Say you have an *ast.Block b that's populated
with statements and you want to insert a statement at index i.

// first put together the statement "a = 42"
identA := ast.NewIdent("a")
fortyTwo := &ast.BasicLit{Kind: token.INT, Value: "42"}
assignment := &ast.AssignStmt{Lhs: []ast.Expr{identA}, Rhs:
[]ast.Expr{fortyTwo}}

// allocate a new statement list big enough for our new statement
list := make([]ast.Stmt, len(b.List) + 1)
copy(list, b.List[:i])
list[i] = assignment
copy(list[i+1:], b.List[i:])
b.List = list

(In some cases you could use append instead of explicitly allocating a
new list if you know you're adding to the end of the block.)

- Evan

John Asmuth

unread,
Aug 4, 2011, 9:46:22 PM8/4/11
to golan...@googlegroups.com, Abhishek Kulkarni


On Thursday, August 4, 2011 6:16:40 PM UTC-4, Evan Shaw wrote:

(In some cases you could use append instead of explicitly allocating a
new list if you know you're adding to the end of the block.)

 The whole point of append is that it will do the allocation for you.


Though the insert trick is a bit cumbersome, admittedly.

Evan Shaw

unread,
Aug 4, 2011, 9:50:46 PM8/4/11
to golan...@googlegroups.com
On Fri, Aug 5, 2011 at 1:46 PM, John Asmuth <jas...@gmail.com> wrote:
>  The whole point of append is that it will do the allocation for you.
> http://code.google.com/p/go-wiki/wiki/SliceTricks

That's a neat trick, but I think my way is clearer even though it's more code.

- Evan

Russ Cox

unread,
Aug 5, 2011, 12:31:05 AM8/5/11
to Evan Shaw, Abhishek Kulkarni, golang-nuts
> // allocate a new statement list big enough for our new statement
> list := make([]ast.Stmt, len(b.List) + 1)
> copy(list, b.List[:i])
> list[i] = assignment
> copy(list[i+1:], b.List[i:])
> b.List = list

var list []ast.Stmt // or = make([]ast.Stmt, 0, len(b.List)+1) if you care
list = append(list, b.List[:i]...)
list = append(list, assignment)
list = append(list, b.List[i:]...)
b.List = list

Russ

Reply all
Reply to author
Forward
0 new messages