Skip to content

Commit 5cb0507

Browse files
committed
Improve checker for builtins
1 parent 10df616 commit 5cb0507

File tree

2 files changed

+43
-24
lines changed

2 files changed

+43
-24
lines changed

checker/checker.go

+28-24
Original file line numberDiff line numberDiff line change
@@ -441,60 +441,64 @@ func (v *visitor) BuiltinNode(node *ast.BuiltinNode) reflect.Type {
441441

442442
case "all", "none", "any", "one":
443443
collection := v.visit(node.Arguments[0])
444+
if !isArray(collection) {
445+
panic(v.error(node.Arguments[0], "builtin %v takes only array (got %v)", node.Name, collection))
446+
}
444447

445448
v.collections = append(v.collections, collection)
446449
closure := v.visit(node.Arguments[1])
447450
v.collections = v.collections[:len(v.collections)-1]
448451

449-
if isArray(collection) {
450-
if isFunc(closure) &&
451-
closure.NumOut() == 1 && isBool(closure.Out(0)) &&
452-
closure.NumIn() == 1 && isInterface(closure.In(0)) {
453-
454-
return boolType
452+
if isFunc(closure) &&
453+
closure.NumOut() == 1 &&
454+
closure.NumIn() == 1 && isInterface(closure.In(0)) {
455455

456+
if !isBool(closure.Out(0)) {
457+
panic(v.error(node.Arguments[1], "closure should return boolean (got %v)", closure.Out(0).String()))
456458
}
457-
panic(v.error(node.Arguments[1], "closure should return bool"))
459+
return boolType
458460
}
459-
panic(v.error(node.Arguments[0], "builtin %v takes only array (got %v)", node.Name, collection))
461+
panic(v.error(node.Arguments[1], "closure should has one input and one output param"))
460462

461463
case "filter":
462464
collection := v.visit(node.Arguments[0])
465+
if !isArray(collection) {
466+
panic(v.error(node.Arguments[0], "builtin %v takes only array (got %v)", node.Name, collection))
467+
}
463468

464469
v.collections = append(v.collections, collection)
465470
closure := v.visit(node.Arguments[1])
466471
v.collections = v.collections[:len(v.collections)-1]
467472

468-
if isArray(collection) {
469-
if isFunc(closure) &&
470-
closure.NumOut() == 1 && isBool(closure.Out(0)) &&
471-
closure.NumIn() == 1 && isInterface(closure.In(0)) {
472-
473-
return collection
473+
if isFunc(closure) &&
474+
closure.NumOut() == 1 &&
475+
closure.NumIn() == 1 && isInterface(closure.In(0)) {
474476

477+
if !isBool(closure.Out(0)) {
478+
panic(v.error(node.Arguments[1], "closure should return boolean (got %v)", closure.Out(0).String()))
475479
}
476-
panic(v.error(node.Arguments[1], "closure should return bool"))
480+
return arrayType
477481
}
478-
panic(v.error(node.Arguments[0], "builtin %v takes only array (got %v)", node.Name, collection))
482+
panic(v.error(node.Arguments[1], "closure should has one input and one output param"))
479483

480484
case "map":
481485
collection := v.visit(node.Arguments[0])
486+
if !isArray(collection) {
487+
panic(v.error(node.Arguments[0], "builtin %v takes only array (got %v)", node.Name, collection))
488+
}
482489

483490
v.collections = append(v.collections, collection)
484491
closure := v.visit(node.Arguments[1])
485492
v.collections = v.collections[:len(v.collections)-1]
486493

487-
if isArray(collection) {
488-
if isFunc(closure) &&
489-
closure.NumOut() == 1 &&
490-
closure.NumIn() == 1 && isInterface(closure.In(0)) {
494+
if isFunc(closure) &&
495+
closure.NumOut() == 1 &&
496+
closure.NumIn() == 1 && isInterface(closure.In(0)) {
491497

492-
return reflect.ArrayOf(0, closure.Out(0))
498+
return reflect.ArrayOf(0, closure.Out(0))
493499

494-
}
495-
panic(v.error(node.Arguments[1], "closure should has one input and one output param"))
496500
}
497-
panic(v.error(node.Arguments[0], "builtin %v takes only array (got %v)", node.Name, collection))
501+
panic(v.error(node.Arguments[1], "closure should has one input and one output param"))
498502

499503
case "count":
500504
collection := v.visit(node.Arguments[0])

checker/checker_test.go

+15
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,21 @@ count(ArrayOfInt, {#})
450450
closure should return boolean (got int) (1:19)
451451
| count(ArrayOfInt, {#})
452452
| ..................^
453+
454+
all(ArrayOfInt, {# + 1})
455+
closure should return boolean (got int) (1:17)
456+
| all(ArrayOfInt, {# + 1})
457+
| ................^
458+
459+
filter(ArrayOfFoo, {.Int64})
460+
closure should return boolean (got int64) (1:20)
461+
| filter(ArrayOfFoo, {.Int64})
462+
| ...................^
463+
464+
map(1, {2})
465+
builtin map takes only array (got int) (1:5)
466+
| map(1, {2})
467+
| ....^
453468
`
454469

455470
func TestCheck_error(t *testing.T) {

0 commit comments

Comments
 (0)