@@ -2,16 +2,9 @@ package nature
22
33import (
44 "reflect"
5- )
65
7- func derefTypeKind (t reflect.Type , k reflect.Kind ) (_ reflect.Type , _ reflect.Kind , changed bool ) {
8- for k == reflect .Pointer {
9- changed = true
10- t = t .Elem ()
11- k = t .Kind ()
12- }
13- return t , k , changed
14- }
6+ "github.com/expr-lang/expr/internal/deref"
7+ )
158
169func fieldName (fieldName string , tag reflect.StructTag ) (string , bool ) {
1710 switch taggedName := tag .Get ("expr" ); taggedName {
@@ -27,7 +20,7 @@ func fieldName(fieldName string, tag reflect.StructTag) (string, bool) {
2720type structData struct {
2821 cache * Cache
2922 rType reflect.Type
30- fields map [string ]structField
23+ fields map [string ]* structField
3124 numField , ownIdx , anonIdx int
3225
3326 curParent , curChild * structData
@@ -39,22 +32,29 @@ type structField struct {
3932 Index []int
4033}
4134
35+ func (s * structData ) setCache (c * Cache ) {
36+ s .cache = c
37+ for _ , sf := range s .fields {
38+ sf .SetCache (c )
39+ }
40+ }
41+
4242func (s * structData ) finished () bool {
4343 return s .ownIdx >= s .numField && // no own fields left to visit
4444 s .anonIdx >= s .numField && // no embedded fields to visit
4545 s .curChild == nil // no child in process of visiting
4646}
4747
48- func (s * structData ) structField (parentEmbed * structData , name string ) ( structField , bool ) {
48+ func (s * structData ) structField (parentEmbed * structData , name string ) * structField {
4949 if s .fields == nil {
5050 if s .numField > 0 {
51- s .fields = make (map [string ]structField , s .numField )
51+ s .fields = make (map [string ]* structField , s .numField )
5252 }
53- } else if f , ok := s .fields [name ]; ok {
54- return f , true
53+ } else if f := s .fields [name ]; f != nil {
54+ return f
5555 }
5656 if s .finished () {
57- return structField {}, false
57+ return nil
5858 }
5959
6060 // Lookup own fields first.
@@ -73,7 +73,7 @@ func (s *structData) structField(parentEmbed *structData, name string) (structFi
7373 continue
7474 }
7575 nt := s .cache .FromType (field .Type )
76- sf := structField {
76+ sf := & structField {
7777 Nature : nt ,
7878 Index : field .Index ,
7979 }
@@ -82,14 +82,14 @@ func (s *structData) structField(parentEmbed *structData, name string) (structFi
8282 parentEmbed .trySet (fName , sf )
8383 }
8484 if fName == name {
85- return sf , true
85+ return sf
8686 }
8787 }
8888
8989 if s .curChild != nil {
90- sf , ok := s .findInEmbedded (parentEmbed , s .curChild , s .curChildIndex , name )
91- if ok {
92- return sf , true
90+ sf := s .findInEmbedded (parentEmbed , s .curChild , s .curChildIndex , name )
91+ if sf != nil {
92+ return sf
9393 }
9494 }
9595
@@ -101,26 +101,26 @@ func (s *structData) structField(parentEmbed *structData, name string) (structFi
101101 if ! field .Anonymous {
102102 continue
103103 }
104- t , k , _ := derefTypeKind (field .Type , field .Type .Kind ())
104+ t , k , _ := deref . TypeKind (field .Type , field .Type .Kind ())
105105 if k != reflect .Struct {
106106 continue
107107 }
108108
109109 childEmbed := s .cache .getStruct (t ).structData
110- sf , ok := s .findInEmbedded (parentEmbed , childEmbed , field .Index , name )
111- if ok {
112- return sf , true
110+ sf := s .findInEmbedded (parentEmbed , childEmbed , field .Index , name )
111+ if sf != nil {
112+ return sf
113113 }
114114 }
115115
116- return structField {}, false
116+ return nil
117117}
118118
119119func (s * structData ) findInEmbedded (
120120 parentEmbed , childEmbed * structData ,
121121 childIndex []int ,
122122 name string ,
123- ) ( structField , bool ) {
123+ ) * structField {
124124 // Set current parent/child data. This allows trySet to handle child fields
125125 // and add them to our struct and to the parent as well if needed
126126 s .curParent = parentEmbed
@@ -145,29 +145,29 @@ func (s *structData) findInEmbedded(
145145 }
146146
147147 // Recheck if we have what we needed from the above sync
148- if sf , ok := s .fields [name ]; ok {
149- return sf , true
148+ if sf := s .fields [name ]; sf != nil {
149+ return sf
150150 }
151151
152152 // Try finding in the child again in case it hasn't finished
153153 if ! childEmbed .finished () {
154- if _ , ok := childEmbed .structField (s , name ); ok {
155- return s .fields [name ], true
154+ if childEmbed .structField (s , name ) != nil {
155+ return s .fields [name ]
156156 }
157157 }
158158
159- return structField {}, false
159+ return nil
160160}
161161
162- func (s * structData ) trySet (name string , sf structField ) {
162+ func (s * structData ) trySet (name string , sf * structField ) {
163163 if _ , ok := s .fields [name ]; ok {
164164 return
165165 }
166- sf .Index = append (s .curChildIndex , sf .Index ... )
167- s .fields [name ] = structField {
166+ sf = & structField {
168167 Nature : sf .Nature ,
169- Index : sf .Index ,
168+ Index : append ( s . curChildIndex , sf .Index ... ) ,
170169 }
170+ s .fields [name ] = sf
171171 if s .curParent != nil {
172172 s .curParent .trySet (name , sf )
173173 }
@@ -178,7 +178,7 @@ func StructFields(c *Cache, t reflect.Type) map[string]Nature {
178178 if t == nil {
179179 return table
180180 }
181- t , k , _ := derefTypeKind (t , t .Kind ())
181+ t , k , _ := deref . TypeKind (t , t .Kind ())
182182 if k == reflect .Struct {
183183 // lookup for a field with an empty name, which will cause to never find a
184184 // match, meaning everything will have been cached.
@@ -195,7 +195,7 @@ type methodset struct {
195195 cache * Cache
196196 rType reflect.Type
197197 kind reflect.Kind
198- methods map [string ]method
198+ methods map [string ]* method
199199 numMethod , idx int
200200}
201201
@@ -204,11 +204,18 @@ type method struct {
204204 nature Nature
205205}
206206
207- func (s * methodset ) method (name string ) (method , bool ) {
207+ func (s * methodset ) setCache (c * Cache ) {
208+ s .cache = c
209+ for _ , m := range s .methods {
210+ m .nature .SetCache (c )
211+ }
212+ }
213+
214+ func (s * methodset ) method (name string ) * method {
208215 if s .methods == nil {
209- s .methods = make (map [string ]method , s .numMethod )
210- } else if m , ok := s .methods [name ]; ok {
211- return m , true
216+ s .methods = make (map [string ]* method , s .numMethod )
217+ } else if m := s .methods [name ]; m != nil {
218+ return m
212219 }
213220 for ; s .idx < s .numMethod ; s .idx ++ {
214221 rm := s .rType .Method (s .idx )
@@ -227,14 +234,14 @@ func (s *methodset) method(name string) (method, bool) {
227234 // different indexes for different types which implement
228235 // the same interface.
229236 }
230- m := method {
237+ m := & method {
231238 Method : rm ,
232239 nature : nt ,
233240 }
234241 s .methods [rm .Name ] = m
235242 if rm .Name == name {
236- return m , true
243+ return m
237244 }
238245 }
239- return method {}, false
246+ return nil
240247}
0 commit comments