Cindy
Cindy

Reputation: 11

Rewrite AST switch stmt with new caseClause

I am trying to add new caseClause into switch statement by Golang AST but keep getting failure. Could you please help check how to change below snippet for below case statement:

case "all":
        def = pool.All{}

 func handleSwitch(ss *ast.SwitchStmt) (ast.Node, bool) {   
        expr := make([]ast.Expr, 1)
        body := make([]ast.Stmt, 1)
        bl := &ast.BasicLit{Kind: token.STRING, Value: "\"all\""}
        expr = append(expr, bl)
        lhs := make([]ast.Expr, 1)
        ident := &ast.Ident{Name: "def"}
        lhs = append(lhs, ident)
        xIdent := &ast.Ident{Name: "pool"}
        sIdent := &ast.Ident{Name: "All"}
        rhs := make([]ast.Expr, 1)
        cl := &ast.CompositeLit {
            Type: &ast.SelectorExpr{
                X: xIdent,
                Sel: sIdent,
            },
        }
        rhs = append(rhs, cl)
        as := &ast.AssignStmt{
            Lhs: lhs,
            Tok: token.ASSIGN,
            Rhs: rhs,
        }
        body = append(body, as)
        cc := &ast.CaseClause{
            List: expr,
            Body: body,
        }
        newCases = append(newCases, cc)
        ss.Body = &ast.BlockStmt{
            List: newCases,
        }
        return ss, true
}

Upvotes: 1

Views: 262

Answers (1)

mkopriva
mkopriva

Reputation: 38313

The problem is that you're allocating slices with make(T, N) and then you're using append with the assumption that it appends from the 0th position. However, in actuality, append will add a new element to the end of a slice and any of its preceding elements will remain unchanged, which is this case means nil, and that nil is what breaks the AST.

See the problem in code:

expr := make([]ast.Expr, 1)
fmt.Println(expr)
// [<nil>]

bl := &ast.BasicLit{ ... }

expr = append(expr, bl)
fmt.Println(expr)
// [<nil> 0xc0000a6020]

To fix this you can either do:

expr := make([]ast.Expr, 0) // or []ast.Expr{}
fmt.Println(expr)
// []

expr = append(expr, bl)
fmt.Println(expr)
// [0xc00000c0c0]

or:

expr := make([]ast.Expr, 1)
fmt.Println(expr)
// [<nil>]

expr[0] = bl
fmt.Println(expr)
// [0xc000114020]

https://play.golang.org/p/g78hrrv2VDD

Upvotes: 0

Related Questions