@@ -10,17 +10,7 @@ import (
1010 "github.com/antonmedv/expr/parser"
1111)
1212
13- func Check (tree * parser.Tree , config * conf.Config ) (t reflect.Type , err error ) {
14- defer func () {
15- if r := recover (); r != nil {
16- if h , ok := r .(file.Error ); ok {
17- err = fmt .Errorf ("%v" , h .Format (tree .Source ))
18- } else {
19- err = fmt .Errorf ("%v" , r )
20- }
21- }
22- }()
23-
13+ func Check (tree * parser.Tree , config * conf.Config ) (reflect.Type , error ) {
2414 v := & visitor {
2515 collections : make ([]reflect.Type , 0 ),
2616 }
@@ -32,7 +22,7 @@ func Check(tree *parser.Tree, config *conf.Config) (t reflect.Type, err error) {
3222 v .defaultType = config .DefaultType
3323 }
3424
35- t = v .visit (tree .Node )
25+ t : = v .visit (tree .Node )
3626
3727 if v .expect != reflect .Invalid {
3828 switch v .expect {
@@ -47,7 +37,11 @@ func Check(tree *parser.Tree, config *conf.Config) (t reflect.Type, err error) {
4737 }
4838 }
4939
50- return
40+ if v .err != nil {
41+ return t , fmt .Errorf ("%v" , v .err .Format (tree .Source ))
42+ }
43+
44+ return t , nil
5145}
5246
5347type visitor struct {
@@ -57,6 +51,7 @@ type visitor struct {
5751 collections []reflect.Type
5852 strict bool
5953 defaultType reflect.Type
54+ err * file.Error
6055}
6156
6257func (v * visitor ) visit (node ast.Node ) reflect.Type {
@@ -111,14 +106,17 @@ func (v *visitor) visit(node ast.Node) reflect.Type {
111106 return t
112107}
113108
114- func (v * visitor ) error (node ast.Node , format string , args ... interface {}) file.Error {
115- return file.Error {
116- Location : node .Location (),
117- Message : fmt .Sprintf (format , args ... ),
109+ func (v * visitor ) error (node ast.Node , format string , args ... interface {}) reflect.Type {
110+ if v .err == nil { // show first error
111+ v .err = & file.Error {
112+ Location : node .Location (),
113+ Message : fmt .Sprintf (format , args ... ),
114+ }
118115 }
116+ return interfaceType // interface represent undefined type
119117}
120118
121- func (v * visitor ) NilNode (node * ast.NilNode ) reflect.Type {
119+ func (v * visitor ) NilNode (* ast.NilNode ) reflect.Type {
122120 return nilType
123121}
124122
@@ -135,22 +133,22 @@ func (v *visitor) IdentifierNode(node *ast.IdentifierNode) reflect.Type {
135133 }
136134 return interfaceType
137135 }
138- panic ( v .error (node , "unknown name %v" , node .Value ) )
136+ return v .error (node , "unknown name %v" , node .Value )
139137}
140138
141- func (v * visitor ) IntegerNode (node * ast.IntegerNode ) reflect.Type {
139+ func (v * visitor ) IntegerNode (* ast.IntegerNode ) reflect.Type {
142140 return integerType
143141}
144142
145- func (v * visitor ) FloatNode (node * ast.FloatNode ) reflect.Type {
143+ func (v * visitor ) FloatNode (* ast.FloatNode ) reflect.Type {
146144 return floatType
147145}
148146
149- func (v * visitor ) BoolNode (node * ast.BoolNode ) reflect.Type {
147+ func (v * visitor ) BoolNode (* ast.BoolNode ) reflect.Type {
150148 return boolType
151149}
152150
153- func (v * visitor ) StringNode (node * ast.StringNode ) reflect.Type {
151+ func (v * visitor ) StringNode (* ast.StringNode ) reflect.Type {
154152 return stringType
155153}
156154
@@ -170,10 +168,10 @@ func (v *visitor) UnaryNode(node *ast.UnaryNode) reflect.Type {
170168 }
171169
172170 default :
173- panic ( v .error (node , "unknown operator (%v)" , node .Operator ) )
171+ return v .error (node , "unknown operator (%v)" , node .Operator )
174172 }
175173
176- panic ( v .error (node , `invalid operation: %v (mismatched type %v)` , node .Operator , t ) )
174+ return v .error (node , `invalid operation: %v (mismatched type %v)` , node .Operator , t )
177175}
178176
179177func (v * visitor ) BinaryNode (node * ast.BinaryNode ) reflect.Type {
@@ -255,11 +253,11 @@ func (v *visitor) BinaryNode(node *ast.BinaryNode) reflect.Type {
255253 }
256254
257255 default :
258- panic ( v .error (node , "unknown operator (%v)" , node .Operator ) )
256+ return v .error (node , "unknown operator (%v)" , node .Operator )
259257
260258 }
261259
262- panic ( v .error (node , `invalid operation: %v (mismatched types %v and %v)` , node .Operator , l , r ) )
260+ return v .error (node , `invalid operation: %v (mismatched types %v and %v)` , node .Operator , l , r )
263261}
264262
265263func (v * visitor ) MatchesNode (node * ast.MatchesNode ) reflect.Type {
@@ -270,7 +268,7 @@ func (v *visitor) MatchesNode(node *ast.MatchesNode) reflect.Type {
270268 return boolType
271269 }
272270
273- panic ( v .error (node , `invalid operation: matches (mismatched types %v and %v)` , l , r ) )
271+ return v .error (node , `invalid operation: matches (mismatched types %v and %v)` , l , r )
274272}
275273
276274func (v * visitor ) PropertyNode (node * ast.PropertyNode ) reflect.Type {
@@ -280,7 +278,7 @@ func (v *visitor) PropertyNode(node *ast.PropertyNode) reflect.Type {
280278 return t
281279 }
282280
283- panic ( v .error (node , "type %v has no field %v" , t , node .Property ) )
281+ return v .error (node , "type %v has no field %v" , t , node .Property )
284282}
285283
286284func (v * visitor ) IndexNode (node * ast.IndexNode ) reflect.Type {
@@ -289,12 +287,12 @@ func (v *visitor) IndexNode(node *ast.IndexNode) reflect.Type {
289287
290288 if t , ok := indexType (t ); ok {
291289 if ! isInteger (i ) && ! isString (i ) {
292- panic ( v .error (node , "invalid operation: cannot use %v as index to %v" , i , t ) )
290+ return v .error (node , "invalid operation: cannot use %v as index to %v" , i , t )
293291 }
294292 return t
295293 }
296294
297- panic ( v .error (node , "invalid operation: type %v does not support indexing" , t ) )
295+ return v .error (node , "invalid operation: type %v does not support indexing" , t )
298296}
299297
300298func (v * visitor ) SliceNode (node * ast.SliceNode ) reflect.Type {
@@ -306,19 +304,19 @@ func (v *visitor) SliceNode(node *ast.SliceNode) reflect.Type {
306304 if node .From != nil {
307305 from := v .visit (node .From )
308306 if ! isInteger (from ) {
309- panic ( v .error (node .From , "invalid operation: non-integer slice index %v" , from ) )
307+ return v .error (node .From , "invalid operation: non-integer slice index %v" , from )
310308 }
311309 }
312310 if node .To != nil {
313311 to := v .visit (node .To )
314312 if ! isInteger (to ) {
315- panic ( v .error (node .To , "invalid operation: non-integer slice index %v" , to ) )
313+ return v .error (node .To , "invalid operation: non-integer slice index %v" , to )
316314 }
317315 }
318316 return t
319317 }
320318
321- panic ( v .error (node , "invalid operation: cannot slice %v" , t ) )
319+ return v .error (node , "invalid operation: cannot slice %v" , t )
322320}
323321
324322func (v * visitor ) FunctionNode (node * ast.FunctionNode ) reflect.Type {
@@ -349,7 +347,7 @@ func (v *visitor) FunctionNode(node *ast.FunctionNode) reflect.Type {
349347 }
350348 return interfaceType
351349 }
352- panic ( v .error (node , "unknown func %v" , node .Name ) )
350+ return v .error (node , "unknown func %v" , node .Name )
353351}
354352
355353func (v * visitor ) MethodNode (node * ast.MethodNode ) reflect.Type {
@@ -359,7 +357,7 @@ func (v *visitor) MethodNode(node *ast.MethodNode) reflect.Type {
359357 return v .checkFunc (fn , method , node , node .Method , node .Arguments )
360358 }
361359 }
362- panic ( v .error (node , "type %v has no method %v" , t , node .Method ) )
360+ return v .error (node , "type %v has no method %v" , t , node .Method )
363361}
364362
365363// checkFunc checks func arguments and returns "return type" of func or method.
@@ -369,10 +367,10 @@ func (v *visitor) checkFunc(fn reflect.Type, method bool, node ast.Node, name st
369367 }
370368
371369 if fn .NumOut () == 0 {
372- panic ( v .error (node , "func %v doesn't return value" , name ) )
370+ return v .error (node , "func %v doesn't return value" , name )
373371 }
374372 if fn .NumOut () != 1 {
375- panic ( v .error (node , "func %v returns more then one value" , name ) )
373+ return v .error (node , "func %v returns more then one value" , name )
376374 }
377375
378376 numIn := fn .NumIn ()
@@ -385,14 +383,14 @@ func (v *visitor) checkFunc(fn reflect.Type, method bool, node ast.Node, name st
385383
386384 if fn .IsVariadic () {
387385 if len (arguments ) < numIn - 1 {
388- panic ( v .error (node , "not enough arguments to call %v" , name ) )
386+ return v .error (node , "not enough arguments to call %v" , name )
389387 }
390388 } else {
391389 if len (arguments ) > numIn {
392- panic ( v .error (node , "too many arguments to call %v" , name ) )
390+ return v .error (node , "too many arguments to call %v" , name )
393391 }
394392 if len (arguments ) < numIn {
395- panic ( v .error (node , "not enough arguments to call %v" , name ) )
393+ return v .error (node , "not enough arguments to call %v" , name )
396394 }
397395 }
398396
@@ -426,7 +424,7 @@ func (v *visitor) checkFunc(fn reflect.Type, method bool, node ast.Node, name st
426424 }
427425
428426 if ! t .AssignableTo (in ) {
429- panic ( v .error (arg , "cannot use %v as argument (type %v) to call %v " , t , in , name ) )
427+ return v .error (arg , "cannot use %v as argument (type %v) to call %v " , t , in , name )
430428 }
431429 }
432430
@@ -441,12 +439,12 @@ func (v *visitor) BuiltinNode(node *ast.BuiltinNode) reflect.Type {
441439 if isArray (param ) || isMap (param ) || isString (param ) {
442440 return integerType
443441 }
444- panic ( v .error (node , "invalid argument for len (type %v)" , param ) )
442+ return v .error (node , "invalid argument for len (type %v)" , param )
445443
446444 case "all" , "none" , "any" , "one" :
447445 collection := v .visit (node .Arguments [0 ])
448446 if ! isArray (collection ) {
449- panic ( v .error (node .Arguments [0 ], "builtin %v takes only array (got %v)" , node .Name , collection ) )
447+ return v .error (node .Arguments [0 ], "builtin %v takes only array (got %v)" , node .Name , collection )
450448 }
451449
452450 v .collections = append (v .collections , collection )
@@ -458,16 +456,16 @@ func (v *visitor) BuiltinNode(node *ast.BuiltinNode) reflect.Type {
458456 closure .NumIn () == 1 && isInterface (closure .In (0 )) {
459457
460458 if ! isBool (closure .Out (0 )) {
461- panic ( v .error (node .Arguments [1 ], "closure should return boolean (got %v)" , closure .Out (0 ).String () ))
459+ return v .error (node .Arguments [1 ], "closure should return boolean (got %v)" , closure .Out (0 ).String ())
462460 }
463461 return boolType
464462 }
465- panic ( v .error (node .Arguments [1 ], "closure should has one input and one output param" ) )
463+ return v .error (node .Arguments [1 ], "closure should has one input and one output param" )
466464
467465 case "filter" :
468466 collection := v .visit (node .Arguments [0 ])
469467 if ! isArray (collection ) {
470- panic ( v .error (node .Arguments [0 ], "builtin %v takes only array (got %v)" , node .Name , collection ) )
468+ return v .error (node .Arguments [0 ], "builtin %v takes only array (got %v)" , node .Name , collection )
471469 }
472470
473471 v .collections = append (v .collections , collection )
@@ -479,16 +477,16 @@ func (v *visitor) BuiltinNode(node *ast.BuiltinNode) reflect.Type {
479477 closure .NumIn () == 1 && isInterface (closure .In (0 )) {
480478
481479 if ! isBool (closure .Out (0 )) {
482- panic ( v .error (node .Arguments [1 ], "closure should return boolean (got %v)" , closure .Out (0 ).String () ))
480+ return v .error (node .Arguments [1 ], "closure should return boolean (got %v)" , closure .Out (0 ).String ())
483481 }
484482 return arrayType
485483 }
486- panic ( v .error (node .Arguments [1 ], "closure should has one input and one output param" ) )
484+ return v .error (node .Arguments [1 ], "closure should has one input and one output param" )
487485
488486 case "map" :
489487 collection := v .visit (node .Arguments [0 ])
490488 if ! isArray (collection ) {
491- panic ( v .error (node .Arguments [0 ], "builtin %v takes only array (got %v)" , node .Name , collection ) )
489+ return v .error (node .Arguments [0 ], "builtin %v takes only array (got %v)" , node .Name , collection )
492490 }
493491
494492 v .collections = append (v .collections , collection )
@@ -501,12 +499,12 @@ func (v *visitor) BuiltinNode(node *ast.BuiltinNode) reflect.Type {
501499
502500 return reflect .SliceOf (closure .Out (0 ))
503501 }
504- panic ( v .error (node .Arguments [1 ], "closure should has one input and one output param" ) )
502+ return v .error (node .Arguments [1 ], "closure should has one input and one output param" )
505503
506504 case "count" :
507505 collection := v .visit (node .Arguments [0 ])
508506 if ! isArray (collection ) {
509- panic ( v .error (node .Arguments [0 ], "builtin %v takes only array (got %v)" , node .Name , collection ) )
507+ return v .error (node .Arguments [0 ], "builtin %v takes only array (got %v)" , node .Name , collection )
510508 }
511509
512510 v .collections = append (v .collections , collection )
@@ -517,15 +515,15 @@ func (v *visitor) BuiltinNode(node *ast.BuiltinNode) reflect.Type {
517515 closure .NumOut () == 1 &&
518516 closure .NumIn () == 1 && isInterface (closure .In (0 )) {
519517 if ! isBool (closure .Out (0 )) {
520- panic ( v .error (node .Arguments [1 ], "closure should return boolean (got %v)" , closure .Out (0 ).String () ))
518+ return v .error (node .Arguments [1 ], "closure should return boolean (got %v)" , closure .Out (0 ).String ())
521519 }
522520
523521 return integerType
524522 }
525- panic ( v .error (node .Arguments [1 ], "closure should has one input and one output param" ) )
523+ return v .error (node .Arguments [1 ], "closure should has one input and one output param" )
526524
527525 default :
528- panic ( v .error (node , "unknown builtin %v" , node .Name ) )
526+ return v .error (node , "unknown builtin %v" , node .Name )
529527 }
530528}
531529
@@ -536,21 +534,21 @@ func (v *visitor) ClosureNode(node *ast.ClosureNode) reflect.Type {
536534
537535func (v * visitor ) PointerNode (node * ast.PointerNode ) reflect.Type {
538536 if len (v .collections ) == 0 {
539- panic ( v .error (node , "cannot use pointer accessor outside closure" ) )
537+ return v .error (node , "cannot use pointer accessor outside closure" )
540538 }
541539
542540 collection := v .collections [len (v .collections )- 1 ]
543541
544542 if t , ok := indexType (collection ); ok {
545543 return t
546544 }
547- panic ( v .error (node , "cannot use %v as array" , collection ) )
545+ return v .error (node , "cannot use %v as array" , collection )
548546}
549547
550548func (v * visitor ) ConditionalNode (node * ast.ConditionalNode ) reflect.Type {
551549 c := v .visit (node .Cond )
552550 if ! isBool (c ) {
553- panic ( v .error (node .Cond , "non-bool expression (type %v) used as condition" , c ) )
551+ return v .error (node .Cond , "non-bool expression (type %v) used as condition" , c )
554552 }
555553
556554 t1 := v .visit (node .Exp1 )
0 commit comments