convert.go raw

   1  package pattern
   2  
   3  import (
   4  	"fmt"
   5  	"go/ast"
   6  	"go/token"
   7  	"go/types"
   8  	"reflect"
   9  )
  10  
  11  var astTypes = map[string]reflect.Type{
  12  	"Ellipsis":       reflect.TypeOf(ast.Ellipsis{}),
  13  	"RangeStmt":      reflect.TypeOf(ast.RangeStmt{}),
  14  	"AssignStmt":     reflect.TypeOf(ast.AssignStmt{}),
  15  	"IndexExpr":      reflect.TypeOf(ast.IndexExpr{}),
  16  	"IndexListExpr":  reflect.TypeOf(ast.IndexListExpr{}),
  17  	"Ident":          reflect.TypeOf(ast.Ident{}),
  18  	"ValueSpec":      reflect.TypeOf(ast.ValueSpec{}),
  19  	"GenDecl":        reflect.TypeOf(ast.GenDecl{}),
  20  	"BinaryExpr":     reflect.TypeOf(ast.BinaryExpr{}),
  21  	"ForStmt":        reflect.TypeOf(ast.ForStmt{}),
  22  	"ArrayType":      reflect.TypeOf(ast.ArrayType{}),
  23  	"DeferStmt":      reflect.TypeOf(ast.DeferStmt{}),
  24  	"MapType":        reflect.TypeOf(ast.MapType{}),
  25  	"ReturnStmt":     reflect.TypeOf(ast.ReturnStmt{}),
  26  	"SliceExpr":      reflect.TypeOf(ast.SliceExpr{}),
  27  	"StarExpr":       reflect.TypeOf(ast.StarExpr{}),
  28  	"UnaryExpr":      reflect.TypeOf(ast.UnaryExpr{}),
  29  	"SendStmt":       reflect.TypeOf(ast.SendStmt{}),
  30  	"SelectStmt":     reflect.TypeOf(ast.SelectStmt{}),
  31  	"ImportSpec":     reflect.TypeOf(ast.ImportSpec{}),
  32  	"IfStmt":         reflect.TypeOf(ast.IfStmt{}),
  33  	"GoStmt":         reflect.TypeOf(ast.GoStmt{}),
  34  	"Field":          reflect.TypeOf(ast.Field{}),
  35  	"SelectorExpr":   reflect.TypeOf(ast.SelectorExpr{}),
  36  	"StructType":     reflect.TypeOf(ast.StructType{}),
  37  	"KeyValueExpr":   reflect.TypeOf(ast.KeyValueExpr{}),
  38  	"FuncType":       reflect.TypeOf(ast.FuncType{}),
  39  	"FuncLit":        reflect.TypeOf(ast.FuncLit{}),
  40  	"FuncDecl":       reflect.TypeOf(ast.FuncDecl{}),
  41  	"ChanType":       reflect.TypeOf(ast.ChanType{}),
  42  	"CallExpr":       reflect.TypeOf(ast.CallExpr{}),
  43  	"CaseClause":     reflect.TypeOf(ast.CaseClause{}),
  44  	"CommClause":     reflect.TypeOf(ast.CommClause{}),
  45  	"CompositeLit":   reflect.TypeOf(ast.CompositeLit{}),
  46  	"EmptyStmt":      reflect.TypeOf(ast.EmptyStmt{}),
  47  	"SwitchStmt":     reflect.TypeOf(ast.SwitchStmt{}),
  48  	"TypeSwitchStmt": reflect.TypeOf(ast.TypeSwitchStmt{}),
  49  	"TypeAssertExpr": reflect.TypeOf(ast.TypeAssertExpr{}),
  50  	"TypeSpec":       reflect.TypeOf(ast.TypeSpec{}),
  51  	"InterfaceType":  reflect.TypeOf(ast.InterfaceType{}),
  52  	"BranchStmt":     reflect.TypeOf(ast.BranchStmt{}),
  53  	"IncDecStmt":     reflect.TypeOf(ast.IncDecStmt{}),
  54  	"BasicLit":       reflect.TypeOf(ast.BasicLit{}),
  55  }
  56  
  57  func ASTToNode(node interface{}) Node {
  58  	switch node := node.(type) {
  59  	case *ast.File:
  60  		panic("cannot convert *ast.File to Node")
  61  	case nil:
  62  		return Nil{}
  63  	case string:
  64  		return String(node)
  65  	case token.Token:
  66  		return Token(node)
  67  	case *ast.ExprStmt:
  68  		return ASTToNode(node.X)
  69  	case *ast.BlockStmt:
  70  		if node == nil {
  71  			return Nil{}
  72  		}
  73  		return ASTToNode(node.List)
  74  	case *ast.FieldList:
  75  		if node == nil {
  76  			return Nil{}
  77  		}
  78  		return ASTToNode(node.List)
  79  	case *ast.BasicLit:
  80  		if node == nil {
  81  			return Nil{}
  82  		}
  83  	case *ast.ParenExpr:
  84  		return ASTToNode(node.X)
  85  	}
  86  
  87  	if node, ok := node.(ast.Node); ok {
  88  		name := reflect.TypeOf(node).Elem().Name()
  89  		T, ok := structNodes[name]
  90  		if !ok {
  91  			panic(fmt.Sprintf("internal error: unhandled type %T", node))
  92  		}
  93  
  94  		if reflect.ValueOf(node).IsNil() {
  95  			return Nil{}
  96  		}
  97  		v := reflect.ValueOf(node).Elem()
  98  		objs := make([]Node, T.NumField())
  99  		for i := 0; i < T.NumField(); i++ {
 100  			f := v.FieldByName(T.Field(i).Name)
 101  			objs[i] = ASTToNode(f.Interface())
 102  		}
 103  
 104  		n, err := populateNode(name, objs, false)
 105  		if err != nil {
 106  			panic(fmt.Sprintf("internal error: %s", err))
 107  		}
 108  		return n
 109  	}
 110  
 111  	s := reflect.ValueOf(node)
 112  	if s.Kind() == reflect.Slice {
 113  		if s.Len() == 0 {
 114  			return List{}
 115  		}
 116  		if s.Len() == 1 {
 117  			return ASTToNode(s.Index(0).Interface())
 118  		}
 119  
 120  		tail := List{}
 121  		for i := s.Len() - 1; i >= 0; i-- {
 122  			head := ASTToNode(s.Index(i).Interface())
 123  			l := List{
 124  				Head: head,
 125  				Tail: tail,
 126  			}
 127  			tail = l
 128  		}
 129  		return tail
 130  	}
 131  
 132  	panic(fmt.Sprintf("internal error: unhandled type %T", node))
 133  }
 134  
 135  func NodeToAST(node Node, state State) interface{} {
 136  	switch node := node.(type) {
 137  	case Binding:
 138  		v, ok := state[node.Name]
 139  		if !ok {
 140  			// really we want to return an error here
 141  			panic("XXX")
 142  		}
 143  		switch v := v.(type) {
 144  		case types.Object:
 145  			return &ast.Ident{Name: v.Name()}
 146  		default:
 147  			return v
 148  		}
 149  	case Builtin, Any, Object, Symbol, Not, Or:
 150  		panic("XXX")
 151  	case List:
 152  		if (node == List{}) {
 153  			return []ast.Node{}
 154  		}
 155  		x := []ast.Node{NodeToAST(node.Head, state).(ast.Node)}
 156  		x = append(x, NodeToAST(node.Tail, state).([]ast.Node)...)
 157  		return x
 158  	case Token:
 159  		return token.Token(node)
 160  	case String:
 161  		return string(node)
 162  	case Nil:
 163  		return nil
 164  	}
 165  
 166  	name := reflect.TypeOf(node).Name()
 167  	T, ok := astTypes[name]
 168  	if !ok {
 169  		panic(fmt.Sprintf("internal error: unhandled type %T", node))
 170  	}
 171  	v := reflect.ValueOf(node)
 172  	out := reflect.New(T)
 173  	for i := 0; i < T.NumField(); i++ {
 174  		fNode := v.FieldByName(T.Field(i).Name)
 175  		if (fNode == reflect.Value{}) {
 176  			continue
 177  		}
 178  		fAST := out.Elem().FieldByName(T.Field(i).Name)
 179  		switch fAST.Type().Kind() {
 180  		case reflect.Slice:
 181  			c := reflect.ValueOf(NodeToAST(fNode.Interface().(Node), state))
 182  			if c.Kind() != reflect.Slice {
 183  				// it's a single node in the pattern, we have to wrap
 184  				// it in a slice
 185  				slice := reflect.MakeSlice(fAST.Type(), 1, 1)
 186  				slice.Index(0).Set(c)
 187  				c = slice
 188  			}
 189  			switch fAST.Interface().(type) {
 190  			case []ast.Node:
 191  				switch cc := c.Interface().(type) {
 192  				case []ast.Node:
 193  					fAST.Set(c)
 194  				case []ast.Expr:
 195  					var slice []ast.Node
 196  					for _, el := range cc {
 197  						slice = append(slice, el)
 198  					}
 199  					fAST.Set(reflect.ValueOf(slice))
 200  				default:
 201  					panic("XXX")
 202  				}
 203  			case []ast.Expr:
 204  				switch cc := c.Interface().(type) {
 205  				case []ast.Node:
 206  					var slice []ast.Expr
 207  					for _, el := range cc {
 208  						slice = append(slice, el.(ast.Expr))
 209  					}
 210  					fAST.Set(reflect.ValueOf(slice))
 211  				case []ast.Expr:
 212  					fAST.Set(c)
 213  				default:
 214  					panic("XXX")
 215  				}
 216  			default:
 217  				panic("XXX")
 218  			}
 219  		case reflect.Int:
 220  			c := reflect.ValueOf(NodeToAST(fNode.Interface().(Node), state))
 221  			switch c.Kind() {
 222  			case reflect.String:
 223  				tok, ok := tokensByString[c.Interface().(string)]
 224  				if !ok {
 225  					// really we want to return an error here
 226  					panic("XXX")
 227  				}
 228  				fAST.SetInt(int64(tok))
 229  			case reflect.Int:
 230  				fAST.Set(c)
 231  			default:
 232  				panic(fmt.Sprintf("internal error: unexpected kind %s", c.Kind()))
 233  			}
 234  		default:
 235  			r := NodeToAST(fNode.Interface().(Node), state)
 236  			if r != nil {
 237  				fAST.Set(reflect.ValueOf(r))
 238  			}
 239  		}
 240  	}
 241  
 242  	return out.Interface().(ast.Node)
 243  }
 244