cuelang.org/go@v0.10.1/internal/pkg/errors.go (about) 1 // Copyright 2020 CUE Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package pkg 16 17 import ( 18 "fmt" 19 20 "cuelang.org/go/cue/errors" 21 "cuelang.org/go/internal/core/adt" 22 ) 23 24 type Bottomer interface { 25 error 26 Bottom() *adt.Bottom 27 } 28 29 type callError struct { 30 b *adt.Bottom 31 } 32 33 func (e *callError) Error() string { 34 return fmt.Sprint(e.b) 35 } 36 37 func (c *CallCtxt) errf(underlying error, format string, args ...interface{}) { 38 var errs errors.Error 39 var code adt.ErrorCode 40 switch x := underlying.(type) { 41 case nil: 42 case Bottomer: 43 b := x.Bottom() 44 errs = b.Err 45 code = b.Code 46 case errors.Error: 47 errs = x 48 case error: 49 errs = errors.Promote(x, "") 50 } 51 vErr := c.ctx.NewPosf(c.Pos(), format, args...) 52 c.Err = &callError{&adt.Bottom{Code: code, Err: errors.Wrap(vErr, errs)}} 53 } 54 55 func (c *CallCtxt) errcf(code adt.ErrorCode, format string, args ...interface{}) { 56 err := c.ctx.NewErrf(format, args...) 57 err.Code = code 58 c.Err = &callError{err} 59 } 60 61 func wrapCallErr(c *CallCtxt, b *adt.Bottom) *adt.Bottom { 62 var err errors.Error 63 for _, e := range errors.Errors(b.Err) { 64 ne := c.ctx.Newf("error in call to %s", c.builtin.name(c.ctx)) 65 err = errors.Append(err, errors.Wrap(ne, e)) 66 } 67 return &adt.Bottom{Code: b.Code, Err: err} 68 } 69 70 func (c *CallCtxt) invalidArgType(arg adt.Value, i int, typ string, err error) { 71 if ve, ok := err.(Bottomer); ok && ve.Bottom().IsIncomplete() { 72 c.Err = ve 73 return 74 } 75 if b, ok := adt.Unwrap(arg).(*adt.Bottom); ok { 76 c.Err = b 77 return 78 } 79 // TODO: make these permanent errors if the value did not originate from 80 // a reference. 81 if err != nil { 82 c.errf(err, 83 "cannot use %s (type %s) as %s in argument %d to %s", 84 arg, arg.Kind(), typ, i, c.Name()) 85 } else { 86 c.errf(err, 87 "cannot use %s (type %s) as %s in argument %d to %s", 88 arg, arg.Kind(), typ, i, c.Name()) 89 } 90 }