@@ -10,17 +10,7 @@ import (
10
10
"github.com/antonmedv/expr/parser"
11
11
)
12
12
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 ) {
24
14
v := & visitor {
25
15
collections : make ([]reflect.Type , 0 ),
26
16
}
@@ -32,7 +22,7 @@ func Check(tree *parser.Tree, config *conf.Config) (t reflect.Type, err error) {
32
22
v .defaultType = config .DefaultType
33
23
}
34
24
35
- t = v .visit (tree .Node )
25
+ t : = v .visit (tree .Node )
36
26
37
27
if v .expect != reflect .Invalid {
38
28
switch v .expect {
@@ -47,7 +37,11 @@ func Check(tree *parser.Tree, config *conf.Config) (t reflect.Type, err error) {
47
37
}
48
38
}
49
39
50
- return
40
+ if v .err != nil {
41
+ return t , fmt .Errorf ("%v" , v .err .Format (tree .Source ))
42
+ }
43
+
44
+ return t , nil
51
45
}
52
46
53
47
type visitor struct {
@@ -57,6 +51,7 @@ type visitor struct {
57
51
collections []reflect.Type
58
52
strict bool
59
53
defaultType reflect.Type
54
+ err * file.Error
60
55
}
61
56
62
57
func (v * visitor ) visit (node ast.Node ) reflect.Type {
@@ -111,14 +106,17 @@ func (v *visitor) visit(node ast.Node) reflect.Type {
111
106
return t
112
107
}
113
108
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
+ }
118
115
}
116
+ return interfaceType // interface represent undefined type
119
117
}
120
118
121
- func (v * visitor ) NilNode (node * ast.NilNode ) reflect.Type {
119
+ func (v * visitor ) NilNode (* ast.NilNode ) reflect.Type {
122
120
return nilType
123
121
}
124
122
@@ -135,22 +133,22 @@ func (v *visitor) IdentifierNode(node *ast.IdentifierNode) reflect.Type {
135
133
}
136
134
return interfaceType
137
135
}
138
- panic ( v .error (node , "unknown name %v" , node .Value ) )
136
+ return v .error (node , "unknown name %v" , node .Value )
139
137
}
140
138
141
- func (v * visitor ) IntegerNode (node * ast.IntegerNode ) reflect.Type {
139
+ func (v * visitor ) IntegerNode (* ast.IntegerNode ) reflect.Type {
142
140
return integerType
143
141
}
144
142
145
- func (v * visitor ) FloatNode (node * ast.FloatNode ) reflect.Type {
143
+ func (v * visitor ) FloatNode (* ast.FloatNode ) reflect.Type {
146
144
return floatType
147
145
}
148
146
149
- func (v * visitor ) BoolNode (node * ast.BoolNode ) reflect.Type {
147
+ func (v * visitor ) BoolNode (* ast.BoolNode ) reflect.Type {
150
148
return boolType
151
149
}
152
150
153
- func (v * visitor ) StringNode (node * ast.StringNode ) reflect.Type {
151
+ func (v * visitor ) StringNode (* ast.StringNode ) reflect.Type {
154
152
return stringType
155
153
}
156
154
@@ -170,10 +168,10 @@ func (v *visitor) UnaryNode(node *ast.UnaryNode) reflect.Type {
170
168
}
171
169
172
170
default :
173
- panic ( v .error (node , "unknown operator (%v)" , node .Operator ) )
171
+ return v .error (node , "unknown operator (%v)" , node .Operator )
174
172
}
175
173
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 )
177
175
}
178
176
179
177
func (v * visitor ) BinaryNode (node * ast.BinaryNode ) reflect.Type {
@@ -255,11 +253,11 @@ func (v *visitor) BinaryNode(node *ast.BinaryNode) reflect.Type {
255
253
}
256
254
257
255
default :
258
- panic ( v .error (node , "unknown operator (%v)" , node .Operator ) )
256
+ return v .error (node , "unknown operator (%v)" , node .Operator )
259
257
260
258
}
261
259
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 )
263
261
}
264
262
265
263
func (v * visitor ) MatchesNode (node * ast.MatchesNode ) reflect.Type {
@@ -270,7 +268,7 @@ func (v *visitor) MatchesNode(node *ast.MatchesNode) reflect.Type {
270
268
return boolType
271
269
}
272
270
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 )
274
272
}
275
273
276
274
func (v * visitor ) PropertyNode (node * ast.PropertyNode ) reflect.Type {
@@ -280,7 +278,7 @@ func (v *visitor) PropertyNode(node *ast.PropertyNode) reflect.Type {
280
278
return t
281
279
}
282
280
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 )
284
282
}
285
283
286
284
func (v * visitor ) IndexNode (node * ast.IndexNode ) reflect.Type {
@@ -289,12 +287,12 @@ func (v *visitor) IndexNode(node *ast.IndexNode) reflect.Type {
289
287
290
288
if t , ok := indexType (t ); ok {
291
289
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 )
293
291
}
294
292
return t
295
293
}
296
294
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 )
298
296
}
299
297
300
298
func (v * visitor ) SliceNode (node * ast.SliceNode ) reflect.Type {
@@ -306,19 +304,19 @@ func (v *visitor) SliceNode(node *ast.SliceNode) reflect.Type {
306
304
if node .From != nil {
307
305
from := v .visit (node .From )
308
306
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 )
310
308
}
311
309
}
312
310
if node .To != nil {
313
311
to := v .visit (node .To )
314
312
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 )
316
314
}
317
315
}
318
316
return t
319
317
}
320
318
321
- panic ( v .error (node , "invalid operation: cannot slice %v" , t ) )
319
+ return v .error (node , "invalid operation: cannot slice %v" , t )
322
320
}
323
321
324
322
func (v * visitor ) FunctionNode (node * ast.FunctionNode ) reflect.Type {
@@ -349,7 +347,7 @@ func (v *visitor) FunctionNode(node *ast.FunctionNode) reflect.Type {
349
347
}
350
348
return interfaceType
351
349
}
352
- panic ( v .error (node , "unknown func %v" , node .Name ) )
350
+ return v .error (node , "unknown func %v" , node .Name )
353
351
}
354
352
355
353
func (v * visitor ) MethodNode (node * ast.MethodNode ) reflect.Type {
@@ -359,7 +357,7 @@ func (v *visitor) MethodNode(node *ast.MethodNode) reflect.Type {
359
357
return v .checkFunc (fn , method , node , node .Method , node .Arguments )
360
358
}
361
359
}
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 )
363
361
}
364
362
365
363
// 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
369
367
}
370
368
371
369
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 )
373
371
}
374
372
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 )
376
374
}
377
375
378
376
numIn := fn .NumIn ()
@@ -385,14 +383,14 @@ func (v *visitor) checkFunc(fn reflect.Type, method bool, node ast.Node, name st
385
383
386
384
if fn .IsVariadic () {
387
385
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 )
389
387
}
390
388
} else {
391
389
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 )
393
391
}
394
392
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 )
396
394
}
397
395
}
398
396
@@ -426,7 +424,7 @@ func (v *visitor) checkFunc(fn reflect.Type, method bool, node ast.Node, name st
426
424
}
427
425
428
426
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 )
430
428
}
431
429
}
432
430
@@ -441,12 +439,12 @@ func (v *visitor) BuiltinNode(node *ast.BuiltinNode) reflect.Type {
441
439
if isArray (param ) || isMap (param ) || isString (param ) {
442
440
return integerType
443
441
}
444
- panic ( v .error (node , "invalid argument for len (type %v)" , param ) )
442
+ return v .error (node , "invalid argument for len (type %v)" , param )
445
443
446
444
case "all" , "none" , "any" , "one" :
447
445
collection := v .visit (node .Arguments [0 ])
448
446
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 )
450
448
}
451
449
452
450
v .collections = append (v .collections , collection )
@@ -458,16 +456,16 @@ func (v *visitor) BuiltinNode(node *ast.BuiltinNode) reflect.Type {
458
456
closure .NumIn () == 1 && isInterface (closure .In (0 )) {
459
457
460
458
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 ())
462
460
}
463
461
return boolType
464
462
}
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" )
466
464
467
465
case "filter" :
468
466
collection := v .visit (node .Arguments [0 ])
469
467
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 )
471
469
}
472
470
473
471
v .collections = append (v .collections , collection )
@@ -479,16 +477,16 @@ func (v *visitor) BuiltinNode(node *ast.BuiltinNode) reflect.Type {
479
477
closure .NumIn () == 1 && isInterface (closure .In (0 )) {
480
478
481
479
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 ())
483
481
}
484
482
return arrayType
485
483
}
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" )
487
485
488
486
case "map" :
489
487
collection := v .visit (node .Arguments [0 ])
490
488
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 )
492
490
}
493
491
494
492
v .collections = append (v .collections , collection )
@@ -501,12 +499,12 @@ func (v *visitor) BuiltinNode(node *ast.BuiltinNode) reflect.Type {
501
499
502
500
return reflect .SliceOf (closure .Out (0 ))
503
501
}
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" )
505
503
506
504
case "count" :
507
505
collection := v .visit (node .Arguments [0 ])
508
506
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 )
510
508
}
511
509
512
510
v .collections = append (v .collections , collection )
@@ -517,15 +515,15 @@ func (v *visitor) BuiltinNode(node *ast.BuiltinNode) reflect.Type {
517
515
closure .NumOut () == 1 &&
518
516
closure .NumIn () == 1 && isInterface (closure .In (0 )) {
519
517
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 ())
521
519
}
522
520
523
521
return integerType
524
522
}
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" )
526
524
527
525
default :
528
- panic ( v .error (node , "unknown builtin %v" , node .Name ) )
526
+ return v .error (node , "unknown builtin %v" , node .Name )
529
527
}
530
528
}
531
529
@@ -536,21 +534,21 @@ func (v *visitor) ClosureNode(node *ast.ClosureNode) reflect.Type {
536
534
537
535
func (v * visitor ) PointerNode (node * ast.PointerNode ) reflect.Type {
538
536
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" )
540
538
}
541
539
542
540
collection := v .collections [len (v .collections )- 1 ]
543
541
544
542
if t , ok := indexType (collection ); ok {
545
543
return t
546
544
}
547
- panic ( v .error (node , "cannot use %v as array" , collection ) )
545
+ return v .error (node , "cannot use %v as array" , collection )
548
546
}
549
547
550
548
func (v * visitor ) ConditionalNode (node * ast.ConditionalNode ) reflect.Type {
551
549
c := v .visit (node .Cond )
552
550
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 )
554
552
}
555
553
556
554
t1 := v .visit (node .Exp1 )
0 commit comments