Skip to content

Commit 3319ba8

Browse files
committed
Move SubType to Nature
1 parent 84b9f25 commit 3319ba8

File tree

6 files changed

+77
-135
lines changed

6 files changed

+77
-135
lines changed

checker/checker.go

+5-20
Original file line numberDiff line numberDiff line change
@@ -410,16 +410,10 @@ func (v *checker) BinaryNode(node *ast.BinaryNode) Nature {
410410

411411
case "..":
412412
if isInteger(l) && isInteger(r) {
413-
return Nature{
414-
Type: arrayType,
415-
SubType: Array{Elem: integerNature},
416-
}
413+
return arrayOf(integerNature)
417414
}
418415
if or(l, r, isInteger) {
419-
return Nature{
420-
Type: arrayType,
421-
SubType: Array{Elem: integerNature},
422-
}
416+
return arrayOf(integerNature)
423417
}
424418

425419
case "??":
@@ -650,10 +644,7 @@ func (v *checker) BuiltinNode(node *ast.BuiltinNode) Nature {
650644
if isUnknown(collection) {
651645
return arrayNature
652646
}
653-
return Nature{
654-
Type: arrayType,
655-
SubType: Array{Elem: collection.Elem()},
656-
}
647+
return arrayOf(collection.Elem())
657648
}
658649
return v.error(node.Arguments[1], "predicate should has one input and one output param")
659650

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

674-
return Nature{
675-
Type: arrayType,
676-
SubType: Array{Elem: closure.Out(0)},
677-
}
665+
return arrayOf(closure.Out(0))
678666
}
679667
return v.error(node.Arguments[1], "predicate should has one input and one output param")
680668

@@ -1199,10 +1187,7 @@ func (v *checker) ArrayNode(node *ast.ArrayNode) Nature {
11991187
prev = curr
12001188
}
12011189
if allElementsAreSameType {
1202-
return Nature{
1203-
Type: arrayNature.Type,
1204-
SubType: Array{Elem: prev},
1205-
}
1190+
return arrayOf(prev)
12061191
}
12071192
return arrayNature
12081193
}

checker/nature/nature.go

+17-30
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,18 @@ var (
1212
)
1313

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

2426
func (n Nature) String() string {
25-
if n.SubType != nil {
26-
return n.SubType.String()
27-
}
2827
if n.Type != nil {
2928
return n.Type.String()
3029
}
@@ -57,8 +56,8 @@ func (n Nature) Elem() Nature {
5756
case reflect.Map, reflect.Ptr:
5857
return Nature{Type: n.Type.Elem()}
5958
case reflect.Array, reflect.Slice:
60-
if array, ok := n.SubType.(Array); ok {
61-
return array.Elem
59+
if n.ArrayOf != nil {
60+
return *n.ArrayOf
6261
}
6362
return Nature{Type: n.Type.Elem()}
6463
}
@@ -180,14 +179,14 @@ func (n Nature) Get(name string) (Nature, bool) {
180179
}, true
181180
}
182181
case reflect.Map:
183-
if f, ok := n.SubType.Get(name); ok {
182+
if f, ok := n.Fields[name]; ok {
184183
return f, true
185184
}
186185
}
187186
return unknown, false
188187
}
189188

190-
func (n Nature) List() map[string]Nature {
189+
func (n Nature) All() map[string]Nature {
191190
table := make(map[string]Nature)
192191

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

217216
case reflect.Map:
218-
if st, ok := n.SubType.(Map); ok {
219-
for key, nt := range st.Fields {
220-
if _, ok := table[key]; ok {
221-
continue
222-
}
223-
table[key] = nt
224-
}
225-
}
226-
v := reflect.ValueOf(n.SubType)
227-
if v.Kind() != reflect.Map {
228-
break
229-
}
230-
for _, key := range v.MapKeys() {
231-
value := v.MapIndex(key)
232-
if key.Kind() == reflect.String && value.IsValid() && value.CanInterface() {
233-
table[key.String()] = Nature{Type: reflect.TypeOf(value.Interface())}
217+
for key, nt := range n.Fields {
218+
if _, ok := table[key]; ok {
219+
continue
234220
}
221+
table[key] = nt
235222
}
236223
}
237224

checker/nature/of.go

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package nature
2+
3+
import (
4+
"fmt"
5+
"reflect"
6+
7+
"github.com/expr-lang/expr/types"
8+
)
9+
10+
func Of(value any) Nature {
11+
if value == nil {
12+
return Nature{Nil: true}
13+
}
14+
15+
v := reflect.ValueOf(value)
16+
17+
switch v.Kind() {
18+
case reflect.Map:
19+
_, strict := value.(types.StrictMap)
20+
fields := make(map[string]Nature, v.Len())
21+
for _, key := range v.MapKeys() {
22+
elem := v.MapIndex(key)
23+
if !elem.IsValid() || !elem.CanInterface() {
24+
panic(fmt.Sprintf("invalid map value: %s", key))
25+
}
26+
face := elem.Interface()
27+
switch face.(type) {
28+
case types.Map, types.StrictMap:
29+
fields[key.String()] = Of(face)
30+
default:
31+
if face == nil {
32+
fields[key.String()] = Nature{Nil: true}
33+
continue
34+
}
35+
fields[key.String()] = Nature{Type: reflect.TypeOf(face)}
36+
37+
}
38+
}
39+
return Nature{
40+
Type: v.Type(),
41+
Fields: fields,
42+
Strict: strict,
43+
}
44+
}
45+
46+
return Nature{Type: v.Type()}
47+
}

checker/nature/types.go

-84
This file was deleted.

checker/types.go

+7
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,13 @@ var (
2727
arrayType = reflect.TypeOf([]any{})
2828
)
2929

30+
func arrayOf(nt Nature) Nature {
31+
return Nature{
32+
Type: arrayType,
33+
ArrayOf: &nt,
34+
}
35+
}
36+
3037
func isNil(nt Nature) bool {
3138
return nt.Nil
3239
}

docgen/docgen.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ func CreateDoc(i any) *Context {
8484
PkgPath: deref.Type(reflect.TypeOf(i)).PkgPath(),
8585
}
8686

87-
for name, t := range nature.Of(i).List() {
87+
for name, t := range nature.Of(i).All() {
8888
if _, ok := c.Variables[Identifier(name)]; ok {
8989
continue
9090
}

0 commit comments

Comments
 (0)