Skip to content

Commit

Permalink
Move SubType to Nature
Browse files Browse the repository at this point in the history
  • Loading branch information
antonmedv committed Jun 2, 2024
1 parent 84b9f25 commit 3319ba8
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 135 deletions.
25 changes: 5 additions & 20 deletions checker/checker.go
Original file line number Diff line number Diff line change
Expand Up @@ -410,16 +410,10 @@ func (v *checker) BinaryNode(node *ast.BinaryNode) Nature {

case "..":
if isInteger(l) && isInteger(r) {
return Nature{
Type: arrayType,
SubType: Array{Elem: integerNature},
}
return arrayOf(integerNature)
}
if or(l, r, isInteger) {
return Nature{
Type: arrayType,
SubType: Array{Elem: integerNature},
}
return arrayOf(integerNature)
}

case "??":
Expand Down Expand Up @@ -650,10 +644,7 @@ func (v *checker) BuiltinNode(node *ast.BuiltinNode) Nature {
if isUnknown(collection) {
return arrayNature
}
return Nature{
Type: arrayType,
SubType: Array{Elem: collection.Elem()},
}
return arrayOf(collection.Elem())
}
return v.error(node.Arguments[1], "predicate should has one input and one output param")

Expand All @@ -671,10 +662,7 @@ func (v *checker) BuiltinNode(node *ast.BuiltinNode) Nature {
closure.NumOut() == 1 &&
closure.NumIn() == 1 && isUnknown(closure.In(0)) {

return Nature{
Type: arrayType,
SubType: Array{Elem: closure.Out(0)},
}
return arrayOf(closure.Out(0))
}
return v.error(node.Arguments[1], "predicate should has one input and one output param")

Expand Down Expand Up @@ -1199,10 +1187,7 @@ func (v *checker) ArrayNode(node *ast.ArrayNode) Nature {
prev = curr
}
if allElementsAreSameType {
return Nature{
Type: arrayNature.Type,
SubType: Array{Elem: prev},
}
return arrayOf(prev)
}
return arrayNature
}
Expand Down
47 changes: 17 additions & 30 deletions checker/nature/nature.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,18 @@ var (
)

type Nature struct {
Type reflect.Type
Nil bool
SubType SubType
Func *builtin.Function
Method bool
MethodIndex int
FieldIndex []int
Type reflect.Type // Type of the value. If nil, then value is unknown.
Func *builtin.Function // Used to pass function type from callee to CallNode.
ArrayOf *Nature // Elem nature of array type (usually Type is []any, but ArrayOf can be any nature).
Fields map[string]Nature // Fields of map type.
Strict bool // If map is types.StrictMap.
Nil bool // If value is nil.
Method bool // If value retrieved from method. Usually used to determine amount of in arguments.
MethodIndex int // Index of method in type.
FieldIndex []int // Index of field in type.
}

func (n Nature) String() string {
if n.SubType != nil {
return n.SubType.String()
}
if n.Type != nil {
return n.Type.String()
}
Expand Down Expand Up @@ -57,8 +56,8 @@ func (n Nature) Elem() Nature {
case reflect.Map, reflect.Ptr:
return Nature{Type: n.Type.Elem()}
case reflect.Array, reflect.Slice:
if array, ok := n.SubType.(Array); ok {
return array.Elem
if n.ArrayOf != nil {
return *n.ArrayOf
}
return Nature{Type: n.Type.Elem()}
}
Expand Down Expand Up @@ -180,14 +179,14 @@ func (n Nature) Get(name string) (Nature, bool) {
}, true
}
case reflect.Map:
if f, ok := n.SubType.Get(name); ok {
if f, ok := n.Fields[name]; ok {
return f, true
}
}
return unknown, false
}

func (n Nature) List() map[string]Nature {
func (n Nature) All() map[string]Nature {
table := make(map[string]Nature)

if n.Type == nil {
Expand Down Expand Up @@ -215,23 +214,11 @@ func (n Nature) List() map[string]Nature {
}

case reflect.Map:
if st, ok := n.SubType.(Map); ok {
for key, nt := range st.Fields {
if _, ok := table[key]; ok {
continue
}
table[key] = nt
}
}
v := reflect.ValueOf(n.SubType)
if v.Kind() != reflect.Map {
break
}
for _, key := range v.MapKeys() {
value := v.MapIndex(key)
if key.Kind() == reflect.String && value.IsValid() && value.CanInterface() {
table[key.String()] = Nature{Type: reflect.TypeOf(value.Interface())}
for key, nt := range n.Fields {
if _, ok := table[key]; ok {
continue
}
table[key] = nt
}
}

Expand Down
47 changes: 47 additions & 0 deletions checker/nature/of.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package nature

import (
"fmt"
"reflect"

"github.com/expr-lang/expr/types"
)

func Of(value any) Nature {
if value == nil {
return Nature{Nil: true}
}

v := reflect.ValueOf(value)

switch v.Kind() {
case reflect.Map:
_, strict := value.(types.StrictMap)
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, types.StrictMap:
fields[key.String()] = Of(face)
default:
if face == nil {
fields[key.String()] = Nature{Nil: true}
continue
}
fields[key.String()] = Nature{Type: reflect.TypeOf(face)}

}
}
return Nature{
Type: v.Type(),
Fields: fields,
Strict: strict,
}
}

return Nature{Type: v.Type()}
}
84 changes: 0 additions & 84 deletions checker/nature/types.go

This file was deleted.

7 changes: 7 additions & 0 deletions checker/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,13 @@ var (
arrayType = reflect.TypeOf([]any{})
)

func arrayOf(nt Nature) Nature {
return Nature{
Type: arrayType,
ArrayOf: &nt,
}
}

func isNil(nt Nature) bool {
return nt.Nil
}
Expand Down
2 changes: 1 addition & 1 deletion docgen/docgen.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ func CreateDoc(i any) *Context {
PkgPath: deref.Type(reflect.TypeOf(i)).PkgPath(),
}

for name, t := range nature.Of(i).List() {
for name, t := range nature.Of(i).All() {
if _, ok := c.Variables[Identifier(name)]; ok {
continue
}
Expand Down

0 comments on commit 3319ba8

Please sign in to comment.