(e ast.Expr, inType super.Type)
| 21 | ) |
| 22 | |
| 23 | func (t *translator) expr(e ast.Expr, inType super.Type) (sem.Expr, super.Type) { |
| 24 | switch e := e.(type) { |
| 25 | case *ast.AggFuncExpr: |
| 26 | expr, _ := t.exprNullable(e.Expr, inType) |
| 27 | nameLower := strings.ToLower(e.Name) |
| 28 | if expr == nil && nameLower != "count" { |
| 29 | t.error(e, fmt.Errorf("aggregator '%s' requires argument", e.Name)) |
| 30 | return badExpr, badType |
| 31 | } |
| 32 | return t.aggFunc(e, nameLower, e.Expr, e.Filter, e.Distinct, inType) |
| 33 | case *ast.ArrayExpr: |
| 34 | elems, elemsType := t.arrayElems(e.Elems, inType) |
| 35 | if subquery := t.arraySubquery(elems); subquery != nil { |
| 36 | return subquery, t.checker.unknown //XXX TBD |
| 37 | } |
| 38 | return &sem.ArrayExpr{ |
| 39 | Node: e, |
| 40 | Elems: elems, |
| 41 | }, t.sctx.LookupTypeArray(elemsType) |
| 42 | case *ast.BinaryExpr: |
| 43 | return t.binaryExpr(e, inType) |
| 44 | case *ast.BetweenExpr: |
| 45 | val, valType := t.expr(e.Expr, inType) |
| 46 | lower, lowerType := t.expr(e.Lower, inType) |
| 47 | upper, upperType := t.expr(e.Upper, inType) |
| 48 | // Copy val so an optimizer change to one instance doesn't affect the other. |
| 49 | expr := &sem.BinaryExpr{ |
| 50 | Node: e, |
| 51 | Op: "and", |
| 52 | LHS: &sem.BinaryExpr{ |
| 53 | Node: e.Lower, |
| 54 | Op: ">=", |
| 55 | LHS: val, |
| 56 | RHS: lower, |
| 57 | }, |
| 58 | RHS: &sem.BinaryExpr{ |
| 59 | Node: e.Upper, |
| 60 | Op: "<=", |
| 61 | LHS: sem.CopyExpr(val), |
| 62 | RHS: upper, |
| 63 | }, |
| 64 | } |
| 65 | t.checker.comparison(lowerType, valType) |
| 66 | t.checker.comparison(valType, upperType) |
| 67 | if e.Not { |
| 68 | return sem.NewUnaryExpr(e, "!", expr), super.TypeBool |
| 69 | } |
| 70 | return expr, super.TypeBool |
| 71 | case *ast.CaseExpr: |
| 72 | return t.semCaseExpr(e, inType) |
| 73 | case *ast.CondExpr: |
| 74 | var errlocs [][]errloc |
| 75 | cond, condType := t.expr(e.Cond, inType) |
| 76 | t.checker.boolean(e.Cond, condType) |
| 77 | t.checker.pushErrs() |
| 78 | thenExpr, thenType := t.expr(e.Then, inType) |
| 79 | if errs := t.checker.popErrs(); len(errs) != 0 { |
| 80 | errlocs = append(errlocs, errs) |
no test coverage detected