@@ -115,6 +115,12 @@ func (n binaryNode) Type(table typesTable) (Type, error) {
115
115
}
116
116
return nil , fmt .Errorf (`invalid operation: %v (mismatched types %v and %v)` , n , ltype , rtype )
117
117
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
+
118
124
}
119
125
120
126
return interfaceType , nil
@@ -173,7 +179,7 @@ func (n methodNode) Type(table typesTable) (Type, error) {
173
179
return nil , err
174
180
}
175
181
}
176
- if t , ok := fieldType (ntype , n .method ); ok {
182
+ if t , ok := methodType (ntype , n .method ); ok {
177
183
if f , ok := funcType (t ); ok {
178
184
return f , nil
179
185
}
@@ -220,15 +226,29 @@ func (n conditionalNode) Type(table typesTable) (Type, error) {
220
226
if ! isBoolType (ctype ) && ! isInterfaceType (ctype ) {
221
227
return nil , fmt .Errorf ("non-bool %v (type %v) used as condition" , n .cond , ctype )
222
228
}
223
- _ , err = n .exp1 .Type (table )
229
+
230
+ t1 , err := n .exp1 .Type (table )
224
231
if err != nil {
225
232
return nil , err
226
233
}
227
- _ , err = n .exp2 .Type (table )
234
+ t2 , err : = n .exp2 .Type (table )
228
235
if err != nil {
229
236
return nil , err
230
237
}
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
232
252
}
233
253
234
254
func (n arrayNode ) Type (table typesTable ) (Type , error ) {
@@ -399,6 +419,46 @@ func fieldType(ntype Type, name string) (Type, bool) {
399
419
return nil , false
400
420
}
401
421
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
+
402
462
func indexType (ntype Type ) (Type , bool ) {
403
463
ntype = dereference (ntype )
404
464
if ntype == nil {
0 commit comments