mirror of
https://github.com/octoleo/syncthing.git
synced 2024-11-14 09:14:10 +00:00
2773 lines
47 KiB
Go
2773 lines
47 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 in the LICENSE file.
|
|
|
|
package ql
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"io"
|
|
"math"
|
|
"math/big"
|
|
"time"
|
|
)
|
|
|
|
// QL types.
|
|
const (
|
|
qBool = 0x62 // 'b'
|
|
qComplex64 = 0x63 // 'c'
|
|
qComplex128 = 0x64 // 'd'
|
|
qFloat32 = 0x66 // 'f'
|
|
qFloat64 = 0x67 // 'g', alias float
|
|
qInt8 = 0x69 // 'i'
|
|
qInt16 = 0x6a // 'j'
|
|
qInt32 = 0x6b // 'k'
|
|
qInt64 = 0x6c // 'l', alias int
|
|
qString = 0x73 // 's'
|
|
qUint8 = 0x75 // 'u', alias byte
|
|
qUint16 = 0x76 // 'v'
|
|
qUint32 = 0x77 // 'w'
|
|
qUint64 = 0x78 // 'x', alias uint
|
|
|
|
qBigInt = 0x49 // 'I'
|
|
qBigRat = 0x52 // 'R'
|
|
qBlob = 0x42 // 'B'
|
|
qDuration = 0x44 // 'D'
|
|
qTime = 0x54 // 'T'
|
|
)
|
|
|
|
var (
|
|
type2Str = map[int]string{
|
|
qBigInt: "bigint",
|
|
qBigRat: "bigrat",
|
|
qBlob: "blob",
|
|
qBool: "bool",
|
|
qComplex128: "complex128",
|
|
qComplex64: "complex64",
|
|
qDuration: "duration",
|
|
qFloat32: "float32",
|
|
qFloat64: "float64",
|
|
qInt16: "int16",
|
|
qInt32: "int32",
|
|
qInt64: "int64",
|
|
qInt8: "int8",
|
|
qString: "string",
|
|
qTime: "time",
|
|
qUint16: "uint16",
|
|
qUint32: "uint32",
|
|
qUint64: "uint64",
|
|
qUint8: "uint8",
|
|
}
|
|
)
|
|
|
|
func typeStr(typ int) (r string) {
|
|
return type2Str[typ]
|
|
}
|
|
|
|
func noEOF(err error) error {
|
|
if err == io.EOF {
|
|
err = nil
|
|
}
|
|
return err
|
|
}
|
|
|
|
func runErr(err error) error { return fmt.Errorf("run time error: %s", err) }
|
|
|
|
func invXOp(s, x interface{}) error {
|
|
return fmt.Errorf("invalid operation: %v[%v] (index of type %T)", s, x, x)
|
|
}
|
|
|
|
func invSOp(s interface{}) error {
|
|
return fmt.Errorf("cannot slice %s (type %T)", s, s)
|
|
}
|
|
|
|
func invNegX(x interface{}) error {
|
|
return fmt.Errorf("invalid string index %v (index must be non-negative)", x)
|
|
}
|
|
|
|
func invNegLO(x interface{}) error {
|
|
return fmt.Errorf("invalid LIMIT or OFFSET value %v (must be non-negative)", x)
|
|
}
|
|
|
|
func invSliceNegX(x interface{}) error {
|
|
return fmt.Errorf("invalid slice index %v (index must be non-negative)", x)
|
|
}
|
|
|
|
func invBoundX(s string, x uint64) error {
|
|
return fmt.Errorf("invalid string index %d (out of bounds for %d-byte string)", x, len(s))
|
|
}
|
|
|
|
func invSliceBoundX(s string, x uint64) error {
|
|
return fmt.Errorf("invalid slice index %d (out of bounds for %d-byte string)", x, len(s))
|
|
}
|
|
|
|
func intExpr(x interface{}) (i int64, err error) {
|
|
switch x := x.(type) {
|
|
case idealInt:
|
|
if x < 0 {
|
|
return 0, invNegLO(x)
|
|
}
|
|
|
|
return int64(x), nil
|
|
case idealRune:
|
|
if x < 0 {
|
|
return 0, invNegLO(x)
|
|
}
|
|
|
|
return int64(x), nil
|
|
case idealUint:
|
|
if x < 0 {
|
|
return 0, invNegLO(x)
|
|
}
|
|
|
|
return int64(x), nil
|
|
case int8:
|
|
if x < 0 {
|
|
return 0, invNegLO(x)
|
|
}
|
|
|
|
return int64(x), nil
|
|
case int16:
|
|
if x < 0 {
|
|
return 0, invNegLO(x)
|
|
}
|
|
|
|
return int64(x), nil
|
|
case int32:
|
|
if x < 0 {
|
|
return 0, invNegLO(x)
|
|
}
|
|
|
|
return int64(x), nil
|
|
case int64:
|
|
if x < 0 {
|
|
return 0, invNegLO(x)
|
|
}
|
|
|
|
return int64(x), nil
|
|
case uint8:
|
|
return int64(x), nil
|
|
case uint16:
|
|
return int64(x), nil
|
|
case uint32:
|
|
return int64(x), nil
|
|
case uint64:
|
|
return int64(x), nil
|
|
default:
|
|
return 0, fmt.Errorf("non-integer expression: %v (value of type %T)", x, x)
|
|
}
|
|
}
|
|
|
|
func limOffExpr(x interface{}) (i uint64, err error) {
|
|
switch x := x.(type) {
|
|
case idealInt:
|
|
if x < 0 {
|
|
return 0, invNegLO(x)
|
|
}
|
|
|
|
return uint64(x), nil
|
|
case idealRune:
|
|
if x < 0 {
|
|
return 0, invNegLO(x)
|
|
}
|
|
|
|
return uint64(x), nil
|
|
case idealUint:
|
|
if x < 0 {
|
|
return 0, invNegLO(x)
|
|
}
|
|
|
|
return uint64(x), nil
|
|
case int8:
|
|
if x < 0 {
|
|
return 0, invNegLO(x)
|
|
}
|
|
|
|
return uint64(x), nil
|
|
case int16:
|
|
if x < 0 {
|
|
return 0, invNegLO(x)
|
|
}
|
|
|
|
return uint64(x), nil
|
|
case int32:
|
|
if x < 0 {
|
|
return 0, invNegLO(x)
|
|
}
|
|
|
|
return uint64(x), nil
|
|
case int64:
|
|
if x < 0 {
|
|
return 0, invNegLO(x)
|
|
}
|
|
|
|
return uint64(x), nil
|
|
case uint8:
|
|
return uint64(x), nil
|
|
case uint16:
|
|
return uint64(x), nil
|
|
case uint32:
|
|
return uint64(x), nil
|
|
case uint64:
|
|
return uint64(x), nil
|
|
default:
|
|
return 0, fmt.Errorf("non-integer used in LIMIT or OFFSET: %v (value of type %T)", x, x)
|
|
}
|
|
}
|
|
|
|
func indexExpr(s *string, x interface{}) (i uint64, err error) {
|
|
switch x := x.(type) {
|
|
case idealFloat:
|
|
if x < 0 {
|
|
return 0, invNegX(x)
|
|
}
|
|
|
|
if s != nil && int(x) >= len(*s) {
|
|
return 0, invBoundX(*s, uint64(x))
|
|
}
|
|
|
|
return uint64(x), nil
|
|
case idealInt:
|
|
if x < 0 {
|
|
return 0, invNegX(x)
|
|
}
|
|
|
|
if s != nil && int64(x) >= int64(len(*s)) {
|
|
return 0, invBoundX(*s, uint64(x))
|
|
}
|
|
|
|
return uint64(x), nil
|
|
case idealRune:
|
|
if x < 0 {
|
|
return 0, invNegX(x)
|
|
}
|
|
|
|
if s != nil && int32(x) >= int32(len(*s)) {
|
|
return 0, invBoundX(*s, uint64(x))
|
|
}
|
|
|
|
return uint64(x), nil
|
|
case idealUint:
|
|
if x < 0 {
|
|
return 0, invNegX(x)
|
|
}
|
|
|
|
if s != nil && uint64(x) >= uint64(len(*s)) {
|
|
return 0, invBoundX(*s, uint64(x))
|
|
}
|
|
|
|
return uint64(x), nil
|
|
case int8:
|
|
if x < 0 {
|
|
return 0, invNegX(x)
|
|
}
|
|
|
|
if s != nil && int(x) >= len(*s) {
|
|
return 0, invBoundX(*s, uint64(x))
|
|
}
|
|
|
|
return uint64(x), nil
|
|
case int16:
|
|
if x < 0 {
|
|
return 0, invNegX(x)
|
|
}
|
|
|
|
if s != nil && int(x) >= len(*s) {
|
|
return 0, invBoundX(*s, uint64(x))
|
|
}
|
|
|
|
return uint64(x), nil
|
|
case int32:
|
|
if x < 0 {
|
|
return 0, invNegX(x)
|
|
}
|
|
|
|
if s != nil && int(x) >= len(*s) {
|
|
return 0, invBoundX(*s, uint64(x))
|
|
}
|
|
|
|
return uint64(x), nil
|
|
case int64:
|
|
if x < 0 {
|
|
return 0, invNegX(x)
|
|
}
|
|
|
|
if s != nil && x >= int64(len(*s)) {
|
|
return 0, invBoundX(*s, uint64(x))
|
|
}
|
|
|
|
return uint64(x), nil
|
|
case uint8:
|
|
if s != nil && int(x) >= len(*s) {
|
|
return 0, invBoundX(*s, uint64(x))
|
|
}
|
|
|
|
return uint64(x), nil
|
|
case uint16:
|
|
if s != nil && int(x) >= len(*s) {
|
|
return 0, invBoundX(*s, uint64(x))
|
|
}
|
|
|
|
return uint64(x), nil
|
|
case uint32:
|
|
if s != nil && x >= uint32(len(*s)) {
|
|
return 0, invBoundX(*s, uint64(x))
|
|
}
|
|
|
|
return uint64(x), nil
|
|
case uint64:
|
|
if s != nil && x >= uint64(len(*s)) {
|
|
return 0, invBoundX(*s, uint64(x))
|
|
}
|
|
|
|
return uint64(x), nil
|
|
default:
|
|
return 0, fmt.Errorf("non-integer string index %v (value of type %T)", x, x)
|
|
}
|
|
}
|
|
|
|
func sliceExpr(s *string, x interface{}, mod int) (i uint64, err error) {
|
|
switch x := x.(type) {
|
|
case idealFloat:
|
|
if x < 0 {
|
|
return 0, invSliceNegX(x)
|
|
}
|
|
|
|
if s != nil && int(x) >= len(*s)+mod {
|
|
return 0, invSliceBoundX(*s, uint64(x))
|
|
}
|
|
|
|
return uint64(x), nil
|
|
case idealInt:
|
|
if x < 0 {
|
|
return 0, invSliceNegX(x)
|
|
}
|
|
|
|
if s != nil && int64(x) >= int64(len(*s)+mod) {
|
|
return 0, invSliceBoundX(*s, uint64(x))
|
|
}
|
|
|
|
return uint64(x), nil
|
|
case idealRune:
|
|
if x < 0 {
|
|
return 0, invSliceNegX(x)
|
|
}
|
|
|
|
if s != nil && int32(x) >= int32(len(*s)+mod) {
|
|
return 0, invSliceBoundX(*s, uint64(x))
|
|
}
|
|
|
|
return uint64(x), nil
|
|
case idealUint:
|
|
if x < 0 {
|
|
return 0, invSliceNegX(x)
|
|
}
|
|
|
|
if s != nil && uint64(x) >= uint64(len(*s)+mod) {
|
|
return 0, invSliceBoundX(*s, uint64(x))
|
|
}
|
|
|
|
return uint64(x), nil
|
|
case int8:
|
|
if x < 0 {
|
|
return 0, invSliceNegX(x)
|
|
}
|
|
|
|
if s != nil && int(x) >= len(*s)+mod {
|
|
return 0, invSliceBoundX(*s, uint64(x))
|
|
}
|
|
|
|
return uint64(x), nil
|
|
case int16:
|
|
if x < 0 {
|
|
return 0, invSliceNegX(x)
|
|
}
|
|
|
|
if s != nil && int(x) >= len(*s)+mod {
|
|
return 0, invSliceBoundX(*s, uint64(x))
|
|
}
|
|
|
|
return uint64(x), nil
|
|
case int32:
|
|
if x < 0 {
|
|
return 0, invSliceNegX(x)
|
|
}
|
|
|
|
if s != nil && int(x) >= len(*s)+mod {
|
|
return 0, invSliceBoundX(*s, uint64(x))
|
|
}
|
|
|
|
return uint64(x), nil
|
|
case int64:
|
|
if x < 0 {
|
|
return 0, invSliceNegX(x)
|
|
}
|
|
|
|
if s != nil && x >= int64(len(*s)+mod) {
|
|
return 0, invSliceBoundX(*s, uint64(x))
|
|
}
|
|
|
|
return uint64(x), nil
|
|
case uint8:
|
|
if s != nil && int(x) >= len(*s)+mod {
|
|
return 0, invSliceBoundX(*s, uint64(x))
|
|
}
|
|
|
|
return uint64(x), nil
|
|
case uint16:
|
|
if s != nil && int(x) >= len(*s)+mod {
|
|
return 0, invSliceBoundX(*s, uint64(x))
|
|
}
|
|
|
|
return uint64(x), nil
|
|
case uint32:
|
|
if s != nil && x >= uint32(len(*s)+mod) {
|
|
return 0, invSliceBoundX(*s, uint64(x))
|
|
}
|
|
|
|
return uint64(x), nil
|
|
case uint64:
|
|
if s != nil && x >= uint64(len(*s)+mod) {
|
|
return 0, invSliceBoundX(*s, uint64(x))
|
|
}
|
|
|
|
return uint64(x), nil
|
|
default:
|
|
return 0, fmt.Errorf("invalid slice index %s (type %T)", x, x)
|
|
}
|
|
}
|
|
|
|
type iop int
|
|
|
|
func (o iop) String() string {
|
|
switch i := int(o); i {
|
|
case andand:
|
|
return "&&"
|
|
case andnot:
|
|
return "&^"
|
|
case lsh:
|
|
return "<<"
|
|
case le:
|
|
return "<="
|
|
case eq:
|
|
return "=="
|
|
case ge:
|
|
return ">="
|
|
case neq:
|
|
return "!="
|
|
case oror:
|
|
return "||"
|
|
case rsh:
|
|
return ">>"
|
|
default:
|
|
return string(i)
|
|
}
|
|
}
|
|
|
|
func ideal(v interface{}) interface{} {
|
|
switch x := v.(type) {
|
|
case idealComplex:
|
|
return complex128(x)
|
|
case idealFloat:
|
|
return float64(x)
|
|
case idealInt:
|
|
return int64(x)
|
|
case idealRune:
|
|
return int64(x)
|
|
case idealUint:
|
|
return uint64(x)
|
|
default:
|
|
return v
|
|
}
|
|
}
|
|
|
|
func eval(v expression, execCtx *execCtx, ctx map[interface{}]interface{}) (y interface{}) {
|
|
y, err := expand1(v.eval(execCtx, ctx))
|
|
if err != nil {
|
|
panic(err) // panic ok here
|
|
}
|
|
return
|
|
}
|
|
|
|
func eval2(a, b expression, execCtx *execCtx, ctx map[interface{}]interface{}) (x, y interface{}) {
|
|
return eval(a, execCtx, ctx), eval(b, execCtx, ctx)
|
|
}
|
|
|
|
func invOp2(x, y interface{}, o int) (interface{}, error) {
|
|
return nil, fmt.Errorf("invalid operation: %v %v %v (mismatched types %T and %T)", x, iop(o), y, ideal(x), ideal(y))
|
|
}
|
|
|
|
func undOp(x interface{}, o int) (interface{}, error) {
|
|
return nil, fmt.Errorf("invalid operation: %v%v (operator %v not defined on %T)", iop(o), x, iop(o), x)
|
|
}
|
|
|
|
func undOp2(x, y interface{}, o int) (interface{}, error) {
|
|
return nil, fmt.Errorf("invalid operation: %v %v %v (operator %v not defined on %T)", x, iop(o), y, iop(o), x)
|
|
}
|
|
|
|
func invConv(val interface{}, typ int) (interface{}, error) {
|
|
return nil, fmt.Errorf("cannot convert %v (type %T) to type %s", val, val, typeStr(typ))
|
|
}
|
|
|
|
func truncConv(val interface{}) (interface{}, error) {
|
|
return nil, fmt.Errorf("constant %v truncated to integer", val)
|
|
}
|
|
|
|
func convert(val interface{}, typ int) (v interface{}, err error) { //NTYPE
|
|
if val == nil {
|
|
return nil, nil
|
|
}
|
|
|
|
switch typ {
|
|
case qBool:
|
|
switch x := val.(type) {
|
|
//case nil:
|
|
//case idealComplex:
|
|
//case idealFloat:
|
|
//case idealInt:
|
|
//case idealRune:
|
|
//case idealUint:
|
|
case bool:
|
|
return bool(x), nil
|
|
//case complex64:
|
|
//case complex128:
|
|
//case float32:
|
|
//case float64:
|
|
//case int8:
|
|
//case int16:
|
|
//case int32:
|
|
//case int64:
|
|
//case string:
|
|
//case uint8:
|
|
//case uint16:
|
|
//case uint32:
|
|
//case uint64:
|
|
default:
|
|
return invConv(val, typ)
|
|
}
|
|
case qComplex64:
|
|
switch x := val.(type) {
|
|
//case nil:
|
|
case idealComplex:
|
|
return complex64(x), nil
|
|
case idealFloat:
|
|
return complex(float32(x), 0), nil
|
|
case idealInt:
|
|
return complex(float32(x), 0), nil
|
|
case idealRune:
|
|
return complex(float32(x), 0), nil
|
|
case idealUint:
|
|
return complex(float32(x), 0), nil
|
|
//case bool:
|
|
case complex64:
|
|
return complex64(x), nil
|
|
case complex128:
|
|
return complex64(x), nil
|
|
//case float32:
|
|
//case float64:
|
|
//case int8:
|
|
//case int16:
|
|
//case int32:
|
|
//case int64:
|
|
//case string:
|
|
//case uint8:
|
|
//case uint16:
|
|
//case uint32:
|
|
//case uint64:
|
|
default:
|
|
return invConv(val, typ)
|
|
}
|
|
case qComplex128:
|
|
switch x := val.(type) {
|
|
//case nil:
|
|
case idealComplex:
|
|
return complex128(x), nil
|
|
case idealFloat:
|
|
return complex(float64(x), 0), nil
|
|
case idealInt:
|
|
return complex(float64(x), 0), nil
|
|
case idealRune:
|
|
return complex(float64(x), 0), nil
|
|
case idealUint:
|
|
return complex(float64(x), 0), nil
|
|
//case bool:
|
|
case complex64:
|
|
return complex128(x), nil
|
|
case complex128:
|
|
return complex128(x), nil
|
|
//case float32:
|
|
//case float64:
|
|
//case int8:
|
|
//case int16:
|
|
//case int32:
|
|
//case int64:
|
|
//case string:
|
|
//case uint8:
|
|
//case uint16:
|
|
//case uint32:
|
|
//case uint64:
|
|
default:
|
|
return invConv(val, typ)
|
|
}
|
|
case qFloat32:
|
|
switch x := val.(type) {
|
|
//case nil:
|
|
//case idealComplex:
|
|
case idealFloat:
|
|
return float32(x), nil
|
|
case idealInt:
|
|
return float32(x), nil
|
|
case idealRune:
|
|
return float32(x), nil
|
|
case idealUint:
|
|
return float32(x), nil
|
|
//case bool:
|
|
//case complex64:
|
|
//case complex128:
|
|
case float32:
|
|
return float32(x), nil
|
|
case float64:
|
|
return float32(x), nil
|
|
case int8:
|
|
return float32(x), nil
|
|
case int16:
|
|
return float32(x), nil
|
|
case int32:
|
|
return float32(x), nil
|
|
case int64:
|
|
return float32(x), nil
|
|
//case string:
|
|
case uint8:
|
|
return float32(x), nil
|
|
case uint16:
|
|
return float32(x), nil
|
|
case uint32:
|
|
return float32(x), nil
|
|
case uint64:
|
|
return float32(x), nil
|
|
case *big.Int:
|
|
v, _ := big.NewRat(1, 1).SetInt(x).Float64()
|
|
return float32(v), nil
|
|
case *big.Rat:
|
|
v, _ := x.Float64()
|
|
return float32(v), nil
|
|
case time.Duration:
|
|
return float32(x), nil
|
|
default:
|
|
return invConv(val, typ)
|
|
}
|
|
case qFloat64:
|
|
switch x := val.(type) {
|
|
//case nil:
|
|
//case idealComplex:
|
|
case idealFloat:
|
|
return float64(x), nil
|
|
case idealInt:
|
|
return float64(x), nil
|
|
case idealRune:
|
|
return float64(x), nil
|
|
case idealUint:
|
|
return float64(x), nil
|
|
//case bool:
|
|
//case complex64:
|
|
//case complex128:
|
|
case float32:
|
|
return float64(x), nil
|
|
case float64:
|
|
return float64(x), nil
|
|
case int8:
|
|
return float64(x), nil
|
|
case int16:
|
|
return float64(x), nil
|
|
case int32:
|
|
return float64(x), nil
|
|
case int64:
|
|
return float64(x), nil
|
|
//case string:
|
|
case uint8:
|
|
return float64(x), nil
|
|
case uint16:
|
|
return float64(x), nil
|
|
case uint32:
|
|
return float64(x), nil
|
|
case uint64:
|
|
return float64(x), nil
|
|
case *big.Int:
|
|
v, _ := big.NewRat(1, 1).SetInt(x).Float64()
|
|
return v, nil
|
|
case *big.Rat:
|
|
v, _ := x.Float64()
|
|
return v, nil
|
|
case time.Duration:
|
|
return float64(x), nil
|
|
default:
|
|
return invConv(val, typ)
|
|
}
|
|
case qInt8:
|
|
switch x := val.(type) {
|
|
//case nil:
|
|
//case idealComplex:
|
|
case idealFloat:
|
|
if _, frac := math.Modf(float64(x)); frac != 0 {
|
|
return truncConv(x)
|
|
}
|
|
|
|
return int8(x), nil
|
|
case idealInt:
|
|
return int8(x), nil
|
|
case idealRune:
|
|
return int8(x), nil
|
|
case idealUint:
|
|
return int8(x), nil
|
|
//case bool:
|
|
//case complex64:
|
|
//case complex128:
|
|
case float32:
|
|
return int8(x), nil
|
|
case float64:
|
|
return int8(x), nil
|
|
case int8:
|
|
return int8(x), nil
|
|
case int16:
|
|
return int8(x), nil
|
|
case int32:
|
|
return int8(x), nil
|
|
case int64:
|
|
return int8(x), nil
|
|
//case string:
|
|
case uint8:
|
|
return int8(x), nil
|
|
case uint16:
|
|
return int8(x), nil
|
|
case uint32:
|
|
return int8(x), nil
|
|
case uint64:
|
|
return int8(x), nil
|
|
case *big.Int:
|
|
return int8(x.Int64()), nil
|
|
case time.Duration:
|
|
return int8(x), nil
|
|
default:
|
|
return invConv(val, typ)
|
|
}
|
|
case qInt16:
|
|
switch x := val.(type) {
|
|
//case nil:
|
|
//case idealComplex:
|
|
case idealFloat:
|
|
if _, frac := math.Modf(float64(x)); frac != 0 {
|
|
return truncConv(x)
|
|
}
|
|
|
|
return int16(x), nil
|
|
case idealInt:
|
|
return int16(x), nil
|
|
case idealRune:
|
|
return int16(x), nil
|
|
case idealUint:
|
|
return int16(x), nil
|
|
//case bool:
|
|
//case complex64:
|
|
//case complex128:
|
|
case float32:
|
|
return int16(x), nil
|
|
case float64:
|
|
return int16(x), nil
|
|
case int8:
|
|
return int16(x), nil
|
|
case int16:
|
|
return int16(x), nil
|
|
case int32:
|
|
return int16(x), nil
|
|
case int64:
|
|
return int16(x), nil
|
|
//case string:
|
|
case uint8:
|
|
return int16(x), nil
|
|
case uint16:
|
|
return int16(x), nil
|
|
case uint32:
|
|
return int16(x), nil
|
|
case uint64:
|
|
return int16(x), nil
|
|
case *big.Int:
|
|
return int16(x.Int64()), nil
|
|
case time.Duration:
|
|
return int16(x), nil
|
|
default:
|
|
return invConv(val, typ)
|
|
}
|
|
case qInt32:
|
|
switch x := val.(type) {
|
|
//case nil:
|
|
//case idealComplex:
|
|
case idealFloat:
|
|
if _, frac := math.Modf(float64(x)); frac != 0 {
|
|
return truncConv(x)
|
|
}
|
|
|
|
return int32(x), nil
|
|
case idealInt:
|
|
return int32(x), nil
|
|
case idealRune:
|
|
return int32(x), nil
|
|
case idealUint:
|
|
return int32(x), nil
|
|
//case bool:
|
|
//case complex64:
|
|
//case complex128:
|
|
case float32:
|
|
return int32(x), nil
|
|
case float64:
|
|
return int32(x), nil
|
|
case int8:
|
|
return int32(x), nil
|
|
case int16:
|
|
return int32(x), nil
|
|
case int32:
|
|
return int32(x), nil
|
|
case int64:
|
|
return int32(x), nil
|
|
//case string:
|
|
case uint8:
|
|
return int32(x), nil
|
|
case uint16:
|
|
return int32(x), nil
|
|
case uint32:
|
|
return int32(x), nil
|
|
case uint64:
|
|
return int32(x), nil
|
|
case *big.Int:
|
|
return int32(x.Int64()), nil
|
|
case time.Duration:
|
|
return int32(x), nil
|
|
default:
|
|
return invConv(val, typ)
|
|
}
|
|
case qInt64:
|
|
switch x := val.(type) {
|
|
//case nil:
|
|
//case idealComplex:
|
|
case idealFloat:
|
|
if _, frac := math.Modf(float64(x)); frac != 0 {
|
|
return truncConv(x)
|
|
}
|
|
|
|
return int64(x), nil
|
|
case idealInt:
|
|
return int64(x), nil
|
|
case idealRune:
|
|
return int64(x), nil
|
|
case idealUint:
|
|
return int64(x), nil
|
|
//case bool:
|
|
//case complex64:
|
|
//case complex128:
|
|
case float32:
|
|
return int64(x), nil
|
|
case float64:
|
|
return int64(x), nil
|
|
case int8:
|
|
return int64(x), nil
|
|
case int16:
|
|
return int64(x), nil
|
|
case int32:
|
|
return int64(x), nil
|
|
case int64:
|
|
return int64(x), nil
|
|
//case string:
|
|
case uint8:
|
|
return int64(x), nil
|
|
case uint16:
|
|
return int64(x), nil
|
|
case uint32:
|
|
return int64(x), nil
|
|
case uint64:
|
|
return int64(x), nil
|
|
case *big.Int:
|
|
return x.Int64(), nil
|
|
case time.Duration:
|
|
return int64(x), nil
|
|
default:
|
|
return invConv(val, typ)
|
|
}
|
|
case qString:
|
|
switch x := val.(type) {
|
|
//case nil:
|
|
//case idealComplex:
|
|
//case idealFloat:
|
|
case idealInt:
|
|
return string(x), nil
|
|
case idealRune:
|
|
return string(x), nil
|
|
case idealUint:
|
|
return string(x), nil
|
|
//case bool:
|
|
//case complex64:
|
|
//case complex128:
|
|
//case float32:
|
|
//case float64:
|
|
case int8:
|
|
return string(x), nil
|
|
case int16:
|
|
return string(x), nil
|
|
case int32:
|
|
return string(x), nil
|
|
case int64:
|
|
return string(x), nil
|
|
case string:
|
|
return string(x), nil
|
|
case uint8:
|
|
return string(x), nil
|
|
case uint16:
|
|
return string(x), nil
|
|
case uint32:
|
|
return string(x), nil
|
|
case uint64:
|
|
return string(x), nil
|
|
case []byte:
|
|
return string(x), nil
|
|
case *big.Int:
|
|
return x.String(), nil
|
|
case time.Time:
|
|
return x.String(), nil
|
|
case time.Duration:
|
|
return x.String(), nil
|
|
default:
|
|
return invConv(val, typ)
|
|
}
|
|
case qUint8:
|
|
switch x := val.(type) {
|
|
//case nil:
|
|
//case idealComplex:
|
|
case idealFloat:
|
|
if _, frac := math.Modf(float64(x)); frac != 0 {
|
|
return truncConv(x)
|
|
}
|
|
|
|
return uint8(x), nil
|
|
case idealInt:
|
|
return uint8(x), nil
|
|
case idealRune:
|
|
return uint8(x), nil
|
|
case idealUint:
|
|
return uint8(x), nil
|
|
//case bool:
|
|
//case complex64:
|
|
//case complex128:
|
|
case float32:
|
|
return uint8(x), nil
|
|
case float64:
|
|
return uint8(x), nil
|
|
case int8:
|
|
return uint8(x), nil
|
|
case int16:
|
|
return uint8(x), nil
|
|
case int32:
|
|
return uint8(x), nil
|
|
case int64:
|
|
return uint8(x), nil
|
|
//case string:
|
|
case uint8:
|
|
return uint8(x), nil
|
|
case uint16:
|
|
return uint8(x), nil
|
|
case uint32:
|
|
return uint8(x), nil
|
|
case uint64:
|
|
return uint8(x), nil
|
|
case *big.Int:
|
|
return uint8(x.Int64()), nil
|
|
case time.Duration:
|
|
return uint8(x), nil
|
|
default:
|
|
return invConv(val, typ)
|
|
}
|
|
case qUint16:
|
|
switch x := val.(type) {
|
|
//case nil:
|
|
//case idealComplex:
|
|
case idealFloat:
|
|
if _, frac := math.Modf(float64(x)); frac != 0 {
|
|
return truncConv(x)
|
|
}
|
|
|
|
return uint16(x), nil
|
|
case idealInt:
|
|
return uint16(x), nil
|
|
case idealRune:
|
|
return uint16(x), nil
|
|
case idealUint:
|
|
return uint16(x), nil
|
|
//case bool:
|
|
//case complex64:
|
|
//case complex128:
|
|
case float32:
|
|
return uint16(x), nil
|
|
case float64:
|
|
return uint16(x), nil
|
|
case int8:
|
|
return uint16(x), nil
|
|
case int16:
|
|
return uint16(x), nil
|
|
case int32:
|
|
return uint16(x), nil
|
|
case int64:
|
|
return uint16(x), nil
|
|
//case string:
|
|
case uint8:
|
|
return uint16(x), nil
|
|
case uint16:
|
|
return uint16(x), nil
|
|
case uint32:
|
|
return uint16(x), nil
|
|
case uint64:
|
|
return uint16(x), nil
|
|
case *big.Int:
|
|
return uint16(x.Int64()), nil
|
|
case time.Duration:
|
|
return uint16(x), nil
|
|
default:
|
|
return invConv(val, typ)
|
|
}
|
|
case qUint32:
|
|
switch x := val.(type) {
|
|
//case nil:
|
|
//case idealComplex:
|
|
case idealFloat:
|
|
if _, frac := math.Modf(float64(x)); frac != 0 {
|
|
return truncConv(x)
|
|
}
|
|
|
|
return uint32(x), nil
|
|
case idealInt:
|
|
return uint32(x), nil
|
|
case idealRune:
|
|
return uint32(x), nil
|
|
case idealUint:
|
|
return uint32(x), nil
|
|
//case bool:
|
|
//case complex64:
|
|
//case complex128:
|
|
case float32:
|
|
return uint32(x), nil
|
|
case float64:
|
|
return uint32(x), nil
|
|
case int8:
|
|
return uint32(x), nil
|
|
case int16:
|
|
return uint32(x), nil
|
|
case int32:
|
|
return uint32(x), nil
|
|
case int64:
|
|
return uint32(x), nil
|
|
//case string:
|
|
case uint8:
|
|
return uint32(x), nil
|
|
case uint16:
|
|
return uint32(x), nil
|
|
case uint32:
|
|
return uint32(x), nil
|
|
case uint64:
|
|
return uint32(x), nil
|
|
case *big.Int:
|
|
return uint32(x.Int64()), nil
|
|
case time.Duration:
|
|
return uint32(x), nil
|
|
default:
|
|
return invConv(val, typ)
|
|
}
|
|
case qUint64:
|
|
switch x := val.(type) {
|
|
//case nil:
|
|
//case idealComplex:
|
|
case idealFloat:
|
|
if _, frac := math.Modf(float64(x)); frac != 0 {
|
|
return truncConv(x)
|
|
}
|
|
|
|
return uint64(x), nil
|
|
case idealInt:
|
|
return uint64(x), nil
|
|
case idealRune:
|
|
return uint64(x), nil
|
|
case idealUint:
|
|
return uint64(x), nil
|
|
//case bool:
|
|
//case complex64:
|
|
//case complex128:
|
|
case float32:
|
|
return uint64(x), nil
|
|
case float64:
|
|
return uint64(x), nil
|
|
case int8:
|
|
return uint64(x), nil
|
|
case int16:
|
|
return uint64(x), nil
|
|
case int32:
|
|
return uint64(x), nil
|
|
case int64:
|
|
return uint64(x), nil
|
|
//case string:
|
|
case uint8:
|
|
return uint64(x), nil
|
|
case uint16:
|
|
return uint64(x), nil
|
|
case uint32:
|
|
return uint64(x), nil
|
|
case uint64:
|
|
return uint64(x), nil
|
|
case *big.Int:
|
|
return x.Uint64(), nil
|
|
case time.Duration:
|
|
return uint64(x), nil
|
|
default:
|
|
return invConv(val, typ)
|
|
}
|
|
case qBlob:
|
|
switch x := val.(type) {
|
|
case string:
|
|
return []byte(x), nil
|
|
case []byte:
|
|
return x, nil
|
|
default:
|
|
return invConv(val, typ)
|
|
}
|
|
case qBigInt:
|
|
switch x := val.(type) {
|
|
// case blob
|
|
// case bool
|
|
//case idealComplex:
|
|
case idealFloat:
|
|
if _, frac := math.Modf(float64(x)); frac != 0 {
|
|
return truncConv(x)
|
|
}
|
|
|
|
rr := big.NewRat(1, 1).SetFloat64(float64(x))
|
|
ii := big.NewInt(0).Set(rr.Num())
|
|
ii.Quo(ii, rr.Denom())
|
|
return ii, nil
|
|
case idealInt:
|
|
return big.NewInt(0).SetInt64(int64(x)), nil
|
|
case idealRune:
|
|
return big.NewInt(0).SetInt64(int64(x)), nil
|
|
case idealUint:
|
|
return big.NewInt(0).SetUint64(uint64(x)), nil
|
|
//case complex64
|
|
//case complex128
|
|
case float32:
|
|
rr := big.NewRat(1, 1).SetFloat64(float64(x))
|
|
ii := big.NewInt(0).Set(rr.Num())
|
|
ii.Quo(ii, rr.Denom())
|
|
return ii, nil
|
|
case float64:
|
|
rr := big.NewRat(1, 1).SetFloat64(float64(x))
|
|
ii := big.NewInt(0).Set(rr.Num())
|
|
ii.Quo(ii, rr.Denom())
|
|
return ii, nil
|
|
case int8:
|
|
return big.NewInt(0).SetInt64(int64(x)), nil
|
|
case int16:
|
|
return big.NewInt(0).SetInt64(int64(x)), nil
|
|
case int32:
|
|
return big.NewInt(0).SetInt64(int64(x)), nil
|
|
case int64:
|
|
return big.NewInt(0).SetInt64(x), nil
|
|
case string:
|
|
y := big.NewInt(0)
|
|
if _, ok := y.SetString(x, 0); !ok {
|
|
return invConv(val, typ)
|
|
}
|
|
|
|
return y, nil
|
|
case uint8:
|
|
return big.NewInt(0).SetUint64(uint64(x)), nil
|
|
case uint16:
|
|
return big.NewInt(0).SetUint64(uint64(x)), nil
|
|
case uint32:
|
|
return big.NewInt(0).SetUint64(uint64(x)), nil
|
|
case uint64:
|
|
return big.NewInt(0).SetUint64(x), nil
|
|
case *big.Int:
|
|
return x, nil
|
|
case *big.Rat:
|
|
ii := big.NewInt(0).Set(x.Num())
|
|
ii.Div(ii, x.Denom())
|
|
return ii, nil
|
|
default:
|
|
return invConv(val, typ)
|
|
}
|
|
case qBigRat:
|
|
switch x := val.(type) {
|
|
// case blob
|
|
// case bool
|
|
//case idealComplex:
|
|
case idealFloat:
|
|
return big.NewRat(1, 1).SetFloat64(float64(x)), nil
|
|
case idealInt:
|
|
return big.NewRat(1, 1).SetInt64(int64(x)), nil
|
|
case idealRune:
|
|
return big.NewRat(1, 1).SetInt64(int64(x)), nil
|
|
case idealUint:
|
|
return big.NewRat(1, 1).SetInt(big.NewInt(0).SetUint64(uint64(x))), nil
|
|
//case complex64
|
|
//case complex128
|
|
case float32:
|
|
return big.NewRat(1, 1).SetFloat64(float64(x)), nil
|
|
case float64:
|
|
return big.NewRat(1, 1).SetFloat64(x), nil
|
|
case int8:
|
|
return big.NewRat(1, 1).SetInt64(int64(x)), nil
|
|
case int16:
|
|
return big.NewRat(1, 1).SetInt64(int64(x)), nil
|
|
case int32:
|
|
return big.NewRat(1, 1).SetInt64(int64(x)), nil
|
|
case int64:
|
|
return big.NewRat(1, 1).SetInt64(x), nil
|
|
case string:
|
|
y := big.NewRat(1, 1)
|
|
if _, ok := y.SetString(x); !ok {
|
|
return invConv(val, typ)
|
|
}
|
|
|
|
return y, nil
|
|
case uint8:
|
|
return big.NewRat(1, 1).SetInt64(int64(x)), nil
|
|
case uint16:
|
|
return big.NewRat(1, 1).SetInt64(int64(x)), nil
|
|
case uint32:
|
|
return big.NewRat(1, 1).SetInt64(int64(x)), nil
|
|
case uint64:
|
|
return big.NewRat(1, 1).SetInt(big.NewInt(0).SetUint64(x)), nil
|
|
case *big.Int:
|
|
return big.NewRat(1, 1).SetInt(x), nil
|
|
case *big.Rat:
|
|
return x, nil
|
|
default:
|
|
return invConv(val, typ)
|
|
}
|
|
case qDuration:
|
|
switch x := val.(type) {
|
|
// case blob
|
|
// case bool
|
|
//case idealComplex:
|
|
case idealFloat:
|
|
return time.Duration(x), nil
|
|
case idealInt:
|
|
return time.Duration(x), nil
|
|
case idealRune:
|
|
return time.Duration(x), nil
|
|
case idealUint:
|
|
return time.Duration(x), nil
|
|
//case complex64
|
|
//case complex128
|
|
case float32:
|
|
return time.Duration(x), nil
|
|
case float64:
|
|
return time.Duration(x), nil
|
|
case int8:
|
|
return time.Duration(x), nil
|
|
case int16:
|
|
return time.Duration(x), nil
|
|
case int32:
|
|
return time.Duration(x), nil
|
|
case int64:
|
|
return time.Duration(x), nil
|
|
case string:
|
|
return time.ParseDuration(x)
|
|
case uint8:
|
|
return time.Duration(x), nil
|
|
case uint16:
|
|
return time.Duration(x), nil
|
|
case uint32:
|
|
return time.Duration(x), nil
|
|
case uint64:
|
|
return time.Duration(x), nil
|
|
case *big.Int:
|
|
return time.Duration(x.Int64()), nil
|
|
case *big.Rat:
|
|
f, _ := x.Float64()
|
|
return time.Duration(f), nil
|
|
case time.Duration:
|
|
return x, nil
|
|
default:
|
|
return invConv(val, typ)
|
|
}
|
|
case qTime:
|
|
switch x := val.(type) {
|
|
// case blob
|
|
// case bool
|
|
//case idealComplex:
|
|
//case idealFloat:
|
|
//case idealInt:
|
|
//case idealRune:
|
|
//case idealUint:
|
|
//case complex64
|
|
//case complex128
|
|
//case float32:
|
|
//case float64:
|
|
//case int8:
|
|
//case int16:
|
|
//case int32:
|
|
//case int64:
|
|
//case string:
|
|
//case uint8:
|
|
//case uint16:
|
|
//case uint32:
|
|
//case uint64:
|
|
//case *big.Int:
|
|
//case *big.Rat:
|
|
//case time.Duration:
|
|
case time.Time:
|
|
return x, nil
|
|
default:
|
|
return invConv(val, typ)
|
|
}
|
|
default:
|
|
panic("internal error 006")
|
|
}
|
|
}
|
|
|
|
func invShiftRHS(lhs, rhs interface{}) (interface{}, error) {
|
|
return nil, fmt.Errorf("invalid operation: %v << %v (shift count type %T, must be unsigned integer)", lhs, rhs, rhs)
|
|
}
|
|
|
|
func invTruncInt(v interface{}) error {
|
|
return fmt.Errorf("constant %v truncated to integer", v)
|
|
}
|
|
|
|
func overflow(v interface{}, typ int) error {
|
|
return fmt.Errorf("constant %v overflows %s", v, typeStr(typ))
|
|
}
|
|
|
|
func typeCheck1(val interface{}, c *col) (interface{}, error) {
|
|
rec := []interface{}{val}
|
|
c = c.clone()
|
|
c.index = 0
|
|
if err := typeCheck(rec, []*col{c}); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return rec[0], nil
|
|
}
|
|
|
|
func typeCheck(rec []interface{}, cols []*col) (err error) {
|
|
for _, c := range cols {
|
|
i := c.index
|
|
if v := rec[i]; !c.typeCheck(v) {
|
|
switch v.(type) {
|
|
case idealComplex:
|
|
y := complex128(v.(idealComplex))
|
|
switch c.typ {
|
|
case qBool:
|
|
case qComplex64:
|
|
rec[i] = complex64(y)
|
|
continue
|
|
case qComplex128:
|
|
rec[i] = complex128(y)
|
|
continue
|
|
case qFloat32, qFloat64, qInt8, qInt16, qInt32, qInt64, qUint8, qUint16, qUint32, qUint64:
|
|
return fmt.Errorf("constant %v truncated to real", y)
|
|
}
|
|
case idealFloat:
|
|
y := float64(v.(idealFloat))
|
|
switch c.typ {
|
|
case qBool:
|
|
case qComplex64:
|
|
rec[i] = complex(float32(y), 0)
|
|
continue
|
|
case qComplex128:
|
|
rec[i] = complex(float64(y), 0)
|
|
continue
|
|
case qFloat32:
|
|
rec[i] = float32(y)
|
|
continue
|
|
case qFloat64:
|
|
rec[i] = float64(y)
|
|
continue
|
|
case qInt8:
|
|
if math.Floor(y) != y {
|
|
return invTruncInt(y)
|
|
}
|
|
|
|
if y < math.MinInt8 || y > math.MaxInt8 {
|
|
return overflow(y, c.typ)
|
|
}
|
|
|
|
rec[i] = int8(y)
|
|
continue
|
|
case qInt16:
|
|
if math.Floor(y) != y {
|
|
return invTruncInt(y)
|
|
}
|
|
|
|
if y < math.MinInt16 || y > math.MaxInt16 {
|
|
return overflow(y, c.typ)
|
|
}
|
|
|
|
rec[i] = int16(y)
|
|
continue
|
|
case qInt32:
|
|
if math.Floor(y) != y {
|
|
return invTruncInt(y)
|
|
}
|
|
|
|
if y < math.MinInt32 || y > math.MaxInt32 {
|
|
return overflow(y, c.typ)
|
|
}
|
|
|
|
rec[i] = int32(y)
|
|
continue
|
|
case qInt64:
|
|
if math.Floor(y) != y {
|
|
return invTruncInt(y)
|
|
}
|
|
|
|
if y < math.MinInt64 || y > math.MaxInt64 {
|
|
return overflow(y, c.typ)
|
|
}
|
|
|
|
rec[i] = int64(y)
|
|
continue
|
|
case qString:
|
|
case qUint8:
|
|
if math.Floor(y) != y {
|
|
return invTruncInt(y)
|
|
}
|
|
|
|
if y < 0 || y > math.MaxUint8 {
|
|
return overflow(y, c.typ)
|
|
}
|
|
|
|
rec[i] = uint8(y)
|
|
continue
|
|
case qUint16:
|
|
if math.Floor(y) != y {
|
|
return invTruncInt(y)
|
|
}
|
|
|
|
if y < 0 || y > math.MaxUint16 {
|
|
return overflow(y, c.typ)
|
|
}
|
|
|
|
rec[i] = uint16(y)
|
|
continue
|
|
case qUint32:
|
|
if math.Floor(y) != y {
|
|
return invTruncInt(y)
|
|
}
|
|
|
|
if y < 0 || y > math.MaxUint32 {
|
|
return overflow(y, c.typ)
|
|
}
|
|
|
|
rec[i] = uint32(y)
|
|
continue
|
|
case qUint64:
|
|
if math.Floor(y) != y {
|
|
return invTruncInt(y)
|
|
}
|
|
|
|
if y < 0 || y > math.MaxUint64 {
|
|
return overflow(y, c.typ)
|
|
}
|
|
|
|
rec[i] = uint64(y)
|
|
continue
|
|
case qBigInt:
|
|
if math.Floor(y) != y {
|
|
return invTruncInt(y)
|
|
}
|
|
|
|
rr := big.NewRat(1, 1).SetFloat64(y)
|
|
ii := big.NewInt(0)
|
|
ii.Set(rr.Num())
|
|
ii.Quo(ii, rr.Denom())
|
|
rec[i] = ii
|
|
continue
|
|
case qBigRat:
|
|
rec[i] = big.NewRat(1, 1).SetFloat64(y)
|
|
continue
|
|
}
|
|
case idealInt:
|
|
y := int64(v.(idealInt))
|
|
switch c.typ {
|
|
case qBool:
|
|
case qComplex64:
|
|
rec[i] = complex(float32(y), 0)
|
|
continue
|
|
case qComplex128:
|
|
rec[i] = complex(float64(y), 0)
|
|
continue
|
|
case qFloat32:
|
|
rec[i] = float32(y)
|
|
continue
|
|
case qFloat64:
|
|
rec[i] = float64(y)
|
|
continue
|
|
case qInt8:
|
|
if y < math.MinInt8 || y > math.MaxInt8 {
|
|
return overflow(y, c.typ)
|
|
}
|
|
|
|
rec[i] = int8(y)
|
|
continue
|
|
case qInt16:
|
|
if y < math.MinInt16 || y > math.MaxInt16 {
|
|
return overflow(y, c.typ)
|
|
}
|
|
|
|
rec[i] = int16(y)
|
|
continue
|
|
case qInt32:
|
|
if y < math.MinInt32 || y > math.MaxInt32 {
|
|
return overflow(y, c.typ)
|
|
}
|
|
|
|
rec[i] = int32(y)
|
|
continue
|
|
case qInt64:
|
|
if y < math.MinInt64 || y > math.MaxInt64 {
|
|
return overflow(y, c.typ)
|
|
}
|
|
|
|
rec[i] = int64(y)
|
|
continue
|
|
case qString:
|
|
case qUint8:
|
|
if y < 0 || y > math.MaxUint8 {
|
|
return overflow(y, c.typ)
|
|
}
|
|
|
|
rec[i] = uint8(y)
|
|
continue
|
|
case qUint16:
|
|
if y < 0 || y > math.MaxUint16 {
|
|
return overflow(y, c.typ)
|
|
}
|
|
|
|
rec[i] = uint16(y)
|
|
continue
|
|
case qUint32:
|
|
if y < 0 || y > math.MaxUint32 {
|
|
return overflow(y, c.typ)
|
|
}
|
|
|
|
rec[i] = uint32(y)
|
|
continue
|
|
case qUint64:
|
|
if y < 0 {
|
|
return overflow(y, c.typ)
|
|
}
|
|
|
|
rec[i] = uint64(y)
|
|
continue
|
|
case qBigInt:
|
|
rec[i] = big.NewInt(y)
|
|
continue
|
|
case qBigRat:
|
|
rec[i] = big.NewRat(1, 1).SetInt64(y)
|
|
continue
|
|
}
|
|
case idealRune:
|
|
y := int64(v.(idealRune))
|
|
switch c.typ {
|
|
case qBool:
|
|
case qComplex64:
|
|
rec[i] = complex(float32(y), 0)
|
|
continue
|
|
case qComplex128:
|
|
rec[i] = complex(float64(y), 0)
|
|
continue
|
|
case qFloat32:
|
|
rec[i] = float32(y)
|
|
continue
|
|
case qFloat64:
|
|
rec[i] = float64(y)
|
|
continue
|
|
case qInt8:
|
|
if y < math.MinInt8 || y > math.MaxInt8 {
|
|
return overflow(y, c.typ)
|
|
}
|
|
|
|
rec[i] = int8(y)
|
|
continue
|
|
case qInt16:
|
|
if y < math.MinInt16 || y > math.MaxInt16 {
|
|
return overflow(y, c.typ)
|
|
}
|
|
|
|
rec[i] = int16(y)
|
|
continue
|
|
case qInt32:
|
|
if y < math.MinInt32 || y > math.MaxInt32 {
|
|
return overflow(y, c.typ)
|
|
}
|
|
|
|
rec[i] = int32(y)
|
|
continue
|
|
case qInt64:
|
|
if y < math.MinInt64 || y > math.MaxInt64 {
|
|
return overflow(y, c.typ)
|
|
}
|
|
|
|
rec[i] = int64(y)
|
|
continue
|
|
case qString:
|
|
case qUint8:
|
|
if y < 0 || y > math.MaxUint8 {
|
|
return overflow(y, c.typ)
|
|
}
|
|
|
|
rec[i] = uint8(y)
|
|
continue
|
|
case qUint16:
|
|
if y < 0 || y > math.MaxUint16 {
|
|
return overflow(y, c.typ)
|
|
}
|
|
|
|
rec[i] = uint16(y)
|
|
continue
|
|
case qUint32:
|
|
if y < 0 {
|
|
return overflow(y, c.typ)
|
|
}
|
|
|
|
rec[i] = uint32(y)
|
|
continue
|
|
case qUint64:
|
|
if y < 0 {
|
|
return overflow(y, c.typ)
|
|
}
|
|
|
|
rec[i] = uint64(y)
|
|
continue
|
|
case qBigInt:
|
|
rec[i] = big.NewInt(y)
|
|
continue
|
|
case qBigRat:
|
|
rec[i] = big.NewRat(1, 1).SetInt64(y)
|
|
continue
|
|
}
|
|
case idealUint:
|
|
y := uint64(v.(idealUint))
|
|
switch c.typ {
|
|
case qBool:
|
|
case qComplex64:
|
|
rec[i] = complex(float32(y), 0)
|
|
continue
|
|
case qComplex128:
|
|
rec[i] = complex(float64(y), 0)
|
|
continue
|
|
case qFloat32:
|
|
rec[i] = float32(y)
|
|
continue
|
|
case qFloat64:
|
|
rec[i] = float64(y)
|
|
continue
|
|
case qInt8:
|
|
if y > math.MaxInt8 {
|
|
return overflow(y, c.typ)
|
|
}
|
|
|
|
rec[i] = int8(y)
|
|
continue
|
|
case qInt16:
|
|
if y > math.MaxInt16 {
|
|
return overflow(y, c.typ)
|
|
}
|
|
|
|
rec[i] = int16(y)
|
|
continue
|
|
case qInt32:
|
|
if y > math.MaxInt32 {
|
|
return overflow(y, c.typ)
|
|
}
|
|
|
|
rec[i] = int32(y)
|
|
continue
|
|
case qInt64:
|
|
if y > math.MaxInt64 {
|
|
return overflow(y, c.typ)
|
|
}
|
|
|
|
rec[i] = int64(y)
|
|
continue
|
|
case qString:
|
|
rec[i] = string(y)
|
|
continue
|
|
case qUint8:
|
|
if y > math.MaxUint8 {
|
|
return overflow(y, c.typ)
|
|
}
|
|
|
|
rec[i] = uint8(y)
|
|
continue
|
|
case qUint16:
|
|
if y > math.MaxUint16 {
|
|
return overflow(y, c.typ)
|
|
}
|
|
|
|
rec[i] = uint16(y)
|
|
continue
|
|
case qUint32:
|
|
if y > math.MaxUint32 {
|
|
return overflow(y, c.typ)
|
|
}
|
|
|
|
rec[i] = uint32(y)
|
|
continue
|
|
case qUint64:
|
|
rec[i] = uint64(y)
|
|
continue
|
|
case qBigInt:
|
|
rec[i] = big.NewInt(0).SetUint64(y)
|
|
continue
|
|
case qBigRat:
|
|
ii := big.NewInt(0).SetUint64(y)
|
|
rec[i] = big.NewRat(1, 1).SetInt(ii)
|
|
continue
|
|
}
|
|
}
|
|
return fmt.Errorf("cannot use %v (type %T) in assignment to, or comparison with, column %s (type %s)", v, ideal(v), c.name, typeStr(c.typ))
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
//TODO collate1 should return errors instead of panicing
|
|
func collate1(a, b interface{}) int {
|
|
switch x := a.(type) {
|
|
case nil:
|
|
if b != nil {
|
|
return -1
|
|
}
|
|
|
|
return 0
|
|
case bool:
|
|
switch y := b.(type) {
|
|
case nil:
|
|
return 1
|
|
case bool:
|
|
if !x && y {
|
|
return -1
|
|
}
|
|
|
|
if x == y {
|
|
return 0
|
|
}
|
|
|
|
return 1
|
|
default:
|
|
// Make bool collate before anything except nil and
|
|
// other bool for index seeking first non NULL value.
|
|
return -1
|
|
}
|
|
case idealComplex:
|
|
switch y := b.(type) {
|
|
case nil:
|
|
return 1
|
|
case idealComplex:
|
|
if x == y {
|
|
return 0
|
|
}
|
|
|
|
if real(x) < real(y) {
|
|
return -1
|
|
}
|
|
|
|
if real(x) > real(y) {
|
|
return 1
|
|
}
|
|
|
|
if imag(x) < imag(y) {
|
|
return -1
|
|
}
|
|
|
|
return 1
|
|
case complex64:
|
|
{
|
|
x, y := complex64(x), complex64(y)
|
|
if x == y {
|
|
return 0
|
|
}
|
|
|
|
if real(x) < real(y) {
|
|
return -1
|
|
}
|
|
|
|
if real(x) > real(y) {
|
|
return 1
|
|
}
|
|
|
|
if imag(x) < imag(y) {
|
|
return -1
|
|
}
|
|
|
|
return 1
|
|
}
|
|
case complex128:
|
|
{
|
|
x := complex128(x)
|
|
if x == y {
|
|
return 0
|
|
}
|
|
|
|
if real(x) < real(y) {
|
|
return -1
|
|
}
|
|
|
|
if real(x) > real(y) {
|
|
return 1
|
|
}
|
|
|
|
if imag(x) < imag(y) {
|
|
return -1
|
|
}
|
|
|
|
return 1
|
|
}
|
|
default:
|
|
panic("internal error 012")
|
|
}
|
|
case idealUint:
|
|
switch y := b.(type) {
|
|
case nil:
|
|
return 1
|
|
case idealUint:
|
|
if x < y {
|
|
return -1
|
|
}
|
|
|
|
if x == y {
|
|
return 0
|
|
}
|
|
|
|
return 1
|
|
case uint8:
|
|
{
|
|
x, y := uint64(x), uint64(y)
|
|
if x < y {
|
|
return -1
|
|
}
|
|
|
|
if x == y {
|
|
return 0
|
|
}
|
|
|
|
return 1
|
|
}
|
|
case uint16:
|
|
{
|
|
x, y := uint64(x), uint64(y)
|
|
if x < y {
|
|
return -1
|
|
}
|
|
|
|
if x == y {
|
|
return 0
|
|
}
|
|
|
|
return 1
|
|
}
|
|
case uint32:
|
|
{
|
|
x, y := uint64(x), uint64(y)
|
|
if x < y {
|
|
return -1
|
|
}
|
|
|
|
if x == y {
|
|
return 0
|
|
}
|
|
|
|
return 1
|
|
}
|
|
case uint64:
|
|
{
|
|
x, y := uint64(x), uint64(y)
|
|
if x < y {
|
|
return -1
|
|
}
|
|
|
|
if x == y {
|
|
return 0
|
|
}
|
|
|
|
return 1
|
|
}
|
|
case uint:
|
|
{
|
|
x, y := uint64(x), uint64(y)
|
|
if x < y {
|
|
return -1
|
|
}
|
|
|
|
if x == y {
|
|
return 0
|
|
}
|
|
|
|
return 1
|
|
}
|
|
default:
|
|
panic("internal error 013")
|
|
}
|
|
case idealRune:
|
|
switch y := b.(type) {
|
|
case nil:
|
|
return 1
|
|
case idealRune:
|
|
if x < y {
|
|
return -1
|
|
}
|
|
|
|
if x == y {
|
|
return 0
|
|
}
|
|
|
|
return 1
|
|
case int8:
|
|
{
|
|
x, y := int64(x), int64(y)
|
|
if x < y {
|
|
return -1
|
|
}
|
|
|
|
if x == y {
|
|
return 0
|
|
}
|
|
|
|
return 1
|
|
}
|
|
case int16:
|
|
{
|
|
x, y := int64(x), int64(y)
|
|
if x < y {
|
|
return -1
|
|
}
|
|
|
|
if x == y {
|
|
return 0
|
|
}
|
|
|
|
return 1
|
|
}
|
|
case int32:
|
|
{
|
|
x, y := int64(x), int64(y)
|
|
if x < y {
|
|
return -1
|
|
}
|
|
|
|
if x == y {
|
|
return 0
|
|
}
|
|
|
|
return 1
|
|
}
|
|
case int64:
|
|
{
|
|
x, y := int64(x), int64(y)
|
|
if x < y {
|
|
return -1
|
|
}
|
|
|
|
if x == y {
|
|
return 0
|
|
}
|
|
|
|
return 1
|
|
}
|
|
case int:
|
|
{
|
|
x, y := int64(x), int64(y)
|
|
if x < y {
|
|
return -1
|
|
}
|
|
|
|
if x == y {
|
|
return 0
|
|
}
|
|
|
|
return 1
|
|
}
|
|
default:
|
|
panic("internal error 014")
|
|
}
|
|
case idealInt:
|
|
switch y := b.(type) {
|
|
case nil:
|
|
return 1
|
|
case idealInt:
|
|
if x < y {
|
|
return -1
|
|
}
|
|
|
|
if x == y {
|
|
return 0
|
|
}
|
|
|
|
return 1
|
|
case int8:
|
|
{
|
|
x, y := int64(x), int64(y)
|
|
if x < y {
|
|
return -1
|
|
}
|
|
|
|
if x == y {
|
|
return 0
|
|
}
|
|
|
|
return 1
|
|
}
|
|
case int16:
|
|
{
|
|
x, y := int64(x), int64(y)
|
|
if x < y {
|
|
return -1
|
|
}
|
|
|
|
if x == y {
|
|
return 0
|
|
}
|
|
|
|
return 1
|
|
}
|
|
case int32:
|
|
{
|
|
x, y := int64(x), int64(y)
|
|
if x < y {
|
|
return -1
|
|
}
|
|
|
|
if x == y {
|
|
return 0
|
|
}
|
|
|
|
return 1
|
|
}
|
|
case int64:
|
|
{
|
|
x, y := int64(x), int64(y)
|
|
if x < y {
|
|
return -1
|
|
}
|
|
|
|
if x == y {
|
|
return 0
|
|
}
|
|
|
|
return 1
|
|
}
|
|
case int:
|
|
{
|
|
x, y := int64(x), int64(y)
|
|
if x < y {
|
|
return -1
|
|
}
|
|
|
|
if x == y {
|
|
return 0
|
|
}
|
|
|
|
return 1
|
|
}
|
|
default:
|
|
panic("internal error 015")
|
|
}
|
|
case idealFloat:
|
|
switch y := b.(type) {
|
|
case nil:
|
|
return 1
|
|
case idealFloat:
|
|
if x < y {
|
|
return -1
|
|
}
|
|
|
|
if x == y {
|
|
return 0
|
|
}
|
|
|
|
return 1
|
|
case float32:
|
|
{
|
|
x, y := float64(x), float64(y)
|
|
if x < y {
|
|
return -1
|
|
}
|
|
|
|
if x == y {
|
|
return 0
|
|
}
|
|
|
|
return 1
|
|
}
|
|
case float64:
|
|
{
|
|
x, y := float64(x), float64(y)
|
|
if x < y {
|
|
return -1
|
|
}
|
|
|
|
if x == y {
|
|
return 0
|
|
}
|
|
|
|
return 1
|
|
}
|
|
default:
|
|
panic("internal error 016")
|
|
}
|
|
case complex64:
|
|
switch y := b.(type) {
|
|
case nil:
|
|
return 1
|
|
case complex64:
|
|
if x == y {
|
|
return 0
|
|
}
|
|
|
|
if real(x) < real(y) {
|
|
return -1
|
|
}
|
|
|
|
if real(x) > real(y) {
|
|
return 1
|
|
}
|
|
|
|
if imag(x) < imag(y) {
|
|
return -1
|
|
}
|
|
|
|
return 1
|
|
case idealComplex:
|
|
{
|
|
x, y := complex64(x), complex64(y)
|
|
if x == y {
|
|
return 0
|
|
}
|
|
|
|
if real(x) < real(y) {
|
|
return -1
|
|
}
|
|
|
|
if real(x) > real(y) {
|
|
return 1
|
|
}
|
|
|
|
if imag(x) < imag(y) {
|
|
return -1
|
|
}
|
|
|
|
return 1
|
|
}
|
|
default:
|
|
panic("internal error 017")
|
|
}
|
|
case complex128:
|
|
switch y := b.(type) {
|
|
case nil:
|
|
return 1
|
|
case complex128:
|
|
if x == y {
|
|
return 0
|
|
}
|
|
|
|
if real(x) < real(y) {
|
|
return -1
|
|
}
|
|
|
|
if real(x) > real(y) {
|
|
return 1
|
|
}
|
|
|
|
if imag(x) < imag(y) {
|
|
return -1
|
|
}
|
|
|
|
return 1
|
|
case idealComplex:
|
|
{
|
|
x, y := complex128(x), complex128(y)
|
|
if x == y {
|
|
return 0
|
|
}
|
|
|
|
if real(x) < real(y) {
|
|
return -1
|
|
}
|
|
|
|
if real(x) > real(y) {
|
|
return 1
|
|
}
|
|
|
|
if imag(x) < imag(y) {
|
|
return -1
|
|
}
|
|
|
|
return 1
|
|
}
|
|
default:
|
|
panic("internal error 018")
|
|
}
|
|
case float32:
|
|
switch y := b.(type) {
|
|
case nil:
|
|
return 1
|
|
case float32:
|
|
if x < y {
|
|
return -1
|
|
}
|
|
|
|
if x == y {
|
|
return 0
|
|
}
|
|
|
|
return 1
|
|
case idealFloat:
|
|
{
|
|
x, y := float32(x), float32(y)
|
|
if x < y {
|
|
return -1
|
|
}
|
|
|
|
if x == y {
|
|
return 0
|
|
}
|
|
|
|
return 1
|
|
}
|
|
default:
|
|
panic("internal error 019")
|
|
}
|
|
case float64:
|
|
switch y := b.(type) {
|
|
case nil:
|
|
return 1
|
|
case float64:
|
|
if x < y {
|
|
return -1
|
|
}
|
|
|
|
if x == y {
|
|
return 0
|
|
}
|
|
|
|
return 1
|
|
case idealFloat:
|
|
{
|
|
x, y := float64(x), float64(y)
|
|
if x < y {
|
|
return -1
|
|
}
|
|
|
|
if x == y {
|
|
return 0
|
|
}
|
|
|
|
return 1
|
|
}
|
|
default:
|
|
panic("internal error 020")
|
|
}
|
|
case int8:
|
|
switch y := b.(type) {
|
|
case nil:
|
|
return 1
|
|
case int8:
|
|
if x < y {
|
|
return -1
|
|
}
|
|
|
|
if x == y {
|
|
return 0
|
|
}
|
|
|
|
return 1
|
|
case idealInt:
|
|
{
|
|
x, y := int64(x), int64(y)
|
|
if x < y {
|
|
return -1
|
|
}
|
|
|
|
if x == y {
|
|
return 0
|
|
}
|
|
|
|
return 1
|
|
}
|
|
default:
|
|
panic("internal error 021")
|
|
}
|
|
case int16:
|
|
switch y := b.(type) {
|
|
case nil:
|
|
return 1
|
|
case int16:
|
|
if x < y {
|
|
return -1
|
|
}
|
|
|
|
if x == y {
|
|
return 0
|
|
}
|
|
|
|
return 1
|
|
case idealInt:
|
|
{
|
|
x, y := int64(x), int64(y)
|
|
if x < y {
|
|
return -1
|
|
}
|
|
|
|
if x == y {
|
|
return 0
|
|
}
|
|
|
|
return 1
|
|
}
|
|
default:
|
|
panic("internal error 022")
|
|
}
|
|
case int32:
|
|
switch y := b.(type) {
|
|
case nil:
|
|
return 1
|
|
case int32:
|
|
if x < y {
|
|
return -1
|
|
}
|
|
|
|
if x == y {
|
|
return 0
|
|
}
|
|
|
|
return 1
|
|
case idealInt:
|
|
{
|
|
x, y := int64(x), int64(y)
|
|
if x < y {
|
|
return -1
|
|
}
|
|
|
|
if x == y {
|
|
return 0
|
|
}
|
|
|
|
return 1
|
|
}
|
|
default:
|
|
panic("internal error 023")
|
|
}
|
|
case int64:
|
|
switch y := b.(type) {
|
|
case nil:
|
|
return 1
|
|
case int64:
|
|
if x < y {
|
|
return -1
|
|
}
|
|
|
|
if x == y {
|
|
return 0
|
|
}
|
|
|
|
return 1
|
|
case idealInt:
|
|
{
|
|
x, y := int64(x), int64(y)
|
|
if x < y {
|
|
return -1
|
|
}
|
|
|
|
if x == y {
|
|
return 0
|
|
}
|
|
|
|
return 1
|
|
}
|
|
default:
|
|
panic("internal error 024")
|
|
}
|
|
case uint8:
|
|
switch y := b.(type) {
|
|
case nil:
|
|
return 1
|
|
case uint8:
|
|
if x < y {
|
|
return -1
|
|
}
|
|
|
|
if x == y {
|
|
return 0
|
|
}
|
|
|
|
return 1
|
|
case idealInt:
|
|
{
|
|
x, y := uint64(x), uint64(y)
|
|
if x < y {
|
|
return -1
|
|
}
|
|
|
|
if x == y {
|
|
return 0
|
|
}
|
|
|
|
return 1
|
|
}
|
|
case idealUint:
|
|
{
|
|
x, y := uint64(x), uint64(y)
|
|
if x < y {
|
|
return -1
|
|
}
|
|
|
|
if x == y {
|
|
return 0
|
|
}
|
|
|
|
return 1
|
|
}
|
|
default:
|
|
panic("internal error 025")
|
|
}
|
|
case uint16:
|
|
switch y := b.(type) {
|
|
case nil:
|
|
return 1
|
|
case uint16:
|
|
if x < y {
|
|
return -1
|
|
}
|
|
|
|
if x == y {
|
|
return 0
|
|
}
|
|
|
|
return 1
|
|
case idealInt:
|
|
{
|
|
x, y := uint64(x), uint64(y)
|
|
if x < y {
|
|
return -1
|
|
}
|
|
|
|
if x == y {
|
|
return 0
|
|
}
|
|
|
|
return 1
|
|
}
|
|
case idealUint:
|
|
{
|
|
x, y := uint64(x), uint64(y)
|
|
if x < y {
|
|
return -1
|
|
}
|
|
|
|
if x == y {
|
|
return 0
|
|
}
|
|
|
|
return 1
|
|
}
|
|
default:
|
|
panic("internal error 026")
|
|
}
|
|
case uint32:
|
|
switch y := b.(type) {
|
|
case nil:
|
|
return 1
|
|
case uint32:
|
|
if x < y {
|
|
return -1
|
|
}
|
|
|
|
if x == y {
|
|
return 0
|
|
}
|
|
|
|
return 1
|
|
case idealInt:
|
|
{
|
|
x, y := uint64(x), uint64(y)
|
|
if x < y {
|
|
return -1
|
|
}
|
|
|
|
if x == y {
|
|
return 0
|
|
}
|
|
|
|
return 1
|
|
}
|
|
case idealUint:
|
|
{
|
|
x, y := uint64(x), uint64(y)
|
|
if x < y {
|
|
return -1
|
|
}
|
|
|
|
if x == y {
|
|
return 0
|
|
}
|
|
|
|
return 1
|
|
}
|
|
default:
|
|
panic("internal error 027")
|
|
}
|
|
case uint64:
|
|
switch y := b.(type) {
|
|
case nil:
|
|
return 1
|
|
case uint64:
|
|
if x < y {
|
|
return -1
|
|
}
|
|
|
|
if x == y {
|
|
return 0
|
|
}
|
|
|
|
return 1
|
|
case idealInt:
|
|
{
|
|
x, y := uint64(x), uint64(y)
|
|
if x < y {
|
|
return -1
|
|
}
|
|
|
|
if x == y {
|
|
return 0
|
|
}
|
|
|
|
return 1
|
|
}
|
|
case idealUint:
|
|
{
|
|
x, y := uint64(x), uint64(y)
|
|
if x < y {
|
|
return -1
|
|
}
|
|
|
|
if x == y {
|
|
return 0
|
|
}
|
|
|
|
return 1
|
|
}
|
|
default:
|
|
panic("internal error 028")
|
|
}
|
|
case string:
|
|
switch y := b.(type) {
|
|
case nil:
|
|
return 1
|
|
case string:
|
|
if x < y {
|
|
return -1
|
|
}
|
|
|
|
if x == y {
|
|
return 0
|
|
}
|
|
|
|
return 1
|
|
default:
|
|
panic("internal error 029")
|
|
}
|
|
case []byte:
|
|
switch y := b.(type) {
|
|
case nil:
|
|
return 1
|
|
case []byte:
|
|
return bytes.Compare(x, y)
|
|
default:
|
|
panic("internal error 030")
|
|
}
|
|
case *big.Int:
|
|
switch y := b.(type) {
|
|
case nil:
|
|
return 1
|
|
case *big.Int:
|
|
return x.Cmp(y)
|
|
case idealInt:
|
|
{
|
|
y := big.NewInt(int64(y))
|
|
return x.Cmp(y)
|
|
}
|
|
case idealUint:
|
|
{
|
|
u := big.NewInt(0)
|
|
u.SetUint64(uint64(y))
|
|
return x.Cmp(u)
|
|
}
|
|
default:
|
|
panic("internal error 031")
|
|
}
|
|
case *big.Rat:
|
|
switch y := b.(type) {
|
|
case nil:
|
|
return 1
|
|
case *big.Rat:
|
|
return x.Cmp(y)
|
|
case idealInt:
|
|
{
|
|
y := big.NewRat(int64(y), 1)
|
|
return x.Cmp(y)
|
|
}
|
|
case idealUint:
|
|
{
|
|
u := big.NewInt(0)
|
|
u.SetUint64(uint64(y))
|
|
var y big.Rat
|
|
y.SetInt(u)
|
|
return x.Cmp(&y)
|
|
}
|
|
default:
|
|
panic("internal error 032")
|
|
}
|
|
case time.Time:
|
|
switch y := b.(type) {
|
|
case nil:
|
|
return 1
|
|
case time.Time:
|
|
if x.Before(y) {
|
|
return -1
|
|
}
|
|
|
|
if x.Equal(y) {
|
|
return 0
|
|
}
|
|
|
|
return 1
|
|
default:
|
|
panic("internal error 033")
|
|
}
|
|
case time.Duration:
|
|
switch y := b.(type) {
|
|
case nil:
|
|
return 1
|
|
case time.Duration:
|
|
if x < y {
|
|
return -1
|
|
}
|
|
|
|
if x == y {
|
|
return 0
|
|
}
|
|
|
|
return 1
|
|
default:
|
|
panic("internal error 034")
|
|
}
|
|
case chunk:
|
|
switch y := b.(type) {
|
|
case nil:
|
|
return 1
|
|
case chunk:
|
|
a, err := x.expand()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
b, err := y.expand()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
return collate1(a, b)
|
|
default:
|
|
panic("internal error 035")
|
|
}
|
|
default:
|
|
//dbg("%T(%v) %T(%v)", a, a, b, b)
|
|
panic("internal error 036")
|
|
}
|
|
}
|
|
|
|
//TODO collate should return errors from collate1
|
|
func collate(x, y []interface{}) (r int) {
|
|
//defer func() { dbg("%v %v -> %v", x, y, r) }()
|
|
nx, ny := len(x), len(y)
|
|
|
|
switch {
|
|
case nx == 0 && ny != 0:
|
|
return -1
|
|
case nx == 0 && ny == 0:
|
|
return 0
|
|
case nx != 0 && ny == 0:
|
|
return 1
|
|
}
|
|
|
|
r = 1
|
|
if nx > ny {
|
|
x, y, r = y, x, -r
|
|
}
|
|
|
|
for i, xi := range x {
|
|
if c := collate1(xi, y[i]); c != 0 {
|
|
return c * r
|
|
}
|
|
}
|
|
|
|
if nx == ny {
|
|
return 0
|
|
}
|
|
|
|
return -r
|
|
}
|
|
|
|
var collators = map[bool]func(a, b []interface{}) int{false: collateDesc, true: collate}
|
|
|
|
func collateDesc(a, b []interface{}) int {
|
|
return -collate(a, b)
|
|
}
|
|
|
|
func isOrderedType(v interface{}) (y interface{}, r bool, err error) {
|
|
//dbg("====")
|
|
//dbg("%T(%v)", v, v)
|
|
//defer func() { dbg("%T(%v)", y, y) }()
|
|
switch x := v.(type) {
|
|
case idealFloat, idealInt, idealRune, idealUint,
|
|
float32, float64,
|
|
int8, int16, int32, int64,
|
|
uint8, uint16, uint32, uint64,
|
|
string:
|
|
return v, true, nil
|
|
case *big.Int, *big.Rat, time.Time, time.Duration:
|
|
return x, true, nil
|
|
case chunk:
|
|
if y, err = x.expand(); err != nil {
|
|
return
|
|
}
|
|
|
|
return isOrderedType(y)
|
|
}
|
|
|
|
return v, false, nil
|
|
}
|
|
|
|
var isSystemName = map[string]bool{
|
|
"__Column": true,
|
|
"__Column2": true,
|
|
"__Index": true,
|
|
"__Index2": true,
|
|
"__Index2_Column": true,
|
|
"__Index2_Expr": true,
|
|
"__Table": true,
|
|
}
|
|
|
|
func qnames(l []string) []string {
|
|
r := make([]string, len(l))
|
|
for i, v := range l {
|
|
r[i] = fmt.Sprintf("%q", v)
|
|
}
|
|
return r
|
|
}
|