1/* 2 * gomacro - A Go interpreter with Lisp-like macros 3 * 4 * Copyright (C) 2017-2019 Massimiliano Ghilardi 5 * 6 * This Source Code Form is subject to the terms of the Mozilla Public 7 * License, v. 2.0. If a copy of the MPL was not distributed with this 8 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 9 * 10 * 11 * util.go 12 * 13 * Created on May 07, 2017 14 * Author Massimiliano Ghilardi 15 */ 16 17package xreflect 18 19import ( 20 "fmt" 21 "go/token" 22 "go/types" 23 "reflect" 24) 25 26func concat(a, b []int) []int { 27 na := len(a) 28 c := make([]int, na+len(b)) 29 copy(c, a) 30 copy(c[na:], b) 31 return c 32} 33 34type Error struct { 35 Type Type 36 format string 37 args []interface{} 38} 39 40func (e *Error) Error() string { 41 return fmt.Sprintf(e.format, e.args...) 42} 43 44func errorf(t Type, format string, args ...interface{}) { 45 panic(&Error{t, format, args}) 46} 47 48func xerrorf(t *xtype, format string, args ...interface{}) { 49 panic(&Error{wrap(t), format, args}) 50} 51 52func dirToGdir(dir reflect.ChanDir) types.ChanDir { 53 var gdir types.ChanDir 54 switch dir { 55 case reflect.RecvDir: 56 gdir = types.RecvOnly 57 case reflect.SendDir: 58 gdir = types.SendOnly 59 case reflect.BothDir: 60 gdir = types.SendRecv 61 } 62 return gdir 63} 64 65func gtypeToKind(t *xtype, gtype types.Type) reflect.Kind { 66 gtype = gtype.Underlying() 67 var kind reflect.Kind 68 switch gtype := gtype.(type) { 69 case *types.Array: 70 kind = reflect.Array 71 case *types.Basic: 72 kind = ToReflectKind(gtype.Kind()) 73 case *types.Chan: 74 kind = reflect.Chan 75 case *types.Signature: 76 kind = reflect.Func 77 case *types.Interface: 78 kind = reflect.Interface 79 case *types.Map: 80 kind = reflect.Map 81 case *types.Pointer: 82 kind = reflect.Ptr 83 case *types.Slice: 84 kind = reflect.Slice 85 case *types.Struct: 86 kind = reflect.Struct 87 // case *types.Named: // impossible, handled above 88 default: 89 xerrorf(t, "unsupported types.Type: %v", gtype) 90 } 91 // debugf("gtypeToKind(%T) -> %v", gtype, kind) 92 return kind 93} 94 95func IsGoUntypedKind(gkind types.BasicKind) bool { 96 switch gkind { 97 case types.UntypedBool, types.UntypedInt, types.UntypedRune, 98 types.UntypedFloat, types.UntypedComplex, types.UntypedString, types.UntypedNil: 99 return true 100 default: 101 return false 102 } 103} 104 105func ToReflectKind(gkind types.BasicKind) reflect.Kind { 106 var kind reflect.Kind 107 switch gkind { 108 case types.Bool, types.UntypedBool: 109 kind = reflect.Bool 110 case types.Int, types.UntypedInt: 111 kind = reflect.Int 112 case types.Int8: 113 kind = reflect.Int8 114 case types.Int16: 115 kind = reflect.Int16 116 case types.Int32, types.UntypedRune: 117 kind = reflect.Int32 118 case types.Int64: 119 kind = reflect.Int64 120 case types.Uint: 121 kind = reflect.Uint 122 case types.Uint8: 123 kind = reflect.Uint8 124 case types.Uint16: 125 kind = reflect.Uint16 126 case types.Uint32: 127 kind = reflect.Uint32 128 case types.Uint64: 129 kind = reflect.Uint64 130 case types.Uintptr: 131 kind = reflect.Uintptr 132 case types.Float32: 133 kind = reflect.Float32 134 case types.Float64, types.UntypedFloat: 135 kind = reflect.Float64 136 case types.Complex64: 137 kind = reflect.Complex64 138 case types.Complex128, types.UntypedComplex: 139 kind = reflect.Complex128 140 case types.String, types.UntypedString: 141 kind = reflect.String 142 case types.UnsafePointer: 143 kind = reflect.UnsafePointer 144 case types.UntypedNil: 145 kind = reflect.Invalid 146 default: 147 errorf(nil, "unsupported types.BasicKind: %v", gkind) 148 } 149 return kind 150} 151 152func ToBasicKind(kind reflect.Kind, untyped bool) types.BasicKind { 153 var gkind types.BasicKind 154 switch kind { 155 case reflect.Bool: 156 if untyped { 157 gkind = types.UntypedBool 158 } else { 159 gkind = types.Bool 160 } 161 case reflect.Int: 162 if untyped { 163 gkind = types.Int 164 } else { 165 gkind = types.UntypedInt 166 } 167 case reflect.Int8: 168 gkind = types.Int8 169 case reflect.Int16: 170 gkind = types.Int16 171 case reflect.Int32: 172 if untyped { 173 gkind = types.UntypedRune 174 } else { 175 gkind = types.Int32 176 } 177 case reflect.Int64: 178 gkind = types.Int64 179 case reflect.Uint: 180 gkind = types.Uint 181 case reflect.Uint8: 182 gkind = types.Uint8 183 case reflect.Uint16: 184 gkind = types.Uint16 185 case reflect.Uint32: 186 gkind = types.Uint32 187 case reflect.Uint64: 188 gkind = types.Uint64 189 case reflect.Uintptr: 190 gkind = types.Uintptr 191 case reflect.Float32: 192 gkind = types.Float32 193 case reflect.Float64: 194 if untyped { 195 gkind = types.UntypedFloat 196 } else { 197 gkind = types.Float64 198 } 199 case reflect.Complex64: 200 gkind = types.Complex64 201 case reflect.Complex128: 202 if untyped { 203 gkind = types.UntypedComplex 204 } else { 205 gkind = types.Complex128 206 } 207 case reflect.String: 208 if untyped { 209 gkind = types.UntypedString 210 } else { 211 gkind = types.String 212 } 213 case reflect.UnsafePointer: 214 gkind = types.UnsafePointer 215 case reflect.Invalid: 216 gkind = types.UntypedNil 217 default: 218 errorf(nil, "unsupported refletc.Kind: %v", kind) 219 } 220 return gkind 221} 222 223func path(gpkg *types.Package) string { 224 if gpkg == nil { 225 return "" 226 } 227 return gpkg.Path() 228} 229 230func toReflectTypes(ts []Type) []reflect.Type { 231 rts := make([]reflect.Type, len(ts)) 232 for i, t := range ts { 233 rts[i] = t.ReflectType() 234 } 235 return rts 236} 237 238func toGoParam(t Type) *types.Var { 239 return types.NewParam(token.NoPos, nil, "", t.GoType()) 240} 241 242func toGoParams(ts []Type) []*types.Var { 243 vars := make([]*types.Var, len(ts)) 244 for i, t := range ts { 245 vars[i] = toGoParam(t) 246 } 247 return vars 248} 249 250func toGoTuple(ts []Type) *types.Tuple { 251 vars := toGoParams(ts) 252 return types.NewTuple(vars...) 253} 254