1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package adt
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 import (
35 "cuelang.org/go/cue/ast"
36 "cuelang.org/go/cue/errors"
37 cueformat "cuelang.org/go/cue/format"
38 "cuelang.org/go/cue/token"
39 )
40
41
42
43 type ErrorCode int8
44
45 const (
46
47 EvalError ErrorCode = iota
48
49
50 UserError
51
52
53
54
55
56 StructuralCycleError
57
58
59
60 IncompleteError
61
62
63
64
65 CycleError
66 )
67
68 func (c ErrorCode) String() string {
69 switch c {
70 case EvalError:
71 return "eval"
72 case UserError:
73 return "user"
74 case StructuralCycleError:
75 return "structural cycle"
76 case IncompleteError:
77 return "incomplete"
78 case CycleError:
79 return "cycle"
80 }
81 return "unknown"
82 }
83
84
85
86
87
88 type Bottom struct {
89 Src ast.Node
90 Err errors.Error
91
92 Code ErrorCode
93
94
95
96 Permanent bool
97 HasRecursive bool
98 ChildError bool
99 NotExists bool
100 ForCycle bool
101
102 Value Value
103 }
104
105 func (x *Bottom) Source() ast.Node { return x.Src }
106 func (x *Bottom) Kind() Kind { return BottomKind }
107 func (x *Bottom) Specialize(k Kind) Value { return x }
108
109 func (b *Bottom) IsIncomplete() bool {
110 if b == nil {
111 return false
112 }
113 return b.Code == IncompleteError || b.Code == CycleError
114 }
115
116
117 func isLiteralBottom(x Expr) bool {
118 b, ok := x.(*Bottom)
119 return ok && b.Code == UserError
120 }
121
122
123 func isError(v Value) bool {
124 if v == nil {
125 return true
126 }
127 _, ok := v.(*Bottom)
128 return ok
129 }
130
131
132 func isIncomplete(v *Vertex) bool {
133 if v == nil {
134 return true
135 }
136 if b, ok := v.BaseValue.(*Bottom); ok {
137 return b.IsIncomplete()
138 }
139 return false
140 }
141
142
143
144
145
146
147
148 func (v *Vertex) AddChildError(recursive *Bottom) {
149 v.ChildErrors = CombineErrors(nil, v.ChildErrors, recursive)
150 if recursive.IsIncomplete() {
151 return
152 }
153 x := v.BaseValue
154 err, _ := x.(*Bottom)
155 if err == nil {
156 v.BaseValue = &Bottom{
157 Code: recursive.Code,
158 Value: v,
159 HasRecursive: true,
160 ChildError: true,
161 Err: recursive.Err,
162 }
163 return
164 }
165
166 err.HasRecursive = true
167 if err.Code > recursive.Code {
168 err.Code = recursive.Code
169 }
170
171 v.BaseValue = err
172 }
173
174
175 func CombineErrors(src ast.Node, x, y Value) *Bottom {
176 a, _ := Unwrap(x).(*Bottom)
177 b, _ := Unwrap(y).(*Bottom)
178
179 if a == b && isCyclePlaceholder(a) {
180 return a
181 }
182 switch {
183 case a != nil && b != nil:
184 case a != nil:
185 return a
186 case b != nil:
187 return b
188 default:
189 return nil
190 }
191
192 if a.Code != b.Code {
193 if a.Code > b.Code {
194 a, b = b, a
195 }
196
197 if b.Code >= IncompleteError {
198 return a
199 }
200 }
201
202 return &Bottom{
203 Src: src,
204 Err: errors.Append(a.Err, b.Err),
205 Code: a.Code,
206 }
207 }
208
209 func addPositions(err *ValueError, c Conjunct) {
210 switch x := c.x.(type) {
211 case *Field:
212
213 err.AddPosition(c.x)
214
215 case *ConjunctGroup:
216 for _, c := range *x {
217 addPositions(err, c)
218 }
219 }
220 if c.CloseInfo.closeInfo != nil {
221 err.AddPosition(c.CloseInfo.location)
222 }
223 }
224
225 func NewRequiredNotPresentError(ctx *OpContext, v *Vertex) *Bottom {
226 saved := ctx.PushArc(v)
227 err := ctx.Newf("field is required but not present")
228 for _, c := range v.Conjuncts {
229 if f, ok := c.x.(*Field); ok && f.ArcType == ArcRequired {
230 err.AddPosition(c.x)
231 }
232 if c.CloseInfo.closeInfo != nil {
233 err.AddPosition(c.CloseInfo.location)
234 }
235 }
236
237 b := &Bottom{
238 Code: IncompleteError,
239 Err: err,
240 }
241 ctx.PopArc(saved)
242 return b
243 }
244
245 func newRequiredFieldInComprehensionError(ctx *OpContext, x *ForClause, v *Vertex) *Bottom {
246 err := ctx.Newf("missing required field in for comprehension: %v", v.Label)
247 err.AddPosition(x.Src)
248 for _, c := range v.Conjuncts {
249 addPositions(err, c)
250 }
251 return &Bottom{
252 Code: IncompleteError,
253 Err: err,
254 }
255 }
256
257 func (v *Vertex) reportFieldIndexError(c *OpContext, pos token.Pos, f Feature) {
258 v.reportFieldError(c, pos, f,
259 "index out of range [%d] with length %d",
260 "undefined field: %s")
261 }
262
263 func (v *Vertex) reportFieldCycleError(c *OpContext, pos token.Pos, f Feature) *Bottom {
264 const msg = "cyclic reference to field %[1]v"
265 b := v.reportFieldError(c, pos, f, msg, msg)
266 return b
267 }
268
269 func (v *Vertex) reportFieldError(c *OpContext, pos token.Pos, f Feature, intMsg, stringMsg string) *Bottom {
270 code := IncompleteError
271 if !v.Accept(c, f) {
272 code = EvalError
273 }
274
275 label := f.SelectorString(c.Runtime)
276
277 var err errors.Error
278 if f.IsInt() {
279 err = c.NewPosf(pos, intMsg, f.Index(), len(v.Elems()))
280 } else {
281 err = c.NewPosf(pos, stringMsg, label)
282 }
283 b := &Bottom{
284 Code: code,
285 Err: err,
286 }
287
288 c.AddBottom(b)
289 return b
290 }
291
292
293 type ValueError struct {
294 r Runtime
295 v *Vertex
296 pos token.Pos
297 auxpos []token.Pos
298 errors.Message
299 }
300
301 func (v *ValueError) AddPosition(n Node) {
302 if n == nil {
303 return
304 }
305 if p := pos(n); p != token.NoPos {
306 for _, q := range v.auxpos {
307 if p == q {
308 return
309 }
310 }
311 v.auxpos = append(v.auxpos, p)
312 }
313 }
314
315 func (v *ValueError) AddClosedPositions(c CloseInfo) {
316 for s := c.closeInfo; s != nil; s = s.parent {
317 if loc := s.location; loc != nil {
318 v.AddPosition(loc)
319 }
320 }
321 }
322
323 func (c *OpContext) errNode() *Vertex {
324 return c.vertex
325 }
326
327
328 func (c *OpContext) MarkPositions() int {
329 return len(c.positions)
330 }
331
332
333 func (c *OpContext) ReleasePositions(p int) {
334 c.positions = c.positions[:p]
335 }
336
337 func (c *OpContext) AddPosition(n Node) {
338 if n != nil {
339 c.positions = append(c.positions, n)
340 }
341 }
342
343 func (c *OpContext) Newf(format string, args ...interface{}) *ValueError {
344 return c.NewPosf(c.pos(), format, args...)
345 }
346
347 func appendNodePositions(a []token.Pos, n Node) []token.Pos {
348 if p := pos(n); p != token.NoPos {
349 a = append(a, p)
350 }
351 if v, ok := n.(*Vertex); ok {
352 for _, c := range v.Conjuncts {
353 switch x := c.x.(type) {
354 case *ConjunctGroup:
355 for _, c := range *x {
356 a = appendNodePositions(a, c.Elem())
357 }
358
359 default:
360 a = appendNodePositions(a, c.Elem())
361 }
362 }
363 }
364 return a
365 }
366
367 func (c *OpContext) NewPosf(p token.Pos, format string, args ...interface{}) *ValueError {
368 var a []token.Pos
369 if len(c.positions) > 0 {
370 a = make([]token.Pos, 0, len(c.positions))
371 for _, n := range c.positions {
372 a = appendNodePositions(a, n)
373 }
374 }
375 for i, arg := range args {
376 switch x := arg.(type) {
377 case Node:
378 a = appendNodePositions(a, x)
379 args[i] = c.Str(x)
380 case ast.Node:
381 b, _ := cueformat.Node(x)
382 if p := x.Pos(); p != token.NoPos {
383 a = append(a, p)
384 }
385 args[i] = string(b)
386 case Feature:
387 args[i] = x.SelectorString(c.Runtime)
388 }
389 }
390 return &ValueError{
391 r: c.Runtime,
392 v: c.errNode(),
393 pos: p,
394 auxpos: a,
395 Message: errors.NewMessagef(format, args...),
396 }
397 }
398
399 func (e *ValueError) Error() string {
400 return errors.String(e)
401 }
402
403 func (e *ValueError) Position() token.Pos {
404 return e.pos
405 }
406
407 func (e *ValueError) InputPositions() (a []token.Pos) {
408 return e.auxpos
409 }
410
411 func (e *ValueError) Path() (a []string) {
412 if e.v == nil {
413 return nil
414 }
415 for _, f := range appendPath(nil, e.v) {
416 a = append(a, f.SelectorString(e.r))
417 }
418 return a
419 }
420
View as plain text