@@ -115,6 +115,12 @@ func (n binaryNode) Type(table typesTable) (Type, error) {
115115 }
116116 return nil , fmt .Errorf (`invalid operation: %v (mismatched types %v and %v)` , n , ltype , rtype )
117117
118+ case "~" :
119+ if (isStringType (ltype ) || isInterfaceType (ltype )) && (isStringType (rtype ) || isInterfaceType (rtype )) {
120+ return textType , nil
121+ }
122+ return nil , fmt .Errorf (`invalid operation: %v (mismatched types %v and %v)` , n , ltype , rtype )
123+
118124 }
119125
120126 return interfaceType , nil
@@ -173,7 +179,7 @@ func (n methodNode) Type(table typesTable) (Type, error) {
173179 return nil , err
174180 }
175181 }
176- if t , ok := fieldType (ntype , n .method ); ok {
182+ if t , ok := methodType (ntype , n .method ); ok {
177183 if f , ok := funcType (t ); ok {
178184 return f , nil
179185 }
@@ -220,15 +226,29 @@ func (n conditionalNode) Type(table typesTable) (Type, error) {
220226 if ! isBoolType (ctype ) && ! isInterfaceType (ctype ) {
221227 return nil , fmt .Errorf ("non-bool %v (type %v) used as condition" , n .cond , ctype )
222228 }
223- _ , err = n .exp1 .Type (table )
229+
230+ t1 , err := n .exp1 .Type (table )
224231 if err != nil {
225232 return nil , err
226233 }
227- _ , err = n .exp2 .Type (table )
234+ t2 , err : = n .exp2 .Type (table )
228235 if err != nil {
229236 return nil , err
230237 }
231- return boolType , nil
238+
239+ if t1 == nil && t2 != nil {
240+ return t2 , nil
241+ }
242+ if t1 != nil && t2 == nil {
243+ return t1 , nil
244+ }
245+ if t1 == nil && t2 == nil {
246+ return nilType , nil
247+ }
248+ if t1 .AssignableTo (t2 ) {
249+ return t1 , nil
250+ }
251+ return interfaceType , nil
232252}
233253
234254func (n arrayNode ) Type (table typesTable ) (Type , error ) {
@@ -399,6 +419,46 @@ func fieldType(ntype Type, name string) (Type, bool) {
399419 return nil , false
400420}
401421
422+ func methodType (ntype Type , name string ) (Type , bool ) {
423+ ntype = dereference (ntype )
424+ if ntype != nil {
425+ switch ntype .Kind () {
426+ case reflect .Interface :
427+ return interfaceType , true
428+ case reflect .Struct :
429+ // First check all struct's methods.
430+ for i := 0 ; i < ntype .NumMethod (); i ++ {
431+ m := ntype .Method (i )
432+ if m .Name == name {
433+ return m .Type , true
434+ }
435+ }
436+
437+ // Second check all struct's fields.
438+ for i := 0 ; i < ntype .NumField (); i ++ {
439+ f := ntype .Field (i )
440+ if ! f .Anonymous && f .Name == name {
441+ return f .Type , true
442+ }
443+ }
444+
445+ // Third check fields of embedded structs.
446+ for i := 0 ; i < ntype .NumField (); i ++ {
447+ f := ntype .Field (i )
448+ if f .Anonymous {
449+ if t , ok := methodType (f .Type , name ); ok {
450+ return t , true
451+ }
452+ }
453+ }
454+ case reflect .Map :
455+ return ntype .Elem (), true
456+ }
457+ }
458+
459+ return nil , false
460+ }
461+
402462func indexType (ntype Type ) (Type , bool ) {
403463 ntype = dereference (ntype )
404464 if ntype == nil {
0 commit comments