blob: 077a08dcd5b574bcf6aded55d28d4fe8b981645b [file] [log] [blame]
// Copyright 2020 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 internal
import (
"fmt"
"cuelang.org/go/cue/errors"
"cuelang.org/go/internal/core/adt"
)
type bottomer interface {
error
Bottom() *adt.Bottom
}
type callError struct {
b *adt.Bottom
}
func (e *callError) Error() string {
return fmt.Sprint(e.b)
}
func (c *CallCtxt) errf(underlying error, format string, args ...interface{}) {
var errs errors.Error
var code adt.ErrorCode
switch x := underlying.(type) {
case nil:
case bottomer:
b := x.Bottom()
errs = b.Err
code = b.Code
case errors.Error:
errs = x
case error:
errs = errors.Promote(x, "")
}
vErr := c.ctx.NewPosf(c.Pos(), format, args...)
c.Err = &callError{&adt.Bottom{Code: code, Err: errors.Wrap(vErr, errs)}}
}
func (c *CallCtxt) errcf(code adt.ErrorCode, format string, args ...interface{}) {
err := c.ctx.NewErrf(format, args...)
err.Code = code
c.Err = &callError{err}
}
func wrapCallErr(c *CallCtxt, b *adt.Bottom) *adt.Bottom {
var err errors.Error
for _, e := range errors.Errors(b.Err) {
const msg = "error in call to %s"
err = errors.Append(err,
errors.Wrapf(e, c.Pos(), msg, c.builtin.name(c.ctx)))
}
return &adt.Bottom{Code: b.Code, Err: err}
}
func (c *CallCtxt) invalidArgType(arg adt.Value, i int, typ string, err error) {
if ve, ok := err.(bottomer); ok && ve.Bottom().IsIncomplete() {
c.Err = ve
return
}
if b, ok := adt.Unwrap(arg).(*adt.Bottom); ok {
c.Err = b
return
}
v, ok := arg.(adt.Value)
// TODO: make these permanent errors if the value did not originate from
// a reference.
if !ok {
c.errf(nil,
"cannot use incomplete value %s as %s in argument %d to %s",
arg, typ, i, c.Name())
}
if err != nil {
c.errf(err,
"cannot use %s (type %s) as %s in argument %d to %s",
arg, v.Kind(), typ, i, c.Name())
} else {
c.errf(err,
"cannot use %s (type %s) as %s in argument %d to %s",
arg, v.Kind(), typ, i, c.Name())
}
}