diff --git a/cue/interpreter/wasm/builtin.go b/cue/interpreter/wasm/builtin.go index a8b9cc84647..31ad0e307a6 100644 --- a/cue/interpreter/wasm/builtin.go +++ b/cue/interpreter/wasm/builtin.go @@ -55,7 +55,9 @@ func generateCallThatReturnsBuiltin(name string, scope adt.Value, args []string, call := &adt.CallExpr{Fun: &adt.Builtin{ Result: adt.TopKind, Name: name, - Func: func(opctx *adt.OpContext, _ []adt.Value) adt.Expr { + Func: func(call *adt.CallContext) adt.Expr { + opctx := call.OpContext() + scope := value.Make(opctx, scope) sig := compileStringsInScope(args, scope) args, result := splitLast(sig) diff --git a/internal/core/adt/call.go b/internal/core/adt/call.go index 0e69682f310..a95ecb35296 100644 --- a/internal/core/adt/call.go +++ b/internal/core/adt/call.go @@ -29,6 +29,10 @@ type CallContext struct { isValidator bool } +func (c *CallContext) OpContext() *OpContext { + return c.ctx +} + func (c *CallContext) Pos() token.Pos { var src ast.Node switch { @@ -57,3 +61,17 @@ func (c *CallContext) AddPositions(err *ValueError) { err.AddPosition(v) } } + +// Args return the pre-evaluated arguments. This function is only used for +// transitioning and will be removed at some point. Use [CallContext.Value] +// instead. +func (c *CallContext) Args() []Value { + return c.args +} + +// Exprs return the unevaluated argument expressions. This function is only used +// for transitioning and will be removed at some point. Use [CallContext.Expr] +// instead. (TODO) +func (c *CallContext) Exprs() []Expr { + return c.call.Args +} diff --git a/internal/core/adt/expr.go b/internal/core/adt/expr.go index 7aa9789f7ba..59e10d234ad 100644 --- a/internal/core/adt/expr.go +++ b/internal/core/adt/expr.go @@ -1544,7 +1544,7 @@ func (x *CallExpr) evaluate(c *OpContext, state combinedFlags) Value { if !call.builtin.checkArgs(c, pos(x), len(x.Args)) { return nil } - return f.RawFunc(c, x.Args) + return f.RawFunc(call) } case *BuiltinValidator: @@ -1637,7 +1637,7 @@ type Builtin struct { // arguments. By default, all arguments are checked to be concrete. NonConcrete bool - Func func(c *OpContext, args []Value) Expr + Func func(call *CallContext) Expr // RawFunc gives low-level control to CUE's internals for builtins. // It should be used when fine control over the evaluation process is @@ -1645,7 +1645,9 @@ type Builtin struct { // gives them fine control over how exactly such value gets evaluated. // A RawFunc may pass CycleInfo, errors and other information through // the Context. - RawFunc func(c *OpContext, args []Expr) Value + // + // TODO: consider merging Func and RawFunc into a single field again. + RawFunc func(call *CallContext) Value Package Feature Name string @@ -1773,7 +1775,7 @@ func (x *Builtin) call(call *CallContext) Expr { saved := c.IsValidator c.IsValidator = call.isValidator - ret := x.Func(c, call.args) + ret := x.Func(call) c.IsValidator = saved return ret diff --git a/internal/core/compile/builtin.go b/internal/core/compile/builtin.go index 79e5bbca477..3ebe42efd4a 100644 --- a/internal/core/compile/builtin.go +++ b/internal/core/compile/builtin.go @@ -35,7 +35,10 @@ var lenBuiltin = &adt.Builtin{ Name: "len", Params: []adt.Param{{Value: &adt.BasicType{K: supportedByLen}}}, Result: adt.IntKind, - Func: func(c *adt.OpContext, args []adt.Value) adt.Expr { + Func: func(call *adt.CallContext) adt.Expr { + c := call.OpContext() + args := call.Args() + v := args[0] if x, ok := v.(*adt.Vertex); ok { x.LockArcs = true @@ -82,7 +85,10 @@ var closeBuiltin = &adt.Builtin{ Name: "close", Params: []adt.Param{structParam}, Result: adt.StructKind, - Func: func(c *adt.OpContext, args []adt.Value) adt.Expr { + Func: func(call *adt.CallContext) adt.Expr { + c := call.OpContext() + args := call.Args() + s, ok := args[0].(*adt.Vertex) if !ok { return c.NewErrf("struct argument must be concrete") @@ -110,7 +116,10 @@ var andBuiltin = &adt.Builtin{ Name: "and", Params: []adt.Param{listParam}, Result: adt.IntKind, - RawFunc: func(c *adt.OpContext, args []adt.Expr) adt.Value { + RawFunc: func(call *adt.CallContext) adt.Value { + c := call.OpContext() + args := call.Exprs() + // Pass through the cycle information from evaluating the first argument. v := c.EvaluateKeepState(args[0]) list := c.RawElems(v) @@ -130,7 +139,10 @@ var orBuiltin = &adt.Builtin{ Params: []adt.Param{listParam}, Result: adt.IntKind, NonConcrete: true, - Func: func(c *adt.OpContext, args []adt.Value) adt.Expr { + Func: func(call *adt.CallContext) adt.Expr { + c := call.OpContext() + args := call.Args() + d := []adt.Disjunct{} for _, c := range c.RawElems(args[0]) { d = append(d, adt.Disjunct{Val: c, Default: false}) @@ -165,7 +177,10 @@ var divBuiltin = &adt.Builtin{ Name: "div", Params: []adt.Param{intParam, intParam}, Result: adt.IntKind, - Func: func(c *adt.OpContext, args []adt.Value) adt.Expr { + Func: func(call *adt.CallContext) adt.Expr { + c := call.OpContext() + args := call.Args() + const name = "argument to div builtin" return intDivOp(c, (*adt.OpContext).IntDiv, name, args) @@ -176,7 +191,10 @@ var modBuiltin = &adt.Builtin{ Name: "mod", Params: []adt.Param{intParam, intParam}, Result: adt.IntKind, - Func: func(c *adt.OpContext, args []adt.Value) adt.Expr { + Func: func(call *adt.CallContext) adt.Expr { + c := call.OpContext() + args := call.Args() + const name = "argument to mod builtin" return intDivOp(c, (*adt.OpContext).IntMod, name, args) @@ -187,7 +205,10 @@ var quoBuiltin = &adt.Builtin{ Name: "quo", Params: []adt.Param{intParam, intParam}, Result: adt.IntKind, - Func: func(c *adt.OpContext, args []adt.Value) adt.Expr { + Func: func(call *adt.CallContext) adt.Expr { + c := call.OpContext() + args := call.Args() + const name = "argument to quo builtin" return intDivOp(c, (*adt.OpContext).IntQuo, name, args) @@ -198,7 +219,10 @@ var remBuiltin = &adt.Builtin{ Name: "rem", Params: []adt.Param{intParam, intParam}, Result: adt.IntKind, - Func: func(c *adt.OpContext, args []adt.Value) adt.Expr { + Func: func(call *adt.CallContext) adt.Expr { + c := call.OpContext() + args := call.Args() + const name = "argument to rem builtin" return intDivOp(c, (*adt.OpContext).IntRem, name, args) diff --git a/internal/core/compile/validator.go b/internal/core/compile/validator.go index 2bdd1a35e4c..fd09478cb60 100644 --- a/internal/core/compile/validator.go +++ b/internal/core/compile/validator.go @@ -30,7 +30,10 @@ var matchNBuiltin = &adt.Builtin{ Params: []adt.Param{topParam, intParam, listParam}, // varargs Result: adt.BoolKind, NonConcrete: true, - Func: func(c *adt.OpContext, args []adt.Value) adt.Expr { + Func: func(call *adt.CallContext) adt.Expr { + c := call.OpContext() + args := call.Args() + if !c.IsValidator { return c.NewErrf("matchN is a validator and should not be used as a function") } @@ -89,7 +92,10 @@ var matchIfBuiltin = &adt.Builtin{ Params: []adt.Param{topParam, topParam, topParam, topParam}, Result: adt.BoolKind, NonConcrete: true, - Func: func(c *adt.OpContext, args []adt.Value) adt.Expr { + Func: func(call *adt.CallContext) adt.Expr { + c := call.OpContext() + args := call.Args() + if !c.IsValidator { return c.NewErrf("matchIf is a validator and should not be used as a function") } diff --git a/internal/core/runtime/extern_test.go b/internal/core/runtime/extern_test.go index f66e4199a28..0d410449a77 100644 --- a/internal/core/runtime/extern_test.go +++ b/internal/core/runtime/extern_test.go @@ -119,7 +119,9 @@ func (c *compilerFake) Compile(name string, scope adt.Value, a *internal.Attr) ( call := &adt.CallExpr{Fun: &adt.Builtin{ Result: adt.TopKind, - Func: func(opctx *adt.OpContext, args []adt.Value) adt.Expr { + Func: func(call *adt.CallContext) adt.Expr { + opctx := call.OpContext() + cuectx := (*cue.Context)(c.runtime) scope := value.Make(opctx, scope) diff --git a/internal/pkg/builtin.go b/internal/pkg/builtin.go index 6795df32c2d..88b75755f7b 100644 --- a/internal/pkg/builtin.go +++ b/internal/pkg/builtin.go @@ -126,7 +126,10 @@ func ToBuiltin(b *Builtin) *adt.Builtin { Package: b.Pkg, Name: b.Name, } - x.Func = func(ctx *adt.OpContext, args []adt.Value) (ret adt.Expr) { + x.Func = func(call *adt.CallContext) (ret adt.Expr) { + ctx := call.OpContext() + args := call.Args() + // call, _ := ctx.Source().(*ast.CallExpr) c := &CallCtxt{ ctx: ctx,