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

Commit

Permalink
cue: introduce Context to replace Runtime
Browse files Browse the repository at this point in the history
Also:
- move the API to be Value- instead of Instance-based.
- Add Encode method
- factor out build code to internal/core/

Change-Id: Id6a71752b75422b972dca15c7ab9423401cb0287
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/9423
Reviewed-by: CUE cueckoo <cueckoo@gmail.com>
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
  • Loading branch information
mpvl committed Apr 21, 2021
1 parent 790bed3 commit 421ead3
Show file tree
Hide file tree
Showing 19 changed files with 507 additions and 118 deletions.
5 changes: 3 additions & 2 deletions cmd/cue/cmd/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import (
"cuelang.org/go/internal"
"cuelang.org/go/internal/encoding"
"cuelang.org/go/internal/filetypes"
"cuelang.org/go/internal/value"
)

// Disallow
Expand Down Expand Up @@ -244,7 +245,7 @@ func newStreamingIterator(b *buildPlan) *streamingIterator {
// TODO: use orphanedSchema
i.r = &cue.Runtime{}
if v := b.encConfig.Schema; v.Exists() {
i.r = internal.GetRuntime(v).(*cue.Runtime)
i.r = value.ConvertToRuntime(v.Context())
}

return i
Expand Down Expand Up @@ -736,7 +737,7 @@ func buildTools(cmd *Command, tags, args []string) (*cue.Instance, error) {
inst = cue.Merge(insts...)
}

r := internal.GetRuntime(inst).(*cue.Runtime)
r := value.ConvertToRuntime(inst.Value().Context())
for _, b := range binst {
for _, i := range b.Imports {
if _, err := r.Build(i); err != nil {
Expand Down
123 changes: 42 additions & 81 deletions cue/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,63 +16,32 @@ 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"
"cuelang.org/go/internal/core/adt"
"cuelang.org/go/internal/core/runtime"
)

// A Runtime is used for creating CUE interpretations.
// A Runtime is used for creating CUE Values.
//
// Any operation that involves two Values or Instances should originate from
// the same Runtime.
//
// The zero value of a Runtime is ready to use.
type Runtime struct {
idx *runtime.Runtime
}

func init() {
internal.GetRuntime = func(instance interface{}) interface{} {
switch x := instance.(type) {
case Value:
return &Runtime{idx: x.idx}

case *Instance:
return &Runtime{idx: x.index}

default:
panic("argument must be Value or *Instance")
}
}

internal.CheckAndForkRuntime = func(runtime, value interface{}) interface{} {
r := runtime.(*Runtime)
idx := value.(Value).idx
if idx != r.idx {
panic("value not from same runtime")
}
return &Runtime{idx: newIndex()}
}
}

func dummyLoad(token.Pos, string) *build.Instance { return nil }
// The zero value of Runtime works for legacy reasons, but
// should not be used. It may panic at some point.
//
// Deprecated: use Context.
type Runtime runtime.Runtime

func (r *Runtime) index() *runtime.Runtime {
if r.idx == nil {
r.idx = newIndex()
}
return r.idx
rt := (*runtime.Runtime)(r)
rt.Init()
return rt
}

func (r *Runtime) complete(p *build.Instance) (*Instance, error) {
func (r *Runtime) complete(p *build.Instance, v *adt.Vertex) (*Instance, error) {
idx := r.index()
if err := p.Complete(); err != nil {
return nil, err
}
inst := loadInstance(idx, p)
inst := getImportFromBuild(idx, p, v)
inst.ImportPath = p.ImportPath
if inst.Err != nil {
return nil, inst.Err
Expand All @@ -84,60 +53,64 @@ func (r *Runtime) complete(p *build.Instance) (*Instance, error) {
// provided as a string, byte slice, io.Reader. The name is used as the file
// name in position information. The source may import builtin packages. Use
// Build to allow importing non-builtin packages.
//
// Deprecated: use Parse or ParseBytes. The use of Instance is being phased out.
func (r *Runtime) Compile(filename string, source interface{}) (*Instance, error) {
ctx := build.NewContext()
p := ctx.NewInstance(filename, dummyLoad)
if err := p.AddFile(filename, source); err != nil {
return nil, p.Err
}
return r.complete(p)
cfg := &runtime.Config{Filename: filename}
v, p := r.index().Compile(cfg, source)
return r.complete(p, v)
}

// CompileFile compiles the given source file into an Instance. The source may
// import builtin packages. Use Build to allow importing non-builtin packages.
//
// Deprecated: use BuildFile. The use of Instance is being phased out.
func (r *Runtime) CompileFile(file *ast.File) (*Instance, error) {
ctx := build.NewContext()
p := ctx.NewInstance(file.Filename, dummyLoad)
err := p.AddSyntax(file)
if err != nil {
return nil, err
}
_, p.PkgName, _ = internal.PackageInfo(file)
return r.complete(p)
v, p := r.index().CompileFile(nil, file)
return r.complete(p, v)
}

// CompileExpr compiles the given source expression into an Instance. The source
// may import builtin packages. Use Build to allow importing non-builtin
// packages.
//
// Deprecated: use BuildExpr. The use of Instance is being phased out.
func (r *Runtime) CompileExpr(expr ast.Expr) (*Instance, error) {
f, err := astutil.ToFile(expr)
v, p, err := r.index().CompileExpr(nil, expr)
if err != nil {
return nil, err
}
return r.CompileFile(f)
return r.complete(p, v)
}

// Parse parses a CUE source value into a CUE Instance. The source code may
// be provided as a string, byte slice, or io.Reader. The name is used as the
// file name in position information. The source may import builtin packages.
// Parse parses a CUE source value into a CUE Instance. The source code may be
// provided as a string, byte slice, or io.Reader. The name is used as the file
// name in position information. The source may import builtin packages.
//
// Deprecated: use Compile
// Deprecated: use ParseString or ParseBytes. The use of Instance is being
// phased out.
func (r *Runtime) Parse(name string, source interface{}) (*Instance, error) {
return r.Compile(name, source)
}

// Build creates an Instance from the given build.Instance. A returned Instance
// may be incomplete, in which case its Err field is set.
func (r *Runtime) Build(instance *build.Instance) (*Instance, error) {
return r.complete(instance)
//
// Deprecated: use Runtime.BuildInstance. The use of Instance is being phased
// out.
func (r *Runtime) Build(p *build.Instance) (*Instance, error) {
v, _ := r.index().Build(nil, p)
return r.complete(p, v)
}

// Build creates one Instance for each build.Instance. A returned Instance
// may be incomplete, in which case its Err field is set.
// Build creates one Instance for each build.Instance. A returned Instance may
// be incomplete, in which case its Err field is set.
//
// Example:
// inst := cue.Build(load.Instances(args))
//
// Deprecated: use Runtime.BuildInstances. The use of Instance is being phased
// out.
func Build(instances []*build.Instance) []*Instance {
if len(instances) == 0 {
panic("cue: list of instances must not be empty")
Expand All @@ -155,10 +128,8 @@ func (r *Runtime) build(instances []*build.Instance) ([]*Instance, error) {
var errs errors.Error

for _, p := range instances {
_ = p.Complete()
errs = errors.Append(errs, p.Err)

i := loadInstance(index, p)
v, _ := index.Build(nil, p)
i := getImportFromBuild(index, p, v)
errs = errors.Append(errs, i.Err)
loaded = append(loaded, i)
}
Expand All @@ -177,16 +148,6 @@ func (r *Runtime) FromExpr(expr ast.Expr) (*Instance, error) {
})
}

// newIndex creates a new index.
func newIndex() *runtime.Runtime {
return runtime.New()
}

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

func loadInstance(idx *runtime.Runtime, p *build.Instance) *Instance {
v, _ := idx.Build(p)
return getImportFromBuild(idx, p, v)
}
Loading

0 comments on commit 421ead3

Please sign in to comment.