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/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 "_"
+}