syncthing/vendor/github.com/cznic/ql/expr.go
2016-06-02 13:53:30 +02:00

4026 lines
74 KiB
Go

// Copyright 2014 The ql Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found pIn the LICENSE file.
package ql
import (
"fmt"
"math/big"
"regexp"
"strings"
"time"
)
var (
_ expression = (*binaryOperation)(nil)
_ expression = (*call)(nil)
_ expression = (*conversion)(nil)
_ expression = (*ident)(nil)
_ expression = (*indexOp)(nil)
_ expression = (*isNull)(nil)
_ expression = (*pIn)(nil)
_ expression = (*pLike)(nil)
_ expression = (*parameter)(nil)
_ expression = (*pexpr)(nil)
_ expression = (*slice)(nil)
_ expression = (*unaryOperation)(nil)
_ expression = value{}
)
type expression interface {
clone(arg []interface{}, unqualify ...string) (expression, error)
eval(execCtx *execCtx, ctx map[interface{}]interface{}) (v interface{}, err error)
isStatic() bool
String() string
}
func cloneExpressionList(arg []interface{}, list []expression, unqualify ...string) ([]expression, error) {
r := make([]expression, len(list))
var err error
for i, v := range list {
if r[i], err = v.clone(arg, unqualify...); err != nil {
return nil, err
}
}
return r, nil
}
func isConstValue(v interface{}) interface{} {
switch x := v.(type) {
case value:
return x.val
case
idealComplex,
idealFloat,
idealInt,
idealRune,
idealUint:
return v
default:
return nil
}
}
func isColumnExpression(v expression) (bool, string) {
x, ok := v.(*ident)
if ok {
return true, x.s
}
c, ok := v.(*call)
if !ok || c.f != "id" || len(c.arg) != 0 {
return false, ""
}
return true, "id()"
}
func mentionedColumns0(e expression, q, nq bool, m map[string]struct{}) {
switch x := e.(type) {
case parameter,
value:
// nop
case *binaryOperation:
mentionedColumns0(x.l, q, nq, m)
mentionedColumns0(x.r, q, nq, m)
case *call:
if x.f != "id" {
for _, e := range x.arg {
mentionedColumns0(e, q, nq, m)
}
}
case *conversion:
mentionedColumns0(x.val, q, nq, m)
case *ident:
if q && x.isQualified() {
m[x.s] = struct{}{}
}
if nq && !x.isQualified() {
m[x.s] = struct{}{}
}
case *indexOp:
mentionedColumns0(x.expr, q, nq, m)
mentionedColumns0(x.x, q, nq, m)
case *isNull:
mentionedColumns0(x.expr, q, nq, m)
case *pexpr:
mentionedColumns0(x.expr, q, nq, m)
case *pIn:
mentionedColumns0(x.expr, q, nq, m)
for _, e := range x.list {
mentionedColumns0(e, q, nq, m)
}
case *pLike:
mentionedColumns0(x.expr, q, nq, m)
mentionedColumns0(x.pattern, q, nq, m)
case *slice:
mentionedColumns0(x.expr, q, nq, m)
if y := x.lo; y != nil {
mentionedColumns0(*y, q, nq, m)
}
if y := x.hi; y != nil {
mentionedColumns0(*y, q, nq, m)
}
case *unaryOperation:
mentionedColumns0(x.v, q, nq, m)
default:
panic("internal error 052")
}
}
func mentionedColumns(e expression) map[string]struct{} {
m := map[string]struct{}{}
mentionedColumns0(e, false, true, m)
return m
}
func mentionedQColumns(e expression) map[string]struct{} {
m := map[string]struct{}{}
mentionedColumns0(e, true, false, m)
return m
}
func staticExpr(e expression) (expression, error) {
if e.isStatic() {
v, err := e.eval(nil, nil)
if err != nil {
return nil, err
}
if v == nil {
return value{nil}, nil
}
return value{v}, nil
}
return e, nil
}
type (
idealComplex complex128
idealFloat float64
idealInt int64
idealRune int32
idealUint uint64
)
type exprTab struct {
expr expression
table string
}
type pexpr struct {
expr expression
}
func (p *pexpr) clone(arg []interface{}, unqualify ...string) (expression, error) {
expr, err := p.expr.clone(arg, unqualify...)
if err != nil {
return nil, err
}
return &pexpr{expr: expr}, nil
}
func (p *pexpr) isStatic() bool { return p.expr.isStatic() }
func (p *pexpr) String() string {
return fmt.Sprintf("(%s)", p.expr)
}
func (p *pexpr) eval(execCtx *execCtx, ctx map[interface{}]interface{}) (v interface{}, err error) {
return p.expr.eval(execCtx, ctx)
}
//DONE newBetween
//LATER like newBetween, check all others have and use new*
func newBetween(expr, lo, hi interface{}, not bool) (expression, error) {
e, err := staticExpr(expr.(expression))
if err != nil {
return nil, err
}
l, err := staticExpr(lo.(expression))
if err != nil {
return nil, err
}
h, err := staticExpr(hi.(expression))
if err != nil {
return nil, err
}
var a, b expression
op := andand
switch {
case not: // e < l || e > h
op = oror
if a, err = newBinaryOperation('<', e, l); err != nil {
return nil, err
}
if b, err = newBinaryOperation('>', e, h); err != nil {
return nil, err
}
default: // e >= l && e <= h
if a, err = newBinaryOperation(ge, e, l); err != nil {
return nil, err
}
if b, err = newBinaryOperation(le, e, h); err != nil {
return nil, err
}
}
if a, err = staticExpr(a); err != nil {
return nil, err
}
if b, err = staticExpr(b); err != nil {
return nil, err
}
ret, err := newBinaryOperation(op, a, b)
if err != nil {
return nil, err
}
return staticExpr(ret)
}
type pLike struct {
expr expression
pattern expression
re *regexp.Regexp
sexpr *string
}
func (p *pLike) clone(arg []interface{}, unqualify ...string) (expression, error) {
expr, err := p.expr.clone(arg, unqualify...)
if err != nil {
return nil, err
}
pattern, err := p.pattern.clone(arg, unqualify...)
if err != nil {
return nil, err
}
return &pLike{
expr: expr,
pattern: pattern,
re: p.re,
sexpr: p.sexpr,
}, nil
}
func (p *pLike) isStatic() bool { return p.expr.isStatic() && p.pattern.isStatic() }
func (p *pLike) String() string { return fmt.Sprintf("%s LIKE %s", p.expr, p.pattern) }
func (p *pLike) eval(execCtx *execCtx, ctx map[interface{}]interface{}) (v interface{}, err error) {
var sexpr string
var ok bool
switch {
case p.sexpr != nil:
sexpr = *p.sexpr
default:
expr, err := expand1(p.expr.eval(execCtx, ctx))
if err != nil {
return nil, err
}
if expr == nil {
return nil, nil
}
sexpr, ok = expr.(string)
if !ok {
return nil, fmt.Errorf("non-string expression in LIKE: %v (value of type %T)", expr, expr)
}
if p.expr.isStatic() {
p.sexpr = new(string)
*p.sexpr = sexpr
}
}
re := p.re
if re == nil {
pattern, err := expand1(p.pattern.eval(execCtx, ctx))
if err != nil {
return nil, err
}
if pattern == nil {
return nil, nil
}
spattern, ok := pattern.(string)
if !ok {
return nil, fmt.Errorf("non-string pattern in LIKE: %v (value of type %T)", pattern, pattern)
}
if re, err = regexp.Compile(spattern); err != nil {
return nil, err
}
if p.pattern.isStatic() {
p.re = re
}
}
return re.MatchString(sexpr), nil
}
type binaryOperation struct {
op int
l, r expression
}
func newBinaryOperation0(op int, x, y interface{}) (v expression, err error) {
if op == eq {
if l, ok := x.(value); ok {
if b, ok := l.val.(bool); ok {
if b { // true == y: y
return y.(expression), nil
}
// false == y: !y
return newUnaryOperation('!', y)
}
}
if r, ok := y.(value); ok {
if b, ok := r.val.(bool); ok {
if b { // x == true: x
return x.(expression), nil
}
// x == false: !x
return newUnaryOperation('!', x)
}
}
}
if op == neq {
if l, ok := x.(value); ok {
if b, ok := l.val.(bool); ok {
if b { // true != y: !y
return newUnaryOperation('!', y)
}
// false != y: y
return y.(expression), nil
}
}
if r, ok := y.(value); ok {
if b, ok := r.val.(bool); ok {
if b { // x != true: !x
return newUnaryOperation('!', x)
}
// x != false: x
return x.(expression), nil
}
}
}
b := binaryOperation{op, x.(expression), y.(expression)}
var lv interface{}
if e := b.l; e.isStatic() {
if lv, err = e.eval(nil, nil); err != nil {
return nil, err
}
b.l = value{lv}
}
if e := b.r; e.isStatic() {
v, err := e.eval(nil, nil)
if err != nil {
return nil, err
}
if v == nil {
return value{nil}, nil
}
if op == '/' || op == '%' {
rb := binaryOperation{eq, e, value{idealInt(0)}}
val, err := rb.eval(nil, nil)
if err != nil {
return nil, err
}
if val.(bool) {
return nil, errDivByZero
}
}
if b.l.isStatic() && lv == nil {
return value{nil}, nil
}
b.r = value{v}
}
if !b.isStatic() {
return &b, nil
}
val, err := b.eval(nil, nil)
return value{val}, err
}
func newBinaryOperation(op int, x, y interface{}) (v expression, err error) {
expr, err := newBinaryOperation0(op, x, y)
if err != nil {
return nil, err
}
b, ok := expr.(*binaryOperation)
if !ok {
return expr, nil
}
if _, ok := b.l.(*ident); ok {
return expr, nil
}
if c, ok := b.l.(*call); ok && c.f == "id" {
return expr, nil
}
var r expression
if r, ok = b.r.(*ident); !ok {
r1, ok := b.r.(*call)
if !ok || r1.f != "id" || len(r1.arg) != 0 {
return expr, nil
}
r = r1
}
// Normalize expr relOp indent: ident invRelOp expr
switch b.op {
case '<':
return &binaryOperation{'>', r, b.l}, nil
case le:
return &binaryOperation{ge, r, b.l}, nil
case '>':
return &binaryOperation{'<', r, b.l}, nil
case ge:
return &binaryOperation{le, r, b.l}, nil
case eq, neq:
return &binaryOperation{b.op, r, b.l}, nil
default:
return expr, nil
}
}
func (o *binaryOperation) isIdentRelOpVal() (bool, string, interface{}, error) {
sid := ""
id, ok := o.l.(*ident)
if !ok {
f, ok := o.l.(*call)
if !ok || f.f != "id" || len(f.arg) != 0 {
return false, "", nil, nil
}
sid = "id()"
} else {
if id.isQualified() {
return false, "", nil, nil
}
sid = id.s
}
if v, ok := o.r.(value); ok {
switch o.op {
case '<',
le,
'>',
ge,
eq,
neq:
return true, sid, v.val, nil
default:
return false, "", nil, nil
}
}
return false, "", nil, nil
}
func (o *binaryOperation) clone(arg []interface{}, unqualify ...string) (expression, error) {
l, err := o.l.clone(arg, unqualify...)
if err != nil {
return nil, err
}
r, err := o.r.clone(arg, unqualify...)
if err != nil {
return nil, err
}
return newBinaryOperation(o.op, l, r)
}
func (o *binaryOperation) isStatic() bool { return o.l.isStatic() && o.r.isStatic() }
func (o *binaryOperation) String() string {
return fmt.Sprintf("%s %s %s", o.l, iop(o.op), o.r)
}
func (o *binaryOperation) eval(execCtx *execCtx, ctx map[interface{}]interface{}) (r interface{}, err error) {
defer func() {
if e := recover(); e != nil {
switch x := e.(type) {
case error:
r, err = nil, x
default:
r, err = nil, fmt.Errorf("%v", x)
}
}
}()
switch op := o.op; op {
case andand:
a, err := expand1(o.l.eval(execCtx, ctx))
if err != nil {
return nil, err
}
switch x := a.(type) {
case nil:
b, err := expand1(o.r.eval(execCtx, ctx))
if err != nil {
return nil, err
}
switch y := b.(type) {
case nil:
return nil, nil
case bool:
if !y {
return false, nil
}
return nil, nil
default:
return invOp2(x, y, op)
}
case bool:
if !x {
return false, nil
}
b, err := expand1(o.r.eval(execCtx, ctx))
if err != nil {
return nil, err
}
switch y := b.(type) {
case nil:
return nil, nil
case bool:
return y, nil
default:
return invOp2(x, y, op)
}
default:
return undOp(x, op)
}
case oror:
a, err := expand1(o.l.eval(execCtx, ctx))
if err != nil {
return nil, err
}
switch x := a.(type) {
case nil:
b, err := expand1(o.r.eval(execCtx, ctx))
if err != nil {
return nil, err
}
switch y := b.(type) {
case nil:
return nil, nil
case bool:
if y {
return y, nil
}
return nil, nil
default:
return invOp2(x, y, op)
}
case bool:
if x {
return x, nil
}
b, err := expand1(o.r.eval(execCtx, ctx))
if err != nil {
return nil, err
}
switch y := b.(type) {
case nil:
return nil, nil
case bool:
return y, nil
default:
return invOp2(x, y, op)
}
default:
return undOp(x, op)
}
case '>':
a, b := o.get2(execCtx, ctx)
if a == nil || b == nil {
return
}
switch x := a.(type) {
//case nil:
case idealComplex:
return undOp2(a, b, op)
case idealFloat:
switch y := b.(type) {
case idealFloat:
return x > y, nil
default:
return invOp2(x, y, op)
}
case idealInt:
switch y := b.(type) {
case idealInt:
return x > y, nil
default:
return invOp2(x, y, op)
}
case idealRune:
switch y := b.(type) {
case idealRune:
return x > y, nil
default:
return invOp2(x, y, op)
}
case idealUint:
switch y := b.(type) {
case idealUint:
return x > y, nil
default:
return invOp2(x, y, op)
}
case bool:
return undOp2(a, b, op)
case complex64:
return undOp2(a, b, op)
case complex128:
return undOp2(a, b, op)
case float32:
switch y := b.(type) {
case float32:
return x > y, nil
default:
return invOp2(x, y, op)
}
case float64:
switch y := b.(type) {
case float64:
return x > y, nil
default:
return invOp2(x, y, op)
}
case int8:
switch y := b.(type) {
case int8:
return x > y, nil
default:
return invOp2(x, y, op)
}
case int16:
switch y := b.(type) {
case int16:
return x > y, nil
default:
return invOp2(x, y, op)
}
case int32:
switch y := b.(type) {
case int32:
return x > y, nil
default:
return invOp2(x, y, op)
}
case int64:
switch y := b.(type) {
case int64:
return x > y, nil
default:
return invOp2(x, y, op)
}
case string:
switch y := b.(type) {
case string:
return x > y, nil
default:
return invOp2(x, y, op)
}
case uint8:
switch y := b.(type) {
case uint8:
return x > y, nil
default:
return invOp2(x, y, op)
}
case uint16:
switch y := b.(type) {
case uint16:
return x > y, nil
default:
return invOp2(x, y, op)
}
case uint32:
switch y := b.(type) {
case uint32:
return x > y, nil
default:
return invOp2(x, y, op)
}
case uint64:
switch y := b.(type) {
case uint64:
return x > y, nil
default:
return invOp2(x, y, op)
}
case *big.Int:
switch y := b.(type) {
case *big.Int:
return x.Cmp(y) > 0, nil
default:
return invOp2(x, y, op)
}
case *big.Rat:
switch y := b.(type) {
case *big.Rat:
return x.Cmp(y) > 0, nil
default:
return invOp2(x, y, op)
}
case time.Duration:
switch y := b.(type) {
case time.Duration:
return x > y, nil
default:
return invOp2(x, y, op)
}
case time.Time:
switch y := b.(type) {
case time.Time:
return x.After(y), nil
default:
return invOp2(x, y, op)
}
default:
return invOp2(a, b, op)
}
case '<':
a, b := o.get2(execCtx, ctx)
if a == nil || b == nil {
return
}
switch x := a.(type) {
//case nil:
case idealComplex:
return undOp2(a, b, op)
case idealFloat:
switch y := b.(type) {
case idealFloat:
return x < y, nil
default:
return invOp2(x, y, op)
}
case idealInt:
switch y := b.(type) {
case idealInt:
return x < y, nil
default:
return invOp2(x, y, op)
}
case idealRune:
switch y := b.(type) {
case idealRune:
return x < y, nil
default:
return invOp2(x, y, op)
}
case idealUint:
switch y := b.(type) {
case idealUint:
return x < y, nil
default:
return invOp2(x, y, op)
}
case bool:
return undOp2(a, b, op)
case complex64:
return undOp2(a, b, op)
case complex128:
return undOp2(a, b, op)
case float32:
switch y := b.(type) {
case float32:
return x < y, nil
default:
return invOp2(x, y, op)
}
case float64:
switch y := b.(type) {
case float64:
return x < y, nil
default:
return invOp2(x, y, op)
}
case int8:
switch y := b.(type) {
case int8:
return x < y, nil
default:
return invOp2(x, y, op)
}
case int16:
switch y := b.(type) {
case int16:
return x < y, nil
default:
return invOp2(x, y, op)
}
case int32:
switch y := b.(type) {
case int32:
return x < y, nil
default:
return invOp2(x, y, op)
}
case int64:
switch y := b.(type) {
case int64:
return x < y, nil
default:
return invOp2(x, y, op)
}
case string:
switch y := b.(type) {
case string:
return x < y, nil
default:
return invOp2(x, y, op)
}
case uint8:
switch y := b.(type) {
case uint8:
return x < y, nil
default:
return invOp2(x, y, op)
}
case uint16:
switch y := b.(type) {
case uint16:
return x < y, nil
default:
return invOp2(x, y, op)
}
case uint32:
switch y := b.(type) {
case uint32:
return x < y, nil
default:
return invOp2(x, y, op)
}
case uint64:
switch y := b.(type) {
case uint64:
return x < y, nil
default:
return invOp2(x, y, op)
}
case *big.Int:
switch y := b.(type) {
case *big.Int:
return x.Cmp(y) < 0, nil
default:
return invOp2(x, y, op)
}
case *big.Rat:
switch y := b.(type) {
case *big.Rat:
return x.Cmp(y) < 0, nil
default:
return invOp2(x, y, op)
}
case time.Duration:
switch y := b.(type) {
case time.Duration:
return x < y, nil
default:
return invOp2(x, y, op)
}
case time.Time:
switch y := b.(type) {
case time.Time:
return x.Before(y), nil
default:
return invOp2(x, y, op)
}
default:
return invOp2(a, b, op)
}
case le:
a, b := o.get2(execCtx, ctx)
if a == nil || b == nil {
return
}
switch x := a.(type) {
//case nil:
case idealComplex:
return undOp2(a, b, op)
case idealFloat:
switch y := b.(type) {
case idealFloat:
return x <= y, nil
default:
return invOp2(x, y, op)
}
case idealInt:
switch y := b.(type) {
case idealInt:
return x <= y, nil
default:
return invOp2(x, y, op)
}
case idealRune:
switch y := b.(type) {
case idealRune:
return x <= y, nil
default:
return invOp2(x, y, op)
}
case idealUint:
switch y := b.(type) {
case idealUint:
return x <= y, nil
default:
return invOp2(x, y, op)
}
case bool:
return undOp2(a, b, op)
case complex64:
return undOp2(a, b, op)
case complex128:
return undOp2(a, b, op)
case float32:
switch y := b.(type) {
case float32:
return x <= y, nil
default:
return invOp2(x, y, op)
}
case float64:
switch y := b.(type) {
case float64:
return x <= y, nil
default:
return invOp2(x, y, op)
}
case int8:
switch y := b.(type) {
case int8:
return x <= y, nil
default:
return invOp2(x, y, op)
}
case int16:
switch y := b.(type) {
case int16:
return x <= y, nil
default:
return invOp2(x, y, op)
}
case int32:
switch y := b.(type) {
case int32:
return x <= y, nil
default:
return invOp2(x, y, op)
}
case int64:
switch y := b.(type) {
case int64:
return x <= y, nil
default:
return invOp2(x, y, op)
}
case string:
switch y := b.(type) {
case string:
return x <= y, nil
default:
return invOp2(x, y, op)
}
case uint8:
switch y := b.(type) {
case uint8:
return x <= y, nil
default:
return invOp2(x, y, op)
}
case uint16:
switch y := b.(type) {
case uint16:
return x <= y, nil
default:
return invOp2(x, y, op)
}
case uint32:
switch y := b.(type) {
case uint32:
return x <= y, nil
default:
return invOp2(x, y, op)
}
case uint64:
switch y := b.(type) {
case uint64:
return x <= y, nil
default:
return invOp2(x, y, op)
}
case *big.Int:
switch y := b.(type) {
case *big.Int:
return x.Cmp(y) <= 0, nil
default:
return invOp2(x, y, op)
}
case *big.Rat:
switch y := b.(type) {
case *big.Rat:
return x.Cmp(y) <= 0, nil
default:
return invOp2(x, y, op)
}
case time.Duration:
switch y := b.(type) {
case time.Duration:
return x <= y, nil
default:
return invOp2(x, y, op)
}
case time.Time:
switch y := b.(type) {
case time.Time:
return x.Before(y) || x.Equal(y), nil
default:
return invOp2(x, y, op)
}
default:
return invOp2(a, b, op)
}
case ge:
a, b := o.get2(execCtx, ctx)
if a == nil || b == nil {
return
}
switch x := a.(type) {
//case nil:
case idealComplex:
return undOp2(a, b, op)
case idealFloat:
switch y := b.(type) {
case idealFloat:
return x >= y, nil
default:
return invOp2(x, y, op)
}
case idealInt:
switch y := b.(type) {
case idealInt:
return x >= y, nil
default:
return invOp2(x, y, op)
}
case idealRune:
switch y := b.(type) {
case idealRune:
return x >= y, nil
default:
return invOp2(x, y, op)
}
case idealUint:
switch y := b.(type) {
case idealUint:
return x >= y, nil
default:
return invOp2(x, y, op)
}
case bool:
return undOp2(a, b, op)
case complex64:
return undOp2(a, b, op)
case complex128:
return undOp2(a, b, op)
case float32:
switch y := b.(type) {
case float32:
return x >= y, nil
default:
return invOp2(x, y, op)
}
case float64:
switch y := b.(type) {
case float64:
return x >= y, nil
default:
return invOp2(x, y, op)
}
case int8:
switch y := b.(type) {
case int8:
return x >= y, nil
default:
return invOp2(x, y, op)
}
case int16:
switch y := b.(type) {
case int16:
return x >= y, nil
default:
return invOp2(x, y, op)
}
case int32:
switch y := b.(type) {
case int32:
return x >= y, nil
default:
return invOp2(x, y, op)
}
case int64:
switch y := b.(type) {
case int64:
return x >= y, nil
default:
return invOp2(x, y, op)
}
case string:
switch y := b.(type) {
case string:
return x >= y, nil
default:
return invOp2(x, y, op)
}
case uint8:
switch y := b.(type) {
case uint8:
return x >= y, nil
default:
return invOp2(x, y, op)
}
case uint16:
switch y := b.(type) {
case uint16:
return x >= y, nil
default:
return invOp2(x, y, op)
}
case uint32:
switch y := b.(type) {
case uint32:
return x >= y, nil
default:
return invOp2(x, y, op)
}
case uint64:
switch y := b.(type) {
case uint64:
return x >= y, nil
default:
return invOp2(x, y, op)
}
case *big.Int:
switch y := b.(type) {
case *big.Int:
return x.Cmp(y) >= 0, nil
default:
return invOp2(x, y, op)
}
case *big.Rat:
switch y := b.(type) {
case *big.Rat:
return x.Cmp(y) >= 0, nil
default:
return invOp2(x, y, op)
}
case time.Duration:
switch y := b.(type) {
case time.Duration:
return x >= y, nil
default:
return invOp2(x, y, op)
}
case time.Time:
switch y := b.(type) {
case time.Time:
return x.After(y) || x.Equal(y), nil
default:
return invOp2(x, y, op)
}
default:
return invOp2(a, b, op)
}
case neq:
a, b := o.get2(execCtx, ctx)
if a == nil || b == nil {
return
}
switch x := a.(type) {
//case nil:
case idealComplex:
switch y := b.(type) {
case idealComplex:
return x != y, nil
default:
return invOp2(x, y, op)
}
case idealFloat:
switch y := b.(type) {
case idealFloat:
return x != y, nil
default:
return invOp2(x, y, op)
}
case idealInt:
switch y := b.(type) {
case idealInt:
return x != y, nil
default:
return invOp2(x, y, op)
}
case idealRune:
switch y := b.(type) {
case idealRune:
return x != y, nil
default:
return invOp2(x, y, op)
}
case idealUint:
switch y := b.(type) {
case idealUint:
return x != y, nil
default:
return invOp2(x, y, op)
}
case bool:
switch y := b.(type) {
case bool:
return x != y, nil
default:
return invOp2(x, y, op)
}
case complex64:
switch y := b.(type) {
case complex64:
return x != y, nil
default:
return invOp2(x, y, op)
}
case complex128:
switch y := b.(type) {
case complex128:
return x != y, nil
default:
return invOp2(x, y, op)
}
case float32:
switch y := b.(type) {
case float32:
return x != y, nil
default:
return invOp2(x, y, op)
}
case float64:
switch y := b.(type) {
case float64:
return x != y, nil
default:
return invOp2(x, y, op)
}
case int8:
switch y := b.(type) {
case int8:
return x != y, nil
default:
return invOp2(x, y, op)
}
case int16:
switch y := b.(type) {
case int16:
return x != y, nil
default:
return invOp2(x, y, op)
}
case int32:
switch y := b.(type) {
case int32:
return x != y, nil
default:
return invOp2(x, y, op)
}
case int64:
switch y := b.(type) {
case int64:
return x != y, nil
default:
return invOp2(x, y, op)
}
case string:
switch y := b.(type) {
case string:
return x != y, nil
default:
return invOp2(x, y, op)
}
case uint8:
switch y := b.(type) {
case uint8:
return x != y, nil
default:
return invOp2(x, y, op)
}
case uint16:
switch y := b.(type) {
case uint16:
return x != y, nil
default:
return invOp2(x, y, op)
}
case uint32:
switch y := b.(type) {
case uint32:
return x != y, nil
default:
return invOp2(x, y, op)
}
case uint64:
switch y := b.(type) {
case uint64:
return x != y, nil
default:
return invOp2(x, y, op)
}
case *big.Int:
switch y := b.(type) {
case *big.Int:
return x.Cmp(y) != 0, nil
default:
return invOp2(x, y, op)
}
case *big.Rat:
switch y := b.(type) {
case *big.Rat:
return x.Cmp(y) != 0, nil
default:
return invOp2(x, y, op)
}
case time.Duration:
switch y := b.(type) {
case time.Duration:
return x != y, nil
default:
return invOp2(x, y, op)
}
case time.Time:
switch y := b.(type) {
case time.Time:
return !x.Equal(y), nil
default:
return invOp2(x, y, op)
}
default:
return invOp2(a, b, op)
}
case eq:
a, b := o.get2(execCtx, ctx)
if a == nil || b == nil {
return
}
switch x := a.(type) {
//case nil:
case idealComplex:
switch y := b.(type) {
case idealComplex:
return x == y, nil
default:
return invOp2(x, y, op)
}
case idealFloat:
switch y := b.(type) {
case idealFloat:
return x == y, nil
default:
return invOp2(x, y, op)
}
case idealInt:
switch y := b.(type) {
case idealInt:
return x == y, nil
default:
return invOp2(x, y, op)
}
case idealRune:
switch y := b.(type) {
case idealRune:
return x == y, nil
default:
return invOp2(x, y, op)
}
case idealUint:
switch y := b.(type) {
case idealUint:
return x == y, nil
default:
return invOp2(x, y, op)
}
case bool:
switch y := b.(type) {
case bool:
return x == y, nil
default:
return invOp2(x, y, op)
}
case complex64:
switch y := b.(type) {
case complex64:
return x == y, nil
default:
return invOp2(x, y, op)
}
case complex128:
switch y := b.(type) {
case complex128:
return x == y, nil
default:
return invOp2(x, y, op)
}
case float32:
switch y := b.(type) {
case float32:
return x == y, nil
default:
return invOp2(x, y, op)
}
case float64:
switch y := b.(type) {
case float64:
return x == y, nil
default:
return invOp2(x, y, op)
}
case int8:
switch y := b.(type) {
case int8:
return x == y, nil
default:
return invOp2(x, y, op)
}
case int16:
switch y := b.(type) {
case int16:
return x == y, nil
default:
return invOp2(x, y, op)
}
case int32:
switch y := b.(type) {
case int32:
return x == y, nil
default:
return invOp2(x, y, op)
}
case int64:
switch y := b.(type) {
case int64:
return x == y, nil
default:
return invOp2(x, y, op)
}
case string:
switch y := b.(type) {
case string:
return x == y, nil
default:
return invOp2(x, y, op)
}
case uint8:
switch y := b.(type) {
case uint8:
return x == y, nil
default:
return invOp2(x, y, op)
}
case uint16:
switch y := b.(type) {
case uint16:
return x == y, nil
default:
return invOp2(x, y, op)
}
case uint32:
switch y := b.(type) {
case uint32:
return x == y, nil
default:
return invOp2(x, y, op)
}
case uint64:
switch y := b.(type) {
case uint64:
return x == y, nil
default:
return invOp2(x, y, op)
}
case *big.Int:
switch y := b.(type) {
case *big.Int:
return x.Cmp(y) == 0, nil
default:
return invOp2(x, y, op)
}
case *big.Rat:
switch y := b.(type) {
case *big.Rat:
return x.Cmp(y) == 0, nil
default:
return invOp2(x, y, op)
}
case time.Duration:
switch y := b.(type) {
case time.Duration:
return x == y, nil
default:
return invOp2(x, y, op)
}
case time.Time:
switch y := b.(type) {
case time.Time:
return x.Equal(y), nil
default:
return invOp2(x, y, op)
}
default:
return invOp2(a, b, op)
}
case '+':
a, b := o.get2(execCtx, ctx)
if a == nil || b == nil {
return
}
switch x := a.(type) {
//case nil:
case idealComplex:
switch y := b.(type) {
case idealComplex:
return idealComplex(complex64(x) + complex64(y)), nil
default:
return invOp2(x, y, op)
}
case idealFloat:
switch y := b.(type) {
case idealFloat:
return idealFloat(float64(x) + float64(y)), nil
default:
return invOp2(x, y, op)
}
case idealInt:
switch y := b.(type) {
case idealInt:
return idealInt(int64(x) + int64(y)), nil
default:
return invOp2(x, y, op)
}
case idealRune:
switch y := b.(type) {
case idealRune:
return idealRune(int64(x) + int64(y)), nil
default:
return invOp2(x, y, op)
}
case idealUint:
switch y := b.(type) {
case idealUint:
return idealUint(uint64(x) + uint64(y)), nil
default:
return invOp2(x, y, op)
}
case bool:
return undOp2(a, b, op)
case complex64:
switch y := b.(type) {
case complex64:
return x + y, nil
default:
return invOp2(x, y, op)
}
case complex128:
switch y := b.(type) {
case complex128:
return x + y, nil
default:
return invOp2(x, y, op)
}
case float32:
switch y := b.(type) {
case float32:
return x + y, nil
default:
return invOp2(x, y, op)
}
case float64:
switch y := b.(type) {
case float64:
return x + y, nil
default:
return invOp2(x, y, op)
}
case int8:
switch y := b.(type) {
case int8:
return x + y, nil
default:
return invOp2(x, y, op)
}
case int16:
switch y := b.(type) {
case int16:
return x + y, nil
default:
return invOp2(x, y, op)
}
case int32:
switch y := b.(type) {
case int32:
return x + y, nil
default:
return invOp2(x, y, op)
}
case int64:
switch y := b.(type) {
case int64:
return x + y, nil
default:
return invOp2(x, y, op)
}
case string:
switch y := b.(type) {
case string:
return x + y, nil
default:
return invOp2(x, y, op)
}
case uint8:
switch y := b.(type) {
case uint8:
return x + y, nil
default:
return invOp2(x, y, op)
}
case uint16:
switch y := b.(type) {
case uint16:
return x + y, nil
default:
return invOp2(x, y, op)
}
case uint32:
switch y := b.(type) {
case uint32:
return x + y, nil
default:
return invOp2(x, y, op)
}
case uint64:
switch y := b.(type) {
case uint64:
return x + y, nil
default:
return invOp2(x, y, op)
}
case *big.Int:
switch y := b.(type) {
case *big.Int:
var z big.Int
return z.Add(x, y), nil
default:
return invOp2(x, y, op)
}
case *big.Rat:
switch y := b.(type) {
case *big.Rat:
var z big.Rat
return z.Add(x, y), nil
default:
return invOp2(x, y, op)
}
case time.Duration:
switch y := b.(type) {
case time.Duration:
return x + y, nil
case time.Time:
return y.Add(x), nil
default:
return invOp2(x, y, op)
}
case time.Time:
switch y := b.(type) {
case time.Duration:
return x.Add(y), nil
default:
return invOp2(x, y, op)
}
default:
return invOp2(a, b, op)
}
case '-':
a, b := o.get2(execCtx, ctx)
if a == nil || b == nil {
return
}
switch x := a.(type) {
//case nil:
case idealComplex:
switch y := b.(type) {
case idealComplex:
return idealComplex(complex64(x) - complex64(y)), nil
default:
return invOp2(x, y, op)
}
case idealFloat:
switch y := b.(type) {
case idealFloat:
return idealFloat(float64(x) - float64(y)), nil
default:
return invOp2(x, y, op)
}
case idealInt:
switch y := b.(type) {
case idealInt:
return idealInt(int64(x) - int64(y)), nil
default:
return invOp2(x, y, op)
}
case idealRune:
switch y := b.(type) {
case idealRune:
return idealRune(int64(x) - int64(y)), nil
default:
return invOp2(x, y, op)
}
case idealUint:
switch y := b.(type) {
case idealUint:
return idealUint(uint64(x) - uint64(y)), nil
default:
return invOp2(x, y, op)
}
case bool:
return undOp2(a, b, op)
case complex64:
switch y := b.(type) {
case complex64:
return x - y, nil
default:
return invOp2(x, y, op)
}
case complex128:
switch y := b.(type) {
case complex128:
return x - y, nil
default:
return invOp2(x, y, op)
}
case float32:
switch y := b.(type) {
case float32:
return x - y, nil
default:
return invOp2(x, y, op)
}
case float64:
switch y := b.(type) {
case float64:
return x - y, nil
default:
return invOp2(x, y, op)
}
case int8:
switch y := b.(type) {
case int8:
return x - y, nil
default:
return invOp2(x, y, op)
}
case int16:
switch y := b.(type) {
case int16:
return x - y, nil
default:
return invOp2(x, y, op)
}
case int32:
switch y := b.(type) {
case int32:
return x - y, nil
default:
return invOp2(x, y, op)
}
case int64:
switch y := b.(type) {
case int64:
return x - y, nil
default:
return invOp2(x, y, op)
}
case string:
return undOp2(a, b, op)
case uint8:
switch y := b.(type) {
case uint8:
return x - y, nil
default:
return invOp2(x, y, op)
}
case uint16:
switch y := b.(type) {
case uint16:
return x - y, nil
default:
return invOp2(x, y, op)
}
case uint32:
switch y := b.(type) {
case uint32:
return x - y, nil
default:
return invOp2(x, y, op)
}
case uint64:
switch y := b.(type) {
case uint64:
return x - y, nil
default:
return invOp2(x, y, op)
}
case *big.Int:
switch y := b.(type) {
case *big.Int:
var z big.Int
return z.Sub(x, y), nil
default:
return invOp2(x, y, op)
}
case *big.Rat:
switch y := b.(type) {
case *big.Rat:
var z big.Rat
return z.Sub(x, y), nil
default:
return invOp2(x, y, op)
}
case time.Duration:
switch y := b.(type) {
case time.Duration:
return x - y, nil
default:
return invOp2(x, y, op)
}
case time.Time:
switch y := b.(type) {
case time.Duration:
return x.Add(-y), nil
case time.Time:
return x.Sub(y), nil
default:
return invOp2(x, y, op)
}
default:
return invOp2(a, b, op)
}
case rsh:
a, b := eval2(o.l, o.r, execCtx, ctx)
if a == nil || b == nil {
return
}
var cnt uint64
switch y := b.(type) {
//case nil:
case idealComplex:
return invShiftRHS(a, b)
case idealFloat:
return invShiftRHS(a, b)
case idealInt:
cnt = uint64(y)
case idealRune:
cnt = uint64(y)
case idealUint:
cnt = uint64(y)
case bool:
return invShiftRHS(a, b)
case complex64:
return invShiftRHS(a, b)
case complex128:
return invShiftRHS(a, b)
case float32:
return invShiftRHS(a, b)
case float64:
return invShiftRHS(a, b)
case int8:
return invShiftRHS(a, b)
case int16:
return invShiftRHS(a, b)
case int32:
return invShiftRHS(a, b)
case int64:
return invShiftRHS(a, b)
case string:
return invShiftRHS(a, b)
case uint8:
cnt = uint64(y)
case uint16:
cnt = uint64(y)
case uint32:
cnt = uint64(y)
case uint64:
cnt = uint64(y)
default:
return invOp2(a, b, op)
}
switch x := a.(type) {
//case nil:
case idealComplex:
return undOp2(a, b, op)
case idealFloat:
return undOp2(a, b, op)
case idealInt:
return idealInt(int64(x) >> cnt), nil
case idealRune:
return idealRune(int64(x) >> cnt), nil
case idealUint:
return idealUint(uint64(x) >> cnt), nil
case bool:
return undOp2(a, b, op)
case complex64:
return undOp2(a, b, op)
case complex128:
return undOp2(a, b, op)
case float32:
return undOp2(a, b, op)
case float64:
return undOp2(a, b, op)
case int8:
return x >> cnt, nil
case int16:
return x >> cnt, nil
case int32:
return x >> cnt, nil
case int64:
return x >> cnt, nil
case string:
return undOp2(a, b, op)
case uint8:
return x >> cnt, nil
case uint16:
return x >> cnt, nil
case uint32:
return x >> cnt, nil
case uint64:
return x >> cnt, nil
case *big.Int:
var z big.Int
return z.Rsh(x, uint(cnt)), nil
case time.Duration:
return x >> cnt, nil
default:
return invOp2(a, b, op)
}
case lsh:
a, b := eval2(o.l, o.r, execCtx, ctx)
if a == nil || b == nil {
return
}
var cnt uint64
switch y := b.(type) {
//case nil:
case idealComplex:
return invShiftRHS(a, b)
case idealFloat:
return invShiftRHS(a, b)
case idealInt:
cnt = uint64(y)
case idealRune:
cnt = uint64(y)
case idealUint:
cnt = uint64(y)
case bool:
return invShiftRHS(a, b)
case complex64:
return invShiftRHS(a, b)
case complex128:
return invShiftRHS(a, b)
case float32:
return invShiftRHS(a, b)
case float64:
return invShiftRHS(a, b)
case int8:
return invShiftRHS(a, b)
case int16:
return invShiftRHS(a, b)
case int32:
return invShiftRHS(a, b)
case int64:
return invShiftRHS(a, b)
case string:
return invShiftRHS(a, b)
case uint8:
cnt = uint64(y)
case uint16:
cnt = uint64(y)
case uint32:
cnt = uint64(y)
case uint64:
cnt = uint64(y)
default:
return invOp2(a, b, op)
}
switch x := a.(type) {
//case nil:
case idealComplex:
return undOp2(a, b, op)
case idealFloat:
return undOp2(a, b, op)
case idealInt:
return idealInt(int64(x) << cnt), nil
case idealRune:
return idealRune(int64(x) << cnt), nil
case idealUint:
return idealUint(uint64(x) << cnt), nil
case bool:
return undOp2(a, b, op)
case complex64:
return undOp2(a, b, op)
case complex128:
return undOp2(a, b, op)
case float32:
return undOp2(a, b, op)
case float64:
return undOp2(a, b, op)
case int8:
return x << cnt, nil
case int16:
return x << cnt, nil
case int32:
return x << cnt, nil
case int64:
return x << cnt, nil
case string:
return undOp2(a, b, op)
case uint8:
return x << cnt, nil
case uint16:
return x << cnt, nil
case uint32:
return x << cnt, nil
case uint64:
return x << cnt, nil
case *big.Int:
var z big.Int
return z.Lsh(x, uint(cnt)), nil
case time.Duration:
return x << cnt, nil
default:
return invOp2(a, b, op)
}
case '&':
a, b := o.get2(execCtx, ctx)
if a == nil || b == nil {
return
}
switch x := a.(type) {
//case nil:
case idealComplex:
return undOp2(a, b, op)
case idealFloat:
return undOp2(a, b, op)
case idealInt:
switch y := b.(type) {
case idealInt:
return idealInt(int64(x) & int64(y)), nil
default:
return invOp2(x, y, op)
}
case idealRune:
switch y := b.(type) {
case idealRune:
return idealRune(int64(x) & int64(y)), nil
default:
return invOp2(x, y, op)
}
case idealUint:
switch y := b.(type) {
case idealUint:
return idealUint(uint64(x) & uint64(y)), nil
default:
return invOp2(x, y, op)
}
case bool:
return undOp2(a, b, op)
case complex64:
return undOp2(a, b, op)
case complex128:
return undOp2(a, b, op)
case float32:
return undOp2(a, b, op)
case float64:
return undOp2(a, b, op)
case int8:
switch y := b.(type) {
case int8:
return x & y, nil
default:
return invOp2(x, y, op)
}
case int16:
switch y := b.(type) {
case int16:
return x & y, nil
default:
return invOp2(x, y, op)
}
case int32:
switch y := b.(type) {
case int32:
return x & y, nil
default:
return invOp2(x, y, op)
}
case int64:
switch y := b.(type) {
case int64:
return x & y, nil
default:
return invOp2(x, y, op)
}
case string:
return undOp2(a, b, op)
case uint8:
switch y := b.(type) {
case uint8:
return x & y, nil
default:
return invOp2(x, y, op)
}
case uint16:
switch y := b.(type) {
case uint16:
return x & y, nil
default:
return invOp2(x, y, op)
}
case uint32:
switch y := b.(type) {
case uint32:
return x & y, nil
default:
return invOp2(x, y, op)
}
case uint64:
switch y := b.(type) {
case uint64:
return x & y, nil
default:
return invOp2(x, y, op)
}
case *big.Int:
switch y := b.(type) {
case *big.Int:
var z big.Int
return z.And(x, y), nil
default:
return invOp2(x, y, op)
}
case time.Duration:
switch y := b.(type) {
case time.Duration:
return x & y, nil
default:
return invOp2(x, y, op)
}
default:
return invOp2(a, b, op)
}
case '|':
a, b := o.get2(execCtx, ctx)
if a == nil || b == nil {
return
}
switch x := a.(type) {
//case nil:
case idealComplex:
return undOp2(a, b, op)
case idealFloat:
return undOp2(a, b, op)
case idealInt:
switch y := b.(type) {
case idealInt:
return idealInt(int64(x) | int64(y)), nil
default:
return invOp2(x, y, op)
}
case idealRune:
switch y := b.(type) {
case idealRune:
return idealRune(int64(x) | int64(y)), nil
default:
return invOp2(x, y, op)
}
case idealUint:
switch y := b.(type) {
case idealUint:
return idealUint(uint64(x) | uint64(y)), nil
default:
return invOp2(x, y, op)
}
case bool:
return undOp2(a, b, op)
case complex64:
return undOp2(a, b, op)
case complex128:
return undOp2(a, b, op)
case float32:
return undOp2(a, b, op)
case float64:
return undOp2(a, b, op)
case int8:
switch y := b.(type) {
case int8:
return x | y, nil
default:
return invOp2(x, y, op)
}
case int16:
switch y := b.(type) {
case int16:
return x | y, nil
default:
return invOp2(x, y, op)
}
case int32:
switch y := b.(type) {
case int32:
return x | y, nil
default:
return invOp2(x, y, op)
}
case int64:
switch y := b.(type) {
case int64:
return x | y, nil
default:
return invOp2(x, y, op)
}
case string:
return undOp2(a, b, op)
case uint8:
switch y := b.(type) {
case uint8:
return x | y, nil
default:
return invOp2(x, y, op)
}
case uint16:
switch y := b.(type) {
case uint16:
return x | y, nil
default:
return invOp2(x, y, op)
}
case uint32:
switch y := b.(type) {
case uint32:
return x | y, nil
default:
return invOp2(x, y, op)
}
case uint64:
switch y := b.(type) {
case uint64:
return x | y, nil
default:
return invOp2(x, y, op)
}
case *big.Int:
switch y := b.(type) {
case *big.Int:
var z big.Int
return z.Or(x, y), nil
default:
return invOp2(x, y, op)
}
case time.Duration:
switch y := b.(type) {
case time.Duration:
return x | y, nil
default:
return invOp2(x, y, op)
}
default:
return invOp2(a, b, op)
}
case andnot:
a, b := o.get2(execCtx, ctx)
if a == nil || b == nil {
return
}
switch x := a.(type) {
//case nil:
case idealComplex:
return undOp2(a, b, op)
case idealFloat:
return undOp2(a, b, op)
case idealInt:
switch y := b.(type) {
case idealInt:
return idealInt(int64(x) &^ int64(y)), nil
default:
return invOp2(x, y, op)
}
case idealRune:
switch y := b.(type) {
case idealRune:
return idealRune(int64(x) &^ int64(y)), nil
default:
return invOp2(x, y, op)
}
case idealUint:
switch y := b.(type) {
case idealUint:
return idealUint(uint64(x) &^ uint64(y)), nil
default:
return invOp2(x, y, op)
}
case bool:
return undOp2(a, b, op)
case complex64:
return undOp2(a, b, op)
case complex128:
return undOp2(a, b, op)
case float32:
return undOp2(a, b, op)
case float64:
return undOp2(a, b, op)
case int8:
switch y := b.(type) {
case int8:
return x &^ y, nil
default:
return invOp2(x, y, op)
}
case int16:
switch y := b.(type) {
case int16:
return x &^ y, nil
default:
return invOp2(x, y, op)
}
case int32:
switch y := b.(type) {
case int32:
return x &^ y, nil
default:
return invOp2(x, y, op)
}
case int64:
switch y := b.(type) {
case int64:
return x &^ y, nil
default:
return invOp2(x, y, op)
}
case string:
return undOp2(a, b, op)
case uint8:
switch y := b.(type) {
case uint8:
return x &^ y, nil
default:
return invOp2(x, y, op)
}
case uint16:
switch y := b.(type) {
case uint16:
return x &^ y, nil
default:
return invOp2(x, y, op)
}
case uint32:
switch y := b.(type) {
case uint32:
return x &^ y, nil
default:
return invOp2(x, y, op)
}
case uint64:
switch y := b.(type) {
case uint64:
return x &^ y, nil
default:
return invOp2(x, y, op)
}
case *big.Int:
switch y := b.(type) {
case *big.Int:
var z big.Int
return z.AndNot(x, y), nil
default:
return invOp2(x, y, op)
}
case time.Duration:
switch y := b.(type) {
case time.Duration:
return x &^ y, nil
default:
return invOp2(x, y, op)
}
default:
return invOp2(a, b, op)
}
case '^':
a, b := o.get2(execCtx, ctx)
if a == nil || b == nil {
return
}
switch x := a.(type) {
//case nil:
case idealComplex:
return undOp2(a, b, op)
case idealFloat:
return undOp2(a, b, op)
case idealInt:
switch y := b.(type) {
case idealInt:
return idealInt(int64(x) ^ int64(y)), nil
default:
return invOp2(x, y, op)
}
case idealRune:
switch y := b.(type) {
case idealRune:
return idealRune(int64(x) ^ int64(y)), nil
default:
return invOp2(x, y, op)
}
case idealUint:
switch y := b.(type) {
case idealUint:
return idealUint(uint64(x) ^ uint64(y)), nil
default:
return invOp2(x, y, op)
}
case bool:
return undOp2(a, b, op)
case complex64:
return undOp2(a, b, op)
case complex128:
return undOp2(a, b, op)
case float32:
return undOp2(a, b, op)
case float64:
return undOp2(a, b, op)
case int8:
switch y := b.(type) {
case int8:
return x ^ y, nil
default:
return invOp2(x, y, op)
}
case int16:
switch y := b.(type) {
case int16:
return x ^ y, nil
default:
return invOp2(x, y, op)
}
case int32:
switch y := b.(type) {
case int32:
return x ^ y, nil
default:
return invOp2(x, y, op)
}
case int64:
switch y := b.(type) {
case int64:
return x ^ y, nil
default:
return invOp2(x, y, op)
}
case string:
return undOp2(a, b, op)
case uint8:
switch y := b.(type) {
case uint8:
return x ^ y, nil
default:
return invOp2(x, y, op)
}
case uint16:
switch y := b.(type) {
case uint16:
return x ^ y, nil
default:
return invOp2(x, y, op)
}
case uint32:
switch y := b.(type) {
case uint32:
return x ^ y, nil
default:
return invOp2(x, y, op)
}
case uint64:
switch y := b.(type) {
case uint64:
return x ^ y, nil
default:
return invOp2(x, y, op)
}
case *big.Int:
switch y := b.(type) {
case *big.Int:
var z big.Int
return z.Xor(x, y), nil
default:
return invOp2(x, y, op)
}
case time.Duration:
switch y := b.(type) {
case time.Duration:
return x ^ y, nil
default:
return invOp2(x, y, op)
}
default:
return invOp2(a, b, op)
}
case '%':
a, b := o.get2(execCtx, ctx)
if a == nil || b == nil {
return
}
switch x := a.(type) {
//case nil:
case idealComplex:
return undOp2(a, b, op)
case idealFloat:
return undOp2(a, b, op)
case idealInt:
switch y := b.(type) {
case idealInt:
return idealInt(int64(x) % int64(y)), nil
default:
return invOp2(x, y, op)
}
case idealRune:
switch y := b.(type) {
case idealRune:
return idealRune(int64(x) % int64(y)), nil
default:
return invOp2(x, y, op)
}
case idealUint:
switch y := b.(type) {
case idealUint:
return idealUint(uint64(x) % uint64(y)), nil
default:
return invOp2(x, y, op)
}
case bool:
return undOp2(a, b, op)
case complex64:
return undOp2(a, b, op)
case complex128:
return undOp2(a, b, op)
case float32:
return undOp2(a, b, op)
case float64:
return undOp2(a, b, op)
case int8:
switch y := b.(type) {
case int8:
return x % y, nil
default:
return invOp2(x, y, op)
}
case int16:
switch y := b.(type) {
case int16:
return x % y, nil
default:
return invOp2(x, y, op)
}
case int32:
switch y := b.(type) {
case int32:
return x % y, nil
default:
return invOp2(x, y, op)
}
case int64:
switch y := b.(type) {
case int64:
return x % y, nil
default:
return invOp2(x, y, op)
}
case string:
return undOp2(a, b, op)
case uint8:
switch y := b.(type) {
case uint8:
return x % y, nil
default:
return invOp2(x, y, op)
}
case uint16:
switch y := b.(type) {
case uint16:
return x % y, nil
default:
return invOp2(x, y, op)
}
case uint32:
switch y := b.(type) {
case uint32:
return x % y, nil
default:
return invOp2(x, y, op)
}
case uint64:
switch y := b.(type) {
case uint64:
return x % y, nil
default:
return invOp2(x, y, op)
}
case *big.Int:
switch y := b.(type) {
case *big.Int:
if y.Sign() == 0 {
return nil, errDivByZero
}
var z big.Int
return z.Mod(x, y), nil
default:
return invOp2(x, y, op)
}
case time.Duration:
switch y := b.(type) {
case time.Duration:
return x % y, nil
default:
return invOp2(x, y, op)
}
default:
return invOp2(a, b, op)
}
case '/':
a, b := o.get2(execCtx, ctx)
if a == nil || b == nil {
return
}
switch x := a.(type) {
//case nil:
case idealComplex:
switch y := b.(type) {
case idealComplex:
return idealComplex(complex64(x) / complex64(y)), nil
default:
return invOp2(x, y, op)
}
case idealFloat:
switch y := b.(type) {
case idealFloat:
return idealFloat(float64(x) / float64(y)), nil
default:
return invOp2(x, y, op)
}
case idealInt:
switch y := b.(type) {
case idealInt:
return idealInt(int64(x) / int64(y)), nil
default:
return invOp2(x, y, op)
}
case idealRune:
switch y := b.(type) {
case idealRune:
return idealRune(int64(x) / int64(y)), nil
default:
return invOp2(x, y, op)
}
case idealUint:
switch y := b.(type) {
case idealUint:
return idealUint(uint64(x) / uint64(y)), nil
default:
return invOp2(x, y, op)
}
case bool:
return undOp2(a, b, op)
case complex64:
switch y := b.(type) {
case complex64:
return x / y, nil
default:
return invOp2(x, y, op)
}
case complex128:
switch y := b.(type) {
case complex128:
return x / y, nil
default:
return invOp2(x, y, op)
}
case float32:
switch y := b.(type) {
case float32:
return x / y, nil
default:
return invOp2(x, y, op)
}
case float64:
switch y := b.(type) {
case float64:
return x / y, nil
default:
return invOp2(x, y, op)
}
case int8:
switch y := b.(type) {
case int8:
return x / y, nil
default:
return invOp2(x, y, op)
}
case int16:
switch y := b.(type) {
case int16:
return x / y, nil
default:
return invOp2(x, y, op)
}
case int32:
switch y := b.(type) {
case int32:
return x / y, nil
default:
return invOp2(x, y, op)
}
case int64:
switch y := b.(type) {
case int64:
return x / y, nil
default:
return invOp2(x, y, op)
}
case string:
return undOp2(a, b, op)
case uint8:
switch y := b.(type) {
case uint8:
return x / y, nil
default:
return invOp2(x, y, op)
}
case uint16:
switch y := b.(type) {
case uint16:
return x / y, nil
default:
return invOp2(x, y, op)
}
case uint32:
switch y := b.(type) {
case uint32:
return x / y, nil
default:
return invOp2(x, y, op)
}
case uint64:
switch y := b.(type) {
case uint64:
return x / y, nil
default:
return invOp2(x, y, op)
}
case *big.Int:
switch y := b.(type) {
case *big.Int:
if y.Sign() == 0 {
return nil, errDivByZero
}
var z big.Int
return z.Quo(x, y), nil
default:
return invOp2(x, y, op)
}
case *big.Rat:
switch y := b.(type) {
case *big.Rat:
if y.Sign() == 0 {
return nil, errDivByZero
}
var z big.Rat
return z.Quo(x, y), nil
default:
return invOp2(x, y, op)
}
case time.Duration:
switch y := b.(type) {
case time.Duration:
return x / y, nil
default:
return invOp2(x, y, op)
}
default:
return invOp2(a, b, op)
}
case '*':
a, b := o.get2(execCtx, ctx)
if a == nil || b == nil {
return
}
switch x := a.(type) {
//case nil:
case idealComplex:
switch y := b.(type) {
case idealComplex:
return idealComplex(complex64(x) * complex64(y)), nil
default:
return invOp2(x, y, op)
}
case idealFloat:
switch y := b.(type) {
case idealFloat:
return idealFloat(float64(x) * float64(y)), nil
default:
return invOp2(x, y, op)
}
case idealInt:
switch y := b.(type) {
case idealInt:
return idealInt(int64(x) * int64(y)), nil
default:
return invOp2(x, y, op)
}
case idealRune:
switch y := b.(type) {
case idealRune:
return idealRune(int64(x) * int64(y)), nil
default:
return invOp2(x, y, op)
}
case idealUint:
switch y := b.(type) {
case idealUint:
return idealUint(uint64(x) * uint64(y)), nil
default:
return invOp2(x, y, op)
}
case bool:
return undOp2(a, b, op)
case complex64:
switch y := b.(type) {
case complex64:
return x * y, nil
default:
return invOp2(x, y, op)
}
case complex128:
switch y := b.(type) {
case complex128:
return x * y, nil
default:
return invOp2(x, y, op)
}
case float32:
switch y := b.(type) {
case float32:
return x * y, nil
default:
return invOp2(x, y, op)
}
case float64:
switch y := b.(type) {
case float64:
return x * y, nil
default:
return invOp2(x, y, op)
}
case int8:
switch y := b.(type) {
case int8:
return x * y, nil
default:
return invOp2(x, y, op)
}
case int16:
switch y := b.(type) {
case int16:
return x * y, nil
default:
return invOp2(x, y, op)
}
case int32:
switch y := b.(type) {
case int32:
return x * y, nil
default:
return invOp2(x, y, op)
}
case int64:
switch y := b.(type) {
case int64:
return x * y, nil
default:
return invOp2(x, y, op)
}
case string:
return undOp2(a, b, op)
case uint8:
switch y := b.(type) {
case uint8:
return x * y, nil
default:
return invOp2(x, y, op)
}
case uint16:
switch y := b.(type) {
case uint16:
return x * y, nil
default:
return invOp2(x, y, op)
}
case uint32:
switch y := b.(type) {
case uint32:
return x * y, nil
default:
return invOp2(x, y, op)
}
case uint64:
switch y := b.(type) {
case uint64:
return x * y, nil
default:
return invOp2(x, y, op)
}
case *big.Int:
switch y := b.(type) {
case *big.Int:
var z big.Int
return z.Mul(x, y), nil
default:
return invOp2(x, y, op)
}
case *big.Rat:
switch y := b.(type) {
case *big.Rat:
var z big.Rat
return z.Mul(x, y), nil
default:
return invOp2(x, y, op)
}
case time.Duration:
switch y := b.(type) {
case time.Duration:
return x * y, nil
default:
return invOp2(x, y, op)
}
default:
return invOp2(a, b, op)
}
default:
panic("internal error 037")
}
}
func (o *binaryOperation) get2(execCtx *execCtx, ctx map[interface{}]interface{}) (x, y interface{}) {
x, y = eval2(o.l, o.r, execCtx, ctx)
//dbg("get2 pIn - ", x, y)
//defer func() {dbg("get2 coerced ", x, y)}()
return coerce(x, y)
}
type ident struct {
s string
}
func (i *ident) clone(arg []interface{}, unqualify ...string) (expression, error) {
x := strings.IndexByte(i.s, '.')
if x < 0 {
return &ident{s: i.s}, nil
}
q := i.s[:x]
for _, v := range unqualify {
if q == v {
return &ident{i.s[x+1:]}, nil
}
}
return &ident{s: i.s}, nil
}
func (i *ident) isQualified() bool { return strings.Contains(i.s, ".") }
func (i *ident) isStatic() bool { return false }
func (i *ident) String() string { return i.s }
func (i *ident) eval(execCtx *execCtx, ctx map[interface{}]interface{}) (v interface{}, err error) {
if _, ok := ctx["$agg0"]; ok {
return int64(0), nil
}
//defer func() { dbg("ident %q -> %v %v", i.s, v, err) }()
v, ok := ctx[i.s]
if !ok {
err = fmt.Errorf("unknown field %s", i.s)
}
return
}
type pInEval struct {
m map[interface{}]struct{} // IN (SELECT...) results
sample interface{}
}
type pIn struct {
expr expression
list []expression
not bool
sel *selectStmt
}
func (n *pIn) clone(arg []interface{}, unqualify ...string) (expression, error) {
expr, err := n.expr.clone(arg, unqualify...)
if err != nil {
return nil, err
}
list, err := cloneExpressionList(arg, n.list)
if err != nil {
return nil, err
}
return &pIn{
expr: expr,
list: list,
not: n.not,
sel: n.sel,
}, nil
}
func (n *pIn) isStatic() bool {
if !n.expr.isStatic() || n.sel != nil {
return false
}
for _, v := range n.list {
if !v.isStatic() {
return false
}
}
return true
}
//LATER newIn
func (n *pIn) String() string {
if n.sel == nil {
a := []string{}
for _, v := range n.list {
a = append(a, v.String())
}
if n.not {
return fmt.Sprintf("%s NOT IN (%s)", n.expr, strings.Join(a, ","))
}
return fmt.Sprintf("%s IN (%s)", n.expr, strings.Join(a, ","))
}
if n.not {
return fmt.Sprintf("%s NOT IN (%s)", n.expr, n.sel)
}
return fmt.Sprintf("%s IN (%s)", n.expr, n.sel)
}
func (n *pIn) eval(execCtx *execCtx, ctx map[interface{}]interface{}) (v interface{}, err error) {
lhs, err := expand1(n.expr.eval(execCtx, ctx))
if err != nil {
return nil, err
}
if lhs == nil {
return nil, nil //TODO Add test for NULL LHS.
}
if n.sel == nil {
for _, v := range n.list {
b, err := newBinaryOperation(eq, value{lhs}, v)
if err != nil {
return nil, err
}
eval, err := b.eval(execCtx, ctx)
if err != nil {
return nil, err
}
if x, ok := eval.(bool); ok && x {
return !n.not, nil
}
}
return n.not, nil
}
var ev *pInEval
ev0 := ctx[n]
if ev0 == nil { // SELECT not yet evaluated.
r, err := n.sel.plan(execCtx)
if err != nil {
return nil, err
}
if g, e := len(r.fieldNames()), 1; g != e {
return false, fmt.Errorf("IN (%s): mismatched field count, have %d, need %d", n.sel, g, e)
}
ev = &pInEval{m: map[interface{}]struct{}{}}
ctx[n] = ev
m := ev.m
typechecked := false
if err := r.do(execCtx, func(id interface{}, data []interface{}) (more bool, err error) {
if typechecked {
if data[0] == nil {
return true, nil
}
m[data[0]] = struct{}{}
}
if data[0] == nil {
return true, nil
}
ev.sample = data[0]
switch ev.sample.(type) {
case bool, byte, complex128, complex64, float32,
float64, int16, int32, int64, int8,
string, uint16, uint32, uint64:
typechecked = true
m[ev.sample] = struct{}{}
return true, nil
default:
return false, fmt.Errorf("IN (%s): invalid field type: %T", n.sel, data[0])
}
}); err != nil {
return nil, err
}
} else {
ev = ev0.(*pInEval)
}
if ev.sample == nil {
return nil, nil
}
_, ok := ev.m[coerce1(lhs, ev.sample)]
return ok != n.not, nil
}
type value struct {
val interface{}
}
func (l value) clone(arg []interface{}, unqualify ...string) (expression, error) {
return value{val: l.val}, nil
}
func (l value) isStatic() bool { return true }
func (l value) String() string {
switch x := l.val.(type) {
case nil:
return "NULL"
case idealComplex:
s := fmt.Sprint(x)
return s[1 : len(s)-1]
case complex64:
s := fmt.Sprint(x)
return s[1 : len(s)-1]
case complex128:
s := fmt.Sprint(x)
return s[1 : len(s)-1]
case string:
return fmt.Sprintf("%q", x)
case time.Duration:
return fmt.Sprintf("duration(%q)", l.val)
case time.Time:
y, m, d := x.Date()
zone, _ := x.Zone()
return fmt.Sprintf("date(%v, %v, %v, %v, %v, %v, %v, %v)", y, m, d, x.Hour(), x.Minute(), x.Second(), x.Nanosecond(), zone)
case *big.Rat:
return fmt.Sprintf("bigrat(%q)", l.val)
case *big.Int:
return fmt.Sprintf(`bigint("%v")`, l.val)
default:
return fmt.Sprintf("%v", l.val)
}
}
func (l value) eval(execCtx *execCtx, ctx map[interface{}]interface{}) (interface{}, error) {
return l.val, nil
}
type conversion struct {
typ int
val expression
}
func (c *conversion) clone(arg []interface{}, unqualify ...string) (expression, error) {
val, err := c.val.clone(arg, unqualify...)
if err != nil {
return nil, err
}
return &conversion{typ: c.typ, val: val}, nil
}
func (c *conversion) isStatic() bool {
return c.val.isStatic()
}
//LATER newConversion or fake unary op
func (c *conversion) String() string {
return fmt.Sprintf("%s(%s)", typeStr(c.typ), c.val)
}
func (c *conversion) eval(execCtx *execCtx, ctx map[interface{}]interface{}) (v interface{}, err error) {
val, err := expand1(c.val.eval(execCtx, ctx))
if err != nil {
return
}
return convert(val, c.typ)
}
type unaryOperation struct {
op int
v expression
}
func newUnaryOperation(op int, x interface{}) (v expression, err error) {
l, ok := x.(expression)
if !ok {
panic("internal error 038")
}
for {
pe, ok := l.(*pexpr)
if ok {
l = pe.expr
continue
}
break
}
if l.isStatic() {
val, err := l.eval(nil, nil)
if err != nil {
return nil, err
}
l = value{val}
}
if op == '!' {
b, ok := l.(*binaryOperation)
if ok {
switch b.op {
case eq:
b.op = neq
return b, nil
case neq:
b.op = eq
return b, nil
case '>':
b.op = le
return b, nil
case ge:
b.op = '<'
return b, nil
case '<':
b.op = ge
return b, nil
case le:
b.op = '>'
return b, nil
}
}
u, ok := l.(*unaryOperation)
if ok && u.op == '!' { // !!x: x
return u.v, nil
}
}
return &unaryOperation{op, l}, nil
}
func (u *unaryOperation) clone(arg []interface{}, unqualify ...string) (expression, error) {
v, err := u.v.clone(arg, unqualify...)
if err != nil {
return nil, err
}
return &unaryOperation{op: u.op, v: v}, nil
}
func (u *unaryOperation) isStatic() bool { return u.v.isStatic() }
func (u *unaryOperation) String() string {
switch u.v.(type) {
case *binaryOperation:
return fmt.Sprintf("%s(%s)", iop(u.op), u.v)
default:
return fmt.Sprintf("%s%s", iop(u.op), u.v)
}
}
// !ident
func (u *unaryOperation) isNotQIdent() (bool, string, expression) {
if u.op != '!' {
return false, "", nil
}
id, ok := u.v.(*ident)
if ok && id.isQualified() {
return true, mustQualifier(id.s), &unaryOperation{'!', &ident{mustSelector(id.s)}}
}
return false, "", nil
}
func (u *unaryOperation) eval(execCtx *execCtx, ctx map[interface{}]interface{}) (r interface{}, err error) {
defer func() {
if e := recover(); e != nil {
switch x := e.(type) {
case error:
r, err = nil, x
default:
r, err = nil, fmt.Errorf("%v", x)
}
}
}()
switch op := u.op; op {
case '!':
a := eval(u.v, execCtx, ctx)
if a == nil {
return
}
switch x := a.(type) {
case bool:
return !x, nil
default:
return undOp(a, op)
}
case '^':
a := eval(u.v, execCtx, ctx)
if a == nil {
return
}
switch x := a.(type) {
//case nil:
case idealComplex:
return undOp(a, op)
case idealFloat:
return undOp(a, op)
case idealInt:
return ^x, nil
case idealRune:
return ^x, nil
case idealUint:
return ^x, nil
case bool:
return undOp(a, op)
case complex64:
return undOp(a, op)
case complex128:
return undOp(a, op)
case float32:
return undOp(a, op)
case float64:
return undOp(a, op)
case int8:
return ^x, nil
case int16:
return ^x, nil
case int32:
return ^x, nil
case int64:
return ^x, nil
case string:
return undOp(a, op)
case uint8:
return ^x, nil
case uint16:
return ^x, nil
case uint32:
return ^x, nil
case uint64:
return ^x, nil
case *big.Int:
var z big.Int
return z.Not(x), nil
case time.Duration:
return ^x, nil
default:
return undOp(a, op)
}
case '+':
a := eval(u.v, execCtx, ctx)
if a == nil {
return
}
switch x := a.(type) {
//case nil:
case idealComplex:
return +x, nil
case idealFloat:
return +x, nil
case idealInt:
return +x, nil
case idealRune:
return +x, nil
case idealUint:
return +x, nil
case bool:
return undOp(a, op)
case complex64:
return +x, nil
case complex128:
return +x, nil
case float32:
return +x, nil
case float64:
return +x, nil
case int8:
return +x, nil
case int16:
return +x, nil
case int32:
return +x, nil
case int64:
return +x, nil
case string:
return undOp(a, op)
case uint8:
return +x, nil
case uint16:
return +x, nil
case uint32:
return +x, nil
case uint64:
return +x, nil
case *big.Int:
var z big.Int
return z.Set(x), nil
case *big.Rat:
var z big.Rat
return z.Set(x), nil
case time.Duration:
return x, nil
default:
return undOp(a, op)
}
case '-':
a := eval(u.v, execCtx, ctx)
if a == nil {
return
}
switch x := a.(type) {
//case nil:
case idealComplex:
return -x, nil
case idealFloat:
return -x, nil
case idealInt:
return -x, nil
case idealRune:
return -x, nil
case idealUint:
return -x, nil
case bool:
return undOp(a, op)
case complex64:
return -x, nil
case complex128:
return -x, nil
case float32:
return -x, nil
case float64:
return -x, nil
case int8:
return -x, nil
case int16:
return -x, nil
case int32:
return -x, nil
case int64:
return -x, nil
case string:
return undOp(a, op)
case uint8:
return -x, nil
case uint16:
return -x, nil
case uint32:
return -x, nil
case uint64:
return -x, nil
case *big.Int:
var z big.Int
return z.Neg(x), nil
case *big.Rat:
var z big.Rat
return z.Neg(x), nil
case time.Duration:
return -x, nil
default:
return undOp(a, op)
}
default:
panic("internal error 039")
}
}
type call struct {
f string
arg []expression
}
func newCall(f string, arg []expression) (v expression, isAgg bool, err error) {
x := builtin[f]
if x.f == nil {
return nil, false, fmt.Errorf("undefined: %s", f)
}
isAgg = x.isAggregate
if g, min, max := len(arg), x.minArgs, x.maxArgs; g < min || g > max {
a := []interface{}{}
for _, v := range arg {
a = append(a, v)
}
return nil, false, badNArgs(min, f, a)
}
c := call{f: f}
for _, val := range arg {
if !val.isStatic() {
c.arg = append(c.arg, val)
continue
}
eval, err := val.eval(nil, nil)
if err != nil {
return nil, isAgg, err
}
c.arg = append(c.arg, value{eval})
}
return &c, isAgg, nil
}
func (c *call) clone(arg []interface{}, unqualify ...string) (expression, error) {
list, err := cloneExpressionList(arg, c.arg)
if err != nil {
return nil, err
}
return &call{f: c.f, arg: list}, nil
}
func (c *call) isStatic() bool {
v := builtin[c.f]
if v.f == nil || !v.isStatic {
return false
}
for _, v := range c.arg {
if !v.isStatic() {
return false
}
}
return true
}
func (c *call) String() string {
a := []string{}
for _, v := range c.arg {
a = append(a, v.String())
}
return fmt.Sprintf("%s(%s)", c.f, strings.Join(a, ", "))
}
func (c *call) eval(execCtx *execCtx, ctx map[interface{}]interface{}) (v interface{}, err error) {
f, ok := builtin[c.f]
if !ok {
return nil, fmt.Errorf("unknown function %s", c.f)
}
isID := c.f == "id"
a := make([]interface{}, len(c.arg))
for i, arg := range c.arg {
if v, err = expand1(arg.eval(execCtx, ctx)); err != nil {
if !isID {
return nil, err
}
if _, ok := arg.(*ident); !ok {
return nil, err
}
a[i] = arg
continue
}
a[i] = v
}
if ctx != nil {
ctx["$fn"] = c
}
return f.f(a, ctx)
}
type parameter struct {
n int
}
func (p parameter) clone(arg []interface{}, unqualify ...string) (expression, error) {
i := p.n - 1
if i < len(arg) {
return value{val: arg[i]}, nil
}
return nil, fmt.Errorf("missing %s", p)
}
func (parameter) isStatic() bool { return false }
func (p parameter) String() string { return fmt.Sprintf("$%d", p.n) }
func (p parameter) eval(execCtx *execCtx, ctx map[interface{}]interface{}) (v interface{}, err error) {
i := p.n - 1
if i < len(execCtx.arg) {
return execCtx.arg[i], nil
}
return nil, fmt.Errorf("missing %s", p)
}
//MAYBE make it an unary operation
type isNull struct {
expr expression
not bool
}
//LATER newIsNull
func (is *isNull) clone(arg []interface{}, unqualify ...string) (expression, error) {
expr, err := is.expr.clone(arg, unqualify...)
if err != nil {
return nil, err
}
return &isNull{expr: expr, not: is.not}, nil
}
func (is *isNull) isStatic() bool { return is.expr.isStatic() }
func (is *isNull) String() string {
if is.not {
return fmt.Sprintf("%s IS NOT NULL", is.expr)
}
return fmt.Sprintf("%s IS NULL", is.expr)
}
func (is *isNull) eval(execCtx *execCtx, ctx map[interface{}]interface{}) (v interface{}, err error) {
val, err := is.expr.eval(execCtx, ctx)
if err != nil {
return
}
return val == nil != is.not, nil
}
type indexOp struct {
expr, x expression
}
func newIndex(sv, xv expression) (v expression, err error) {
s, fs, i := "", false, uint64(0)
x := indexOp{sv, xv}
if x.expr.isStatic() {
v, err := x.expr.eval(nil, nil)
if err != nil {
return nil, err
}
if v == nil {
return value{nil}, nil
}
if s, fs = v.(string); !fs {
return nil, invXOp(sv, xv)
}
x.expr = value{s}
}
if x.x.isStatic() {
v, err := x.x.eval(nil, nil)
if err != nil {
return nil, err
}
if v == nil {
return value{nil}, nil
}
var p *string
if fs {
p = &s
}
if i, err = indexExpr(p, v); err != nil {
return nil, err
}
x.x = value{i}
}
return &x, nil
}
func (x *indexOp) clone(arg []interface{}, unqualify ...string) (expression, error) {
expr, err := x.expr.clone(arg, unqualify...)
if err != nil {
return nil, err
}
x2, err := x.x.clone(arg, unqualify...)
if err != nil {
return nil, err
}
return &indexOp{expr: expr, x: x2}, nil
}
func (x *indexOp) isStatic() bool {
return x.expr.isStatic() && x.x.isStatic()
}
func (x *indexOp) String() string { return fmt.Sprintf("%s[%s]", x.expr, x.x) }
func (x *indexOp) eval(execCtx *execCtx, ctx map[interface{}]interface{}) (v interface{}, err error) {
s0, err := x.expr.eval(execCtx, ctx)
if err != nil {
return nil, runErr(err)
}
s, ok := s0.(string)
if !ok {
return nil, runErr(invXOp(s0, x.x))
}
i0, err := x.x.eval(execCtx, ctx)
if err != nil {
return nil, runErr(err)
}
if i0 == nil {
return nil, nil
}
i, err := indexExpr(&s, i0)
if err != nil {
return nil, runErr(err)
}
return s[i], nil
}
type slice struct {
expr expression
lo, hi *expression
}
func newSlice(e expression, lo, hi *expression) (v expression, err error) {
y := slice{e, lo, hi}
var val interface{}
if e := y.expr; e.isStatic() {
if val, err = e.eval(nil, nil); err != nil {
return nil, err
}
if val == nil {
return value{nil}, nil
}
y.expr = value{val}
}
if p := y.lo; p != nil {
if e := expr(*p); e.isStatic() {
if val, err = e.eval(nil, nil); err != nil {
return nil, err
}
if val == nil {
return value{nil}, nil
}
v := expression(value{val})
y.lo = &v
}
}
if p := y.hi; p != nil {
if e := expr(*p); e.isStatic() {
if val, err = e.eval(nil, nil); err != nil {
return nil, err
}
if val == nil {
return value{nil}, nil
}
v := expression(value{val})
y.hi = &v
}
}
return &y, nil
}
func (s *slice) clone(arg []interface{}, unqualify ...string) (expression, error) {
expr, err := s.expr.clone(arg, unqualify...)
if err != nil {
return nil, err
}
r := &slice{expr: expr, lo: s.lo, hi: s.hi}
if s.lo != nil {
e, err := (*s.lo).clone(arg, unqualify...)
if err != nil {
return nil, err
}
r.lo = &e
}
if s.hi != nil {
e, err := (*s.hi).clone(arg, unqualify...)
if err != nil {
return nil, err
}
r.hi = &e
}
return r, nil
}
func (s *slice) eval(execCtx *execCtx, ctx map[interface{}]interface{}) (v interface{}, err error) {
s0, err := s.expr.eval(execCtx, ctx)
if err != nil {
return
}
if s0 == nil {
return
}
ss, ok := s0.(string)
if !ok {
return nil, runErr(invSOp(s0))
}
var iLo, iHi uint64
if s.lo != nil {
i, err := (*s.lo).eval(execCtx, ctx)
if err != nil {
return nil, err
}
if i == nil {
return nil, err
}
if iLo, err = sliceExpr(&ss, i, 0); err != nil {
return nil, err
}
}
iHi = uint64(len(ss))
if s.hi != nil {
i, err := (*s.hi).eval(execCtx, ctx)
if err != nil {
return nil, err
}
if i == nil {
return nil, err
}
if iHi, err = sliceExpr(&ss, i, 1); err != nil {
return nil, err
}
}
return ss[iLo:iHi], nil
}
func (s *slice) isStatic() bool {
if !s.expr.isStatic() {
return false
}
if p := s.lo; p != nil && !(*p).isStatic() {
return false
}
if p := s.hi; p != nil && !(*p).isStatic() {
return false
}
return false
}
func (s *slice) String() string {
switch {
case s.lo == nil && s.hi == nil:
return fmt.Sprintf("%v[:]", s.expr)
case s.lo == nil && s.hi != nil:
return fmt.Sprintf("%v[:%v]", s.expr, *s.hi)
case s.lo != nil && s.hi == nil:
return fmt.Sprintf("%v[%v:]", s.expr, *s.lo)
default: //case s.lo != nil && s.hi != nil:
return fmt.Sprintf("%v[%v:%v]", s.expr, *s.lo, *s.hi)
}
}