github.com/traefik/yaegi@v0.15.1/internal/cmd/genop/genop.go (about)

     1  package main
     2  
     3  import (
     4  	"bytes"
     5  	"go/format"
     6  	"log"
     7  	"os"
     8  	"strings"
     9  	"text/template"
    10  )
    11  
    12  const model = `package interp
    13  
    14  // Code generated by 'go run ../internal/cmd/genop/genop.go'. DO NOT EDIT.
    15  
    16  import (
    17  	"go/constant"
    18  	"go/token"
    19  	"reflect"
    20  )
    21  
    22  // Arithmetic operators
    23  {{range $name, $op := .Arithmetic}}
    24  func {{$name}}(n *node) {
    25  	next := getExec(n.tnext)
    26  	typ := n.typ.concrete().TypeOf()
    27  	isInterface := n.typ.TypeOf().Kind() == reflect.Interface
    28  	dest := genValueOutput(n, typ)
    29  	c0, c1 := n.child[0], n.child[1]
    30  
    31  	switch typ.Kind() {
    32  	{{- if $op.Str}}
    33  	case reflect.String:
    34  		switch {
    35  		case isInterface:
    36  			v0 := genValue(c0)
    37  			v1 := genValue(c1)
    38  			n.exec = func(f *frame) bltn {
    39  				dest(f).Set(reflect.ValueOf(v0(f).String() {{$op.Name}} v1(f).String()).Convert(typ))
    40  				return next
    41  			}
    42  		case c0.rval.IsValid():
    43  			s0 := vString(c0.rval)
    44  			v1 := genValue(c1)
    45  			n.exec = func(f *frame) bltn {
    46  				dest(f).SetString(s0 {{$op.Name}} v1(f).String())
    47  				return next
    48  			}
    49  		case c1.rval.IsValid():
    50  			v0 := genValue(c0)
    51  			s1 :=  vString(c1.rval)
    52  			n.exec = func(f *frame) bltn {
    53  				dest(f).SetString(v0(f).String() {{$op.Name}} s1)
    54  				return next
    55  			}
    56  		default:
    57  			v0 := genValue(c0)
    58  			v1 := genValue(c1)
    59  			n.exec = func(f *frame) bltn {
    60  				dest(f).SetString(v0(f).String() {{$op.Name}} v1(f).String())
    61  				return next
    62  			}
    63  		}
    64  	{{- end}}
    65  	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
    66  		switch {
    67  		case isInterface:
    68  			v0 := genValueInt(c0)
    69  			{{- if $op.Shift}}
    70  			v1 := genValueUint(c1)
    71  			{{else}}
    72  			v1 := genValueInt(c1)
    73  			{{end -}}
    74  			n.exec = func(f *frame) bltn {
    75  				_, i := v0(f)
    76  				_, j := v1(f)
    77  				dest(f).Set(reflect.ValueOf(i {{$op.Name}} j).Convert(typ))
    78  				return next
    79  			}
    80  		case c0.rval.IsValid():
    81  			i := vInt(c0.rval)
    82  			{{- if $op.Shift}}
    83  			v1 := genValueUint(c1)
    84  			{{else}}
    85  			v1 := genValueInt(c1)
    86  			{{end -}}
    87  			n.exec = func(f *frame) bltn {
    88  				_, j := v1(f)
    89  				dest(f).SetInt(i {{$op.Name}} j)
    90  				return next
    91  			}
    92  		case c1.rval.IsValid():
    93  			v0 := genValueInt(c0)
    94  			{{- if $op.Shift}}
    95  			j := vUint(c1.rval)
    96  			{{else}}
    97  			j := vInt(c1.rval)
    98  			{{end -}}
    99  			n.exec = func(f *frame) bltn {
   100  				_, i := v0(f)
   101  				dest(f).SetInt(i {{$op.Name}} j)
   102  				return next
   103  			}
   104  		default:
   105  			v0 := genValueInt(c0)
   106  			{{- if $op.Shift}}
   107  			v1 := genValueUint(c1)
   108  			{{else}}
   109  			v1 := genValueInt(c1)
   110  			{{end -}}
   111  			n.exec = func(f *frame) bltn {
   112  				_, i := v0(f)
   113  				_, j := v1(f)
   114  				dest(f).SetInt(i {{$op.Name}} j)
   115  				return next
   116  			}
   117  		}
   118  	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
   119  		switch {
   120  		case isInterface:
   121  			v0 := genValueUint(c0)
   122  			v1 := genValueUint(c1)
   123  			n.exec = func(f *frame) bltn {
   124  				_, i := v0(f)
   125  				_, j := v1(f)
   126  				dest(f).Set(reflect.ValueOf(i {{$op.Name}} j).Convert(typ))
   127  				return next
   128  			}
   129  		case c0.rval.IsValid():
   130  			i := vUint(c0.rval)
   131  			v1 := genValueUint(c1)
   132  			n.exec = func(f *frame) bltn {
   133  				_, j := v1(f)
   134  				dest(f).SetUint(i {{$op.Name}} j)
   135  				return next
   136  			}
   137  		case c1.rval.IsValid():
   138  			j := vUint(c1.rval)
   139  			v0 := genValueUint(c0)
   140  			n.exec = func(f *frame) bltn {
   141  				_, i := v0(f)
   142  				dest(f).SetUint(i {{$op.Name}} j)
   143  				return next
   144  			}
   145  		default:
   146  			v0 := genValueUint(c0)
   147  			v1 := genValueUint(c1)
   148  			n.exec = func(f *frame) bltn {
   149  				_, i := v0(f)
   150  				_, j := v1(f)
   151  				dest(f).SetUint(i {{$op.Name}} j)
   152  				return next
   153  			}
   154  		}
   155  	{{- if $op.Float}}
   156  	case reflect.Float32, reflect.Float64:
   157  		switch {
   158  		case isInterface:
   159  			v0 := genValueFloat(c0)
   160  			v1 := genValueFloat(c1)
   161  			n.exec = func(f *frame) bltn {
   162  				_, i := v0(f)
   163  				_, j := v1(f)
   164  				dest(f).Set(reflect.ValueOf(i {{$op.Name}} j).Convert(typ))
   165  				return next
   166  			}
   167  		case c0.rval.IsValid():
   168  			i := vFloat(c0.rval)
   169  			v1 := genValueFloat(c1)
   170  			n.exec = func(f *frame) bltn {
   171  				_, j := v1(f)
   172  				dest(f).SetFloat(i {{$op.Name}} j)
   173  				return next
   174  			}
   175  		case c1.rval.IsValid():
   176  			j := vFloat(c1.rval)
   177  			v0 := genValueFloat(c0)
   178  			n.exec = func(f *frame) bltn {
   179  				_, i := v0(f)
   180  				dest(f).SetFloat(i {{$op.Name}} j)
   181  				return next
   182  			}
   183  		default:
   184  			v0 := genValueFloat(c0)
   185  			v1 := genValueFloat(c1)
   186  			n.exec = func(f *frame) bltn {
   187  				_, i := v0(f)
   188  				_, j := v1(f)
   189  				dest(f).SetFloat(i {{$op.Name}} j)
   190  				return next
   191  			}
   192  		}
   193  	case reflect.Complex64, reflect.Complex128:
   194  		switch {
   195  		case isInterface:
   196  			v0 := genComplex(c0)
   197  			v1 := genComplex(c1)
   198  			n.exec = func(f *frame) bltn {
   199  				dest(f).Set(reflect.ValueOf(v0(f) {{$op.Name}} v1(f)).Convert(typ))
   200  				return next
   201  			}
   202  		case c0.rval.IsValid():
   203  			r0 := vComplex(c0.rval)
   204  			v1 := genComplex(c1)
   205  			n.exec = func(f *frame) bltn {
   206  				dest(f).SetComplex(r0 {{$op.Name}} v1(f))
   207  				return next
   208  			}
   209  		case c1.rval.IsValid():
   210  			r1 := vComplex(c1.rval)
   211  			v0 := genComplex(c0)
   212  			n.exec = func(f *frame) bltn {
   213  				dest(f).SetComplex(v0(f) {{$op.Name}} r1)
   214  				return next
   215  			}
   216  		default:
   217  			v0 := genComplex(c0)
   218  			v1 := genComplex(c1)
   219  			n.exec = func(f *frame) bltn {
   220  				dest(f).SetComplex(v0(f) {{$op.Name}} v1(f))
   221  				return next
   222  			}
   223  		}
   224  	{{- end}}
   225  	}
   226  }
   227  
   228  func {{$name}}Const(n *node) {
   229  	v0, v1 := n.child[0].rval, n.child[1].rval
   230  	{{- if $op.Shift}}
   231  	isConst := (v0.IsValid() && isConstantValue(v0.Type()))
   232  	{{- else}}
   233  	isConst := (v0.IsValid() && isConstantValue(v0.Type())) && (v1.IsValid() && isConstantValue(v1.Type()))
   234  	{{- end}}
   235  	t := n.typ.rtype
   236  	if isConst {
   237  		t = constVal
   238  	}
   239  	n.rval = reflect.New(t).Elem()
   240  	switch {
   241  	case isConst:
   242  		{{- if $op.Shift}}
   243  		v := constant.Shift(vConstantValue(v0), token.{{tokenFromName $name}}, uint(vUint(v1)))
   244  		n.rval.Set(reflect.ValueOf(v))
   245  		{{- else if (eq $op.Name "/")}}
   246  		var operator token.Token
   247  		// When the result of the operation is expected to be an int (because both
   248  		// operands are ints), we want to force the type of the whole expression to be an
   249  		// int (and not a float), which is achieved by using the QUO_ASSIGN operator.
   250  		if n.typ.untyped && isInt(n.typ.rtype) {
   251  			operator = token.QUO_ASSIGN
   252  		} else {
   253  			operator = token.QUO
   254  		}
   255  		v := constant.BinaryOp(vConstantValue(v0), operator, vConstantValue(v1))
   256  		n.rval.Set(reflect.ValueOf(v))
   257  		{{- else}}
   258  		{{- if $op.Int}}
   259  		v := constant.BinaryOp(constant.ToInt(vConstantValue(v0)), token.{{tokenFromName $name}}, constant.ToInt(vConstantValue(v1)))
   260  		{{- else}}
   261  		v := constant.BinaryOp(vConstantValue(v0), token.{{tokenFromName $name}}, vConstantValue(v1))
   262  		{{- end}}
   263  		n.rval.Set(reflect.ValueOf(v))
   264  		{{- end}}
   265  	{{- if $op.Str}}
   266  	case isString(t):
   267  		n.rval.SetString(vString(v0) {{$op.Name}} vString(v1))
   268  	{{- end}}
   269  	{{- if $op.Float}}
   270  	case isComplex(t):
   271  		n.rval.SetComplex(vComplex(v0) {{$op.Name}} vComplex(v1))
   272  	case isFloat(t):
   273  		n.rval.SetFloat(vFloat(v0) {{$op.Name}} vFloat(v1))
   274  	{{- end}}
   275  	case isUint(t):
   276  		n.rval.SetUint(vUint(v0) {{$op.Name}} vUint(v1))
   277  	case isInt(t):
   278  		{{- if $op.Shift}}
   279  		n.rval.SetInt(vInt(v0) {{$op.Name}} vUint(v1))
   280  		{{- else}}
   281  		n.rval.SetInt(vInt(v0) {{$op.Name}} vInt(v1))
   282  		{{- end}}
   283  	}
   284  }
   285  {{end}}
   286  // Assign operators
   287  {{range $name, $op := .Arithmetic}}
   288  func {{$name}}Assign(n *node) {
   289  	next := getExec(n.tnext)
   290  	typ := n.typ.TypeOf()
   291  	c0, c1 := n.child[0], n.child[1]
   292  	setMap := isMapEntry(c0)
   293  	var mapValue, indexValue func(*frame) reflect.Value
   294  
   295  	if setMap {
   296          mapValue = genValue(c0.child[0])
   297          indexValue = genValue(c0.child[1])
   298      }
   299  
   300  	if c1.rval.IsValid() {
   301  		switch typ.Kind() {
   302  		{{- if $op.Str}}
   303  		case reflect.String:
   304  			v0 := genValueString(c0)
   305  			v1 := vString(c1.rval)
   306  			n.exec = func(f *frame) bltn {
   307  				v, s := v0(f)
   308  				v.SetString(s {{$op.Name}} v1)
   309  				if setMap {
   310  					mapValue(f).SetMapIndex(indexValue(f), v)
   311  				}
   312  				return next
   313  			}
   314  		{{- end}}
   315  		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
   316  			v0 := genValueInt(c0)
   317  			{{- if $op.Shift}}
   318  			j := vUint(c1.rval)
   319  			{{else}}
   320  			j := vInt(c1.rval)
   321  			{{end -}}
   322  			n.exec = func(f *frame) bltn {
   323  				v, i := v0(f)
   324  				v.SetInt(i {{$op.Name}} j)
   325  				if setMap {
   326  					mapValue(f).SetMapIndex(indexValue(f), v)
   327  				}
   328  				return next
   329  			}
   330  		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
   331  			v0 := genValueUint(c0)
   332  			j := vUint(c1.rval)
   333  			n.exec = func(f *frame) bltn {
   334  				v, i := v0(f)
   335  				v.SetUint(i {{$op.Name}} j)
   336  				if setMap {
   337  					mapValue(f).SetMapIndex(indexValue(f), v)
   338  				}
   339  				return next
   340  			}
   341  		{{- if $op.Float}}
   342  		case reflect.Float32, reflect.Float64:
   343  			v0 := genValueFloat(c0)
   344  			j := vFloat(c1.rval)
   345  			n.exec = func(f *frame) bltn {
   346  				v, i := v0(f)
   347  				v.SetFloat(i {{$op.Name}} j)
   348  				if setMap {
   349  					mapValue(f).SetMapIndex(indexValue(f), v)
   350  				}
   351  				return next
   352  			}
   353  		case reflect.Complex64, reflect.Complex128:
   354  			v0 := genValue(c0)
   355  			v1 := vComplex(c1.rval)
   356  			n.exec = func(f *frame) bltn {
   357  				v := v0(f)
   358  				v.SetComplex(v.Complex() {{$op.Name}} v1)
   359  				if setMap {
   360  					mapValue(f).SetMapIndex(indexValue(f), v)
   361  				}
   362  				return next
   363  			}
   364  		{{- end}}
   365  		}
   366  	} else {
   367  		switch typ.Kind() {
   368  		{{- if $op.Str}}
   369  		case reflect.String:
   370  			v0 := genValueString(c0)
   371  			v1 := genValue(c1)
   372  			n.exec = func(f *frame) bltn {
   373  				v, s := v0(f)
   374  				v.SetString(s {{$op.Name}} v1(f).String())
   375  				if setMap {
   376  					mapValue(f).SetMapIndex(indexValue(f), v)
   377  				}
   378  				return next
   379  			}
   380  		{{- end}}
   381  		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
   382  			v0 := genValueInt(c0)
   383  			{{- if $op.Shift}}
   384  			v1 := genValueUint(c1)
   385  			{{else}}
   386  			v1 := genValueInt(c1)
   387  			{{end -}}
   388  			n.exec = func(f *frame) bltn {
   389  				v, i := v0(f)
   390  				_, j := v1(f)
   391  				v.SetInt(i {{$op.Name}} j)
   392  				if setMap {
   393  					mapValue(f).SetMapIndex(indexValue(f), v)
   394  				}
   395  				return next
   396  			}
   397  		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
   398  			v0 := genValueUint(c0)
   399  			v1 := genValueUint(c1)
   400  			n.exec = func(f *frame) bltn {
   401  				v, i := v0(f)
   402  				_, j := v1(f)
   403  				v.SetUint(i {{$op.Name}} j)
   404  				if setMap {
   405  					mapValue(f).SetMapIndex(indexValue(f), v)
   406  				}
   407  				return next
   408  			}
   409  		{{- if $op.Float}}
   410  		case reflect.Float32, reflect.Float64:
   411  			v0 := genValueFloat(c0)
   412  			v1 := genValueFloat(c1)
   413  			n.exec = func(f *frame) bltn {
   414  				v, i := v0(f)
   415  				_, j := v1(f)
   416  				v.SetFloat(i {{$op.Name}} j)
   417  				if setMap {
   418  					mapValue(f).SetMapIndex(indexValue(f), v)
   419  				}
   420  				return next
   421  			}
   422  		case reflect.Complex64, reflect.Complex128:
   423  			v0 := genValue(c0)
   424  			v1 := genValue(c1)
   425  			n.exec = func(f *frame) bltn {
   426  				v := v0(f)
   427  				v.SetComplex(v.Complex() {{$op.Name}} v1(f).Complex())
   428  				if setMap {
   429  					mapValue(f).SetMapIndex(indexValue(f), v)
   430  				}
   431  				return next
   432  			}
   433  		{{- end}}
   434  		}
   435  	}
   436  }
   437  {{end}}
   438  {{range $name, $op := .IncDec}}
   439  func {{$name}}(n *node) {
   440  	next := getExec(n.tnext)
   441  	typ := n.typ.TypeOf()
   442  	c0 := n.child[0]
   443  	setMap := isMapEntry(c0)
   444  	var mapValue, indexValue func(*frame) reflect.Value
   445  
   446  	if setMap {
   447          mapValue = genValue(c0.child[0])
   448          indexValue = genValue(c0.child[1])
   449      }
   450  
   451  	switch typ.Kind() {
   452  	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
   453  		v0 := genValueInt(c0)
   454  		n.exec = func(f *frame) bltn {
   455  			v, i := v0(f)
   456  			v.SetInt(i {{$op.Name}} 1)
   457  			if setMap {
   458                  mapValue(f).SetMapIndex(indexValue(f), v)
   459              }
   460  			return next
   461  		}
   462  	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
   463  		v0 := genValueUint(c0)
   464  		n.exec = func(f *frame) bltn {
   465  			v, i := v0(f)
   466  			v.SetUint(i {{$op.Name}} 1)
   467  			if setMap {
   468                  mapValue(f).SetMapIndex(indexValue(f), v)
   469              }
   470  			return next
   471  		}
   472  	case reflect.Float32, reflect.Float64:
   473  		v0 := genValueFloat(c0)
   474  		n.exec = func(f *frame) bltn {
   475  			v, i := v0(f)
   476  			v.SetFloat(i {{$op.Name}} 1)
   477  			if setMap {
   478                  mapValue(f).SetMapIndex(indexValue(f), v)
   479              }
   480  			return next
   481  		}
   482  	case reflect.Complex64, reflect.Complex128:
   483  		v0 := genValue(c0)
   484  		n.exec = func(f *frame) bltn {
   485  			v := v0(f)
   486  			v.SetComplex(v.Complex() {{$op.Name}} 1)
   487  			if setMap {
   488                  mapValue(f).SetMapIndex(indexValue(f), v)
   489              }
   490  			return next
   491  		}
   492  	}
   493  }
   494  {{end}}
   495  {{range $name, $op := .Unary}}
   496  func {{$name}}Const(n *node) {
   497  	v0 := n.child[0].rval
   498  	isConst := v0.IsValid() && isConstantValue(v0.Type())
   499  	t := n.typ.rtype
   500  	if isConst {
   501  		t = constVal
   502  	}
   503  	n.rval = reflect.New(t).Elem()
   504  
   505  	{{- if $op.Bool}}
   506  	if isConst {
   507  		v := constant.UnaryOp(token.{{tokenFromName $name}}, vConstantValue(v0), 0)
   508  		n.rval.Set(reflect.ValueOf(v))
   509  	} else {
   510  		n.rval.SetBool({{$op.Name}} v0.Bool())
   511  	}
   512  	{{- else}}
   513  	switch {
   514  	case isConst:
   515  		v := constant.UnaryOp(token.{{tokenFromName $name}}, vConstantValue(v0), 0)
   516  		n.rval.Set(reflect.ValueOf(v))
   517  	case isUint(t):
   518  		n.rval.SetUint({{$op.Name}} v0.Uint())
   519  	case isInt(t):
   520  		n.rval.SetInt({{$op.Name}} v0.Int())
   521  	{{- if $op.Float}}
   522  	case isFloat(t):
   523  		n.rval.SetFloat({{$op.Name}} v0.Float())
   524  	case isComplex(t):
   525  		n.rval.SetComplex({{$op.Name}} v0.Complex())
   526  	{{- end}}
   527  	}
   528  	{{- end}}
   529  }
   530  {{end}}
   531  {{range $name, $op := .Comparison}}
   532  func {{$name}}(n *node) {
   533  	tnext := getExec(n.tnext)
   534  	dest := genValueOutput(n, reflect.TypeOf(true))
   535  	typ := n.typ.concrete().TypeOf()
   536  	isInterface := n.typ.TypeOf().Kind() == reflect.Interface
   537  	c0, c1 := n.child[0], n.child[1]
   538  	t0, t1 := c0.typ.TypeOf(), c1.typ.TypeOf()
   539  
   540  	{{- if or (eq $op.Name "==") (eq $op.Name "!=") }}
   541  
   542  	if c0.typ.cat == linkedT || c1.typ.cat == linkedT {
   543  		switch {
   544  		case isInterface:
   545  			v0 := genValue(c0)
   546  			v1 := genValue(c1)
   547  			dest := genValue(n)
   548  			n.exec = func(f *frame) bltn {
   549  				i0 := v0(f).Interface()
   550  				i1 := v1(f).Interface()
   551  				dest(f).Set(reflect.ValueOf(i0 {{$op.Name}} i1).Convert(typ))
   552  				return tnext
   553  			}
   554  		case c0.rval.IsValid():
   555  			i0 := c0.rval.Interface()
   556  			v1 := genValue(c1)
   557  			if n.fnext != nil {
   558  				fnext := getExec(n.fnext)
   559  				n.exec = func(f *frame) bltn {
   560  					i1 := v1(f).Interface()
   561  					if i0 {{$op.Name}} i1 {
   562  						dest(f).SetBool(true)
   563  						return tnext
   564  					}
   565  					dest(f).SetBool(false)
   566  					return fnext
   567  				}
   568  			} else {
   569  				dest := genValue(n)
   570  				n.exec = func(f *frame) bltn {
   571  					i1 := v1(f).Interface()
   572  					dest(f).SetBool(i0 {{$op.Name}} i1)
   573  					return tnext
   574  				}
   575  			}
   576  		case c1.rval.IsValid():
   577  			i1 := c1.rval.Interface()
   578  			v0 := genValue(c0)
   579  			if n.fnext != nil {
   580  				fnext := getExec(n.fnext)
   581  				n.exec = func(f *frame) bltn {
   582  					i0 := v0(f).Interface()
   583  					if i0 {{$op.Name}} i1 {
   584  						dest(f).SetBool(true)
   585  						return tnext
   586  					}
   587  					dest(f).SetBool(false)
   588  					return fnext
   589  				}
   590  			} else {
   591  				dest := genValue(n)
   592  				n.exec = func(f *frame) bltn {
   593  					i0 := v0(f).Interface()
   594  					dest(f).SetBool(i0 {{$op.Name}} i1)
   595  					return tnext
   596  				}
   597  			}
   598  		default:
   599  			v0 := genValue(c0)
   600  			v1 := genValue(c1)
   601  			if n.fnext != nil {
   602  				fnext := getExec(n.fnext)
   603  				n.exec = func(f *frame) bltn {
   604  					i0 := v0(f).Interface()
   605  					i1 := v1(f).Interface()
   606  					if i0 {{$op.Name}} i1 {
   607  						dest(f).SetBool(true)
   608  						return tnext
   609  					}
   610  					dest(f).SetBool(false)
   611  					return fnext
   612  				}
   613  			} else {
   614  				dest := genValue(n)
   615  				n.exec = func(f *frame) bltn {
   616  					i0 := v0(f).Interface()
   617  					i1 := v1(f).Interface()
   618  					dest(f).SetBool(i0 {{$op.Name}} i1)
   619  					return tnext
   620  				}
   621  			}
   622  		}
   623  		return
   624  	}
   625  
   626  	// Do not attempt to optimize '==' or '!=' if an operand is an interface.
   627  	// This will preserve proper dynamic type checking at runtime. For static types,
   628  	// type checks are already performed, so bypass them if possible.
   629  	if t0.Kind() == reflect.Interface || t1.Kind() == reflect.Interface {
   630  		v0 := genValue(c0)
   631  		v1 := genValue(c1)
   632  		if n.fnext != nil {
   633  			fnext := getExec(n.fnext)
   634  			n.exec = func(f *frame) bltn {
   635  				i0 := v0(f).Interface()
   636  				i1 := v1(f).Interface()
   637  				if i0 {{$op.Name}} i1 {
   638  					dest(f).SetBool(true)
   639  					return tnext
   640  				}
   641  				dest(f).SetBool(false)
   642  				return fnext
   643  			}
   644  		} else {
   645  			dest := genValue(n)
   646  			n.exec = func(f *frame) bltn {
   647  				i0 := v0(f).Interface()
   648  				i1 := v1(f).Interface()
   649  				dest(f).SetBool(i0 {{$op.Name}} i1)
   650  				return tnext
   651  			}
   652  		}
   653  		return
   654  	}
   655  	{{- end}}
   656  
   657  	switch {
   658  	case isString(t0) || isString(t1):
   659  		switch {
   660  		case isInterface:
   661  			v0 := genValueString(c0)
   662  			v1 := genValueString(c1)
   663  			n.exec = func(f *frame) bltn {
   664  				_, s0 := v0(f)
   665  				_, s1 := v1(f)
   666  				dest(f).Set(reflect.ValueOf(s0 {{$op.Name}} s1).Convert(typ))
   667  				return tnext
   668  			}
   669  		case c0.rval.IsValid():
   670  			s0 :=  vString(c0.rval)
   671  			v1 := genValueString(c1)
   672  			if n.fnext != nil {
   673  				fnext := getExec(n.fnext)
   674  				n.exec = func(f *frame) bltn {
   675  					_, s1 := v1(f)
   676  					if s0 {{$op.Name}} s1 {
   677  						dest(f).SetBool(true)
   678  						return tnext
   679  					}
   680  					dest(f).SetBool(false)
   681  					return fnext
   682  				}
   683  			} else {
   684  				n.exec = func(f *frame) bltn {
   685  					_, s1 := v1(f)
   686  					dest(f).SetBool(s0 {{$op.Name}} s1)
   687  					return tnext
   688  				}
   689  			}
   690  		case c1.rval.IsValid():
   691  			s1 :=  vString(c1.rval)
   692  			v0 := genValueString(c0)
   693  			if n.fnext != nil {
   694  				fnext := getExec(n.fnext)
   695  				n.exec = func(f *frame) bltn {
   696  					_, s0 := v0(f)
   697  					if s0 {{$op.Name}} s1 {
   698  						dest(f).SetBool(true)
   699  						return tnext
   700  					}
   701  					dest(f).SetBool(false)
   702  					return fnext
   703  				}
   704  			} else {
   705  				n.exec = func(f *frame) bltn {
   706  					_, s0 := v0(f)
   707  					dest(f).SetBool(s0 {{$op.Name}} s1)
   708  					return tnext
   709  				}
   710  			}
   711  		default:
   712  			v0 := genValueString(c0)
   713  			v1 := genValueString(c1)
   714  			if n.fnext != nil {
   715  				fnext := getExec(n.fnext)
   716  				n.exec = func(f *frame) bltn {
   717  					_, s0 := v0(f)
   718  					_, s1 := v1(f)
   719  					if s0 {{$op.Name}} s1 {
   720  						dest(f).SetBool(true)
   721  						return tnext
   722  					}
   723  					dest(f).SetBool(false)
   724  					return fnext
   725  				}
   726  			} else {
   727  				n.exec = func(f *frame) bltn {
   728  					_, s0 := v0(f)
   729  					_, s1 := v1(f)
   730  					dest(f).SetBool(s0 {{$op.Name}} s1)
   731  					return tnext
   732  				}
   733  			}
   734  		}
   735  	case isFloat(t0) || isFloat(t1):
   736  		switch {
   737  		case isInterface:
   738  			v0 := genValueFloat(c0)
   739  			v1 := genValueFloat(c1)
   740  			n.exec = func(f *frame) bltn {
   741  				_, s0 := v0(f)
   742  				_, s1 := v1(f)
   743  				dest(f).Set(reflect.ValueOf(s0 {{$op.Name}} s1).Convert(typ))
   744  				return tnext
   745  			}
   746  		case c0.rval.IsValid():
   747  			s0 := vFloat(c0.rval)
   748  			v1 := genValueFloat(c1)
   749  			if n.fnext != nil {
   750  				fnext := getExec(n.fnext)
   751  				n.exec = func(f *frame) bltn {
   752  					_, s1 := v1(f)
   753  					if s0 {{$op.Name}} s1 {
   754  						dest(f).SetBool(true)
   755  						return tnext
   756  					}
   757  					dest(f).SetBool(false)
   758  					return fnext
   759  				}
   760  			} else {
   761  				n.exec = func(f *frame) bltn {
   762  					_, s1 := v1(f)
   763  					dest(f).SetBool(s0 {{$op.Name}} s1)
   764  					return tnext
   765  				}
   766  			}
   767  		case c1.rval.IsValid():
   768  			s1 := vFloat(c1.rval)
   769  			v0 := genValueFloat(c0)
   770  			if n.fnext != nil {
   771  				fnext := getExec(n.fnext)
   772  				n.exec = func(f *frame) bltn {
   773  					_, s0 := v0(f)
   774  					if s0 {{$op.Name}} s1 {
   775  						dest(f).SetBool(true)
   776  						return tnext
   777  					}
   778  					dest(f).SetBool(false)
   779  					return fnext
   780  				}
   781  			} else {
   782  				dest := genValue(n)
   783  				n.exec = func(f *frame) bltn {
   784  					_, s0 := v0(f)
   785  					dest(f).SetBool(s0 {{$op.Name}} s1)
   786  					return tnext
   787  				}
   788  			}
   789  		default:
   790  			v0 := genValueFloat(c0)
   791  			v1 := genValueFloat(c1)
   792  			if n.fnext != nil {
   793  				fnext := getExec(n.fnext)
   794  				n.exec = func(f *frame) bltn {
   795  					_, s0 := v0(f)
   796  					_, s1 := v1(f)
   797  					if s0 {{$op.Name}} s1 {
   798  						dest(f).SetBool(true)
   799  						return tnext
   800  					}
   801  					dest(f).SetBool(false)
   802  					return fnext
   803  				}
   804  			} else {
   805  				dest := genValue(n)
   806  				n.exec = func(f *frame) bltn {
   807  					_, s0 := v0(f)
   808  					_, s1 := v1(f)
   809  					dest(f).SetBool(s0 {{$op.Name}} s1)
   810  					return tnext
   811  				}
   812  			}
   813  		}
   814  	case isUint(t0) || isUint(t1):
   815  		switch {
   816  		case isInterface:
   817  			v0 := genValueUint(c0)
   818  			v1 := genValueUint(c1)
   819  			n.exec = func(f *frame) bltn {
   820  				_, s0 := v0(f)
   821  				_, s1 := v1(f)
   822  				dest(f).Set(reflect.ValueOf(s0 {{$op.Name}} s1).Convert(typ))
   823  				return tnext
   824  			}
   825  		case c0.rval.IsValid():
   826  			s0 := vUint(c0.rval)
   827  			v1 := genValueUint(c1)
   828  			if n.fnext != nil {
   829  				fnext := getExec(n.fnext)
   830  				n.exec = func(f *frame) bltn {
   831  					_, s1 := v1(f)
   832  					if s0 {{$op.Name}} s1 {
   833  						dest(f).SetBool(true)
   834  						return tnext
   835  					}
   836  					dest(f).SetBool(false)
   837  					return fnext
   838  				}
   839  			} else {
   840  				dest := genValue(n)
   841  				n.exec = func(f *frame) bltn {
   842  					_, s1 := v1(f)
   843  					dest(f).SetBool(s0 {{$op.Name}} s1)
   844  					return tnext
   845  				}
   846  			}
   847  		case c1.rval.IsValid():
   848  			s1 := vUint(c1.rval)
   849  			v0 := genValueUint(c0)
   850  			if n.fnext != nil {
   851  				fnext := getExec(n.fnext)
   852  				n.exec = func(f *frame) bltn {
   853  					_, s0 := v0(f)
   854  					if s0 {{$op.Name}} s1 {
   855  						dest(f).SetBool(true)
   856  						return tnext
   857  					}
   858  					dest(f).SetBool(false)
   859  					return fnext
   860  				}
   861  			} else {
   862  				dest := genValue(n)
   863  				n.exec = func(f *frame) bltn {
   864  					_, s0 := v0(f)
   865  					dest(f).SetBool(s0 {{$op.Name}} s1)
   866  					return tnext
   867  				}
   868  			}
   869  		default:
   870  			v0 := genValueUint(c0)
   871  			v1 := genValueUint(c1)
   872  			if n.fnext != nil {
   873  				fnext := getExec(n.fnext)
   874  				n.exec = func(f *frame) bltn {
   875  					_, s0 := v0(f)
   876  					_, s1 := v1(f)
   877  					if s0 {{$op.Name}} s1 {
   878  						dest(f).SetBool(true)
   879  						return tnext
   880  					}
   881  					dest(f).SetBool(false)
   882  					return fnext
   883  				}
   884  			} else {
   885  				dest := genValue(n)
   886  				n.exec = func(f *frame) bltn {
   887  					_, s0 := v0(f)
   888  					_, s1 := v1(f)
   889  					dest(f).SetBool(s0 {{$op.Name}} s1)
   890  					return tnext
   891  				}
   892  			}
   893  		}
   894  	case isInt(t0) || isInt(t1):
   895  		switch {
   896  		case isInterface:
   897  			v0 := genValueInt(c0)
   898  			v1 := genValueInt(c1)
   899  			n.exec = func(f *frame) bltn {
   900  				_, s0 := v0(f)
   901  				_, s1 := v1(f)
   902  				dest(f).Set(reflect.ValueOf(s0 {{$op.Name}} s1).Convert(typ))
   903  				return tnext
   904  			}
   905  		case c0.rval.IsValid():
   906  			s0 := vInt(c0.rval)
   907  			v1 := genValueInt(c1)
   908  			if n.fnext != nil {
   909  				fnext := getExec(n.fnext)
   910  				n.exec = func(f *frame) bltn {
   911  					_, s1 := v1(f)
   912  					if s0 {{$op.Name}} s1 {
   913  						dest(f).SetBool(true)
   914  						return tnext
   915  					}
   916  					dest(f).SetBool(false)
   917  					return fnext
   918  				}
   919  			} else {
   920  				dest := genValue(n)
   921  				n.exec = func(f *frame) bltn {
   922  					_, s1 := v1(f)
   923  					dest(f).SetBool(s0 {{$op.Name}} s1)
   924  					return tnext
   925  				}
   926  			}
   927  		case c1.rval.IsValid():
   928  			s1 := vInt(c1.rval)
   929  			v0 := genValueInt(c0)
   930  			if n.fnext != nil {
   931  				fnext := getExec(n.fnext)
   932  				n.exec = func(f *frame) bltn {
   933  					_, s0 := v0(f)
   934  					if s0 {{$op.Name}} s1 {
   935  						dest(f).SetBool(true)
   936  						return tnext
   937  					}
   938  					dest(f).SetBool(false)
   939  					return fnext
   940  				}
   941  			} else {
   942  				dest := genValue(n)
   943  				n.exec = func(f *frame) bltn {
   944  					_, s0 := v0(f)
   945  					dest(f).SetBool(s0 {{$op.Name}} s1)
   946  					return tnext
   947  				}
   948  			}
   949  		default:
   950  			v0 := genValueInt(c0)
   951  			v1 := genValueInt(c1)
   952  			if n.fnext != nil {
   953  				fnext := getExec(n.fnext)
   954  				n.exec = func(f *frame) bltn {
   955  					_, s0 := v0(f)
   956  					_, s1 := v1(f)
   957  					if s0 {{$op.Name}} s1 {
   958  						dest(f).SetBool(true)
   959  						return tnext
   960  					}
   961  					dest(f).SetBool(false)
   962  					return fnext
   963  				}
   964  			} else {
   965  				dest := genValue(n)
   966  				n.exec = func(f *frame) bltn {
   967  					_, s0 := v0(f)
   968  					_, s1 := v1(f)
   969  					dest(f).SetBool(s0 {{$op.Name}} s1)
   970  					return tnext
   971  				}
   972  			}
   973  		}
   974  	{{- if $op.Complex}}
   975  	case isComplex(t0) || isComplex(t1):
   976  		switch {
   977  		case isInterface:
   978  			v0 := genComplex(c0)
   979  			v1 := genComplex(c1)
   980  			n.exec = func(f *frame) bltn {
   981  				s0 := v0(f)
   982  				s1 := v1(f)
   983  				dest(f).Set(reflect.ValueOf(s0 {{$op.Name}} s1).Convert(typ))
   984  				return tnext
   985  			}
   986  		case c0.rval.IsValid():
   987  			s0 := vComplex(c0.rval)
   988  			v1 := genComplex(c1)
   989  			if n.fnext != nil {
   990  				fnext := getExec(n.fnext)
   991  				n.exec = func(f *frame) bltn {
   992  					s1 := v1(f)
   993  					if s0 {{$op.Name}} s1 {
   994  						dest(f).SetBool(true)
   995  						return tnext
   996  					}
   997  					dest(f).SetBool(false)
   998  					return fnext
   999  				}
  1000  			} else {
  1001  				n.exec = func(f *frame) bltn {
  1002  					s1 := v1(f)
  1003  					dest(f).SetBool(s0 {{$op.Name}} s1)
  1004  					return tnext
  1005  				}
  1006  			}
  1007  		case c1.rval.IsValid():
  1008  			s1 := vComplex(c1.rval)
  1009  			v0 := genComplex(c0)
  1010  			if n.fnext != nil {
  1011  				fnext := getExec(n.fnext)
  1012  				n.exec = func(f *frame) bltn {
  1013  					s0 := v0(f)
  1014  					if s0 {{$op.Name}} s1 {
  1015  						dest(f).SetBool(true)
  1016  						return tnext
  1017  					}
  1018  					dest(f).SetBool(false)
  1019  					return fnext
  1020  				}
  1021  			} else {
  1022  				dest := genValue(n)
  1023  				n.exec = func(f *frame) bltn {
  1024  					s0 := v0(f)
  1025  					dest(f).SetBool(s0 {{$op.Name}} s1)
  1026  					return tnext
  1027  				}
  1028  			}
  1029  		default:
  1030  			v0 := genComplex(c0)
  1031  			v1 := genComplex(c1)
  1032  			if n.fnext != nil {
  1033  				fnext := getExec(n.fnext)
  1034  				n.exec = func(f *frame) bltn {
  1035  					s0 := v0(f)
  1036  					s1 := v1(f)
  1037  					if s0 {{$op.Name}} s1 {
  1038  						dest(f).SetBool(true)
  1039  						return tnext
  1040  					}
  1041  					dest(f).SetBool(false)
  1042  					return fnext
  1043  				}
  1044  			} else {
  1045  				n.exec = func(f *frame) bltn {
  1046  					s0 := v0(f)
  1047  					s1 := v1(f)
  1048  					dest(f).SetBool(s0 {{$op.Name}} s1)
  1049  					return tnext
  1050  				}
  1051  			}
  1052  		}
  1053  	default:
  1054  		switch {
  1055  		case isInterface:
  1056  			v0 := genValue(c0)
  1057  			v1 := genValue(c1)
  1058  			n.exec = func(f *frame) bltn {
  1059  				i0 := v0(f).Interface()
  1060  				i1 := v1(f).Interface()
  1061  				dest(f).Set(reflect.ValueOf(i0 {{$op.Name}} i1).Convert(typ))
  1062  				return tnext
  1063  			}
  1064  		case c0.rval.IsValid():
  1065  			i0 := c0.rval.Interface()
  1066  			v1 := genValue(c1)
  1067  			if n.fnext != nil {
  1068  				fnext := getExec(n.fnext)
  1069  				n.exec = func(f *frame) bltn {
  1070  					i1 := v1(f).Interface()
  1071  					if i0 {{$op.Name}} i1 {
  1072  						dest(f).SetBool(true)
  1073  						return tnext
  1074  					}
  1075  					dest(f).SetBool(false)
  1076  					return fnext
  1077  				}
  1078  			} else {
  1079  				dest := genValue(n)
  1080  				n.exec = func(f *frame) bltn {
  1081  					i1 := v1(f).Interface()
  1082  					dest(f).SetBool(i0 {{$op.Name}} i1)
  1083  					return tnext
  1084  				}
  1085  			}
  1086  		case c1.rval.IsValid():
  1087  			i1 := c1.rval.Interface()
  1088  			v0 := genValue(c0)
  1089  			if n.fnext != nil {
  1090  				fnext := getExec(n.fnext)
  1091  				n.exec = func(f *frame) bltn {
  1092  					i0 := v0(f).Interface()
  1093  					if i0 {{$op.Name}} i1 {
  1094  						dest(f).SetBool(true)
  1095  						return tnext
  1096  					}
  1097  					dest(f).SetBool(false)
  1098  					return fnext
  1099  				}
  1100  			} else {
  1101  				dest := genValue(n)
  1102  				n.exec = func(f *frame) bltn {
  1103  					i0 := v0(f).Interface()
  1104  					dest(f).SetBool(i0 {{$op.Name}} i1)
  1105  					return tnext
  1106  				}
  1107  			}
  1108  		default:
  1109  			v0 := genValue(c0)
  1110  			v1 := genValue(c1)
  1111  			if n.fnext != nil {
  1112  				fnext := getExec(n.fnext)
  1113  				n.exec = func(f *frame) bltn {
  1114  					i0 := v0(f).Interface()
  1115  					i1 := v1(f).Interface()
  1116  					if i0 {{$op.Name}} i1 {
  1117  						dest(f).SetBool(true)
  1118  						return tnext
  1119  					}
  1120  					dest(f).SetBool(false)
  1121  					return fnext
  1122  				}
  1123  			} else {
  1124  				dest := genValue(n)
  1125  				n.exec = func(f *frame) bltn {
  1126  					i0 := v0(f).Interface()
  1127  					i1 := v1(f).Interface()
  1128  					dest(f).SetBool(i0 {{$op.Name}} i1)
  1129  					return tnext
  1130  				}
  1131  			}
  1132  		}
  1133  	{{- end}}
  1134  	}
  1135  }
  1136  {{end}}
  1137  `
  1138  
  1139  // Op define operator name and properties.
  1140  type Op struct {
  1141  	Name    string // +, -, ...
  1142  	Str     bool   // true if operator applies to string
  1143  	Float   bool   // true if operator applies to float
  1144  	Complex bool   // true if operator applies to complex
  1145  	Shift   bool   // true if operator is a shift operation
  1146  	Bool    bool   // true if operator applies to bool
  1147  	Int     bool   // true if operator applies to int only
  1148  }
  1149  
  1150  func main() {
  1151  	base := template.New("genop")
  1152  	base.Funcs(template.FuncMap{
  1153  		"tokenFromName": func(name string) string {
  1154  			switch name {
  1155  			case "andNot":
  1156  				return "AND_NOT"
  1157  			case "neg":
  1158  				return "SUB"
  1159  			case "pos":
  1160  				return "ADD"
  1161  			case "bitNot":
  1162  				return "XOR"
  1163  			default:
  1164  				return strings.ToUpper(name)
  1165  			}
  1166  		},
  1167  	})
  1168  	parse, err := base.Parse(model)
  1169  	if err != nil {
  1170  		log.Fatal(err)
  1171  	}
  1172  
  1173  	b := &bytes.Buffer{}
  1174  	data := map[string]interface{}{
  1175  		"Arithmetic": map[string]Op{
  1176  			"add":    {"+", true, true, true, false, false, false},
  1177  			"sub":    {"-", false, true, true, false, false, false},
  1178  			"mul":    {"*", false, true, true, false, false, false},
  1179  			"quo":    {"/", false, true, true, false, false, false},
  1180  			"rem":    {"%", false, false, false, false, false, true},
  1181  			"shl":    {"<<", false, false, false, true, false, true},
  1182  			"shr":    {">>", false, false, false, true, false, true},
  1183  			"and":    {"&", false, false, false, false, false, true},
  1184  			"or":     {"|", false, false, false, false, false, true},
  1185  			"xor":    {"^", false, false, false, false, false, true},
  1186  			"andNot": {"&^", false, false, false, false, false, true},
  1187  		},
  1188  		"IncDec": map[string]Op{
  1189  			"inc": {Name: "+"},
  1190  			"dec": {Name: "-"},
  1191  		},
  1192  		"Comparison": map[string]Op{
  1193  			"equal":        {Name: "==", Complex: true},
  1194  			"greater":      {Name: ">", Complex: false},
  1195  			"greaterEqual": {Name: ">=", Complex: false},
  1196  			"lower":        {Name: "<", Complex: false},
  1197  			"lowerEqual":   {Name: "<=", Complex: false},
  1198  			"notEqual":     {Name: "!=", Complex: true},
  1199  		},
  1200  		"Unary": map[string]Op{
  1201  			"not":    {Name: "!", Float: false, Bool: true},
  1202  			"neg":    {Name: "-", Float: true, Bool: false},
  1203  			"pos":    {Name: "+", Float: true, Bool: false},
  1204  			"bitNot": {Name: "^", Float: false, Bool: false, Int: true},
  1205  		},
  1206  	}
  1207  	if err = parse.Execute(b, data); err != nil {
  1208  		log.Fatal(err)
  1209  	}
  1210  
  1211  	// gofmt
  1212  	source, err := format.Source(b.Bytes())
  1213  	if err != nil {
  1214  		log.Fatal(err)
  1215  	}
  1216  
  1217  	if err = os.WriteFile("op.go", source, 0o666); err != nil {
  1218  		log.Fatal(err)
  1219  	}
  1220  }