| // Copyright 2018 The CUE Authors |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| package cue |
| |
| import ( |
| "cuelang.org/go/cue/errors" |
| "cuelang.org/go/cue/token" |
| "cuelang.org/go/internal/core/adt" |
| ) |
| |
| func (v Value) toErr(b *bottom) (err errors.Error) { |
| errs := errors.Errors(b.Err) |
| if len(errs) > 1 { |
| for _, e := range errs { |
| bb := *b |
| bb.Err = e |
| err = errors.Append(err, &valueError{v: v, err: &bb}) |
| } |
| return err |
| } |
| return &valueError{v: v, err: b} |
| } |
| |
| var _ errors.Error = &valueError{} |
| |
| // A valueError is returned as a result of evaluating a value. |
| type valueError struct { |
| v Value |
| err *bottom |
| } |
| |
| func (e *valueError) Bottom() *adt.Bottom { return e.err } |
| |
| func (e *valueError) Error() string { |
| return errors.String(e) |
| } |
| |
| func (e *valueError) Position() token.Pos { |
| if e.err.Err != nil { |
| return e.err.Err.Position() |
| } |
| src := e.err.Source() |
| if src == nil { |
| return token.NoPos |
| } |
| return src.Pos() |
| } |
| |
| func (e *valueError) InputPositions() []token.Pos { |
| if e.err.Err == nil { |
| return nil |
| } |
| return e.err.Err.InputPositions() |
| } |
| |
| func (e *valueError) Msg() (string, []interface{}) { |
| if e.err.Err == nil { |
| return "", nil |
| } |
| return e.err.Err.Msg() |
| } |
| |
| func (e *valueError) Path() (a []string) { |
| if e.err.Err != nil { |
| a = e.err.Err.Path() |
| if a != nil { |
| return a |
| } |
| } |
| return e.v.appendPath(nil) |
| } |
| |
| type errCode = adt.ErrorCode |
| |
| const ( |
| codeNotExist = adt.NotExistError |
| codeIncomplete = adt.IncompleteError |
| ) |
| |
| var errNotExists = &adt.Bottom{ |
| Code: codeNotExist, |
| Err: errors.Newf(token.NoPos, "undefined value"), |
| } |
| |
| func exists(v value) bool { |
| if err, ok := v.(*bottom); ok { |
| return err.Code != codeNotExist |
| } |
| return true |
| } |
| |
| func (idx *index) mkErr(src source, args ...interface{}) *bottom { |
| var e *adt.Bottom |
| var code errCode = -1 |
| outer: |
| for i, a := range args { |
| switch x := a.(type) { |
| case errCode: |
| code = x |
| case *bottom: |
| e = adt.CombineErrors(nil, e, x) |
| case []*bottom: |
| for _, b := range x { |
| e = adt.CombineErrors(nil, e, b) |
| } |
| case errors.Error: |
| e = adt.CombineErrors(nil, e, &adt.Bottom{Err: x}) |
| case value: |
| case string: |
| args := args[i+1:] |
| // Do not expand message so that errors can be localized. |
| pos := pos(src) |
| if code < 0 { |
| code = 0 |
| } |
| e = adt.CombineErrors(nil, e, &adt.Bottom{ |
| Code: code, |
| Err: errors.Newf(pos, x, args...), |
| }) |
| break outer |
| } |
| } |
| if code >= 0 { |
| e.Code = code |
| } |
| return e |
| } |