mirror of
https://github.com/hanzoai/expr.git
synced 2026-09-24 16:58:58 +00:00
Refactor generate
This commit is contained in:
+210
-169
@@ -1,189 +1,230 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"go/format"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
func check(e error) {
|
||||
if e != nil {
|
||||
panic(e)
|
||||
func main() {
|
||||
var b bytes.Buffer
|
||||
err := template.Must(
|
||||
template.New("helpers").
|
||||
Funcs(template.FuncMap{
|
||||
"cases": func(op string) string { return cases(op, false) },
|
||||
"cases_int_only": func(op string) string { return cases(op, true) },
|
||||
}).
|
||||
Parse(helpers),
|
||||
).Execute(&b, types)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
formatted, err := format.Source(b.Bytes())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Print(string(formatted))
|
||||
}
|
||||
|
||||
func main() {
|
||||
var data string
|
||||
var types = []string{
|
||||
"uint",
|
||||
"uint8",
|
||||
"uint16",
|
||||
"uint32",
|
||||
"uint64",
|
||||
"int",
|
||||
"int8",
|
||||
"int16",
|
||||
"int32",
|
||||
"int64",
|
||||
"float32",
|
||||
"float64",
|
||||
}
|
||||
|
||||
func cases(op string, noFloat bool) string {
|
||||
var out string
|
||||
echo := func(s string, xs ...interface{}) {
|
||||
data += fmt.Sprintf(s, xs...) + "\n"
|
||||
out += fmt.Sprintf(s, xs...) + "\n"
|
||||
}
|
||||
|
||||
echo(`// Code generated by vm/runtime/generate/main.go. DO NOT EDIT.`)
|
||||
echo(``)
|
||||
echo(`package runtime`)
|
||||
echo(`import (`)
|
||||
echo(`"fmt"`)
|
||||
echo(`"reflect"`)
|
||||
echo(`"time"`)
|
||||
echo(`)`)
|
||||
|
||||
types := []string{
|
||||
"uint",
|
||||
"uint8",
|
||||
"uint16",
|
||||
"uint32",
|
||||
"uint64",
|
||||
"int",
|
||||
"int8",
|
||||
"int16",
|
||||
"int32",
|
||||
"int64",
|
||||
"float32",
|
||||
"float64",
|
||||
}
|
||||
|
||||
helpers := []struct {
|
||||
name, op string
|
||||
noFloat, string bool
|
||||
}{
|
||||
{
|
||||
name: "Equal",
|
||||
op: "==",
|
||||
string: true,
|
||||
},
|
||||
{
|
||||
name: "Less",
|
||||
op: "<",
|
||||
string: true,
|
||||
},
|
||||
{
|
||||
name: "More",
|
||||
op: ">",
|
||||
string: true,
|
||||
},
|
||||
{
|
||||
name: "LessOrEqual",
|
||||
op: "<=",
|
||||
string: true,
|
||||
},
|
||||
{
|
||||
name: "MoreOrEqual",
|
||||
op: ">=",
|
||||
string: true,
|
||||
},
|
||||
{
|
||||
name: "Add",
|
||||
op: "+",
|
||||
string: true,
|
||||
},
|
||||
{
|
||||
name: "Subtract",
|
||||
op: "-",
|
||||
},
|
||||
{
|
||||
name: "Multiply",
|
||||
op: "*",
|
||||
},
|
||||
{
|
||||
name: "Divide",
|
||||
op: "/",
|
||||
},
|
||||
{
|
||||
name: "Modulo",
|
||||
op: "%",
|
||||
noFloat: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, helper := range helpers {
|
||||
name := helper.name
|
||||
op := helper.op
|
||||
echo(`func %v(a, b interface{}) interface{} {`, name)
|
||||
echo(`switch x := a.(type) {`)
|
||||
for i, a := range types {
|
||||
if helper.noFloat && strings.HasPrefix(a, "float") {
|
||||
for i, a := range types {
|
||||
if noFloat && strings.HasPrefix(a, "float") {
|
||||
continue
|
||||
}
|
||||
echo(`case %v:`, a)
|
||||
echo(`switch y := b.(type) {`)
|
||||
for j, b := range types {
|
||||
if noFloat && strings.HasPrefix(b, "float") {
|
||||
continue
|
||||
}
|
||||
echo(`case %v:`, a)
|
||||
echo(`switch y := b.(type) {`)
|
||||
for j, b := range types {
|
||||
if helper.noFloat && strings.HasPrefix(b, "float") {
|
||||
continue
|
||||
}
|
||||
echo(`case %v:`, b)
|
||||
if i == j {
|
||||
echo(`return x %v y`, op)
|
||||
}
|
||||
if i < j {
|
||||
echo(`return %v(x) %v y`, b, op)
|
||||
}
|
||||
if i > j {
|
||||
echo(`return x %v %v(y)`, op, a)
|
||||
}
|
||||
echo(`case %v:`, b)
|
||||
if i == j {
|
||||
echo(`return x %v y`, op)
|
||||
}
|
||||
if i < j {
|
||||
echo(`return %v(x) %v y`, b, op)
|
||||
}
|
||||
if i > j {
|
||||
echo(`return x %v %v(y)`, op, a)
|
||||
}
|
||||
echo(`}`)
|
||||
}
|
||||
if helper.string {
|
||||
echo(`case string:`)
|
||||
echo(`switch y := b.(type) {`)
|
||||
echo(`case string: return x %v y`, op)
|
||||
echo(`}`)
|
||||
}
|
||||
switch op {
|
||||
case "==":
|
||||
echo(`case time.Time:`)
|
||||
echo(`switch y := b.(type) {`)
|
||||
echo(`case time.Time: return x.Equal(y)`)
|
||||
echo(`}`)
|
||||
case "<":
|
||||
echo(`case time.Time:`)
|
||||
echo(`switch y := b.(type) {`)
|
||||
echo(`case time.Time: return x.Before(y)`)
|
||||
echo(`}`)
|
||||
case ">":
|
||||
echo(`case time.Time:`)
|
||||
echo(`switch y := b.(type) {`)
|
||||
echo(`case time.Time: return x.After(y)`)
|
||||
echo(`}`)
|
||||
case "<=":
|
||||
echo(`case time.Time:`)
|
||||
echo(`switch y := b.(type) {`)
|
||||
echo(`case time.Time: return x.Before(y) || x.Equal(y)`)
|
||||
echo(`}`)
|
||||
case ">=":
|
||||
echo(`case time.Time:`)
|
||||
echo(`switch y := b.(type) {`)
|
||||
echo(`case time.Time: return x.After(y) || x.Equal(y)`)
|
||||
echo(`}`)
|
||||
case "+":
|
||||
echo(`case time.Time:`)
|
||||
echo(`switch y := b.(type) {`)
|
||||
echo(`case time.Duration: return x.Add(y)`)
|
||||
echo(`}`)
|
||||
echo(`case time.Duration:`)
|
||||
echo(`switch y := b.(type) {`)
|
||||
echo(`case time.Time: return y.Add(x)`)
|
||||
echo(`}`)
|
||||
case "-":
|
||||
echo(`case time.Time:`)
|
||||
echo(`switch y := b.(type) {`)
|
||||
echo(`case time.Time: return x.Sub(y)`)
|
||||
echo(`}`)
|
||||
}
|
||||
echo(`}`)
|
||||
if name == "Equal" {
|
||||
echo(`if IsNil(a) && IsNil(b) { return true }`)
|
||||
echo(`return reflect.DeepEqual(a, b)`)
|
||||
} else {
|
||||
echo(`panic(fmt.Sprintf("invalid operation: %%T %%v %%T", a, "%v", b))`, op)
|
||||
}
|
||||
echo(`}`)
|
||||
echo(``)
|
||||
}
|
||||
|
||||
b, err := format.Source([]byte(data))
|
||||
check(err)
|
||||
err = ioutil.WriteFile("helpers.go", b, 0644)
|
||||
check(err)
|
||||
return strings.TrimRight(out, "\n")
|
||||
}
|
||||
|
||||
const helpers = `// Code generated by vm/runtime/generate/main.go. DO NOT EDIT.
|
||||
|
||||
package runtime
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"time"
|
||||
)
|
||||
|
||||
func Equal(a, b interface{}) interface{} {
|
||||
switch x := a.(type) {
|
||||
{{ cases "==" }}
|
||||
case string:
|
||||
switch y := b.(type) {
|
||||
case string:
|
||||
return x == y
|
||||
}
|
||||
case time.Time:
|
||||
switch y := b.(type) {
|
||||
case time.Time:
|
||||
return x.Equal(y)
|
||||
}
|
||||
}
|
||||
if IsNil(a) && IsNil(b) {
|
||||
return true
|
||||
}
|
||||
return reflect.DeepEqual(a, b)
|
||||
}
|
||||
|
||||
func Less(a, b interface{}) interface{} {
|
||||
switch x := a.(type) {
|
||||
{{ cases "<" }}
|
||||
case string:
|
||||
switch y := b.(type) {
|
||||
case string:
|
||||
return x < y
|
||||
}
|
||||
case time.Time:
|
||||
switch y := b.(type) {
|
||||
case time.Time:
|
||||
return x.Before(y)
|
||||
}
|
||||
}
|
||||
panic(fmt.Sprintf("invalid operation: %T %v %T", a, "<", b))
|
||||
}
|
||||
|
||||
func More(a, b interface{}) interface{} {
|
||||
switch x := a.(type) {
|
||||
{{ cases ">" }}
|
||||
case string:
|
||||
switch y := b.(type) {
|
||||
case string:
|
||||
return x > y
|
||||
}
|
||||
case time.Time:
|
||||
switch y := b.(type) {
|
||||
case time.Time:
|
||||
return x.After(y)
|
||||
}
|
||||
}
|
||||
panic(fmt.Sprintf("invalid operation: %T %v %T", a, ">", b))
|
||||
}
|
||||
|
||||
func LessOrEqual(a, b interface{}) interface{} {
|
||||
switch x := a.(type) {
|
||||
{{ cases "<=" }}
|
||||
case string:
|
||||
switch y := b.(type) {
|
||||
case string:
|
||||
return x <= y
|
||||
}
|
||||
case time.Time:
|
||||
switch y := b.(type) {
|
||||
case time.Time:
|
||||
return x.Before(y) || x.Equal(y)
|
||||
}
|
||||
}
|
||||
panic(fmt.Sprintf("invalid operation: %T %v %T", a, "<=", b))
|
||||
}
|
||||
|
||||
func MoreOrEqual(a, b interface{}) interface{} {
|
||||
switch x := a.(type) {
|
||||
{{ cases ">=" }}
|
||||
case string:
|
||||
switch y := b.(type) {
|
||||
case string:
|
||||
return x >= y
|
||||
}
|
||||
case time.Time:
|
||||
switch y := b.(type) {
|
||||
case time.Time:
|
||||
return x.After(y) || x.Equal(y)
|
||||
}
|
||||
}
|
||||
panic(fmt.Sprintf("invalid operation: %T %v %T", a, ">=", b))
|
||||
}
|
||||
|
||||
func Add(a, b interface{}) interface{} {
|
||||
switch x := a.(type) {
|
||||
{{ cases "+" }}
|
||||
case string:
|
||||
switch y := b.(type) {
|
||||
case string:
|
||||
return x + y
|
||||
}
|
||||
case time.Time:
|
||||
switch y := b.(type) {
|
||||
case time.Duration:
|
||||
return x.Add(y)
|
||||
}
|
||||
case time.Duration:
|
||||
switch y := b.(type) {
|
||||
case time.Time:
|
||||
return y.Add(x)
|
||||
}
|
||||
}
|
||||
panic(fmt.Sprintf("invalid operation: %T %v %T", a, "+", b))
|
||||
}
|
||||
|
||||
func Subtract(a, b interface{}) interface{} {
|
||||
switch x := a.(type) {
|
||||
{{ cases "-" }}
|
||||
case time.Time:
|
||||
switch y := b.(type) {
|
||||
case time.Time:
|
||||
return x.Sub(y)
|
||||
}
|
||||
}
|
||||
panic(fmt.Sprintf("invalid operation: %T %v %T", a, "-", b))
|
||||
}
|
||||
|
||||
func Multiply(a, b interface{}) interface{} {
|
||||
switch x := a.(type) {
|
||||
{{ cases "*" }}
|
||||
}
|
||||
panic(fmt.Sprintf("invalid operation: %T %v %T", a, "*", b))
|
||||
}
|
||||
|
||||
func Divide(a, b interface{}) interface{} {
|
||||
switch x := a.(type) {
|
||||
{{ cases "/" }}
|
||||
}
|
||||
panic(fmt.Sprintf("invalid operation: %T %v %T", a, "/", b))
|
||||
}
|
||||
|
||||
func Modulo(a, b interface{}) interface{} {
|
||||
switch x := a.(type) {
|
||||
{{ cases_int_only "%" }}
|
||||
}
|
||||
panic(fmt.Sprintf("invalid operation: %T %v %T", a, "%", b))
|
||||
}
|
||||
`
|
||||
|
||||
Reference in New Issue
Block a user