Skip to content
This repository has been archived by the owner on Nov 18, 2021. It is now read-only.

Commit

Permalink
cue: add InferBuiltins EncodeOption
Browse files Browse the repository at this point in the history
This functionality is currently partially internal or deprecated.
This adds this functionality to the new API.

This also removes a cyclic dependency in package dependencies
that needs to be removed for the implementation of structure
sharing.

This moves resolveExpr to below BuildExpr, as their bodies are
almost the same (functionally the same at the moment).
This also removes dead code.

Expresses the old CompileExpr in terms of the new BuildExpr.
This is mostly done as a  verification and to allow automatic
rewrites in the future.

Change-Id: I7d63aa097dd8f652b9b0b0181a2b148c8bb1f2d4
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/9571
Reviewed-by: CUE cueckoo <cueckoo@gmail.com>
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
Reviewed-by: Paul Jolly <paul@myitcv.org.uk>
  • Loading branch information
mpvl committed Apr 30, 2021
1 parent b9e7d90 commit d9af603
Show file tree
Hide file tree
Showing 8 changed files with 79 additions and 150 deletions.
7 changes: 5 additions & 2 deletions cmd/cue/cmd/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -350,8 +350,11 @@ func (i *expressionIter) value() cue.Value {
if len(i.expr) == 0 {
return i.iter.value()
}
// TODO: replace with FillPath.
return value.EvalExpr(i.iter.value(), i.expr[i.i])
v := i.iter.value()
return v.Context().BuildExpr(i.expr[i.i],
cue.Scope(v),
cue.InferBuiltins(true),
)
}

type config struct {
Expand Down
20 changes: 14 additions & 6 deletions cue/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package cue

import (
"cuelang.org/go/cue/ast"
"cuelang.org/go/cue/ast/astutil"
"cuelang.org/go/cue/build"
"cuelang.org/go/cue/errors"
"cuelang.org/go/internal/core/adt"
Expand Down Expand Up @@ -78,11 +79,22 @@ func (r *hiddenRuntime) CompileFile(file *ast.File) (*Instance, error) {
//
// Deprecated: use BuildExpr. The use of Instance is being phased out.
func (r *hiddenRuntime) CompileExpr(expr ast.Expr) (*Instance, error) {
v, p, err := r.runtime().CompileExpr(nil, expr)
f, err := astutil.ToFile(expr)
if err != nil {
return nil, err
}
return r.complete(p, v)
v := (*Context)(r).BuildExpr(expr)
err = v.Err()
inst := &Instance{
index: r.runtime(),
root: v.v,
inst: &build.Instance{
Files: []*ast.File{f},
},
Err: errors.Promote(err, ""),
Incomplete: err != nil,
}
return inst, err
}

// Parse parses a CUE source value into a CUE Instance. The source code may be
Expand Down Expand Up @@ -149,7 +161,3 @@ func (r *hiddenRuntime) FromExpr(expr ast.Expr) (*Instance, error) {
Decls: []ast.Decl{&ast.EmbedDecl{Expr: expr}},
})
}

func isBuiltin(s string) bool {
return runtime.SharedRuntime.IsBuiltinPackage(s)
}
49 changes: 47 additions & 2 deletions cue/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,12 @@ package cue

import (
"cuelang.org/go/cue/ast"
"cuelang.org/go/cue/ast/astutil"
"cuelang.org/go/cue/build"
"cuelang.org/go/cue/errors"
"cuelang.org/go/cue/token"
"cuelang.org/go/internal/core/adt"
"cuelang.org/go/internal/core/compile"
"cuelang.org/go/internal/core/convert"
"cuelang.org/go/internal/core/debug"
"cuelang.org/go/internal/core/eval"
Expand Down Expand Up @@ -78,6 +81,23 @@ func Filename(filename string) BuildOption {
return func(o *runtime.Config) { o.Filename = filename }
}

// InferBuiltins allows unresolved references to bind to builtin packages with a
// unique package name.
//
// This option is intended for evaluating expressions in a context where import
// statements cannot be used. It is not recommended to use this for evaluating
// CUE files.
func InferBuiltins(elide bool) BuildOption {
return func(o *runtime.Config) {
o.Imports = func(x *ast.Ident) (pkgPath string) {
if !o.Runtime.IsBuiltinPackage(x.Name) {
return ""
}
return x.Name
}
}
}

func (c *Context) parseOptions(options []BuildOption) (cfg runtime.Config) {
cfg.Runtime = (*runtime.Runtime)(c)
for _, f := range options {
Expand Down Expand Up @@ -143,14 +163,39 @@ func (c *Context) compile(v *adt.Vertex, p *build.Instance) Value {
// The returned Value will represent an error, accessible through Err, if any
// error occurred.
func (c *Context) BuildExpr(x ast.Expr, options ...BuildOption) Value {
r := c.runtime()
cfg := c.parseOptions(options)
v, p, err := c.runtime().CompileExpr(&cfg, x)

ctx := c.ctx()

astutil.ResolveExpr(x, errFn)
conjunct, err := compile.Expr(&cfg.Config, r, anonymousPkg, x)
if err != nil {
return c.makeError(p.Err)
return c.makeError(err)
}
v := adt.Resolve(ctx, conjunct)

return c.make(v)
}

func errFn(pos token.Pos, msg string, args ...interface{}) {}

// resolveExpr binds unresolved expressions to values in the expression or v.
func resolveExpr(ctx *adt.OpContext, v *adt.Vertex, x ast.Expr) adt.Value {
cfg := &compile.Config{Scope: v}

astutil.ResolveExpr(x, errFn)

c, err := compile.Expr(cfg, ctx, anonymousPkg, x)
if err != nil {
return &adt.Bottom{Err: err}
}
return adt.Resolve(ctx, c)
}

// anonymousPkg reports a package path that can never resolve to a valid package.
const anonymousPkg = "_"

// CompileString parses and build a Value from the given source string.
//
// The returned Value will represent an error, accessible through Err, if any
Expand Down
70 changes: 5 additions & 65 deletions cue/instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,66 +190,6 @@ func (inst *Instance) eval(ctx *adt.OpContext) adt.Value {
return v
}

// pkgID reports a package path that can never resolve to a valid package.
func pkgID() string {
return "_"
}

// evalExpr evaluates expr within scope.
func evalExpr(ctx *adt.OpContext, scope *adt.Vertex, expr ast.Expr) adt.Value {
cfg := &compile.Config{
Scope: scope,
Imports: func(x *ast.Ident) (pkgPath string) {
if !isBuiltin(x.Name) {
return ""
}
return x.Name
},
}

c, err := compile.Expr(cfg, ctx, pkgID(), expr)
if err != nil {
return &adt.Bottom{Err: err}
}
return adt.Resolve(ctx, c)

// scope.Finalize(ctx) // TODO: not appropriate here.
// switch s := scope.Value.(type) {
// case *bottom:
// return s
// case *adt.StructMarker:
// default:
// return ctx.mkErr(scope, "instance is not a struct, found %s", scope.Kind())
// }

// c := ctx

// x, err := compile.Expr(&compile.Config{Scope: scope}, c.Runtime, expr)
// if err != nil {
// return c.NewErrf("could not evaluate %s: %v", c.Str(x), err)
// }

// env := &adt.Environment{Vertex: scope}

// switch v := x.(type) {
// case adt.Value:
// return v
// case adt.Resolver:
// r, err := c.Resolve(env, v)
// if err != nil {
// return err
// }
// return r

// case adt.Evaluator:
// e, _ := c.Evaluate(env, x)
// return e

// }

// return c.NewErrf("could not evaluate %s", c.Str(x))
}

// ID returns the package identifier that uniquely qualifies module and
// package name.
func (inst *Instance) ID() string {
Expand Down Expand Up @@ -278,12 +218,12 @@ func (inst *Instance) Value() Value {
// Eval evaluates an expression within an existing instance.
//
// Expressions may refer to builtin packages if they can be uniquely identified.
//
// Deprecated: use
// inst.Value().Context().BuildExpr(expr, Scope(inst.Value), InferBuiltins(true))
func (inst *hiddenInstance) Eval(expr ast.Expr) Value {
ctx := newContext(inst.index)
v := inst.root
v.Finalize(ctx)
result := evalExpr(ctx, v, expr)
return newValueRoot(inst.index, ctx, result)
v := inst.Value()
return v.Context().BuildExpr(expr, Scope(v), InferBuiltins(true))
}

// DO NOT USE.
Expand Down
19 changes: 0 additions & 19 deletions cue/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,7 @@
package cue

import (
"cuelang.org/go/cue/ast"
"cuelang.org/go/cue/ast/astutil"
"cuelang.org/go/cue/token"
"cuelang.org/go/internal/core/adt"
"cuelang.org/go/internal/core/compile"
)

// This file contains query-related code.
Expand All @@ -38,21 +34,6 @@ func getScopePrefix(v Value, p Path) *adt.Vertex {
return v.v
}

func errFn(pos token.Pos, msg string, args ...interface{}) {}

// resolveExpr binds unresolved expressions to values in the expression or v.
func resolveExpr(ctx *adt.OpContext, v *adt.Vertex, x ast.Expr) adt.Value {
cfg := &compile.Config{Scope: v}

astutil.ResolveExpr(x, errFn)

c, err := compile.Expr(cfg, ctx, pkgID(), x)
if err != nil {
return &adt.Bottom{Err: err}
}
return adt.Resolve(ctx, c)
}

// LookupPath reports the value for path p relative to v.
func (v Value) LookupPath(p Path) Value {
if v.v == nil {
Expand Down
9 changes: 0 additions & 9 deletions internal/core/runtime/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,15 +114,6 @@ func (r *Runtime) CompileFile(cfg *Config, file *ast.File) (*adt.Vertex, *build.
return v, p
}

func (r *Runtime) CompileExpr(cfg *Config, expr ast.Expr) (*adt.Vertex, *build.Instance, error) {
f, err := astutil.ToFile(expr)
if err != nil {
return nil, nil, err
}
v, p := r.CompileFile(cfg, f)
return v, p, p.Err
}

func (x *Runtime) buildSpec(cfg *Config, b *build.Instance, spec *ast.ImportSpec) (errs errors.Error) {
info, err := astutil.ParseImportSpec(spec)
if err != nil {
Expand Down
38 changes: 0 additions & 38 deletions internal/value/value.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,8 @@ import (
"strings"

"cuelang.org/go/cue"
"cuelang.org/go/cue/ast"
"cuelang.org/go/cue/errors"
"cuelang.org/go/internal/core/adt"
"cuelang.org/go/internal/core/compile"
"cuelang.org/go/internal/core/convert"
"cuelang.org/go/internal/core/eval"
"cuelang.org/go/internal/core/runtime"
Expand Down Expand Up @@ -97,39 +95,3 @@ func FromGoType(r *cue.Context, x interface{}) cue.Value {
n.AddConjunct(adt.MakeRootConjunct(nil, expr))
return r.Encode(n)
}

// EvalExpr evaluates an expression within an existing struct value.
// Identifiers only resolve to values defined within the struct.
//
// Expressions may refer to builtin packages if they can be uniquely identified
func EvalExpr(value cue.Value, expr ast.Expr) cue.Value {
r, scope := ToInternal(value)
ctx := eval.NewContext(r, nil)

cfg := &compile.Config{
Scope: scope,
Imports: func(x *ast.Ident) (pkgPath string) {
if !isBuiltin(x.Name) {
return ""
}
return x.Name
},
}

c, err := compile.Expr(cfg, ctx, pkgID(), expr)
if err != nil {
return MakeError(r, err)
}
v := adt.Resolve(ctx, c)

return (*cue.Context)(r).Encode(v)
}

func isBuiltin(s string) bool {
return runtime.SharedRuntime.IsBuiltinPackage(s)
}

// pkgID reports a package path that can never resolve to a valid package.
func pkgID() string {
return "_"
}
17 changes: 8 additions & 9 deletions pkg/encoding/yaml/manual.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import (
"cuelang.org/go/internal"
cueyaml "cuelang.org/go/internal/encoding/yaml"
"cuelang.org/go/internal/third_party/yaml"
"cuelang.org/go/internal/value"
)

// Marshal returns the YAML encoding of v.
Expand Down Expand Up @@ -84,7 +83,7 @@ func Validate(b []byte, v cue.Value) (bool, error) {
if err != nil {
return false, err
}
r := value.ConvertToRuntime(v.Context())
r := v.Context()
for {
expr, err := d.Decode()
if err != nil {
Expand All @@ -94,8 +93,8 @@ func Validate(b []byte, v cue.Value) (bool, error) {
return false, err
}

inst, err := r.CompileExpr(expr)
if err != nil {
x := r.BuildExpr(expr)
if err := x.Err(); err != nil {
return false, err
}

Expand All @@ -108,7 +107,7 @@ func Validate(b []byte, v cue.Value) (bool, error) {
// if err := v.Subsume(inst.Value(), cue.Final()); err != nil {
// return false, err
// }
x := v.Unify(inst.Value())
x = v.Unify(x)
if err := x.Err(); err != nil {
return false, err
}
Expand All @@ -128,7 +127,7 @@ func ValidatePartial(b []byte, v cue.Value) (bool, error) {
if err != nil {
return false, err
}
r := value.ConvertToRuntime(v.Context())
r := v.Context()
for {
expr, err := d.Decode()
if err != nil {
Expand All @@ -138,12 +137,12 @@ func ValidatePartial(b []byte, v cue.Value) (bool, error) {
return false, err
}

inst, err := r.CompileExpr(expr)
if err != nil {
x := r.BuildExpr(expr)
if err := x.Err(); err != nil {
return false, err
}

if x := v.Unify(inst.Value()); x.Err() != nil {
if x := v.Unify(x); x.Err() != nil {
return false, x.Err()
}
}
Expand Down

0 comments on commit d9af603

Please sign in to comment.