OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [tags/] [gnu-dev/] [fsf-gcc-snapshot-1-mar-12/] [or1k-gcc/] [libgo/] [go/] [go/] [ast/] [walk.go] - Rev 783

Compare with Previous | Blame | View Log

// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package ast

import "fmt"

// A Visitor's Visit method is invoked for each node encountered by Walk.
// If the result visitor w is not nil, Walk visits each of the children
// of node with the visitor w, followed by a call of w.Visit(nil).
type Visitor interface {
        Visit(node Node) (w Visitor)
}

// Helper functions for common node lists. They may be empty.

func walkIdentList(v Visitor, list []*Ident) {
        for _, x := range list {
                Walk(v, x)
        }
}

func walkExprList(v Visitor, list []Expr) {
        for _, x := range list {
                Walk(v, x)
        }
}

func walkStmtList(v Visitor, list []Stmt) {
        for _, x := range list {
                Walk(v, x)
        }
}

func walkDeclList(v Visitor, list []Decl) {
        for _, x := range list {
                Walk(v, x)
        }
}

// TODO(gri): Investigate if providing a closure to Walk leads to
//            simpler use (and may help eliminate Inspect in turn).

// Walk traverses an AST in depth-first order: It starts by calling
// v.Visit(node); node must not be nil. If the visitor w returned by
// v.Visit(node) is not nil, Walk is invoked recursively with visitor
// w for each of the non-nil children of node, followed by a call of
// w.Visit(nil).
//
func Walk(v Visitor, node Node) {
        if v = v.Visit(node); v == nil {
                return
        }

        // walk children
        // (the order of the cases matches the order
        // of the corresponding node types in ast.go)
        switch n := node.(type) {
        // Comments and fields
        case *Comment:
                // nothing to do

        case *CommentGroup:
                for _, c := range n.List {
                        Walk(v, c)
                }

        case *Field:
                if n.Doc != nil {
                        Walk(v, n.Doc)
                }
                walkIdentList(v, n.Names)
                Walk(v, n.Type)
                if n.Tag != nil {
                        Walk(v, n.Tag)
                }
                if n.Comment != nil {
                        Walk(v, n.Comment)
                }

        case *FieldList:
                for _, f := range n.List {
                        Walk(v, f)
                }

        // Expressions
        case *BadExpr, *Ident, *BasicLit:
                // nothing to do

        case *Ellipsis:
                if n.Elt != nil {
                        Walk(v, n.Elt)
                }

        case *FuncLit:
                Walk(v, n.Type)
                Walk(v, n.Body)

        case *CompositeLit:
                if n.Type != nil {
                        Walk(v, n.Type)
                }
                walkExprList(v, n.Elts)

        case *ParenExpr:
                Walk(v, n.X)

        case *SelectorExpr:
                Walk(v, n.X)
                Walk(v, n.Sel)

        case *IndexExpr:
                Walk(v, n.X)
                Walk(v, n.Index)

        case *SliceExpr:
                Walk(v, n.X)
                if n.Low != nil {
                        Walk(v, n.Low)
                }
                if n.High != nil {
                        Walk(v, n.High)
                }

        case *TypeAssertExpr:
                Walk(v, n.X)
                if n.Type != nil {
                        Walk(v, n.Type)
                }

        case *CallExpr:
                Walk(v, n.Fun)
                walkExprList(v, n.Args)

        case *StarExpr:
                Walk(v, n.X)

        case *UnaryExpr:
                Walk(v, n.X)

        case *BinaryExpr:
                Walk(v, n.X)
                Walk(v, n.Y)

        case *KeyValueExpr:
                Walk(v, n.Key)
                Walk(v, n.Value)

        // Types
        case *ArrayType:
                if n.Len != nil {
                        Walk(v, n.Len)
                }
                Walk(v, n.Elt)

        case *StructType:
                Walk(v, n.Fields)

        case *FuncType:
                Walk(v, n.Params)
                if n.Results != nil {
                        Walk(v, n.Results)
                }

        case *InterfaceType:
                Walk(v, n.Methods)

        case *MapType:
                Walk(v, n.Key)
                Walk(v, n.Value)

        case *ChanType:
                Walk(v, n.Value)

        // Statements
        case *BadStmt:
                // nothing to do

        case *DeclStmt:
                Walk(v, n.Decl)

        case *EmptyStmt:
                // nothing to do

        case *LabeledStmt:
                Walk(v, n.Label)
                Walk(v, n.Stmt)

        case *ExprStmt:
                Walk(v, n.X)

        case *SendStmt:
                Walk(v, n.Chan)
                Walk(v, n.Value)

        case *IncDecStmt:
                Walk(v, n.X)

        case *AssignStmt:
                walkExprList(v, n.Lhs)
                walkExprList(v, n.Rhs)

        case *GoStmt:
                Walk(v, n.Call)

        case *DeferStmt:
                Walk(v, n.Call)

        case *ReturnStmt:
                walkExprList(v, n.Results)

        case *BranchStmt:
                if n.Label != nil {
                        Walk(v, n.Label)
                }

        case *BlockStmt:
                walkStmtList(v, n.List)

        case *IfStmt:
                if n.Init != nil {
                        Walk(v, n.Init)
                }
                Walk(v, n.Cond)
                Walk(v, n.Body)
                if n.Else != nil {
                        Walk(v, n.Else)
                }

        case *CaseClause:
                walkExprList(v, n.List)
                walkStmtList(v, n.Body)

        case *SwitchStmt:
                if n.Init != nil {
                        Walk(v, n.Init)
                }
                if n.Tag != nil {
                        Walk(v, n.Tag)
                }
                Walk(v, n.Body)

        case *TypeSwitchStmt:
                if n.Init != nil {
                        Walk(v, n.Init)
                }
                Walk(v, n.Assign)
                Walk(v, n.Body)

        case *CommClause:
                if n.Comm != nil {
                        Walk(v, n.Comm)
                }
                walkStmtList(v, n.Body)

        case *SelectStmt:
                Walk(v, n.Body)

        case *ForStmt:
                if n.Init != nil {
                        Walk(v, n.Init)
                }
                if n.Cond != nil {
                        Walk(v, n.Cond)
                }
                if n.Post != nil {
                        Walk(v, n.Post)
                }
                Walk(v, n.Body)

        case *RangeStmt:
                Walk(v, n.Key)
                if n.Value != nil {
                        Walk(v, n.Value)
                }
                Walk(v, n.X)
                Walk(v, n.Body)

        // Declarations
        case *ImportSpec:
                if n.Doc != nil {
                        Walk(v, n.Doc)
                }
                if n.Name != nil {
                        Walk(v, n.Name)
                }
                Walk(v, n.Path)
                if n.Comment != nil {
                        Walk(v, n.Comment)
                }

        case *ValueSpec:
                if n.Doc != nil {
                        Walk(v, n.Doc)
                }
                walkIdentList(v, n.Names)
                if n.Type != nil {
                        Walk(v, n.Type)
                }
                walkExprList(v, n.Values)
                if n.Comment != nil {
                        Walk(v, n.Comment)
                }

        case *TypeSpec:
                if n.Doc != nil {
                        Walk(v, n.Doc)
                }
                Walk(v, n.Name)
                Walk(v, n.Type)
                if n.Comment != nil {
                        Walk(v, n.Comment)
                }

        case *BadDecl:
                // nothing to do

        case *GenDecl:
                if n.Doc != nil {
                        Walk(v, n.Doc)
                }
                for _, s := range n.Specs {
                        Walk(v, s)
                }

        case *FuncDecl:
                if n.Doc != nil {
                        Walk(v, n.Doc)
                }
                if n.Recv != nil {
                        Walk(v, n.Recv)
                }
                Walk(v, n.Name)
                Walk(v, n.Type)
                if n.Body != nil {
                        Walk(v, n.Body)
                }

        // Files and packages
        case *File:
                if n.Doc != nil {
                        Walk(v, n.Doc)
                }
                Walk(v, n.Name)
                walkDeclList(v, n.Decls)
                for _, g := range n.Comments {
                        Walk(v, g)
                }
                // don't walk n.Comments - they have been
                // visited already through the individual
                // nodes

        case *Package:
                for _, f := range n.Files {
                        Walk(v, f)
                }

        default:
                fmt.Printf("ast.Walk: unexpected node type %T", n)
                panic("ast.Walk")
        }

        v.Visit(nil)
}

type inspector func(Node) bool

func (f inspector) Visit(node Node) Visitor {
        if f(node) {
                return f
        }
        return nil
}

// Inspect traverses an AST in depth-first order: It starts by calling
// f(node); node must not be nil. If f returns true, Inspect invokes f
// for all the non-nil children of node, recursively.
//
func Inspect(node Node, f func(Node) bool) {
        Walk(inspector(f), node)
}

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.