Skip to content

Commit

Permalink
Improve types pkg
Browse files Browse the repository at this point in the history
  • Loading branch information
antonmedv committed Jun 4, 2024
1 parent a31b1fe commit a32f683
Show file tree
Hide file tree
Showing 7 changed files with 150 additions and 59 deletions.
2 changes: 1 addition & 1 deletion checker/checker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1074,7 +1074,7 @@ func TestCheck_types(t *testing.T) {
env := types.Map{
"foo": types.StrictMap{
"bar": types.Map{
"baz": "",
"baz": types.String,
},
},
}
Expand Down
47 changes: 0 additions & 47 deletions checker/nature/of.go

This file was deleted.

7 changes: 1 addition & 6 deletions conf/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"github.com/expr-lang/expr/ast"
"github.com/expr-lang/expr/builtin"
"github.com/expr-lang/expr/checker/nature"
"github.com/expr-lang/expr/types"
"github.com/expr-lang/expr/vm/runtime"
)

Expand Down Expand Up @@ -53,11 +52,7 @@ func New(env any) *Config {
func (c *Config) WithEnv(env any) {
c.Strict = true
c.EnvObject = env
c.Env = nature.Of(env)
c.Env.Strict = true // To keep backward compatibility with expr.AllowUndefinedVariables()
if _, ok := env.(types.Map); ok {
c.Env.Strict = false
}
c.Env = Env(env)
}

func (c *Config) ConstExpr(name string) {
Expand Down
73 changes: 73 additions & 0 deletions conf/env.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package conf

import (
"fmt"
"reflect"

. "github.com/expr-lang/expr/checker/nature"
"github.com/expr-lang/expr/internal/deref"
"github.com/expr-lang/expr/types"
)

func Env(env any) Nature {
if env == nil {
return Nature{
Type: reflect.TypeOf(map[string]any{}),
Strict: true,
}
}

switch env := env.(type) {
case types.Map:
return env.Nature()

case types.StrictMap:
return env.Nature()
}

v := reflect.ValueOf(env)
d := deref.Value(v)

switch d.Kind() {
case reflect.Struct:
return Nature{
Type: v.Type(),
Strict: true,
}

case reflect.Map:
n := Nature{
Type: v.Type(),
Fields: make(map[string]Nature, v.Len()),
}

for _, key := range v.MapKeys() {
elem := v.MapIndex(key)
if !elem.IsValid() || !elem.CanInterface() {
panic(fmt.Sprintf("invalid map value: %s", key))
}

face := elem.Interface()

switch face.(type) {
case types.Map:
n.Fields[key.String()] = face.(types.Map).Nature()

case types.StrictMap:
n.Fields[key.String()] = face.(types.StrictMap).Nature()

default:
if face == nil {
n.Fields[key.String()] = Nature{Nil: true}
continue
}
n.Fields[key.String()] = Nature{Type: reflect.TypeOf(face)}
}

}

return n
}

panic(fmt.Sprintf("unknown type %T", env))
}
3 changes: 2 additions & 1 deletion docgen/docgen.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"strings"

"github.com/expr-lang/expr/checker/nature"
"github.com/expr-lang/expr/conf"
"github.com/expr-lang/expr/internal/deref"
)

Expand Down Expand Up @@ -84,7 +85,7 @@ func CreateDoc(i any) *Context {
PkgPath: deref.Type(reflect.TypeOf(i)).PkgPath(),
}

for name, t := range nature.Of(i).All() {
for name, t := range conf.Env(i).All() {
if _, ok := c.Variables[Identifier(name)]; ok {
continue
}
Expand Down
4 changes: 2 additions & 2 deletions expr_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2705,7 +2705,7 @@ func TestExpr_nil_op_str(t *testing.T) {
func TestExpr_env_types_map(t *testing.T) {
envTypes := types.Map{
"foo": types.StrictMap{
"bar": "value",
"bar": types.String,
},
}

Expand All @@ -2726,7 +2726,7 @@ func TestExpr_env_types_map(t *testing.T) {
func TestExpr_env_types_map_error(t *testing.T) {
envTypes := types.Map{
"foo": types.StrictMap{
"bar": "value",
"bar": types.String,
},
}

Expand Down
73 changes: 71 additions & 2 deletions types/types.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,74 @@
package types

type Map map[string]any
import (
"reflect"

type StrictMap map[string]any
. "github.com/expr-lang/expr/checker/nature"
)

func TypeOf(v any) Type {
return rtype{t: reflect.TypeOf(v)}
}

var (
Int = TypeOf(0)
Int8 = TypeOf(int8(0))
Int16 = TypeOf(int16(0))
Int32 = TypeOf(int32(0))
Int64 = TypeOf(int64(0))
Uint = TypeOf(uint(0))
Uint8 = TypeOf(uint8(0))
Uint16 = TypeOf(uint16(0))
Uint32 = TypeOf(uint32(0))
Uint64 = TypeOf(uint64(0))
Float = TypeOf(float32(0))
Float64 = TypeOf(float64(0))
String = TypeOf("")
Bool = TypeOf(true)
Nil = nilType{}
)

type Type interface {
Nature() Nature
}

type nilType struct{}

func (nilType) Nature() Nature {
return Nature{Nil: true}
}

type rtype struct {
t reflect.Type
}

func (r rtype) Nature() Nature {
return Nature{Type: r.t}
}

type Map map[string]Type

func (m Map) Nature() Nature {
nt := Nature{
Type: reflect.TypeOf(map[string]any{}),
Fields: make(map[string]Nature, len(m)),
}
for k, v := range m {
nt.Fields[k] = v.Nature()
}
return nt
}

type StrictMap map[string]Type

func (m StrictMap) Nature() Nature {
nt := Nature{
Type: reflect.TypeOf(map[string]any{}),
Fields: make(map[string]Nature, len(m)),
Strict: true,
}
for k, v := range m {
nt.Fields[k] = v.Nature()
}
return nt
}

0 comments on commit a32f683

Please sign in to comment.