1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package adt
16
17 import (
18 "github.com/cockroachdb/apd/v3"
19
20 "cuelang.org/go/internal"
21 )
22
23
24
25
26
27 func SimplifyBounds(ctx *OpContext, k Kind, x, y *BoundValue) Value {
28 xv := x.Value
29 yv := y.Value
30
31 cmp, xCat := opInfo(x.Op)
32 _, yCat := opInfo(y.Op)
33
34
35
36 switch {
37 case xCat == yCat:
38 switch x.Op {
39
40
41 case EqualOp, NotEqualOp, MatchOp, NotMatchOp:
42 if test(ctx, EqualOp, xv, yv) {
43 return x
44 }
45 return nil
46 }
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64 if test(ctx, cmp, xv, yv) {
65 return x
66 }
67 return y
68
69 case xCat == -yCat:
70 if xCat == -1 {
71 x, y = y, x
72 }
73 a, aOK := xv.(*Num)
74 b, bOK := yv.(*Num)
75
76 if !aOK || !bOK {
77 break
78 }
79
80 var d, lo, hi apd.Decimal
81 lo.Set(&a.X)
82 hi.Set(&b.X)
83 if k&FloatKind == 0 {
84
85 if x.Op == GreaterEqualOp {
86
87 _, _ = internal.BaseContext.Ceil(&lo, &a.X)
88 } else {
89
90 _, _ = internal.BaseContext.Floor(&lo, &a.X)
91 }
92 if y.Op == LessEqualOp {
93
94 _, _ = internal.BaseContext.Floor(&hi, &b.X)
95 } else {
96
97 _, _ = internal.BaseContext.Ceil(&hi, &b.X)
98 }
99 }
100
101 cond, err := internal.BaseContext.Sub(&d, &hi, &lo)
102 if cond.Inexact() || err != nil {
103 break
104 }
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132 switch diff, err := d.Int64(); {
133 case diff == 1:
134 if k&FloatKind == 0 {
135 if x.Op == GreaterEqualOp && y.Op == LessThanOp {
136 return ctx.newNum(&lo, k&NumKind, x, y)
137 }
138 if x.Op == GreaterThanOp && y.Op == LessEqualOp {
139 return ctx.newNum(&hi, k&NumKind, x, y)
140 }
141 }
142
143 case diff == 2:
144 if k&FloatKind == 0 && x.Op == GreaterThanOp && y.Op == LessThanOp {
145 _, _ = internal.BaseContext.Add(&d, d.SetInt64(1), &lo)
146 return ctx.newNum(&d, k&NumKind, x, y)
147
148 }
149
150 case diff == 0 && err == nil:
151 if x.Op == GreaterEqualOp && y.Op == LessEqualOp {
152 return ctx.newNum(&lo, k&NumKind, x, y)
153 }
154 fallthrough
155
156 case d.Negative:
157 return ctx.NewErrf("incompatible bounds %v and %v", x, y)
158 }
159
160 case x.Op == NotEqualOp:
161 if !test(ctx, y.Op, xv, yv) {
162 return y
163 }
164
165 case y.Op == NotEqualOp:
166 if !test(ctx, x.Op, yv, xv) {
167 return x
168 }
169 }
170 return nil
171 }
172
173 func opInfo(op Op) (cmp Op, norm int) {
174 switch op {
175 case GreaterThanOp:
176 return GreaterEqualOp, 1
177 case GreaterEqualOp:
178 return GreaterThanOp, 1
179 case LessThanOp:
180 return LessEqualOp, -1
181 case LessEqualOp:
182 return LessThanOp, -1
183 case NotEqualOp:
184 return NotEqualOp, 0
185 case MatchOp:
186 return MatchOp, 2
187 case NotMatchOp:
188 return NotMatchOp, 3
189 }
190 panic("cue: unreachable")
191 }
192
193 func test(ctx *OpContext, op Op, a, b Value) bool {
194 if b, ok := BinOp(ctx, op, a, b).(*Bool); ok {
195 return b.B
196 }
197 return false
198 }
199
200
201
202
203
204
205 func SimplifyValidator(ctx *OpContext, v, w Validator) Validator {
206 switch x := v.(type) {
207 case *BuiltinValidator:
208 switch y := w.(type) {
209 case *BuiltinValidator:
210 if x == y {
211 return x
212 }
213 if x.Builtin != y.Builtin || len(x.Args) != len(y.Args) {
214 return nil
215 }
216 for i, a := range x.Args {
217 if !Equal(ctx, a, y.Args[i], CheckStructural) {
218 return nil
219 }
220 }
221 return x
222 }
223 }
224 return nil
225 }
226
View as plain text