Skip to content

Commit

Permalink
semantic check: identify boolean udfs (#4886)
Browse files Browse the repository at this point in the history
Update the semantic analyzer isBool function to identify user-defined
functions that return a boolean value.
  • Loading branch information
mattnibs authored Nov 16, 2023
1 parent 48342ce commit bedcc95
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 4 deletions.
12 changes: 8 additions & 4 deletions compiler/semantic/op.go
Original file line number Diff line number Diff line change
Expand Up @@ -1014,7 +1014,7 @@ func (a *analyzer) semOpExpr(e ast.Expr, seq dag.Seq) (dag.Seq, error) {
if err != nil {
return nil, err
}
if isBool(out) {
if a.isBool(out) {
return append(seq, dag.NewFilter(out)), nil
}
return append(seq, &dag.Yield{
Expand All @@ -1023,12 +1023,12 @@ func (a *analyzer) semOpExpr(e ast.Expr, seq dag.Seq) (dag.Seq, error) {
}), nil
}

func isBool(e dag.Expr) bool {
func (a *analyzer) isBool(e dag.Expr) bool {
switch e := e.(type) {
case *dag.Literal:
return e.Value == "true" || e.Value == "false"
case *dag.UnaryExpr:
return isBool(e.Operand)
return a.isBool(e.Operand)
case *dag.BinaryExpr:
switch e.Op {
case "and", "or", "in", "==", "!=", "<", "<=", ">", ">=":
Expand All @@ -1037,8 +1037,12 @@ func isBool(e dag.Expr) bool {
return false
}
case *dag.Conditional:
return isBool(e.Then) && isBool(e.Else)
return a.isBool(e.Then) && a.isBool(e.Else)
case *dag.Call:
// If udf recurse to inner expression.
if f, _ := a.scope.LookupExpr(e.Name); f != nil {
return a.isBool(f.(*dag.Func).Expr)
}
if e.Name == "cast" {
if len(e.Args) != 2 {
return false
Expand Down
14 changes: 14 additions & 0 deletions compiler/ztests/udf-implied-where.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
script: |
zc -C -s 'func h(e): ( has(e) ) h(foo)'
outputs:
- name: stdout
data: |
reader
| (
func h(e): (
has(e)
)
where h(foo)
)

0 comments on commit bedcc95

Please sign in to comment.