internal: replace untyped functions with typed ones
- UnifyBuiltin
- FromGoValue / FromGoType
- EvalExpr
Change-Id: I361630412b48ca2c0c5fbc31f627e53a8921ecb0
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/9425
Reviewed-by: CUE cueckoo <cueckoo@gmail.com>
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
diff --git a/cmd/cue/cmd/common.go b/cmd/cue/cmd/common.go
index 123c390..ac06401 100644
--- a/cmd/cue/cmd/common.go
+++ b/cmd/cue/cmd/common.go
@@ -31,7 +31,6 @@
"cuelang.org/go/cue/load"
"cuelang.org/go/cue/parser"
"cuelang.org/go/cue/token"
- "cuelang.org/go/internal"
"cuelang.org/go/internal/encoding"
"cuelang.org/go/internal/filetypes"
"cuelang.org/go/internal/value"
@@ -350,7 +349,8 @@
if len(i.expr) == 0 {
return i.iter.value()
}
- return internal.EvalExpr(i.iter.value(), i.expr[i.i]).(cue.Value)
+ // TODO: replace with FillPath.
+ return value.EvalExpr(i.iter.value(), i.expr[i.i])
}
type config struct {
diff --git a/cmd/cue/cmd/custom.go b/cmd/cue/cmd/custom.go
index ead236c..a19cce0 100644
--- a/cmd/cue/cmd/custom.go
+++ b/cmd/cue/cmd/custom.go
@@ -29,7 +29,6 @@
"cuelang.org/go/cue"
"cuelang.org/go/cue/errors"
- "cuelang.org/go/internal"
itask "cuelang.org/go/internal/task"
"cuelang.org/go/internal/value"
_ "cuelang.org/go/pkg/tool/cli" // Register tasks
@@ -201,7 +200,7 @@
}
// Verify entry against template.
- v = internal.UnifyBuiltin(v, kind).(cue.Value)
+ v = value.UnifyBuiltin(v, kind)
if err := v.Err(); err != nil {
return nil, errors.Promote(err, "newTask")
}
diff --git a/cue/builtin.go b/cue/builtin.go
index ee88ab1..74aa56b 100644
--- a/cue/builtin.go
+++ b/cue/builtin.go
@@ -15,12 +15,8 @@
package cue
import (
- "strings"
-
"cuelang.org/go/cue/token"
- "cuelang.org/go/internal"
"cuelang.org/go/internal/core/adt"
- "cuelang.org/go/internal/core/runtime"
)
func pos(n adt.Node) (p token.Pos) {
@@ -33,23 +29,3 @@
}
return src.Pos()
}
-
-func init() {
- // TODO: unroll this function. Should no longer be necessary to be internal.
- internal.UnifyBuiltin = func(val interface{}, kind string) interface{} {
- v := val.(Value)
-
- p := strings.Split(kind, ".")
- pkg, name := p[0], p[1]
- s, _ := runtime.SharedRuntime.LoadImport(pkg)
- if s == nil {
- return v
- }
- a := s.Lookup(v.idx.Label(name, false))
- if a == nil {
- return v
- }
-
- return v.Unify(makeValue(v.idx, a))
- }
-}
diff --git a/cue/go.go b/cue/go.go
deleted file mode 100644
index bd77055..0000000
--- a/cue/go.go
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2020 CUE Authors
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package cue
-
-import (
- "cuelang.org/go/internal"
- "cuelang.org/go/internal/core/adt"
- "cuelang.org/go/internal/core/convert"
- "cuelang.org/go/internal/core/eval"
-)
-
-func init() {
- internal.FromGoValue = func(runtime, x interface{}, nilIsTop bool) interface{} {
- r := runtime.(*Runtime)
- ctx := eval.NewContext(r.index(), nil)
- v := convert.GoValueToValue(ctx, x, nilIsTop)
- n := adt.ToVertex(v)
- return Value{r.index(), n}
- }
-
- internal.FromGoType = func(runtime, x interface{}) interface{} {
- r := runtime.(*Runtime)
- ctx := eval.NewContext(r.index(), nil)
- expr, err := convert.GoTypeToExpr(ctx, x)
- if err != nil {
- expr = &adt.Bottom{Err: err}
- }
- n := &adt.Vertex{}
- n.AddConjunct(adt.MakeRootConjunct(nil, expr))
- return Value{r.index(), n}
-
- // return convertType(runtime.(*Runtime), x)
- }
-}
diff --git a/cue/instance.go b/cue/instance.go
index cae1f9a..c0b47f6 100644
--- a/cue/instance.go
+++ b/cue/instance.go
@@ -173,15 +173,6 @@
return v
}
-func init() {
- internal.EvalExpr = func(value, expr interface{}) interface{} {
- v := value.(Value)
- e := expr.(ast.Expr)
- ctx := newContext(v.idx)
- return newValueRoot(v.idx, ctx, evalExpr(ctx, v.v, e))
- }
-}
-
// pkgID reports a package path that can never resolve to a valid package.
func pkgID() string {
return "_"
diff --git a/cuego/cuego.go b/cuego/cuego.go
index f2460a3..9b71a96 100644
--- a/cuego/cuego.go
+++ b/cuego/cuego.go
@@ -20,8 +20,9 @@
"sync"
"cuelang.org/go/cue"
+ "cuelang.org/go/cue/cuecontext"
"cuelang.org/go/cue/parser"
- "cuelang.org/go/internal"
+ "cuelang.org/go/internal/value"
)
// DefaultContext is the shared context used with top-level functions.
@@ -159,12 +160,12 @@
var (
mutex sync.Mutex
instance *cue.Instance
- runtime = &cue.Runtime{}
+ runtime = cuecontext.New()
)
func init() {
var err error
- instance, err = runtime.Compile("<cuego>", "{}")
+ instance, err = value.ConvertToRuntime(runtime).Compile("<cuego>", "{}")
if err != nil {
panic(err)
}
@@ -176,7 +177,7 @@
// Instance) here as any previously unrecognized field can never match an
// existing one and can only be merged.
mutex.Lock()
- v = internal.FromGoValue(runtime, x, nilIsNull).(cue.Value)
+ v = value.FromGoValue(runtime, x, nilIsNull)
mutex.Unlock()
if err := v.Err(); err != nil {
return v, err
@@ -204,7 +205,7 @@
// Instance) here as any previously unrecognized field can never match an
// existing one and can only be merged.
mutex.Lock()
- v := internal.FromGoType(runtime, x).(cue.Value)
+ v := value.FromGoType(runtime, x)
mutex.Unlock()
return v
}
diff --git a/encoding/gocode/gocodec/codec.go b/encoding/gocode/gocodec/codec.go
index 0951959..3d0035d 100644
--- a/encoding/gocode/gocodec/codec.go
+++ b/encoding/gocode/gocodec/codec.go
@@ -25,7 +25,6 @@
"cuelang.org/go/cue"
"cuelang.org/go/cue/cuecontext"
- "cuelang.org/go/internal"
"cuelang.org/go/internal/value"
)
@@ -36,7 +35,7 @@
// A Codec decodes and encodes CUE from and to Go values and validates and
// completes Go values based on CUE templates.
type Codec struct {
- runtime *cue.Runtime
+ runtime *cue.Context
mutex sync.RWMutex
}
@@ -46,7 +45,7 @@
// Runtime is not used elsewhere while using Codec. However, only the concurrent
// use of Decode, Validate, and Complete is efficient.
func New(r *cue.Runtime, c *Config) *Codec {
- return &Codec{runtime: r}
+ return &Codec{runtime: value.ConvertToContext(r)}
}
// ExtractType extracts a CUE value from a Go type.
@@ -162,24 +161,24 @@
return w.Unify(v).Decode(x)
}
-func fromGoValue(r *cue.Runtime, x interface{}, allowDefault bool) (cue.Value, error) {
- v := internal.FromGoValue(r, x, allowDefault).(cue.Value)
+func fromGoValue(r *cue.Context, x interface{}, allowDefault bool) (cue.Value, error) {
+ v := value.FromGoValue(r, x, allowDefault)
if err := v.Err(); err != nil {
return v, err
}
return v, nil
}
-func fromGoType(r *cue.Runtime, x interface{}) (cue.Value, error) {
- v := internal.FromGoType(r, x).(cue.Value)
+func fromGoType(r *cue.Context, x interface{}) (cue.Value, error) {
+ v := value.FromGoType(r, x)
if err := v.Err(); err != nil {
return v, err
}
return v, nil
}
-func checkAndForkContext(r *cue.Runtime, v cue.Value) *cue.Runtime {
- rr := value.ConvertToRuntime(v.Context())
+func checkAndForkContext(r *cue.Context, v cue.Value) *cue.Context {
+ rr := v.Context()
if r != rr {
panic("value not from same runtime")
}
diff --git a/internal/internal.go b/internal/internal.go
index 9cd1500..1dfc178 100644
--- a/internal/internal.go
+++ b/internal/internal.go
@@ -43,30 +43,6 @@
// incomplete.
var ErrIncomplete = errors.New("incomplete value")
-// 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
-//
-// Both value and result are of type cue.Value, but are an interface to prevent
-// cyclic dependencies.
-//
-// TODO: extract interface
-var EvalExpr func(value, expr interface{}) (result interface{})
-
-// FromGoValue converts an arbitrary Go value to the corresponding CUE value.
-// instance must be of type *cue.Instance.
-// The returned value is a cue.Value, which the caller must cast to.
-var FromGoValue func(instance, x interface{}, allowDefault bool) interface{}
-
-// FromGoType converts an arbitrary Go type to the corresponding CUE value.
-// instance must be of type *cue.Instance.
-// The returned value is a cue.Value, which the caller must cast to.
-var FromGoType func(instance, x interface{}) interface{}
-
-// UnifyBuiltin returns the given Value unified with the given builtin template.
-var UnifyBuiltin func(v interface{}, kind string) interface{}
-
// MakeInstance makes a new instance from a value.
var MakeInstance func(value interface{}) (instance interface{})
diff --git a/internal/value/value.go b/internal/value/value.go
index a91343b..35e208c 100644
--- a/internal/value/value.go
+++ b/internal/value/value.go
@@ -17,8 +17,15 @@
package value
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"
"cuelang.org/go/internal/types"
)
@@ -38,17 +45,91 @@
return t.R, t.V
}
-// TODO:
// Make wraps cue.MakeValue.
func Make(ctx *adt.OpContext, v adt.Value) cue.Value {
return (*cue.Context)(ctx.Impl().(*runtime.Runtime)).Encode(v)
}
-//
-// func Make(r *runtime.Runtime, v *adt.Vertex) cue.Value {
-// return cue.Value{}
-// }
+func MakeError(r *runtime.Runtime, err errors.Error) cue.Value {
+ b := &adt.Bottom{Err: err}
+ node := &adt.Vertex{BaseValue: b}
+ node.UpdateStatus(adt.Finalized)
+ node.AddConjunct(adt.MakeRootConjunct(nil, b))
+ return (*cue.Context)(r).Encode(node)
+}
-// func MakeError(r *runtime.Runtime, err error) cue.Value {
-// return cue.Value{}
-// }
+// UnifyBuiltin returns the given Value unified with the given builtin template.
+func UnifyBuiltin(v cue.Value, kind string) cue.Value {
+ p := strings.Split(kind, ".")
+ pkg, name := p[0], p[1]
+ s, _ := runtime.SharedRuntime.LoadImport(pkg)
+ if s == nil {
+ return v
+ }
+
+ ctx := v.Context()
+ a := s.Lookup((*runtime.Runtime)(ctx).Label(name, false))
+ if a == nil {
+ return v
+ }
+
+ return v.Unify(ctx.Encode(a))
+}
+
+func FromGoValue(r *cue.Context, x interface{}, nilIsTop bool) cue.Value {
+ rt := (*runtime.Runtime)(r)
+ rt.Init()
+ ctx := eval.NewContext(rt, nil)
+ v := convert.GoValueToValue(ctx, x, nilIsTop)
+ n := adt.ToVertex(v)
+ return r.Encode(n)
+}
+
+func FromGoType(r *cue.Context, x interface{}) cue.Value {
+ rt := (*runtime.Runtime)(r)
+ rt.Init()
+ ctx := eval.NewContext(rt, nil)
+ expr, err := convert.GoTypeToExpr(ctx, x)
+ if err != nil {
+ expr = &adt.Bottom{Err: err}
+ }
+ n := &adt.Vertex{}
+ 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 "_"
+}
diff --git a/pkg/tool/file/file_test.go b/pkg/tool/file/file_test.go
index c9bc38f..983be53 100644
--- a/pkg/tool/file/file_test.go
+++ b/pkg/tool/file/file_test.go
@@ -24,8 +24,8 @@
"cuelang.org/go/cue"
"cuelang.org/go/cue/parser"
- "cuelang.org/go/internal"
"cuelang.org/go/internal/task"
+ "cuelang.org/go/internal/value"
)
func parse(t *testing.T, kind, expr string) cue.Value {
@@ -40,7 +40,7 @@
if err != nil {
t.Fatal(err)
}
- return internal.UnifyBuiltin(i.Value(), kind).(cue.Value)
+ return value.UnifyBuiltin(i.Value(), kind)
}
func TestRead(t *testing.T) {
v := parse(t, "tool/file.Read", `{filename: "testdata/input.foo"}`)
diff --git a/pkg/tool/os/env_test.go b/pkg/tool/os/env_test.go
index 8a6d9fb..1680a87 100644
--- a/pkg/tool/os/env_test.go
+++ b/pkg/tool/os/env_test.go
@@ -26,8 +26,8 @@
"cuelang.org/go/cue/errors"
"cuelang.org/go/cue/parser"
"cuelang.org/go/cue/token"
- "cuelang.org/go/internal"
"cuelang.org/go/internal/task"
+ "cuelang.org/go/internal/value"
)
func TestGetenv(t *testing.T) {
@@ -140,5 +140,5 @@
if err != nil {
t.Fatal(err)
}
- return internal.UnifyBuiltin(i.Value(), kind).(cue.Value)
+ return value.UnifyBuiltin(i.Value(), kind)
}