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  }