blob: 1390f49caf992583163679ace77e772efdbb5c5d [file] [log] [blame]
// 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
}