package types import ( "fmt" ) var ( Debug bool = false ) func dbg(f string, xs ...interface{}) { if Debug { fmt.Printf(f,xs...) } } func (n *Node) HasFunc() bool { if n == nil { return false } for _,c := range n.Children { if c.Kind == "Function" || c.HasFunc() { return true } } return false } func Parse(s string) (*Node, error) { s2, n := TypeName(s,NewNode("AST")) //fmt.Printf("%p Parsed %s\n",n,s) if s2 != "" { return n,fmt.Errorf("Parse failed or incomplete. Remainder: %s",s2) } return n, nil } //Evaluate a node to determine if it is a pointer or array func (n *Node) isIndirect(k string) bool { if n.stripIndirect(k) == nil { return false } return true } //Strip one level of pointer or array indirection from a node func (n *Node) stripIndirect(k string) *Node { if n == nil { return nil } i := len(n.Children) - 1 if i < 1 { return nil } ret := NewNode(n.Kind) cs := append([]*Node{},n.Children...) dbg("stripIndirect(): i = %d\n",i) //Scan backwords skipping TypeQualifier and NullableAnnotation tags for ;i > 0 && (cs[i].Kind == "TypeQualifier" || cs[i].Kind == "NullableAnnotation") ; i-- { } if cs[i].Kind == k { dbg("stripIndirect(): last node is %s\n",k) ret.Children = cs[:i] return ret } if i > 1 && cs[i-1].Kind == "Parenthesized" { j := len(cs[i-1].Children) - 1 for ;j > 0 && (cs[i-1].Children[j].Kind == "TypeQualifier" || cs[i-1].Children[j].Kind == "NullableAnnotation"); j-- { } if cs[i-1].Children[j].Kind != k { return nil } if j == 0 { // strip Parenthesized tag cs[i-1] = cs[i] ret.Children = cs[:i] return ret } // strip last child from Parenthesized tag cs[i-1].Children = cs[i-1].Children[:j] ret.Children = cs return ret } return nil } //PointsTo, when called on a pointer node returns a node describing the type //pointed to. Otherwise returns nil when called on non-pointer types. func (n *Node) PointsTo() *Node { dbg("PointsTo()\n") return n.stripIndirect("Pointer") } //IsPointer returns true if the node is a pointer func (n *Node) IsPointer() bool { if pt := n.PointsTo(); pt != nil { return true } return n.IsInstancetype() || n.IsId() } //ArrayOf, when called on an array node returns a node describing the type //of the elements of the array. Otherwise returns nil when called on //non-array types. func (n *Node) ArrayOf() *Node { dbg("ArrayOf()\n") return n.stripIndirect("Array") } //IsArray returns true if the node is an array func (n *Node) IsArray() bool { return n.ArrayOf() != nil } func (n *Node) IsStruct() bool { if n == nil || len(n.Children) < 1 { return false } i := 0 for ; i