@@ -54,7 +54,7 @@ func (n unaryNode) Type(table typesTable) (Type, error) {
5454
5555 switch n .operator {
5656 case "!" , "not" :
57- if isBoolType (ntype ) {
57+ if isBoolType (ntype ) || isInterfaceType ( ntype ) {
5858 return boolType , nil
5959 }
6060 return nil , fmt .Errorf (`invalid operation: %v (mismatched type %v)` , n , ntype )
@@ -80,8 +80,15 @@ func (n binaryNode) Type(table typesTable) (Type, error) {
8080 return boolType , nil
8181 }
8282 return nil , fmt .Errorf (`invalid operation: %v (mismatched types %v and %v)` , n , ltype , rtype )
83+
8384 case "or" , "||" , "and" , "&&" :
84- if isBoolType (ltype ) && isBoolType (rtype ) {
85+ if (isBoolType (ltype ) || isInterfaceType (ltype )) && (isBoolType (rtype ) || isInterfaceType (rtype )) {
86+ return boolType , nil
87+ }
88+ return nil , fmt .Errorf (`invalid operation: %v (mismatched types %v and %v)` , n , ltype , rtype )
89+
90+ case "|" , "^" , "&" , "<" , ">" , ">=" , "<=" , "+" , "-" , "*" , "/" , "%" , "**" , ".." :
91+ if (isNumberType (ltype ) || isInterfaceType (ltype )) && (isNumberType (rtype ) || isInterfaceType (rtype )) {
8592 return boolType , nil
8693 }
8794 return nil , fmt .Errorf (`invalid operation: %v (mismatched types %v and %v)` , n , ltype , rtype )
@@ -91,7 +98,19 @@ func (n binaryNode) Type(table typesTable) (Type, error) {
9198}
9299
93100func (n matchesNode ) Type (table typesTable ) (Type , error ) {
94- return boolType , nil
101+ var err error
102+ ltype , err := n .left .Type (table )
103+ if err != nil {
104+ return nil , err
105+ }
106+ rtype , err := n .right .Type (table )
107+ if err != nil {
108+ return nil , err
109+ }
110+ if (isStringType (ltype ) || isInterfaceType (ltype )) && (isStringType (rtype ) || isInterfaceType (rtype )) {
111+ return boolType , nil
112+ }
113+ return nil , fmt .Errorf (`invalid operation: %v (mismatched types %v and %v)` , n , ltype , rtype )
95114}
96115
97116func (n propertyNode ) Type (table typesTable ) (Type , error ) {
@@ -141,8 +160,14 @@ func (n methodNode) Type(table typesTable) (Type, error) {
141160}
142161
143162func (n builtinNode ) Type (table typesTable ) (Type , error ) {
163+ for _ , node := range n .arguments {
164+ _ , err := node .Type (table )
165+ if err != nil {
166+ return nil , err
167+ }
168+ }
144169 if _ , ok := builtins [n .name ]; ok {
145- return nil , nil
170+ return interfaceType , nil
146171 }
147172 return nil , fmt .Errorf ("%v undefined" , n )
148173}
@@ -167,7 +192,7 @@ func (n conditionalNode) Type(table typesTable) (Type, error) {
167192 if err != nil {
168193 return nil , err
169194 }
170- if ! isBoolType (ctype ) {
195+ if ! isBoolType (ctype ) && ! isInterfaceType ( ctype ) {
171196 return nil , fmt .Errorf ("non-bool %v (type %v) used as condition" , n .cond , ctype )
172197 }
173198 _ , err = n .exp1 .Type (table )
@@ -216,60 +241,88 @@ func (n pairNode) Type(table typesTable) (Type, error) {
216241
217242// helper funcs for reflect
218243
219- func isComparable (ltype Type , rtype Type ) bool {
220- ltype = dereference (ltype )
221- if ltype == nil {
222- return true
223- }
224- rtype = dereference (rtype )
225- if rtype == nil {
226- return true
244+ func isComparable (l Type , r Type ) bool {
245+ l = dereference (l )
246+ r = dereference (r )
247+
248+ if l == nil || r == nil {
249+ return true // It is possible to compare with nil.
227250 }
228251
229- if canBeNumberType ( ltype ) && canBeNumberType ( rtype ) {
252+ if isNumberType ( l ) && isNumberType ( r ) {
230253 return true
231- } else if ltype .Kind () == reflect .Interface {
254+ } else if l .Kind () == reflect .Interface {
232255 return true
233- } else if rtype .Kind () == reflect .Interface {
256+ } else if r .Kind () == reflect .Interface {
234257 return true
235- } else if ltype == rtype {
258+ } else if l == r {
236259 return true
237260 }
238261 return false
239262}
240263
241- func isBoolType (ntype Type ) bool {
242- ntype = dereference (ntype )
243- if ntype == nil {
244- return false
264+ func isInterfaceType (t Type ) bool {
265+ t = dereference (t )
266+ if t != nil {
267+ switch t .Kind () {
268+ case reflect .Interface :
269+ return true
270+ }
245271 }
272+ return false
273+ }
246274
247- switch ntype .Kind () {
248- case reflect .Interface :
249- return true
250- case reflect .Bool :
251- return true
275+ func isNumberType (t Type ) bool {
276+ t = dereference (t )
277+ if t != nil {
278+ switch t .Kind () {
279+ case reflect .Float32 , reflect .Float64 :
280+ fallthrough
281+ case reflect .Int , reflect .Int8 , reflect .Int16 , reflect .Int32 , reflect .Int64 :
282+ fallthrough
283+ case reflect .Uint , reflect .Uint8 , reflect .Uint16 , reflect .Uint32 , reflect .Uint64 :
284+ return true
285+ }
252286 }
253287 return false
254288}
255289
256- func fieldType (ntype Type , name string ) (Type , bool ) {
257- ntype = dereference (ntype )
258- if ntype == nil {
259- return nil , false
290+ func isBoolType (t Type ) bool {
291+ t = dereference (t )
292+ if t != nil {
293+ switch t .Kind () {
294+ case reflect .Bool :
295+ return true
296+ }
260297 }
298+ return false
299+ }
261300
262- switch ntype . Kind () {
263- case reflect . Interface :
264- return interfaceType , true
265- case reflect . Struct :
266- if t , ok := ntype . FieldByName ( name ); ok {
267- return t . Type , true
301+ func isStringType ( t Type ) bool {
302+ t = dereference ( t )
303+ if t != nil {
304+ switch t . Kind () {
305+ case reflect . String :
306+ return true
268307 }
269- case reflect .Map :
270- return ntype .Elem (), true
271308 }
309+ return false
310+ }
272311
312+ func fieldType (ntype Type , name string ) (Type , bool ) {
313+ ntype = dereference (ntype )
314+ if ntype != nil {
315+ switch ntype .Kind () {
316+ case reflect .Interface :
317+ return interfaceType , true
318+ case reflect .Struct :
319+ if t , ok := ntype .FieldByName (name ); ok {
320+ return t .Type , true
321+ }
322+ case reflect .Map :
323+ return ntype .Elem (), true
324+ }
325+ }
273326 return nil , false
274327}
275328
0 commit comments