src

Go monorepo.
git clone git://code.dwrz.net/src
Log | Files | Refs

convert.go (6573B)


      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.TypeFor[ast.Ellipsis](),
     13 	"RangeStmt":      reflect.TypeFor[ast.RangeStmt](),
     14 	"AssignStmt":     reflect.TypeFor[ast.AssignStmt](),
     15 	"IndexExpr":      reflect.TypeFor[ast.IndexExpr](),
     16 	"IndexListExpr":  reflect.TypeFor[ast.IndexListExpr](),
     17 	"Ident":          reflect.TypeFor[ast.Ident](),
     18 	"ValueSpec":      reflect.TypeFor[ast.ValueSpec](),
     19 	"GenDecl":        reflect.TypeFor[ast.GenDecl](),
     20 	"BinaryExpr":     reflect.TypeFor[ast.BinaryExpr](),
     21 	"ForStmt":        reflect.TypeFor[ast.ForStmt](),
     22 	"ArrayType":      reflect.TypeFor[ast.ArrayType](),
     23 	"DeferStmt":      reflect.TypeFor[ast.DeferStmt](),
     24 	"MapType":        reflect.TypeFor[ast.MapType](),
     25 	"ReturnStmt":     reflect.TypeFor[ast.ReturnStmt](),
     26 	"SliceExpr":      reflect.TypeFor[ast.SliceExpr](),
     27 	"StarExpr":       reflect.TypeFor[ast.StarExpr](),
     28 	"UnaryExpr":      reflect.TypeFor[ast.UnaryExpr](),
     29 	"SendStmt":       reflect.TypeFor[ast.SendStmt](),
     30 	"SelectStmt":     reflect.TypeFor[ast.SelectStmt](),
     31 	"ImportSpec":     reflect.TypeFor[ast.ImportSpec](),
     32 	"IfStmt":         reflect.TypeFor[ast.IfStmt](),
     33 	"GoStmt":         reflect.TypeFor[ast.GoStmt](),
     34 	"Field":          reflect.TypeFor[ast.Field](),
     35 	"SelectorExpr":   reflect.TypeFor[ast.SelectorExpr](),
     36 	"StructType":     reflect.TypeFor[ast.StructType](),
     37 	"KeyValueExpr":   reflect.TypeFor[ast.KeyValueExpr](),
     38 	"FuncType":       reflect.TypeFor[ast.FuncType](),
     39 	"FuncLit":        reflect.TypeFor[ast.FuncLit](),
     40 	"FuncDecl":       reflect.TypeFor[ast.FuncDecl](),
     41 	"ChanType":       reflect.TypeFor[ast.ChanType](),
     42 	"CallExpr":       reflect.TypeFor[ast.CallExpr](),
     43 	"CaseClause":     reflect.TypeFor[ast.CaseClause](),
     44 	"CommClause":     reflect.TypeFor[ast.CommClause](),
     45 	"CompositeLit":   reflect.TypeFor[ast.CompositeLit](),
     46 	"EmptyStmt":      reflect.TypeFor[ast.EmptyStmt](),
     47 	"SwitchStmt":     reflect.TypeFor[ast.SwitchStmt](),
     48 	"TypeSwitchStmt": reflect.TypeFor[ast.TypeSwitchStmt](),
     49 	"TypeAssertExpr": reflect.TypeFor[ast.TypeAssertExpr](),
     50 	"TypeSpec":       reflect.TypeFor[ast.TypeSpec](),
     51 	"InterfaceType":  reflect.TypeFor[ast.InterfaceType](),
     52 	"BranchStmt":     reflect.TypeFor[ast.BranchStmt](),
     53 	"IncDecStmt":     reflect.TypeFor[ast.IncDecStmt](),
     54 	"BasicLit":       reflect.TypeFor[ast.BasicLit](),
     55 }
     56 
     57 func ASTToNode(node any) 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) any {
    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 }