From 14b457843a37ca5fe73602879eccaedbe21dbec7 Mon Sep 17 00:00:00 2001 From: Roger Peppe Date: Fri, 27 Feb 2026 16:48:47 +0000 Subject: [PATCH] internal/core/adt: preparatory work for user-defined functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When introducing user-callable functions, we want to make a break with the past and not support some of the modes that the current builtin function calls support (like, for example, we want a clear distinction between functions and validators). In order to do that, the plan is to introduce a new `adt.Func` type to implement the new semantics rather than complicate the already complex `adt.Builtin` logic. That means that we want the `CallExpr` logic to be independent of the `Builtin` logic, but they are both somewhat intertwined currently. Factor out `Builtin.rawCall` from `CallExpr.evaluate` in order to separate the two some more, and also rename `CallContext` to `BuiltinCallContext` make it clear that the type is about Builtin calls - we will use a different API for `adt.Func`. This should have no semantic effect at all. Signed-off-by: Roger Peppe Change-Id: I2d33b14a8cf5c431dd70cc7a9e14930ba43d807f Reviewed-on: https://cue.gerrithub.io/c/cue-lang/cue/+/1232332 Unity-Result: CUE porcuepine TryBot-Result: CUEcueckoo Reviewed-by: Daniel Martí --- cue/interpreter/wasm/builtin.go | 2 +- internal/core/adt/call.go | 20 ++++---- internal/core/adt/expr.go | 68 +++++++++++++--------------- internal/core/compile/builtin.go | 24 +++++----- internal/core/compile/validator.go | 4 +- internal/core/runtime/extern_test.go | 2 +- internal/encoding/yaml/validate.go | 2 +- internal/pkg/builtin.go | 8 ++-- internal/pkg/context.go | 34 +++++++------- 9 files changed, 80 insertions(+), 84 deletions(-) diff --git a/cue/interpreter/wasm/builtin.go b/cue/interpreter/wasm/builtin.go index 0a66d532c..06246fa8f 100644 --- a/cue/interpreter/wasm/builtin.go +++ b/cue/interpreter/wasm/builtin.go @@ -55,7 +55,7 @@ func generateCallThatReturnsBuiltin(name string, scope adt.Value, args []string, call := &adt.CallExpr{Fun: &adt.Builtin{ Result: adt.TopKind, Name: name, - Func: func(call adt.CallContext) adt.Expr { + Func: func(call adt.BuiltinCallContext) adt.Expr { opctx := call.OpContext() scope := value.Make(opctx, scope) diff --git a/internal/core/adt/call.go b/internal/core/adt/call.go index a67960ad9..ac4f38ee2 100644 --- a/internal/core/adt/call.go +++ b/internal/core/adt/call.go @@ -18,9 +18,9 @@ import ( "cuelang.org/go/cue/token" ) -// A CallContext holds all relevant information for a function call to +// A BuiltinCallContext holds all relevant information for a function call to // be executed. -type CallContext struct { +type BuiltinCallContext struct { ctx *OpContext call *CallExpr builtin *Builtin @@ -28,27 +28,27 @@ type CallContext struct { isValidator bool } -func (c CallContext) OpContext() *OpContext { +func (c BuiltinCallContext) OpContext() *OpContext { return c.ctx } -func (c CallContext) Pos() token.Pos { +func (c BuiltinCallContext) Pos() token.Pos { if c.call != nil { return Pos(c.call) } return Pos(c.builtin) } -func (c CallContext) Value(i int) Value { +func (c BuiltinCallContext) Value(i int) Value { return c.args[i] } // NumParams returns the total number of parameters to this function. -func (c CallContext) NumParams() int { +func (c BuiltinCallContext) NumParams() int { return len(c.args) } -func (c CallContext) AddPositions(err *ValueError) { +func (c BuiltinCallContext) AddPositions(err *ValueError) { for _, v := range c.args { err.AddPosition(v) } @@ -60,7 +60,7 @@ func (c CallContext) AddPositions(err *ValueError) { // // This method of getting an argument should be used when the argument is used // as a schema and may contain cycles. -func (c CallContext) Arg(i int) Value { +func (c BuiltinCallContext) Arg(i int) Value { // If the call context represents a validator call, the argument will be // offset by 1. if c.isValidator { @@ -77,7 +77,7 @@ func (c CallContext) Arg(i int) Value { } // Expr returns the nth argument expression without evaluating it. -func (c CallContext) Expr(i int) Expr { +func (c BuiltinCallContext) Expr(i int) Expr { // If the call context represents a validator call, the argument will be // offset by 1. if c.isValidator { @@ -92,6 +92,6 @@ func (c CallContext) Expr(i int) Expr { return x } -func (c CallContext) Errf(format string, args ...interface{}) *Bottom { +func (c BuiltinCallContext) Errf(format string, args ...interface{}) *Bottom { return c.ctx.NewErrf(format, args...) } diff --git a/internal/core/adt/expr.go b/internal/core/adt/expr.go index 3e8062754..f5525659d 100644 --- a/internal/core/adt/expr.go +++ b/internal/core/adt/expr.go @@ -1446,11 +1446,6 @@ func (x *CallExpr) Source() ast.Node { } func (x *CallExpr) evaluate(c *OpContext, state Flags) Value { - call := CallContext{ - ctx: c, - call: x, - } - fun := c.value(x.Fun, Flags{ status: partial, condition: concreteKnown, @@ -1458,13 +1453,7 @@ func (x *CallExpr) evaluate(c *OpContext, state Flags) Value { }) switch f := fun.(type) { case *Builtin: - call.builtin = f - if f.RawFunc != nil { - if !call.builtin.checkArgs(c, Pos(x), len(x.Args)) { - return nil - } - return f.RawFunc(call) - } + return f.rawCall(c, x, state) case *BuiltinValidator: // We allow a validator that takes no arguments except the validated @@ -1472,6 +1461,7 @@ func (x *CallExpr) evaluate(c *OpContext, state Flags) Value { switch { case f.Src != nil: c.AddErrf("cannot call previously called validator %s", x.Fun) + return nil case f.Builtin.IsValidator(len(x.Args)): v := *f @@ -1479,9 +1469,8 @@ func (x *CallExpr) evaluate(c *OpContext, state Flags) Value { return &v default: - call.builtin = f.Builtin + return f.Builtin.rawCall(c, x, state) } - default: if !IsConcrete(fun) && fun.Kind()&FuncKind != 0 { c.addErrf(IncompleteError, Pos(x.Fun), "cannot call non-concrete value %s (type %s)", x.Fun, kind(fun)) @@ -1490,7 +1479,20 @@ func (x *CallExpr) evaluate(c *OpContext, state Flags) Value { } return nil } +} +func (builtin *Builtin) rawCall(c *OpContext, call *CallExpr, state Flags) Value { + callCtx := BuiltinCallContext{ + ctx: c, + call: call, + builtin: builtin, + } + if builtin.RawFunc != nil { + if !builtin.checkArgs(c, Pos(call), len(call.Args)) { + return nil + } + return builtin.RawFunc(callCtx) + } // Arguments to functions are open. This mostly matters for NonConcrete // builtins. saved := c.ci @@ -1501,8 +1503,8 @@ func (x *CallExpr) evaluate(c *OpContext, state Flags) Value { c.ci.FromEmbed = saved.FromEmbed }() - args := make([]Value, 0, len(x.Args)) - for i, a := range x.Args { + args := make([]Value, 0, len(call.Args)) + for i, a := range call.Args { saved := c.errs c.errs = nil // XXX: XXX: clear id.closeContext per argument and remove from runTask? @@ -1510,7 +1512,7 @@ func (x *CallExpr) evaluate(c *OpContext, state Flags) Value { runMode := state.mode cond := state.condition var expr Value - if call.builtin.NonConcrete { + if builtin.NonConcrete { state = Flags{ status: state.status, condition: cond, @@ -1540,8 +1542,8 @@ func (x *CallExpr) evaluate(c *OpContext, state Flags) Value { if c.errs == nil { // There SHOULD be an error in the context. If not, we generate // one. - c.Assertf(Pos(x.Fun), c.HasErr(), - "argument %d to function %s is incomplete", i, x.Fun) + c.Assertf(Pos(call.Fun), c.HasErr(), + "argument %d to function %s is incomplete", i, call.Fun) } case *Bottom: @@ -1556,11 +1558,11 @@ func (x *CallExpr) evaluate(c *OpContext, state Flags) Value { if c.HasErr() { return nil } - if call.builtin.IsValidator(len(args)) { - return &BuiltinValidator{x, call.builtin, args} + if builtin.IsValidator(len(args)) { + return &BuiltinValidator{call, builtin, args} } - call.args = args - result := call.builtin.call(call) + callCtx.args = args + result := builtin.call(callCtx) if result == nil { return nil } @@ -1579,7 +1581,7 @@ type Builtin struct { // arguments. By default, all arguments are checked to be concrete. NonConcrete bool - Func func(call CallContext) Expr + Func func(call BuiltinCallContext) Expr // RawFunc gives low-level control to CUE's internals for builtins. // It should be used when fine control over the evaluation process is @@ -1589,7 +1591,7 @@ type Builtin struct { // the Context. // // TODO: consider merging Func and RawFunc into a single field again. - RawFunc func(call CallContext) Value + RawFunc func(call BuiltinCallContext) Value // Added indicates as of which language version this builtin can be used. Added string @@ -1599,8 +1601,7 @@ type Builtin struct { } type Param struct { - Name Feature // name of the argument; mostly for documentation - Value Value // Could become Value later, using disjunctions for defaults. + Value Value } // Kind returns the kind mask of this parameter. @@ -1673,7 +1674,7 @@ func (x *Builtin) checkArgs(c *OpContext, p token.Pos, numArgs int) bool { return true } -func (x *Builtin) call(call CallContext) Expr { +func (x *Builtin) call(call BuiltinCallContext) Expr { c := call.ctx p := call.Pos() @@ -1685,9 +1686,6 @@ func (x *Builtin) call(call CallContext) Expr { call.args = append(call.args, x.Params[i].Default()) } for i, a := range call.args { - if x.Params[i].Kind() == BottomKind { - continue - } if b := bottom(a); b != nil { return b } @@ -1765,18 +1763,16 @@ func (x *BuiltinValidator) validate(c *OpContext, v Value) *Bottom { args[0] = v copy(args[1:], x.Args) - call := CallContext{ + return validateWithBuiltin(BuiltinCallContext{ ctx: c, call: x.Src, builtin: x.Builtin, args: args, isValidator: true, - } - - return validateWithBuiltin(call) + }) } -func validateWithBuiltin(call CallContext) *Bottom { +func validateWithBuiltin(call BuiltinCallContext) *Bottom { var severeness ErrorCode var err errors.Error diff --git a/internal/core/compile/builtin.go b/internal/core/compile/builtin.go index 390bb3833..854afc547 100644 --- a/internal/core/compile/builtin.go +++ b/internal/core/compile/builtin.go @@ -43,7 +43,7 @@ var errorBuiltin = &adt.Builtin{ Params: []adt.Param{stringParam}, Result: adt.BottomKind, - RawFunc: func(call adt.CallContext) adt.Value { + RawFunc: func(call adt.BuiltinCallContext) adt.Value { ctx := call.OpContext() arg := call.Expr(0) @@ -86,7 +86,7 @@ var lenBuiltin = &adt.Builtin{ Name: "len", Params: []adt.Param{{Value: &adt.BasicType{K: supportedByLen}}}, Result: adt.IntKind, - Func: func(call adt.CallContext) adt.Expr { + Func: func(call adt.BuiltinCallContext) adt.Expr { c := call.OpContext() v := call.Value(0) @@ -134,7 +134,7 @@ var closeBuiltin = &adt.Builtin{ Name: "close", Params: []adt.Param{structParam}, Result: adt.StructKind, - Func: func(call adt.CallContext) adt.Expr { + Func: func(call adt.BuiltinCallContext) adt.Expr { c := call.OpContext() s, ok := call.Value(0).(*adt.Vertex) if !ok { @@ -154,7 +154,7 @@ var closeAllBuiltin = &adt.Builtin{ Name: "__closeAll", Params: []adt.Param{topParam}, Result: adt.TopKind, - Func: func(call adt.CallContext) adt.Expr { + Func: func(call adt.BuiltinCallContext) adt.Expr { c := call.OpContext() x := call.Expr(0) @@ -184,7 +184,7 @@ var recloseBuiltin = &adt.Builtin{ Name: "__reclose", Params: []adt.Param{topParam}, Result: adt.TopKind, - Func: func(call adt.CallContext) adt.Expr { + Func: func(call adt.BuiltinCallContext) adt.Expr { c := call.OpContext() x := call.Expr(0) @@ -219,7 +219,7 @@ var andBuiltin = &adt.Builtin{ Name: "and", Params: []adt.Param{listParam}, Result: adt.IntKind, - Func: func(call adt.CallContext) adt.Expr { + Func: func(call adt.BuiltinCallContext) adt.Expr { c := call.OpContext() seq := c.RawElems(call.Value(0)) a := []adt.Value{} @@ -238,7 +238,7 @@ var orBuiltin = &adt.Builtin{ Params: []adt.Param{listParam}, Result: adt.IntKind, NonConcrete: true, - Func: func(call adt.CallContext) adt.Expr { + Func: func(call adt.BuiltinCallContext) adt.Expr { c := call.OpContext() d := []adt.Disjunct{} @@ -275,7 +275,7 @@ var divBuiltin = &adt.Builtin{ Name: "div", Params: []adt.Param{intParam, intParam}, Result: adt.IntKind, - Func: func(call adt.CallContext) adt.Expr { + Func: func(call adt.BuiltinCallContext) adt.Expr { c := call.OpContext() const name = "argument to div builtin" return intDivOp(c, (*adt.OpContext).IntDiv, name, call.Value(0), call.Value(1)) @@ -286,7 +286,7 @@ var modBuiltin = &adt.Builtin{ Name: "mod", Params: []adt.Param{intParam, intParam}, Result: adt.IntKind, - Func: func(call adt.CallContext) adt.Expr { + Func: func(call adt.BuiltinCallContext) adt.Expr { c := call.OpContext() const name = "argument to mod builtin" @@ -299,7 +299,7 @@ var quoBuiltin = &adt.Builtin{ Name: "quo", Params: []adt.Param{intParam, intParam}, Result: adt.IntKind, - Func: func(call adt.CallContext) adt.Expr { + Func: func(call adt.BuiltinCallContext) adt.Expr { c := call.OpContext() const name = "argument to quo builtin" return intDivOp(c, (*adt.OpContext).IntQuo, name, call.Value(0), call.Value(1)) @@ -310,7 +310,7 @@ var remBuiltin = &adt.Builtin{ Name: "rem", Params: []adt.Param{intParam, intParam}, Result: adt.IntKind, - Func: func(call adt.CallContext) adt.Expr { + Func: func(call adt.BuiltinCallContext) adt.Expr { c := call.OpContext() const name = "argument to rem builtin" return intDivOp(c, (*adt.OpContext).IntRem, name, call.Value(0), call.Value(1)) @@ -332,7 +332,7 @@ var testExperiment = &adt.Builtin{ Name: "testExperiment", Params: []adt.Param{topParam}, Result: adt.TopKind, - Func: func(call adt.CallContext) adt.Expr { + Func: func(call adt.BuiltinCallContext) adt.Expr { if call.Pos().Experiment().Testing { return call.Value(0) } else { diff --git a/internal/core/compile/validator.go b/internal/core/compile/validator.go index ba07004fd..278cf43fe 100644 --- a/internal/core/compile/validator.go +++ b/internal/core/compile/validator.go @@ -29,7 +29,7 @@ var matchNBuiltin = &adt.Builtin{ Params: []adt.Param{topParam, intParam, listParam}, // varargs Result: adt.BoolKind, NonConcrete: true, - Func: func(call adt.CallContext) adt.Expr { + Func: func(call adt.BuiltinCallContext) adt.Expr { c := call.OpContext() if !c.IsValidator { @@ -87,7 +87,7 @@ var matchIfBuiltin = &adt.Builtin{ Params: []adt.Param{topParam, topParam, topParam, topParam}, Result: adt.BoolKind, NonConcrete: true, - Func: func(call adt.CallContext) adt.Expr { + Func: func(call adt.BuiltinCallContext) adt.Expr { c := call.OpContext() if !c.IsValidator { diff --git a/internal/core/runtime/extern_test.go b/internal/core/runtime/extern_test.go index 16966f946..8f3b3d4b3 100644 --- a/internal/core/runtime/extern_test.go +++ b/internal/core/runtime/extern_test.go @@ -119,7 +119,7 @@ func (c *compilerFake) Compile(name string, scope adt.Value, a *internal.Attr) ( call := &adt.CallExpr{Fun: &adt.Builtin{ Result: adt.TopKind, - Func: func(call adt.CallContext) adt.Expr { + Func: func(call adt.BuiltinCallContext) adt.Expr { opctx := call.OpContext() cuectx := (*cue.Context)(c.runtime) diff --git a/internal/encoding/yaml/validate.go b/internal/encoding/yaml/validate.go index d4807446f..f4fe03cfc 100644 --- a/internal/encoding/yaml/validate.go +++ b/internal/encoding/yaml/validate.go @@ -29,7 +29,7 @@ import ( // // If Validate is called in a broader context, like a validation or function // call, the cycle context of n should be accumulated in c before this call. -// This can be done by using the Expr method on the CallContext. +// This can be done by using the Expr method on the BuiltinCallContext. func Validate(c *adt.OpContext, b []byte, v cue.Value) (bool, error) { d := NewDecoder("yaml.Validate", b) r := v.Context() diff --git a/internal/pkg/builtin.go b/internal/pkg/builtin.go index d4d5ef039..4ffaf6901 100644 --- a/internal/pkg/builtin.go +++ b/internal/pkg/builtin.go @@ -130,14 +130,14 @@ func ToBuiltin(b *Builtin) *adt.Builtin { Package: b.Pkg, Name: b.Name, } - x.Func = func(call adt.CallContext) (ret adt.Expr) { + x.Func = func(call adt.BuiltinCallContext) (ret adt.Expr) { ctx := call.OpContext() // call, _ := ctx.Source().(*ast.CallExpr) c := &CallCtxt{ - CallContext: call, - ctx: ctx, - builtin: b, + BuiltinCallContext: call, + ctx: ctx, + builtin: b, } defer func() { var errVal interface{} = c.Err diff --git a/internal/pkg/context.go b/internal/pkg/context.go index 0a3bf5c22..db68b6007 100644 --- a/internal/pkg/context.go +++ b/internal/pkg/context.go @@ -28,7 +28,7 @@ import ( // CallCtxt is passed to builtin implementations that need to use a cue.Value. This is an internal type. Its interface may change. type CallCtxt struct { - adt.CallContext + adt.BuiltinCallContext ctx *adt.OpContext builtin *Builtin Err any @@ -46,7 +46,7 @@ func (c *CallCtxt) Do() bool { // Schema returns the ith argument as is, without converting it to a cue.Value. // -// TODO: Schema should use CallContext.Expr to capture cycle information. +// TODO: Schema should use [adt.BuiltinCallContext.Expr] to capture cycle information. // However, this only makes sense if functions also use the same OpContext for // further evaluation. We should enforce as we port the old calls. func (c *CallCtxt) Schema(i int) Schema { @@ -56,7 +56,7 @@ func (c *CallCtxt) Schema(i int) Schema { // Value returns a finalized cue.Value for the ith argument. func (c *CallCtxt) Value(i int) cue.Value { - v := value.Make(c.ctx, c.CallContext.Value(i)) + v := value.Make(c.ctx, c.BuiltinCallContext.Value(i)) if c.builtin.NonConcrete { // In case NonConcrete is false, the concreteness is already checked // at call time. We may want to use finalize semantics in both cases, @@ -72,7 +72,7 @@ func (c *CallCtxt) Value(i int) cue.Value { } func (c *CallCtxt) Struct(i int) Struct { - x := c.CallContext.Value(i) + x := c.BuiltinCallContext.Value(i) if c.builtin.NonConcrete { x = adt.Default(x) } @@ -106,7 +106,7 @@ func (c *CallCtxt) Rune(i int) rune { return rune(c.intValue(i, 32, "rune")) } func (c *CallCtxt) Int64(i int) int64 { return c.intValue(i, 64, "int64") } func (c *CallCtxt) intValue(i, bitLen int, typ string) int64 { - arg := c.CallContext.Value(i) + arg := c.BuiltinCallContext.Value(i) if num, _ := c.ctx.EvaluateKeepState(arg).(*adt.Num); num != nil { // In the happy path, avoid converting to the public [cue.Value] API, which is wasteful. if n, err := num.X.Int64(); err == nil && bits.Len64(uint64(n)) <= bitLen { @@ -135,7 +135,7 @@ func (c *CallCtxt) Uint32(i int) uint32 { return uint32(c.uintValue(i, 32, "uint func (c *CallCtxt) Uint64(i int) uint64 { return c.uintValue(i, 64, "uint64") } func (c *CallCtxt) uintValue(i, bitLen int, typ string) uint64 { - arg := c.CallContext.Value(i) + arg := c.BuiltinCallContext.Value(i) if num, _ := c.ctx.EvaluateKeepState(arg).(*adt.Num); num != nil { // In the happy path, avoid converting to the public [cue.Value] API, which is wasteful. // Note that [apd.Decimal] has an Int64 method, but no Uint64 method, @@ -159,7 +159,7 @@ func (c *CallCtxt) uintValue(i, bitLen int, typ string) uint64 { } func (c *CallCtxt) Decimal(i int) *apd.Decimal { - arg := c.CallContext.Value(i) + arg := c.BuiltinCallContext.Value(i) if num, _ := c.ctx.EvaluateKeepState(arg).(*adt.Num); num != nil { // In the happy path, avoid converting to the public [cue.Value] API, which is wasteful. return &num.X @@ -174,7 +174,7 @@ func (c *CallCtxt) Decimal(i int) *apd.Decimal { } func (c *CallCtxt) Float64(i int) float64 { - arg := c.CallContext.Value(i) + arg := c.BuiltinCallContext.Value(i) if num, _ := c.ctx.EvaluateKeepState(arg).(*adt.Num); num != nil { // In the happy path, avoid converting to the public [cue.Value] API, which is wasteful. if f, err := num.X.Float64(); err == nil { @@ -191,7 +191,7 @@ func (c *CallCtxt) Float64(i int) float64 { } func (c *CallCtxt) BigInt(i int) *big.Int { - arg := c.CallContext.Value(i) + arg := c.BuiltinCallContext.Value(i) if num, _ := c.ctx.EvaluateKeepState(arg).(*adt.Num); num != nil { // In the happy path, avoid converting to the public [cue.Value] API, which is wasteful. return num.BigInt(nil) @@ -208,7 +208,7 @@ func (c *CallCtxt) BigInt(i int) *big.Int { var ten = big.NewInt(10) func (c *CallCtxt) BigFloat(i int) *big.Float { - arg := c.CallContext.Value(i) + arg := c.BuiltinCallContext.Value(i) x := value.Make(c.ctx, arg) var mant big.Int exp, err := x.MantExp(&mant) @@ -227,7 +227,7 @@ func (c *CallCtxt) BigFloat(i int) *big.Float { } func (c *CallCtxt) String(i int) string { - arg := c.CallContext.Value(i) + arg := c.BuiltinCallContext.Value(i) if str, _ := c.ctx.EvaluateKeepState(arg).(*adt.String); str != nil { // In the happy path, avoid converting to the public [cue.Value] API, which is wasteful. return str.Str @@ -242,7 +242,7 @@ func (c *CallCtxt) String(i int) string { } func (c *CallCtxt) Bytes(i int) []byte { - arg := c.CallContext.Value(i) + arg := c.BuiltinCallContext.Value(i) if bs, _ := c.ctx.EvaluateKeepState(arg).(*adt.Bytes); bs != nil { // In the happy path, avoid converting to the public [cue.Value] API, which is wasteful. return bs.B @@ -257,7 +257,7 @@ func (c *CallCtxt) Bytes(i int) []byte { } func (c *CallCtxt) Reader(i int) io.Reader { - arg := c.CallContext.Value(i) + arg := c.BuiltinCallContext.Value(i) x := value.Make(c.ctx, arg) // TODO: optimize for string and bytes cases r, err := x.Reader() @@ -269,7 +269,7 @@ func (c *CallCtxt) Reader(i int) io.Reader { } func (c *CallCtxt) Bool(i int) bool { - arg := c.CallContext.Value(i) + arg := c.BuiltinCallContext.Value(i) if b, _ := c.ctx.EvaluateKeepState(arg).(*adt.Bool); b != nil { // In the happy path, avoid converting to the public [cue.Value] API, which is wasteful. return b.B @@ -284,7 +284,7 @@ func (c *CallCtxt) Bool(i int) bool { } func (c *CallCtxt) List(i int) (a []cue.Value) { - arg := c.CallContext.Value(i) + arg := c.BuiltinCallContext.Value(i) x := value.Make(c.ctx, arg) v, err := x.List() if err != nil { @@ -306,7 +306,7 @@ func (c *CallCtxt) CueList(i int) List { } func (c *CallCtxt) Iter(i int) (a cue.Iterator) { - arg := c.CallContext.Value(i) + arg := c.BuiltinCallContext.Value(i) x := value.Make(c.ctx, arg) v, err := x.List() if err != nil { @@ -316,7 +316,7 @@ func (c *CallCtxt) Iter(i int) (a cue.Iterator) { } func (c *CallCtxt) getList(i int) *adt.Vertex { - x := c.CallContext.Value(i) + x := c.BuiltinCallContext.Value(i) if c.builtin.NonConcrete { x = adt.Default(x) } -- 2.51.2