Skip to content

Commit 48a3857

Browse files
committed
Add type checks for "in" operator
1 parent 8a82eee commit 48a3857

File tree

2 files changed

+54
-0
lines changed

2 files changed

+54
-0
lines changed

type.go

+42
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,15 @@ func (n binaryNode) Type(table typesTable) (Type, error) {
8888
}
8989
return nil, fmt.Errorf(`invalid operation: %v (mismatched types %v and %v)`, n, ltype, rtype)
9090

91+
case "in", "not in":
92+
if (isStringType(ltype) || isInterfaceType(ltype)) && (isStructType(rtype) || isInterfaceType(rtype)) {
93+
return boolType, nil
94+
}
95+
if isArrayType(rtype) || isMapType(rtype) || isInterfaceType(rtype) {
96+
return boolType, nil
97+
}
98+
return nil, fmt.Errorf(`invalid operation: %v (mismatched types %v and %v)`, n, ltype, rtype)
99+
91100
case "<", ">", ">=", "<=":
92101
if (isNumberType(ltype) || isInterfaceType(ltype)) && (isNumberType(rtype) || isInterfaceType(rtype)) {
93102
return boolType, nil
@@ -325,6 +334,39 @@ func isStringType(t Type) bool {
325334
return false
326335
}
327336

337+
func isArrayType(t Type) bool {
338+
t = dereference(t)
339+
if t != nil {
340+
switch t.Kind() {
341+
case reflect.Slice, reflect.Array:
342+
return true
343+
}
344+
}
345+
return false
346+
}
347+
348+
func isMapType(t Type) bool {
349+
t = dereference(t)
350+
if t != nil {
351+
switch t.Kind() {
352+
case reflect.Map:
353+
return true
354+
}
355+
}
356+
return false
357+
}
358+
359+
func isStructType(t Type) bool {
360+
t = dereference(t)
361+
if t != nil {
362+
switch t.Kind() {
363+
case reflect.Struct:
364+
return true
365+
}
366+
}
367+
return false
368+
}
369+
328370
func fieldType(ntype Type, name string) (Type, bool) {
329371
ntype = dereference(ntype)
330372
if ntype != nil {

type_test.go

+12
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ var typeTests = []typeTest{
5252
"nil == nil",
5353
"nil == IntPtr",
5454
"Foo2p.Bar.Baz",
55+
"Str in Foo",
56+
"Str in Arr",
57+
"nil in Arr",
58+
"Str not in Foo2p",
5559
"Int | Num",
5660
"Int ^ Num",
5761
"Int & Num",
@@ -268,6 +272,14 @@ var typeErrorTests = []typeErrorTest{
268272
"NilFn() and OkFn()",
269273
"invalid operation: NilFn() and OkFn() (mismatched types <nil> and bool)",
270274
},
275+
{
276+
"'str' in Str",
277+
`invalid operation: "str" in Str (mismatched types string and string)`,
278+
},
279+
{
280+
"1 in Foo",
281+
"invalid operation: 1 in Foo (mismatched types float64 and *expr_test.foo)",
282+
},
271283
}
272284

273285
type abc interface {

0 commit comments

Comments
 (0)