github.com/machinefi/w3bstream@v1.6.5-rc9.0.20240426031326-b8c7c4876e72/pkg/depends/gen/codegen/gen_impls.go (about) 1 package codegen 2 3 import ( 4 "fmt" 5 "go/token" 6 "reflect" 7 "regexp" 8 "sort" 9 "strconv" 10 "strings" 11 ) 12 13 func Var(t SnippetType, names ...string) *SnippetField { 14 return &SnippetField{Type: t, Names: Idents(names...)} 15 } 16 17 func Type(name string) *NamedType { return &NamedType{Name: Ident(name)} } 18 19 func Interface(methods ...IfCanBeIfMethod) *InterfaceType { return &InterfaceType{Methods: methods} } 20 21 func Literal(s string) *SnippetLiteral { 22 ret := SnippetLiteral(s) 23 return &ret 24 } 25 26 func TypeAssert(typ SnippetType, z Snippet) *SnippetTypeAssertExpr { 27 return &SnippetTypeAssertExpr{Asserter: z, Type: typ} 28 } 29 30 func Compose(typ SnippetType, elements ...Snippet) *SnippetLiteralCompose { 31 return &SnippetLiteralCompose{Type: typ, Elements: elements} 32 } 33 34 func Comments(cmt ...string) *SnippetComments { 35 comments := make([]string, 0, len(cmt)) 36 for _, c := range cmt { 37 comments = append(comments, strings.Split(c, "\n")...) 38 } 39 return &SnippetComments{OneLine: false, Comments: comments} 40 } 41 42 func KeyValue(k, v Snippet) *SnippetKVExpr { return &SnippetKVExpr{K: k, V: v} } 43 44 func Ident(s string) *SnippetIdent { 45 values := strings.Split(s, ".") 46 47 if !IsValidIdent(values[0]) { 48 panic(fmt.Errorf("`%s` is not a valid identifier", values[0])) 49 } 50 if len(values) == 2 { 51 if !IsValidIdent(values[1]) { 52 panic(fmt.Errorf("`%s` is not a valid identifier", values[1])) 53 } 54 } 55 56 ret := SnippetIdent(s) 57 return &ret 58 } 59 60 func Idents(s ...string) []*SnippetIdent { 61 ret := make([]*SnippetIdent, 0, len(s)) 62 for _, ident := range s { 63 ret = append(ret, Ident(ident)) 64 } 65 return ret 66 } 67 68 func Define(ls ...SnippetCanAddr) *SnippetAssignStmt { 69 return &SnippetAssignStmt{Token: token.DEFINE, Ls: ls} 70 } 71 72 func Assign(ls ...SnippetCanAddr) *SnippetAssignStmt { 73 return &SnippetAssignStmt{Token: token.ASSIGN, Ls: ls} 74 } 75 76 func AssignWith(tok token.Token, ls ...SnippetCanAddr) *SnippetAssignStmt { 77 return &SnippetAssignStmt{Token: tok, Ls: ls} 78 } 79 80 func Inc(v SnippetCanAddr) *SnippetIncExpr { return &SnippetIncExpr{Value: v} } 81 82 func Dec(v SnippetCanAddr) *SnippetDecExpr { return &SnippetDecExpr{Value: v} } 83 84 func Ref(lead Snippet, refs ...Snippet) *SnippetRefExpr { 85 return &SnippetRefExpr{Lead: lead, Refs: refs} 86 } 87 88 func Access(v SnippetCanAddr, index int) *SnippetAccessExpr { 89 return &SnippetAccessExpr{V: v, Index: Valuer(index)} 90 } 91 92 func AccessWith(v SnippetCanAddr, index Snippet) *SnippetAccessExpr { 93 return &SnippetAccessExpr{V: v, Index: index} 94 } 95 96 func CaseClause(s ...Snippet) *SnippetCaseClause { 97 return &SnippetCaseClause{Case: s} 98 } 99 100 func ForRange(ranger Snippet, k, v *SnippetIdent) *SnippetForRangeStmt { 101 var kv, vv = AnonymousIdent, AnonymousIdent 102 if k != nil { 103 kv = *k 104 } 105 if v != nil { 106 vv = *v 107 } 108 return &SnippetForRangeStmt{Ranger: ranger, K: kv, V: vv} 109 } 110 111 func For(init, cond, post Snippet) *SnippetForStmt { 112 return &SnippetForStmt{Init: init, Cond: cond, Post: post} 113 } 114 115 func If(cond Snippet) *SnippetIfStmt { return &SnippetIfStmt{Cond: cond} } 116 117 func Switch(cond Snippet) *SnippetSwitchStmt { 118 return &SnippetSwitchStmt{Cond: cond} 119 } 120 121 func Select(clauses ...*SnippetCaseClause) *SnippetSelectStmt { 122 return &SnippetSelectStmt{Clauses: clauses} 123 } 124 125 func Star(typ SnippetType) *SnippetStarExpr { return &SnippetStarExpr{T: typ} } 126 127 func AccessValue(v SnippetCanAddr) *SnippetAccessValueExpr { return &SnippetAccessValueExpr{V: v} } 128 129 func Addr(val SnippetCanAddr) *SnippetAddrExpr { return &SnippetAddrExpr{V: val} } 130 131 func Paren(s Snippet) *SnippetParenExpr { return &SnippetParenExpr{V: s} } 132 133 func Arrow(ch Snippet) *SnippetArrowExpr { return &SnippetArrowExpr{Chan: ch} } 134 135 func Casting(ori Snippet, tar Snippet) *SnippetCallExpr { return CallWith(ori, tar) } 136 137 func Call(name string, args ...Snippet) *SnippetCallExpr { 138 var callee Snippet 139 if IsBuiltinFunc(name) { 140 callee = SnippetIdent(name) 141 } else { 142 callee = Ident(name) 143 } 144 145 return &SnippetCallExpr{Callee: callee, Args: args} 146 } 147 148 func CallWith(callee Snippet, args ...Snippet) *SnippetCallExpr { 149 return &SnippetCallExpr{Callee: callee, Args: args} 150 } 151 152 func CallMakeChan(t SnippetType, length int) *SnippetCallExpr { 153 return Call("make", Chan(t), Valuer(length)) 154 } 155 156 func Return(s ...Snippet) *SnippetReturnStmt { return &SnippetReturnStmt{Res: s} } 157 158 func Func(args ...*SnippetField) *FuncType { return &FuncType{Args: args} } 159 160 func Chan(t SnippetType) *ChanType { return &ChanType{T: t, Mode: ChanModeRW} } 161 162 func ChanRO(t SnippetType) *ChanType { return &ChanType{T: t, Mode: ChanModeRO} } 163 164 func ChanWO(t SnippetType) *ChanType { return &ChanType{T: t, Mode: ChanModeWO} } 165 166 func Array(t SnippetType, l int) *ArrayType { return &ArrayType{T: t, Len: l} } 167 168 func Slice(t SnippetType) *SliceType { return &SliceType{T: t} } 169 170 func Map(k, v SnippetType) *MapType { return &MapType{Tk: k, Tv: v} } 171 172 func Ellipsis(t SnippetType) *EllipsisType { return &EllipsisType{T: t} } 173 174 func Struct(fields ...*SnippetField) *StructType { 175 return &StructType{Fields: fields} 176 } 177 178 func DeclConst(specs ...SnippetSpec) *SnippetTypeDecl { 179 return &SnippetTypeDecl{Token: token.CONST, Specs: specs} 180 } 181 182 func DeclVar(specs ...SnippetSpec) *SnippetTypeDecl { 183 return &SnippetTypeDecl{Token: token.VAR, Specs: specs} 184 } 185 186 func DeclType(specs ...SnippetSpec) *SnippetTypeDecl { 187 return &SnippetTypeDecl{Token: token.TYPE, Specs: specs} 188 } 189 190 func ValueWithAlias(alias FnAlaise) func(interface{}) Snippet { 191 return func(v interface{}) Snippet { 192 rv := reflect.ValueOf(v) 193 rt := reflect.TypeOf(v) 194 195 val := ValueWithAlias(alias) 196 typ := TypeWithAlias(alias) 197 198 switch rv.Kind() { 199 case reflect.Ptr: 200 return Addr(Paren(val(rv.Elem().Interface()))) 201 202 case reflect.Struct: 203 values := make([]Snippet, 0) 204 for i := 0; i < rv.NumField(); i++ { 205 fi := rv.Field(i) 206 ft := rt.Field(i) 207 208 if !ft.IsExported() { 209 continue 210 } 211 212 if !IsEmptyValue(fi) { 213 values = append(values, 214 KeyValue(Ident(ft.Name), val(fi.Interface()))) 215 } 216 } 217 return Compose(typ(rt), values...) 218 219 case reflect.Map: 220 values := make([]Snippet, 0) 221 for _, key := range rv.MapKeys() { 222 values = append(values, KeyValue( 223 val(key.Interface()), 224 val(rv.MapIndex(key).Interface())), 225 ) 226 } 227 // to make sure snippet map is ordered 228 sort.Slice(values, func(i, j int) bool { 229 ik := string(values[i].(*SnippetKVExpr).K.Bytes()) 230 jk := string(values[j].(*SnippetKVExpr).K.Bytes()) 231 return ik < jk 232 }) 233 return Compose(typ(rt), values...) 234 235 case reflect.Slice, reflect.Array: 236 values := make([]Snippet, 0) 237 for i := 0; i < rv.Len(); i++ { 238 values = append(values, val(rv.Index(i).Interface())) 239 } 240 return Compose(typ(rt), values...) 241 242 case reflect.Int, reflect.Uint, 243 reflect.Uint8, reflect.Int8, 244 reflect.Int16, reflect.Uint16, 245 reflect.Int64, reflect.Uint64, 246 reflect.Uint32: 247 return Literal(fmt.Sprintf("%d", v)) 248 249 case reflect.Int32: 250 if vr, ok := v.(rune); ok { 251 s := strconv.QuoteRune(vr) 252 if len(s) == 3 { 253 return Literal(s) 254 } 255 } 256 return Literal(fmt.Sprintf("%d", v)) 257 258 case reflect.Bool: 259 return Literal(strconv.FormatBool(v.(bool))) 260 261 case reflect.Float32: 262 return Literal(strconv.FormatFloat(float64(v.(float32)), 'f', -1, 32)) 263 264 case reflect.Float64: 265 return Literal(strconv.FormatFloat(v.(float64), 'f', -1, 32)) 266 267 case reflect.String: 268 return Literal(strconv.Quote(v.(string))) 269 270 case reflect.Invalid: 271 return SnippetBuiltIn("nil") 272 273 default: 274 panic(fmt.Errorf("%v is an unsupported type", v)) 275 } 276 } 277 } 278 279 func TypeWithAlias(aliase FnAlaise) func(reflect.Type) SnippetType { 280 return func(t reflect.Type) SnippetType { 281 if t.PkgPath() != "" { 282 return Type(aliase(t.PkgPath()) + "." + t.Name()) 283 } 284 285 tof := TypeWithAlias(aliase) 286 switch t.Kind() { 287 case reflect.Ptr: 288 return Star(tof(t.Elem())) 289 case reflect.Chan: 290 return Chan(tof(t.Elem())) 291 case reflect.Array: 292 return Array(tof(t.Elem()), t.Len()) 293 case reflect.Slice: 294 return Slice(tof(t.Elem())) 295 case reflect.Map: 296 return Map(tof(t.Key()), tof(t.Elem())) 297 case reflect.Struct: 298 fields := make([]*SnippetField, 0) 299 for i := 0; i < t.NumField(); i++ { 300 f := t.Field(i) 301 if f.Anonymous { 302 fields = append( 303 fields, 304 Var(tof(f.Type)).WithTag(string(f.Tag)), 305 ) 306 } else { 307 fields = append( 308 fields, 309 Var(tof(f.Type), f.Name).WithTag(string(f.Tag)), 310 ) 311 } 312 } 313 return Struct(fields...) 314 default: 315 return BuiltInType(t.String()) 316 } 317 } 318 } 319 320 func ExprWithAlias(alias FnAlaise) func(string, ...interface{}) SnippetExpr { 321 val := ValueWithAlias(alias) 322 regexpExprHolder := regexp.MustCompile(`(\$\d+)|\?`) 323 324 return func(f string, args ...interface{}) SnippetExpr { 325 idx := 0 326 return SnippetExpr( 327 regexpExprHolder.ReplaceAllStringFunc( 328 f, 329 func(i string) string { 330 arg := args[idx] 331 idx++ 332 if s, ok := arg.(Snippet); ok { 333 return Stringify(s) 334 } 335 return Stringify(val(arg)) 336 }, 337 ), 338 ) 339 } 340 }