cue: make internal cue port main API implementation

- rm cue/*.go
- mv internal/legacy/cue/*.go cue/
- rename imports
- go

Change-Id: I553ce372ad457b1d73126b0a3f7be8224e415e80
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/6742
Reviewed-by: CUE cueckoo <cueckoo@gmail.com>
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
diff --git a/cmd/cue/cmd/add.go b/cmd/cue/cmd/add.go
index 812e642..d13035c 100644
--- a/cmd/cue/cmd/add.go
+++ b/cmd/cue/cmd/add.go
@@ -27,12 +27,12 @@
 
 	"github.com/spf13/cobra"
 
+	"cuelang.org/go/cue"
 	"cuelang.org/go/cue/build"
 	"cuelang.org/go/cue/format"
 	"cuelang.org/go/cue/load"
 	"cuelang.org/go/cue/parser"
 	"cuelang.org/go/internal"
-	"cuelang.org/go/internal/legacy/cue"
 )
 
 func newAddCmd(c *Command) *cobra.Command {
diff --git a/cmd/cue/cmd/common.go b/cmd/cue/cmd/common.go
index c63e2b5..bf0321e 100644
--- a/cmd/cue/cmd/common.go
+++ b/cmd/cue/cmd/common.go
@@ -25,6 +25,7 @@
 	"golang.org/x/text/language"
 	"golang.org/x/text/message"
 
+	"cuelang.org/go/cue"
 	"cuelang.org/go/cue/ast"
 	"cuelang.org/go/cue/build"
 	"cuelang.org/go/cue/errors"
@@ -34,7 +35,6 @@
 	"cuelang.org/go/internal"
 	"cuelang.org/go/internal/encoding"
 	"cuelang.org/go/internal/filetypes"
-	"cuelang.org/go/internal/legacy/cue"
 )
 
 // Disallow
diff --git a/cmd/cue/cmd/custom.go b/cmd/cue/cmd/custom.go
index 7bd85f0..9a6976c 100644
--- a/cmd/cue/cmd/custom.go
+++ b/cmd/cue/cmd/custom.go
@@ -28,9 +28,9 @@
 	"github.com/spf13/cobra"
 	"golang.org/x/sync/errgroup"
 
+	"cuelang.org/go/cue"
 	"cuelang.org/go/cue/errors"
 	"cuelang.org/go/internal"
-	"cuelang.org/go/internal/legacy/cue"
 	itask "cuelang.org/go/internal/task"
 	"cuelang.org/go/internal/walk"
 	_ "cuelang.org/go/pkg/tool/cli" // Register tasks
diff --git a/cmd/cue/cmd/eval.go b/cmd/cue/cmd/eval.go
index bcbf383..8d94aa8 100644
--- a/cmd/cue/cmd/eval.go
+++ b/cmd/cue/cmd/eval.go
@@ -19,12 +19,12 @@
 
 	"github.com/spf13/cobra"
 
+	"cuelang.org/go/cue"
 	"cuelang.org/go/cue/ast"
 	"cuelang.org/go/cue/format"
 	"cuelang.org/go/internal"
 	"cuelang.org/go/internal/encoding"
 	"cuelang.org/go/internal/filetypes"
-	"cuelang.org/go/internal/legacy/cue"
 )
 
 // newEvalCmd creates a new eval command
diff --git a/cmd/cue/cmd/orphans.go b/cmd/cue/cmd/orphans.go
index eb5ca75..de54d92 100644
--- a/cmd/cue/cmd/orphans.go
+++ b/cmd/cue/cmd/orphans.go
@@ -20,6 +20,7 @@
 	"regexp"
 	"strconv"
 
+	"cuelang.org/go/cue"
 	"cuelang.org/go/cue/ast"
 	"cuelang.org/go/cue/ast/astutil"
 	"cuelang.org/go/cue/build"
@@ -28,7 +29,6 @@
 	"cuelang.org/go/cue/token"
 	"cuelang.org/go/internal"
 	"cuelang.org/go/internal/encoding"
-	"cuelang.org/go/internal/legacy/cue"
 )
 
 // This file contains logic for placing orphan files within a CUE namespace.
diff --git a/cmd/cue/cmd/tags.go b/cmd/cue/cmd/tags.go
index 5d4beec..00912ef 100644
--- a/cmd/cue/cmd/tags.go
+++ b/cmd/cue/cmd/tags.go
@@ -17,13 +17,13 @@
 import (
 	"strings"
 
+	"cuelang.org/go/cue"
 	"cuelang.org/go/cue/ast"
 	"cuelang.org/go/cue/build"
 	"cuelang.org/go/cue/errors"
 	"cuelang.org/go/cue/token"
 	"cuelang.org/go/internal"
 	"cuelang.org/go/internal/cli"
-	"cuelang.org/go/internal/legacy/cue"
 )
 
 func decorateInstances(cmd *Command, tags []string, a []*build.Instance) {
diff --git a/cmd/cue/cmd/vet.go b/cmd/cue/cmd/vet.go
index 8020055..deb623d 100644
--- a/cmd/cue/cmd/vet.go
+++ b/cmd/cue/cmd/vet.go
@@ -18,8 +18,8 @@
 	"github.com/spf13/cobra"
 	"golang.org/x/text/message"
 
+	"cuelang.org/go/cue"
 	"cuelang.org/go/cue/errors"
-	"cuelang.org/go/internal/legacy/cue"
 )
 
 const vetDoc = `vet validates CUE and other data files
diff --git a/internal/legacy/cue/alias.go b/cue/alias.go
similarity index 100%
rename from internal/legacy/cue/alias.go
rename to cue/alias.go
diff --git a/cue/ast.go b/cue/ast.go
deleted file mode 100644
index 815865c..0000000
--- a/cue/ast.go
+++ /dev/null
@@ -1,838 +0,0 @@
-// Copyright 2018 The 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 (
-	"fmt"
-	"strconv"
-	"strings"
-
-	"golang.org/x/xerrors"
-
-	"cuelang.org/go/cue/ast"
-	"cuelang.org/go/cue/build"
-	"cuelang.org/go/cue/errors"
-	"cuelang.org/go/cue/literal"
-	"cuelang.org/go/cue/token"
-	"cuelang.org/go/internal"
-)
-
-// insertFile inserts the given file at the root of the instance.
-//
-// The contents will be merged (unified) with any pre-existing value. In this
-// case an error may be reported, but only if the merge failed at the top-level.
-// Other errors will be recorded at the respective values in the tree.
-//
-// There should be no unresolved identifiers in file, meaning the Node field
-// of all identifiers should be set to a non-nil value.
-func (inst *Instance) insertFile(f *ast.File) errors.Error {
-	// TODO: insert by converting to value first so that the trim command can
-	// also remove top-level fields.
-	// First process single file.
-	v := newVisitor(inst.index, inst.inst, inst.rootStruct, inst.scope, false)
-	v.astState.astMap[f] = inst.rootStruct
-	// TODO: fix cmd/import to resolve references in the AST before
-	// inserting. For now, we accept errors that did not make it up to the tree.
-	result := v.walk(f)
-	if isBottom(result) {
-		val := newValueRoot(v.ctx(), result)
-		v.errors = errors.Append(v.errors, val.toErr(result.(*bottom)))
-	}
-	return v.errors
-}
-
-type astVisitor struct {
-	*astState
-	object *structLit
-
-	parent *astVisitor
-	sel    string // label or index; may be '*'
-	// For single line fields, the doc comment is applied to the inner-most
-	// field value.
-	//
-	//   // This comment is for bar.
-	//   foo bar: value
-	//
-	doc *docNode
-
-	inSelector int
-}
-
-func (v *astVisitor) ctx() *context {
-	return v.astState.ctx
-}
-
-type astState struct {
-	ctx *context
-	*index
-	inst *build.Instance
-
-	litParser   *litParser
-	resolveRoot *structLit
-	allowAuto   bool // allow builtin packages without import
-
-	// make unique per level to avoid reuse of structs being an issue.
-	astMap   map[ast.Node]scope
-	aliasMap map[ast.Node]value
-
-	errors errors.Error
-}
-
-func (s *astState) mapScope(n ast.Node) (m scope) {
-	if m = s.astMap[n]; m == nil {
-		m = newStruct(newNode(n))
-		s.astMap[n] = m
-	}
-	return m
-}
-
-func (s *astState) setScope(n ast.Node, v scope) {
-	if m, ok := s.astMap[n]; ok && m != v {
-		panic("already defined")
-	}
-	s.astMap[n] = v
-}
-
-func newVisitor(idx *index, inst *build.Instance, obj, resolveRoot *structLit, allowAuto bool) *astVisitor {
-	ctx := idx.newContext()
-	return newVisitorCtx(ctx, inst, obj, resolveRoot, allowAuto)
-}
-
-func newVisitorCtx(ctx *context, inst *build.Instance, obj, resolveRoot *structLit, allowAuto bool) *astVisitor {
-	v := &astVisitor{
-		object: obj,
-	}
-	v.astState = &astState{
-		ctx:         ctx,
-		index:       ctx.index,
-		inst:        inst,
-		litParser:   &litParser{ctx: ctx},
-		resolveRoot: resolveRoot,
-		allowAuto:   allowAuto,
-		astMap:      map[ast.Node]scope{},
-		aliasMap:    map[ast.Node]value{},
-	}
-	return v
-}
-
-func (v *astVisitor) errf(n ast.Node, format string, args ...interface{}) evaluated {
-	v.astState.errors = errors.Append(v.astState.errors, &nodeError{
-		path:    v.appendPath(nil),
-		n:       n,
-		Message: errors.NewMessage(format, args),
-	})
-	arguments := append([]interface{}{format}, args...)
-	return v.mkErr(newNode(n), arguments...)
-}
-
-func (v *astVisitor) appendPath(a []string) []string {
-	if v.parent != nil {
-		a = v.parent.appendPath(a)
-	}
-	if v.sel != "" {
-		a = append(a, v.sel)
-	}
-	return a
-}
-
-func (v *astVisitor) resolve(n *ast.Ident) value {
-	ctx := v.ctx()
-	name := v.ident(n)
-	label := v.Label(name, true)
-	if r := v.resolveRoot; r != nil {
-		for _, a := range r.Arcs {
-			if a.Label == label {
-				return &selectorExpr{newExpr(n),
-					&nodeRef{baseValue: newExpr(n), node: r, label: label}, label}
-			}
-		}
-		if v.inSelector > 0 && v.allowAuto {
-			if p := getBuiltinShorthandPkg(ctx, name); p != nil {
-				return &nodeRef{newExpr(n), p, label}
-			}
-		}
-	}
-	return nil
-}
-
-func (v *astVisitor) loadImport(imp *ast.ImportSpec) evaluated {
-	ctx := v.ctx()
-	path, err := literal.Unquote(imp.Path.Value)
-	if err != nil {
-		return v.errf(imp, "illformed import spec")
-	}
-	// TODO: allow builtin *and* imported package. The result is a unified
-	// struct.
-	if p := getBuiltinPkg(ctx, path); p != nil {
-		return p
-	}
-	bimp := v.inst.LookupImport(path)
-	if bimp == nil {
-		return v.errf(imp, "package %q not found", path)
-	}
-	impInst := v.index.loadInstance(bimp)
-	return impInst.rootValue.evalPartial(ctx)
-}
-
-func (v *astVisitor) ident(n *ast.Ident) string {
-	str, err := ast.ParseIdent(n)
-	if err != nil {
-		v.errf(n, "invalid literal: %v", err)
-		return n.Name
-	}
-	return str
-}
-
-// We probably don't need to call Walk.s
-func (v *astVisitor) walk(astNode ast.Node) (ret value) {
-	switch n := astNode.(type) {
-	case *ast.File:
-		obj := v.object
-		v1 := &astVisitor{
-			astState: v.astState,
-			object:   obj,
-		}
-		for _, e := range n.Decls {
-			switch x := e.(type) {
-			case *ast.EmbedDecl:
-				if v1.object.emit == nil {
-					v1.object.emit = v1.walk(x.Expr)
-				} else {
-					v1.object.emit = mkBin(v.ctx(), token.NoPos, opUnify, v1.object.emit, v1.walk(x.Expr))
-				}
-			case *ast.Ellipsis:
-				// handled elsewhere
-
-			default:
-				v1.walk(e)
-			}
-		}
-		ret = obj
-
-	case *ast.Package:
-		// NOTE: Do NOT walk the identifier of the package here, as it is not
-		// supposed to resolve to anything.
-
-	case *ast.ImportDecl:
-		for _, s := range n.Specs {
-			v.walk(s)
-		}
-
-	case *ast.ImportSpec:
-		val := v.loadImport(n)
-		if !isBottom(val) {
-			v.setScope(n, val.(*structLit))
-		}
-
-	case *ast.StructLit:
-		obj := v.mapScope(n).(*structLit)
-		v1 := &astVisitor{
-			astState: v.astState,
-			object:   obj,
-			parent:   v,
-		}
-		passDoc := len(n.Elts) == 1 && !n.Lbrace.IsValid() && v.doc != nil
-		if passDoc {
-			v1.doc = v.doc
-		}
-		ret = obj
-		for i, e := range n.Elts {
-			switch x := e.(type) {
-			case *ast.Ellipsis:
-				if i != len(n.Elts)-1 {
-					return v1.walk(x.Type) // Generate an error
-				}
-				f := v.ctx().Label("_", true)
-				sig := &params{}
-				sig.add(f, &basicType{newNode(x), stringKind})
-				template := &lambdaExpr{newNode(x), sig, &top{newNode(x)}}
-				v1.object.addTemplate(v.ctx(), x.Pos(), nil, template)
-
-			case *ast.EmbedDecl:
-				old := v.ctx().inDefinition
-				v.ctx().inDefinition = 0
-				e := v1.walk(x.Expr)
-				v.ctx().inDefinition = old
-				if isBottom(e) {
-					return e
-				}
-				if e.Kind()&structKind == 0 {
-					return v1.errf(x, "can only embed structs (found %v)", e.Kind())
-				}
-				ret = mkBin(v1.ctx(), x.Pos(), opUnifyUnchecked, ret, e)
-				// TODO: preserve order of embedded fields. We cannot split into
-				// separate unifications here, as recursive references point to
-				// obj and would have to be dereferenced and copied.
-				// Solving this is best done with a generic topological sort
-				// mechanism.
-
-			case *ast.Field, *ast.Alias, *ast.LetClause:
-				v1.walk(e)
-
-			case *ast.Comprehension:
-				v1.walk(x)
-
-			case *ast.Attribute:
-				// Nothing to do.
-			}
-		}
-		if v.ctx().inDefinition > 0 && !obj.optionals.isFull() {
-			// For embeddings this is handled in binOp, in which case the
-			// isClosed bit is cleared if a template is introduced.
-			obj.closeStatus = toClose
-		}
-		if passDoc {
-			v.doc = v1.doc // signal usage of document back to parent.
-		}
-
-	case *ast.ListLit:
-		v1 := &astVisitor{
-			astState: v.astState,
-			object:   v.object,
-			parent:   v,
-		}
-
-		if len(n.Elts) == 1 {
-			if c, ok := n.Elts[0].(*ast.Comprehension); ok {
-				yielder := &yield{baseValue: newExpr(c.Value)}
-				lc := &listComprehension{
-					newExpr(c),
-					wrapClauses(v, yielder, c.Clauses),
-				}
-				// we don't support key for lists (yet?)
-
-				// TODO(hack): unwrap struct lit if embedding of one element.
-				// We do this as we do not yet support embedding of scalar
-				// values in general. This prohibits:
-				// - having fields alongside embedded values
-				// - having more than one embedded value.
-				// The latter would not be too hard to circumvent.
-				expr := c.Value
-				if s, ok := expr.(*ast.StructLit); ok && len(s.Elts) == 1 {
-					if e, ok := s.Elts[0].(*ast.EmbedDecl); ok {
-						expr = e.Expr
-					}
-				}
-				yielder.value = v.walk(expr)
-				return lc
-			}
-		}
-
-		elts, ellipsis := internal.ListEllipsis(n)
-
-		arcs := []arc{}
-		for i, e := range elts {
-			if _, ok := e.(*ast.Comprehension); ok {
-				return v.errf(e, "comprehensions must be a single element within list (for now)")
-			}
-			elem := v1.walk(e)
-			if elem == nil {
-				// TODO: it would be consistent to allow aliasing in lists
-				// as well, with a similar meaning as alias declarations in
-				// structs.
-				return v.errf(n, "alias not allowed in list")
-			}
-			v1.sel = strconv.Itoa(i)
-			arcs = append(arcs, arc{Label: label(i), v: elem})
-		}
-		s := &structLit{baseValue: newExpr(n), Arcs: arcs}
-		list := &list{baseValue: newExpr(n), elem: s}
-		list.initLit()
-		if ellipsis != nil {
-			list.len = newBound(v.ctx(), list.baseValue, opGeq, intKind, list.len)
-			if ellipsis.Type != nil {
-				list.typ = v1.walk(ellipsis.Type)
-			}
-		}
-		ret = list
-
-	case *ast.Ellipsis:
-		return v.errf(n, "ellipsis (...) only allowed at end of list or struct")
-
-	case *ast.Comprehension:
-		yielder := &yield{baseValue: newExpr(n.Value)}
-		sc := &structComprehension{
-			newNode(n),
-			wrapClauses(v, yielder, n.Clauses),
-		}
-		// we don't support key for lists (yet?)
-		switch n.Value.(type) {
-		case *ast.StructLit:
-		default:
-			// Caught by parser, usually.
-			v.errf(n, "comprehension must be struct")
-		}
-		yielder.value = v.walk(n.Value)
-		v.object.comprehensions = append(v.object.comprehensions, compValue{comp: sc})
-
-	case *ast.Field:
-		opt := n.Optional != token.NoPos
-		isDef := internal.IsDefinition(n.Label) || n.Token == token.ISA
-		if isDef {
-			ctx := v.ctx()
-			ctx.inDefinition++
-			defer func() { ctx.inDefinition-- }()
-		}
-		attrs, err := createAttrs(v.ctx(), newNode(n), n.Attrs)
-		if err != nil {
-			return v.errf(n, err.format, err.args)
-		}
-		var leftOverDoc *docNode
-		for _, c := range n.Comments() {
-			if c.Position == 0 {
-				leftOverDoc = v.doc
-				v.doc = &docNode{n: n}
-				break
-			}
-		}
-
-		lab := n.Label
-		if a, ok := lab.(*ast.Alias); ok {
-			if lab, ok = a.Expr.(ast.Label); !ok {
-				return v.errf(n, "alias expression is not a valid label")
-			}
-		}
-
-		switch x := lab.(type) {
-		case *ast.Interpolation:
-			v.sel = "?"
-			// Must be struct comprehension.
-			fc := &fieldComprehension{
-				baseValue: newDecl(n),
-				key:       v.walk(x),
-				val:       v.walk(n.Value),
-				opt:       opt,
-				def:       isDef,
-				doc:       leftOverDoc,
-				attrs:     attrs,
-			}
-			v.object.comprehensions = append(v.object.comprehensions, compValue{comp: fc})
-
-		case *ast.ListLit:
-			if len(x.Elts) != 1 {
-				return v.errf(x, "optional label expression must have exactly one element; found %d", len(x.Elts))
-			}
-			var f label
-			expr := x.Elts[0]
-			a, ok := expr.(*ast.Alias)
-			if ok {
-				expr = a.Expr
-				f = v.Label(v.ident(a.Ident), true)
-			} else {
-				f = v.Label("_", true)
-			}
-
-			// Parse the key filter or a bulk-optional field. The special value
-			// of nil to mean "all fields".
-			var key value
-			if i, ok := expr.(*ast.Ident); !ok || (i.Name != "string" && i.Name != "_") {
-				key = v.walk(expr)
-			}
-			v.sel = "*"
-
-			sig := &params{}
-			sig.add(f, &basicType{newNode(lab), stringKind})
-			template := &lambdaExpr{newNode(n), sig, nil}
-
-			v.setScope(n, template)
-			template.value = v.walk(n.Value)
-
-			v.object.addTemplate(v.ctx(), token.NoPos, key, template)
-
-		case *ast.TemplateLabel:
-			if isDef {
-				v.errf(x, "map element type cannot be a definition")
-			}
-			v.sel = "*"
-			f := v.Label(v.ident(x.Ident), true)
-
-			sig := &params{}
-			sig.add(f, &basicType{newNode(lab), stringKind})
-			template := &lambdaExpr{newNode(n), sig, nil}
-
-			v.setScope(n, template)
-			template.value = v.walk(n.Value)
-
-			v.object.addTemplate(v.ctx(), token.NoPos, nil, template)
-
-		case *ast.BasicLit, *ast.Ident:
-			v.sel, _, _ = ast.LabelName(x)
-			if v.sel == "_" {
-				if _, ok := x.(*ast.BasicLit); ok {
-					v.sel = "*"
-				}
-			}
-			f, ok := v.NodeLabel(x)
-			if !ok {
-				return v.errf(lab, "invalid field name: %v", lab)
-			}
-			val := v.walk(n.Value)
-			if val == nil {
-				return v.errf(lab, "invalid field value: %v",
-					internal.DebugStr(n.Value))
-			}
-			v.object.insertValue(v.ctx(), f, opt, isDef, val, attrs, v.doc)
-			v.doc = leftOverDoc
-
-		default:
-			panic("cue: unknown label type")
-		}
-
-	case *ast.Alias, *ast.LetClause:
-		// parsed verbatim at reference.
-
-	case *ast.ListComprehension:
-		yielder := &yield{baseValue: newExpr(n.Expr)}
-		lc := &listComprehension{
-			newExpr(n),
-			wrapClauses(v, yielder, n.Clauses),
-		}
-		// we don't support key for lists (yet?)
-		yielder.value = v.walk(n.Expr)
-		return lc
-
-	// Expressions
-	case *ast.Ident:
-		name := v.ident(n)
-
-		if name == "_" {
-			ret = &top{newNode(n)}
-			break
-		}
-
-		if n.Node == nil {
-			if ret = v.resolve(n); ret != nil {
-				break
-			}
-
-			// TODO: consider supporting GraphQL-style names:
-			// String, Bytes, Boolean, Integer, Number.
-			// These names will not conflict with idiomatic camel-case JSON.
-			switch name {
-			case "_":
-				return &top{newExpr(n)}
-			case "string", "__string":
-				return &basicType{newExpr(n), stringKind}
-			case "bytes", "__bytes":
-				return &basicType{newExpr(n), bytesKind}
-			case "bool", "__bool":
-				return &basicType{newExpr(n), boolKind}
-			case "int", "__int":
-				return &basicType{newExpr(n), intKind}
-			case "float", "__float":
-				return &basicType{newExpr(n), floatKind}
-			case "number", "__number":
-				return &basicType{newExpr(n), numKind}
-
-			case "len", "__len":
-				return lenBuiltin
-			case "close", "__close":
-				return closeBuiltin
-			case "and", "__and":
-				return andBuiltin
-			case "or", "__or":
-				return orBuiltin
-			}
-			if r, ok := predefinedRanges[name]; ok {
-				return r
-			}
-
-			ret = v.errf(n, "reference %q not found", name)
-			break
-		}
-
-		// Type of reference      Scope          Node
-		// Let Clause             File/Struct    LetClause
-		// Alias declaration      File/Struct    Alias (deprecated)
-		// Illegal Reference      File/Struct
-		// Fields
-		//    Label               File/Struct    ParenExpr, Ident, BasicLit
-		//    Value               File/Struct    Field
-		// Template               Field          Template
-		// Fields inside lambda
-		//    Label               Field          Expr
-		//    Value               Field          Field
-		// Pkg                    nil            ImportSpec
-		var expr ast.Expr
-		switch x := n.Node.(type) {
-		case *ast.Alias:
-			expr = x.Expr
-		case *ast.LetClause:
-			expr = x.Expr
-		}
-
-		if expr != nil {
-			// TODO(lang): should we exempt definitions? The substitution
-			// principle says we should not.
-			if ret = v.aliasMap[expr]; ret != nil {
-				break
-			}
-			old := v.ctx().inDefinition
-			v.ctx().inDefinition = 0
-			ret = v.walk(expr)
-			v.aliasMap[expr] = ret
-			v.ctx().inDefinition = old
-			break
-		}
-
-		f := v.Label(name, true)
-		if _, ok := n.Node.(*ast.ImportSpec); ok {
-			n2 := v.mapScope(n.Node)
-			ref := &nodeRef{baseValue: newExpr(n), node: n2, label: f}
-			ret = ref
-			break
-		}
-
-		// TODO: probably unused. Verify and remove.
-		if n.Scope == nil {
-			// Package or direct ancestor node.
-			n2 := v.mapScope(n.Node)
-			ref := &nodeRef{baseValue: newExpr(n), node: n2, label: f}
-			ret = ref
-			break
-		}
-
-		n2 := v.mapScope(n.Scope)
-		ret = &nodeRef{baseValue: newExpr(n), node: n2}
-
-		// Allow different names to refer to the same field in unification. We
-		// do this by anonymizing the the reference. This then has to be
-		// resolved again when referring to lambdas.
-		l, lambda := n2.(*lambdaExpr)
-		if lambda && len(l.params.arcs) == 1 {
-			f = 0
-		}
-
-		if field, ok := n.Node.(*ast.Field); ok {
-			if lambda {
-				// inside bulk optional.
-				ret = v.errf(n, "referencing field (%q) within lambda not yet unsupported", name)
-				break
-			}
-			name, _, err := ast.LabelName(field.Label)
-			switch {
-			case xerrors.Is(err, ast.ErrIsExpression):
-				a := field.Label.(*ast.Alias)
-				ret = &indexExpr{newExpr(n), ret, v.walk(a.Expr)}
-
-			case err != nil:
-				ret = v.errf(n, "invalid label: %v", err)
-
-			case name != "":
-				f = v.Label(name, true)
-				ret = &selectorExpr{newExpr(n), ret, f}
-
-			default:
-				// TODO: support dynamically computed label lookup.
-				// Should that also support lookup of definitions?
-				ret = v.errf(n, "unsupported field alias %q", name)
-			}
-			break
-		}
-
-		ret = &selectorExpr{newExpr(n), ret, f}
-
-	case *ast.BottomLit:
-		// TODO: record inline comment.
-		ret = &bottom{baseValue: newExpr(n), Code: codeUser, format: "from source"}
-
-	case *ast.BadDecl:
-		// nothing to do
-
-	case *ast.BadExpr:
-		ret = v.errf(n, "invalid expression")
-
-	case *ast.BasicLit:
-		ret = v.litParser.parse(n)
-
-	case *ast.Interpolation:
-		if len(n.Elts) == 0 {
-			return v.errf(n, "invalid interpolation")
-		}
-		first, ok1 := n.Elts[0].(*ast.BasicLit)
-		last, ok2 := n.Elts[len(n.Elts)-1].(*ast.BasicLit)
-		if !ok1 || !ok2 {
-			return v.errf(n, "invalid interpolation")
-		}
-		if len(n.Elts) == 1 {
-			ret = v.walk(n.Elts[0])
-			break
-		}
-		lit := &interpolation{baseValue: newExpr(n), K: stringKind}
-		ret = lit
-		info, prefixLen, _, err := literal.ParseQuotes(first.Value, last.Value)
-		if err != nil {
-			return v.errf(n, "invalid interpolation: %v", err)
-		}
-		prefix := ""
-		for i := 0; i < len(n.Elts); i += 2 {
-			l, ok := n.Elts[i].(*ast.BasicLit)
-			if !ok {
-				return v.errf(n, "invalid interpolation")
-			}
-			s := l.Value
-			if !strings.HasPrefix(s, prefix) {
-				return v.errf(l, "invalid interpolation: unmatched ')'")
-			}
-			s = l.Value[prefixLen:]
-			x := parseString(v.ctx(), l, info, s)
-			lit.Parts = append(lit.Parts, x)
-			if i+1 < len(n.Elts) {
-				lit.Parts = append(lit.Parts, v.walk(n.Elts[i+1]))
-			}
-			prefix = ")"
-			prefixLen = 1
-		}
-
-	case *ast.ParenExpr:
-		ret = v.walk(n.X)
-
-	case *ast.SelectorExpr:
-		v.inSelector++
-		ret = &selectorExpr{
-			newExpr(n),
-			v.walk(n.X),
-			v.Label(v.ident(n.Sel), true),
-		}
-		v.inSelector--
-
-	case *ast.IndexExpr:
-		ret = &indexExpr{newExpr(n), v.walk(n.X), v.walk(n.Index)}
-
-	case *ast.SliceExpr:
-		slice := &sliceExpr{baseValue: newExpr(n), X: v.walk(n.X)}
-		if n.Low != nil {
-			slice.Lo = v.walk(n.Low)
-		}
-		if n.High != nil {
-			slice.Hi = v.walk(n.High)
-		}
-		ret = slice
-
-	case *ast.CallExpr:
-		call := &callExpr{baseValue: newExpr(n), Fun: v.walk(n.Fun)}
-		for _, a := range n.Args {
-			call.Args = append(call.Args, v.walk(a))
-		}
-		ret = call
-
-	case *ast.UnaryExpr:
-		switch n.Op {
-		case token.NOT, token.ADD, token.SUB:
-			ret = &unaryExpr{
-				newExpr(n),
-				tokenMap[n.Op],
-				v.walk(n.X),
-			}
-		case token.GEQ, token.GTR, token.LSS, token.LEQ,
-			token.NEQ, token.MAT, token.NMAT:
-			ret = newBound(
-				v.ctx(),
-				newExpr(n),
-				tokenMap[n.Op],
-				topKind|nonGround,
-				v.walk(n.X),
-			)
-
-		case token.MUL:
-			return v.errf(n, "preference mark not allowed at this position")
-		default:
-			return v.errf(n, "unsupported unary operator %q", n.Op)
-		}
-
-	case *ast.BinaryExpr:
-		switch n.Op {
-		case token.OR:
-			d := &disjunction{baseValue: newExpr(n)}
-			v.addDisjunctionElem(d, n.X, false)
-			v.addDisjunctionElem(d, n.Y, false)
-			ret = d
-
-		default:
-			ret = updateBin(v.ctx(), &binaryExpr{
-				newExpr(n),
-				tokenMap[n.Op], // op
-				v.walk(n.X),    // left
-				v.walk(n.Y),    // right
-			})
-		}
-
-	case *ast.CommentGroup:
-		// Nothing to do for a free-floating comment group.
-
-	case *ast.Attribute:
-		// Nothing to do for now.
-
-	// nothing to do
-	// case *syntax.EmbedDecl:
-	default:
-		// TODO: unhandled node.
-		// value = ctx.mkErr(n, "unknown node type %T", n)
-		panic(fmt.Sprintf("unimplemented %T", n))
-
-	}
-	return ret
-}
-
-func (v *astVisitor) addDisjunctionElem(d *disjunction, n ast.Node, mark bool) {
-	switch x := n.(type) {
-	case *ast.BinaryExpr:
-		if x.Op == token.OR {
-			v.addDisjunctionElem(d, x.X, mark)
-			v.addDisjunctionElem(d, x.Y, mark)
-			return
-		}
-	case *ast.UnaryExpr:
-		if x.Op == token.MUL {
-			mark = true
-			n = x.X
-		}
-		d.HasDefaults = true
-	}
-	d.Values = append(d.Values, dValue{v.walk(n), mark})
-}
-
-func wrapClauses(v *astVisitor, y yielder, clauses []ast.Clause) yielder {
-	for _, c := range clauses {
-		if n, ok := c.(*ast.ForClause); ok {
-			params := &params{}
-			fn := &lambdaExpr{newExpr(n.Source), params, nil}
-			v.setScope(n, fn)
-		}
-	}
-	for i := len(clauses) - 1; i >= 0; i-- {
-		switch n := clauses[i].(type) {
-		case *ast.ForClause:
-			fn := v.mapScope(n).(*lambdaExpr)
-			fn.value = y
-
-			key := "_"
-			if n.Key != nil {
-				key = v.ident(n.Key)
-			}
-			f := v.Label(key, true)
-			fn.add(f, &basicType{newExpr(n.Key), stringKind | intKind})
-
-			f = v.Label(v.ident(n.Value), true)
-			fn.add(f, &top{})
-
-			y = &feed{newExpr(n.Source), v.walk(n.Source), fn}
-
-		case *ast.IfClause:
-			y = &guard{newExpr(n.Condition), v.walk(n.Condition), y}
-		}
-	}
-	return y
-}
diff --git a/cue/ast/astutil/file_test.go b/cue/ast/astutil/file_test.go
index 27861c5..15f0636 100644
--- a/cue/ast/astutil/file_test.go
+++ b/cue/ast/astutil/file_test.go
@@ -18,11 +18,11 @@
 	"strings"
 	"testing"
 
+	"cuelang.org/go/cue"
 	"cuelang.org/go/cue/ast"
 	"cuelang.org/go/cue/ast/astutil"
 	"cuelang.org/go/cue/format"
 	"cuelang.org/go/cue/token"
-	"cuelang.org/go/internal/legacy/cue"
 	"github.com/google/go-cmp/cmp"
 )
 
diff --git a/cue/ast_test.go b/cue/ast_test.go
deleted file mode 100644
index 1b37205..0000000
--- a/cue/ast_test.go
+++ /dev/null
@@ -1,645 +0,0 @@
-// Copyright 2018 The 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 (
-	"bytes"
-	"strings"
-	"testing"
-
-	"github.com/stretchr/testify/assert"
-
-	"cuelang.org/go/cue/ast"
-	"cuelang.org/go/cue/errors"
-	"cuelang.org/go/cue/parser"
-	"cuelang.org/go/internal"
-)
-
-func TestCompile(t *testing.T) {
-	testCases := []struct {
-		in  string
-		out string
-	}{{
-		in: `{
-		  foo: 1,
-		}`,
-		out: "<0>{<1>{foo: 1}, }", // emitted value, but no top-level fields
-	}, {
-		in: `
-		foo: 1
-		`,
-		out: "<0>{foo: 1}",
-	}, {
-		in: `
-		a: true
-		b: 2K
-		c: 4_5
-		d: "abc"
-		e: 3e2 // 3h1m2ss
-		"": 8
-		`,
-		out: `<0>{"": 8, a: true, b: 2000, c: 45, d: "abc", e: 3e+2}`,
-	}, {
-		in: `
-		a: null
-		b: true
-		c: false
-		`,
-		out: "<0>{a: null, b: true, c: false}",
-	}, {
-		in: `
-		a: <1
-		b: >= 0 & <= 10
-		c: != null
-		d: >100
-		`,
-		out: `<0>{a: <1, b: (>=0 & <=10), c: !=null, d: >100}`,
-	}, {
-		in: "" +
-			`a: "\(4)",
-			b: "one \(a) two \(  a + c  )",
-			c: "one"`,
-		out: `<0>{a: ""+4+"", b: "one "+<0>.a+" two "+(<0>.a + <0>.c)+"", c: "one"}`,
-	}, {
-		in: "" +
-			`a: """
-				multi
-				""",
-			b: '''
-				hello world
-				goodbye globe
-				welcome back planet
-				'''`,
-		out: `<0>{a: "multi", b: 'hello world\ngoodbye globe\nwelcome back planet'}`,
-	}, {
-		in: "" +
-			`a: """
-				multi \(4)
-				""",
-			b: """
-				hello \("world")
-				goodbye \("globe")
-				welcome back \("planet")
-				"""`,
-		out: `<0>{a: "multi "+4+"", b: "hello "+"world"+"\ngoodbye "+"globe"+"\nwelcome back "+"planet"+""}`,
-	}, {
-		in: `
-		a: _
-		b: int
-		c: float
-		d: bool
-		e: string
-		`,
-		out: "<0>{a: _, b: int, c: float, d: bool, e: string}",
-	}, {
-		in: `
-		a: null
-		b: true
-		c: false
-		`,
-		out: "<0>{a: null, b: true, c: false}",
-	}, {
-		in: `
-		null: null
-		true: true
-		false: false
-		`,
-		out: "<0>{null: null, true: true, false: false}",
-	}, {
-		in: `
-		a: 1 + 2
-		b: -2 - 3
-		c: !d
-		d: true
-		`,
-		out: "<0>{a: (1 + 2), b: (-2 - 3), c: !<0>.d, d: true}",
-	}, {
-		in: `
-			l0: 3*[int]
-			l0: [1, 2, 3]
-			l1: <=5*[string]
-			l1: ["a", "b"]
-			l2: (<=5)*[{ a: int }]
-			l2: [{a: 1}, {a: 2, b: 3}]
-			l3: (<=10)*[int]
-			l3: [1, 2, 3, ...]
-			l4: [1, 2, ...]
-			l4: [...int]
-			l5: [1, ...int]
-
-			s1: ((<=6)*[int])[2:3]
-			s2: [0,2,3][1:2]
-
-			e0: (>=2 & <=5)*[{}]
-			e0: [{}]
-			`,
-		out: `<0>{l0: ((3 * [int]) & [1,2,3]), l1: ((<=5 * [string]) & ["a","b"]), l2: ((<=5 * [<1>{a: int}]) & [<2>{a: 1},<3>{a: 2, b: 3}]), l3: ((<=10 * [int]) & [1,2,3, ...]), l4: ([1,2, ...] & [, ...int]), l5: [1, ...int], s1: (<=6 * [int])[2:3], s2: [0,2,3][1:2], e0: (((>=2 & <=5) * [<4>{}]) & [<5>{}])}`,
-	}, {
-		in: `
-		a: 5 | "a" | true
-		aa: 5 | *"a" | true
-		b: c: {
-			cc: { ccc: 3 }
-		}
-		d: true
-		`,
-		out: "<0>{a: (5 | \"a\" | true), aa: (5 | *\"a\" | true), b: <1>{c: <2>{cc: <3>{ccc: 3}}}, d: true}",
-	}, {
-		in: `
-		a: a: { b: a } // referencing ancestor nodes is legal.
-		a: b: a.a      // do lookup before merging of nodes
-		b: a.a        // different node as a.a.b, as first node counts
-		c: a          // same node as b, as first node counts
-		d: a["a"]
-		`,
-		out: `<0>{a: (<1>{a: <2>{b: <1>.a}} & <3>{b: <0>.a.a}), b: <0>.a.a, c: <0>.a, d: <0>.a["a"]}`,
-		// TODO(#152): should be
-		// out: `<0>{a: (<1>{a: <2>{b: <2>}} & <3>{b: <3>.a}), b: <0>.a.a, c: <0>.a, d: <0>.a["a"]}`,
-	}, {
-		// bunch of aliases
-		in: `
-		let a1 = a2
-		let a2 = 5
-		b: a1
-		let a3 = d
-		c: {
-			d: {
-				r: a3
-			}
-			r: a3
-		}
-		d: { e: 4 }
-		`,
-		out: `<0>{b: 5, c: <1>{d: <2>{r: <0>.d}, r: <0>.d}, d: <3>{e: 4}}`,
-	}, {
-		// aliases with errors
-		in: `
-		let e1 = 1
-		let e1 = 2
-		e1v: e1
-		e2: "a"
-		let e2 = "a"
-		`,
-		out: `alias "e1" redeclared in same scope:` + "\n" +
-			"    test:3:3\n" +
-			`cannot have both alias and field with name "e2" in same scope:` + "\n" +
-			"    test:6:3\n" +
-			"<0>{}",
-	}, {
-		in: `
-		let a = b
-		b: {
-			c: a // reference to own root.
-		}
-		`,
-		out: `<0>{b: <1>{c: <0>.b}}`,
-		// }, {
-		// 	// TODO: Support this:
-		// 	// optional fields
-		// 	in: `
-		// 		X=[string]: { chain: X | null }
-		// 		`,
-		// 	out: `
-		// 		`,
-	}, {
-		// optional fields
-		in: `
-			[ID=string]: { name: ID }
-			A="foo=bar": 3
-			a: A
-			B=bb: 4
-			b1: B
-			b1: bb
-			C="\(a)": 5
-			c: C
-			`,
-		out: `<0>{[]: <1>(ID: string)-><2>{name: <1>.ID}, "foo=bar": 3, a: <0>."foo=bar", bb: 4, b1: (<0>.bb & <0>.bb), c: <0>[""+<0>.a+""]""+<0>.a+"": 5}`,
-	}, {
-		// optional fields with key filters
-		in: `
-			JobID: =~"foo"
-			a: [JobID]: { name: string }
-
-			[<"s"]: { other: string }
-			`,
-		out: `<0>{` +
-			`[<"s"]: <1>(_: string)-><2>{other: string}, ` +
-			`JobID: =~"foo", a: <3>{` +
-			`[<0>.JobID]: <4>(_: string)-><5>{name: string}, ` +
-			`}}`,
-	}, {
-		// Issue #251
-		// TODO: the is one of the cases where it is relatively easy to catch
-		// a structural cycle. We should be able, however, to break the cycle
-		// with a post-validation constraint. Clean this up with the evaluator
-		// update.
-		in: `
-		{
-			[x]: 3
-		}
-		x:   "x"
-		`,
-		out: "reference \"x\" in label expression refers to field against which it would be matched:\n    test:3:5\n<0>{}",
-	}, {
-		// illegal alias usage
-		in: `
-			[X=string]: { chain: X | null }
-			a: X
-			Y=[string]: 3
-			a: X
-			`,
-		out: `a: invalid label: cannot reference fields with square brackets labels outside the field value:
-    test:3:7
-a: invalid label: cannot reference fields with square brackets labels outside the field value:
-    test:5:7
-<0>{}`,
-	}, {
-		// detect duplicate aliases, even if illegal
-		in: `
-		[X=string]: int
-		X=[string]: int
-		Y=foo: int
-		let Y=3
-		Z=[string]: { Z=3, a: int } // allowed
-		`,
-		out: `alias "X" redeclared in same scope:
-    test:3:3
-alias "Y" redeclared in same scope:
-    test:5:3
-<0>{}`,
-	}, {
-		in: `
-		a: {
-			[name=_]: { n: name }
-			k: 1
-		}
-		b: {
-			[X=_]: { x: 0, y: 1 }
-			v: {}
-		}
-		`,
-		out: `<0>{a: <1>{[]: <2>(name: string)-><3>{n: <2>.name}, k: 1}, b: <4>{[]: <5>(X: string)-><6>{x: 0, y: 1}, v: <7>{}}}`,
-	}, {
-		in: `
-		a: {
-			for k, v in b if b.a < k {
-				"\(k)": v
-			}
-		}
-		b: {
-			a: 1
-			b: 2
-			c: 3
-		}
-		`,
-		out: `<0>{a: <1>{ <2>for k, v in <0>.b if (<0>.b.a < <2>.k) yield <3>{""+<2>.k+"": <2>.v}}, b: <4>{a: 1, b: 2, c: 3}}`,
-	}, {
-		in: `
-			a: { for k, v in b {"\(v)": v} }
-			b: { a: "aa", b: "bb", c: "cc" }
-			`,
-		out: `<0>{a: <1>{ <2>for k, v in <0>.b yield <3>{""+<2>.v+"": <2>.v}}, b: <4>{a: "aa", b: "bb", c: "cc"}}`,
-	}, {
-		in: `
-			a: [ for _, v in b { v } ]
-			b: { a: 1, b: 2, c: 3 }
-			`,
-		out: `<0>{a: [ <1>for _, v in <0>.b yield <1>.v ], b: <2>{a: 1, b: 2, c: 3}}`,
-	}, {
-		in: `
-			a: >=1 & <=2
-			b: >=1 & >=2 & <=3
-			c: >="a" & <"b"
-			d: >(2+3) & <(4+5)
-			`,
-		out: `<0>{a: (>=1 & <=2), b: ((>=1 & >=2) & <=3), c: (>="a" & <"b"), d: (>(2 + 3) & <(4 + 5))}`,
-	}, {
-		in: `
-			a: *1,
-			b: **1 | 2
-		`,
-		out: `a: preference mark not allowed at this position:
-    test:2:7
-b: preference mark not allowed at this position:
-    test:3:8
-<0>{}`,
-	}, {
-		in: `
-			a: int @foo(1,"str")
-		`,
-		out: "<0>{a: int @foo(1,\"str\")}",
-	}, {
-		in: `
-			a: int @b([,b) // invalid
-		`,
-		out: "unexpected ')':\n    test:2:18\nattribute missing ')':\n    test:3:3\n<0>{}",
-	}, {
-		in: `
-		a: d: {
-			#base
-			#info: {
-				...
-			}
-			Y: #info.X
-		}
-
-		#base: {
-			#info: {...}
-		}
-
-		a: [Name=string]: { #info: {
-			X: "foo"
-		}}
-		`,
-		out: `<0>{` +
-			`a: (<1>{d: <2>{#info: <3>{...}, Y: <2>.#info.X}, <0>.#base} & <4>{[]: <5>(Name: string)-><6>{#info: <7>C{X: "foo"}}, }), ` +
-			`#base: <8>C{#info: <9>{...}}}`,
-	}, {
-		in: `
-		#def: {
-			Type: string
-			Text: string
-			Size: int
-		}
-
-		#def: {
-			Type: "B"
-			Size: 0
-		} | {
-			Type: "A"
-			Size: 1
-		}
-		`,
-		out: `<0>{` +
-			`#def: (<1>C{Size: int, Type: string, Text: string} & (<2>C{Size: 0, Type: "B"} | <3>C{Size: 1, Type: "A"}))` +
-			`}`,
-	}, {
-		// Issue #172
-		in: `
-		package testenv
-		#env_: [NAME=_]: [VALUE=_]
-		#env_: foo: "bar"
-			`,
-		out: "#env_.*: alias not allowed in list:\n    test:3:20\n<0>{}",
-	}, {
-		// Issue #276
-		in: `
-			a:     int=<100
-			`,
-		out: "alias \"int\" not allowed as value:\n    test:2:11\n<0>{}",
-	}}
-	for _, tc := range testCases {
-		t.Run("", func(t *testing.T) {
-			ctx, root, err := compileFileWithErrors(t, tc.in)
-			buf := &bytes.Buffer{}
-			if err != nil {
-				errors.Print(buf, err, nil)
-			}
-			buf.WriteString(debugStr(ctx, root))
-			got := buf.String()
-			if got != tc.out {
-				t.Errorf("output differs:\ngot  %q\nwant %q", got, tc.out)
-			}
-		})
-	}
-}
-
-func TestEmit(t *testing.T) {
-	testCases := []struct {
-		in  string
-		out string
-		rw  rewriteMode
-	}{{
-		in: `"\(hello), \(world)!"` + `
-		hello: "Hello"
-		world: "World"
-		`,
-		out: `""+<0>.hello+", "+<0>.world+"!"`,
-		rw:  evalRaw,
-	}, {
-		in: `"\(hello), \(world)!"` + `
-		hello: "Hello"
-		world: "World"
-		`,
-		out: `"Hello, World!"`,
-		rw:  evalPartial,
-	}, {
-		// Ambiguous disjunction must cary over to emit value.
-		in: `baz
-
-		baz: {
-			a: 8000 | 7080
-			a: 7080 | int
-		}`,
-		out: `<0>{a: (8000 | 7080)}`,
-		rw:  evalFull,
-	}}
-	for _, tc := range testCases {
-		t.Run("", func(t *testing.T) {
-			ctx, root := compileFile(t, tc.in)
-			v := testResolve(ctx, root.emit, tc.rw)
-			if got := debugStr(ctx, v); got != tc.out {
-				t.Errorf("output differs:\ngot  %q\nwant %q", got, tc.out)
-			}
-		})
-	}
-}
-
-func TestEval(t *testing.T) {
-	testCases := []struct {
-		in   string
-		expr string
-		out  string
-	}{{
-		in: `
-			hello: "Hello"
-			world: "World"
-			`,
-		expr: `"\(hello), \(world)!"`,
-		out:  `"Hello, World!"`,
-	}, {
-		in: `
-			a: { b: 2, c: 3 }
-			z: 1
-			`,
-		expr: `a.b + a.c + z`,
-		out:  `6`,
-	}, {
-		in: `
-			a: { b: 2, c: 3 }
-			`,
-		expr: `{ d: a.b + a.c }`,
-		out:  `<0>{d: 5}`,
-	}, {
-		in: `
-			a: "Hello World!"
-			`,
-		expr: `strings.ToUpper(a)`,
-		out:  `"HELLO WORLD!"`,
-	}, {
-		in: `
-			a: 0x8
-			b: 0x1`,
-		expr: `bits.Or(a, b)`, // package shorthand
-		out:  `9`,
-	}, {
-		in: `
-			a: 0x8
-			b: 0x1`,
-		expr: `math.Or(a, b)`,
-		out:  `_|_(<0>.Or:undefined field "Or")`,
-	}, {
-		in:   `a: 0x8`,
-		expr: `mathematics.Abs(a)`,
-		out:  `_|_(reference "mathematics" not found)`,
-	}}
-	for _, tc := range testCases {
-		t.Run("", func(t *testing.T) {
-			ctx, inst, errs := compileInstance(t, tc.in)
-			if errs != nil {
-				t.Fatal(errs)
-			}
-			expr, err := parser.ParseExpr("<test>", tc.expr)
-			if err != nil {
-				t.Fatal(err)
-			}
-			evaluated := evalExpr(ctx, inst.eval(ctx), expr)
-			v := testResolve(ctx, evaluated, evalFull)
-			if got := debugStr(ctx, v); got != tc.out {
-				t.Errorf("output differs:\ngot  %q\nwant %q", got, tc.out)
-			}
-		})
-	}
-}
-
-func TestResolution(t *testing.T) {
-	testCases := []struct {
-		name string
-		in   string
-		err  string
-	}{{
-		name: "package name identifier should not resolve to anything",
-		in: `package time
-
-		import "time"
-
-		a: time.Time
-		`,
-	}, {
-		name: "duplicate_imports.cue",
-		in: `
-		import "time"
-		import time "math"
-
-		t: time.Time
-		`,
-		err: "time redeclared as imported package name",
-	}, {
-		name: "unused_import",
-		in: `
-			import "time"
-			`,
-		err: `imported and not used: "time"`,
-	}, {
-		name: "nonexisting import package",
-		in:   `import "doesnotexist"`,
-		err:  `package "doesnotexist" not found`,
-	}, {
-		name: "duplicate with different name okay",
-		in: `
-		import "time"
-		import time2 "time"
-
-		a: time.Time
-		b: time2.Time
-		`,
-	}}
-	for _, tc := range testCases {
-		t.Run(tc.name, func(t *testing.T) {
-			var r Runtime
-			_, err := r.Compile(tc.name, tc.in)
-			got := err == nil
-			want := tc.err == ""
-			if got != want {
-				t.Fatalf("got %v; want %v", err, tc.err)
-			}
-			if err != nil {
-				if s := err.Error(); !strings.Contains(s, tc.err) {
-					t.Errorf("got %v; want %v", err, tc.err)
-				}
-			}
-		})
-	}
-}
-
-func TestShadowing(t *testing.T) {
-	spec := ast.NewImport(nil, "list")
-	testCases := []struct {
-		file *ast.File
-		want string
-	}{{
-		file: &ast.File{Decls: []ast.Decl{
-			&ast.ImportDecl{Specs: []*ast.ImportSpec{spec}},
-			&ast.EmbedDecl{
-				Expr: ast.NewStruct(
-					&ast.Field{
-						Label: mustParseExpr(`list`).(*ast.Ident),
-						Value: ast.NewCall(
-							ast.NewSel(
-								&ast.Ident{Name: "list", Node: spec},
-								"Min")),
-					})},
-		}},
-		want: "import \"list\", let LIST=list, {list: LIST.Min()}",
-	}, {
-		file: &ast.File{Decls: []ast.Decl{
-			&ast.ImportDecl{Specs: []*ast.ImportSpec{spec}},
-			&ast.Field{
-				Label: ast.NewIdent("a"),
-				Value: ast.NewStruct(&ast.Field{
-					Label: mustParseExpr(`list`).(*ast.Ident),
-					Value: ast.NewCall(
-						ast.NewSel(&ast.Ident{Name: "list", Node: spec}, "Min")),
-				}),
-			},
-		}},
-		want: "import \"list\", let LIST=list, a: {list: LIST.Min()}",
-	}}
-	for _, tc := range testCases {
-		t.Run("", func(t *testing.T) {
-			var r Runtime
-			inst, err := r.CompileFile(tc.file)
-			if err != nil {
-				t.Fatal(err)
-			}
-
-			ctx := r.index().newContext()
-
-			n, _ := export(ctx, inst, inst.rootStruct, options{
-				raw: true,
-			})
-			got := internal.DebugStr(n)
-			assert.Equal(t, got, tc.want)
-		})
-	}
-}
-
-func mustParseExpr(expr string) ast.Expr {
-	ex, err := parser.ParseExpr("cue", expr)
-	if err != nil {
-		panic(err)
-	}
-	return ex
-}
diff --git a/cue/attr.go b/cue/attr.go
deleted file mode 100644
index 235bed7..0000000
--- a/cue/attr.go
+++ /dev/null
@@ -1,132 +0,0 @@
-// Copyright 2019 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 (
-	"sort"
-	"strings"
-
-	"cuelang.org/go/cue/ast"
-	"cuelang.org/go/internal"
-)
-
-// This file includes functionality for parsing attributes.
-// These functions are slightly more permissive than the spec. Together with the
-// scanner and parser the full spec is implemented, though.
-
-// attributes is used to store per-key attribute text for a fields.
-// It deliberately does not implement the value interface, as it should
-// never act as a value in any way.
-type attributes struct {
-	attr []attr
-}
-type attr struct {
-	text   string
-	offset int
-}
-
-func (a *attr) key() string {
-	return a.text[1:a.offset]
-}
-
-func (a *attr) body() string {
-	return a.text[a.offset+1 : len(a.text)-1]
-}
-
-func createAttrs(ctx *context, src source, attrs []*ast.Attribute) (a *attributes, err *bottom) {
-	if len(attrs) == 0 {
-		return nil, nil
-	}
-	as := []attr{}
-	for _, a := range attrs {
-		index := strings.IndexByte(a.Text, '(')
-		n := len(a.Text)
-		if index < 2 || a.Text[0] != '@' || a.Text[n-1] != ')' {
-			return nil, ctx.mkErr(newNode(a), "invalid attribute %q", a.Text)
-		}
-		as = append(as, attr{a.Text[:n], index})
-
-		if err := internal.ParseAttrBody(src.Pos(), a.Text[index+1:n-1]).Err; err != nil {
-			return nil, ctx.mkErr(newNode(a), err)
-		}
-	}
-
-	sort.SliceStable(as, func(i, j int) bool { return as[i].text < as[j].text })
-	// TODO: remove these restrictions.
-	for i := 1; i < len(as); i++ {
-		if ai, aj := as[i-1], as[i]; ai.key() == aj.key() {
-			n := newNode(attrs[0])
-			return nil, ctx.mkErr(n, "multiple attributes for key %q", ai.key())
-		}
-	}
-
-	return &attributes{as}, nil
-}
-
-// unifyAttrs merges the attributes from a and b. It may return either a or b
-// if a and b are identical.
-func unifyAttrs(ctx *context, src source, a, b *attributes) (atrs *attributes, err evaluated) {
-	if a == b {
-		return a, nil
-	}
-	if a == nil {
-		return b, nil
-	}
-	if b == nil {
-		return a, nil
-	}
-
-	if len(a.attr) == len(b.attr) {
-		for i, x := range a.attr {
-			if x != b.attr[i] {
-				goto notSame
-			}
-		}
-		return a, nil
-	}
-
-notSame:
-	as := append(a.attr, b.attr...)
-
-	// remove duplicates and error on conflicts
-	sort.Slice(as, func(i, j int) bool { return as[i].text < as[j].text })
-	k := 0
-	for i := 1; i < len(as); i++ {
-		if ak, ai := as[k], as[i]; ak.key() == ai.key() {
-			if ak.body() == ai.body() {
-				continue
-			}
-			return nil, ctx.mkErr(src, "conflicting attributes for key %q", ai.key())
-		}
-		k++
-		as[k] = as[i]
-	}
-
-	return &attributes{as[:k+1]}, nil
-}
-
-// parsedAttr holds positional information for a single parsedAttr.
-type parsedAttr struct {
-	fields []keyValue
-}
-
-type keyValue struct {
-	data  string
-	equal int // index of equal sign or 0 if non-existing
-}
-
-func (kv *keyValue) text() string  { return kv.data }
-func (kv *keyValue) key() string   { return kv.data[:kv.equal] }
-func (kv *keyValue) value() string { return kv.data[kv.equal+1:] }
diff --git a/cue/attr_test.go b/cue/attr_test.go
deleted file mode 100644
index 3a929c4..0000000
--- a/cue/attr_test.go
+++ /dev/null
@@ -1,155 +0,0 @@
-// Copyright 2019 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 (
-	"reflect"
-	"strings"
-	"testing"
-
-	"cuelang.org/go/cue/ast"
-)
-
-func TestCreateAttrs(t *testing.T) {
-	testdata := []struct {
-		// space-separated lists of attributes
-		in, out string
-		err     string
-	}{{
-		in:  "@foo()",
-		out: "foo:",
-	}, {
-		in:  "@b(bb) @aaa(aa,)",
-		out: "aaa:aa, b:bb",
-	}, {
-		in:  "@b(a,",
-		err: "invalid attribute",
-	}, {
-		in:  "@b(foo) @b(foo)",
-		err: "attributes",
-	}, {
-		in:  "@b('' ,b)",
-		err: "invalid attribute",
-	}, {
-		in:  `@foo(,"bar")`,
-		out: `foo:,"bar"`,
-	}, {
-		in:  `@foo("bar",1)`,
-		out: `foo:"bar",1`,
-	}, {
-		in:  `@foo("bar")`,
-		out: `foo:"bar"`,
-	}, {
-		in:  `@foo(,"bar",1)`,
-		out: `foo:,"bar",1`,
-	}}
-	for _, tc := range testdata {
-		t.Run(tc.in, func(t *testing.T) {
-			a := []*ast.Attribute{}
-			for _, s := range strings.Split(tc.in, " ") {
-				a = append(a, &ast.Attribute{Text: s})
-			}
-			attrs, err := createAttrs(&context{}, baseValue{}, a)
-
-			if tc.err != "" {
-				if err == nil || !strings.Contains(debugStr(&context{}, err), tc.err) {
-					t.Errorf("error was %v; want %v", err, tc.err)
-				}
-				return
-			}
-			if err != nil {
-				t.Fatal(err)
-			}
-			sa := []string{}
-			for _, a := range attrs.attr {
-				sa = append(sa, a.key()+":"+a.body())
-			}
-			if got := strings.Join(sa, " "); got != tc.out {
-				t.Errorf("got %v; want %v", got, tc.out)
-			}
-		})
-	}
-}
-
-func TestUnifyAttrs(t *testing.T) {
-	parse := func(s string) *attributes {
-		a := []*ast.Attribute{}
-		for _, s := range strings.Split(s, " ") {
-			a = append(a, &ast.Attribute{Text: s})
-		}
-		attrs, _ := createAttrs(&context{}, baseValue{}, a)
-		return attrs
-	}
-	foo := parse("@foo()")
-
-	testdata := []struct {
-		// space-separated lists of attributes
-		a, b, out *attributes
-		err       string
-	}{{
-		a:   nil,
-		b:   nil,
-		out: nil,
-	}, {
-		a:   nil,
-		b:   foo,
-		out: foo,
-	}, {
-		a:   foo,
-		b:   nil,
-		out: foo,
-	}, {
-		a:   foo,
-		b:   foo,
-		out: foo,
-	}, {
-		a:   foo,
-		b:   parse("@bar()"),
-		out: parse("@bar() @foo()"),
-	}, {
-		a:   foo,
-		b:   parse("@bar() @foo()"),
-		out: parse("@bar() @foo()"),
-	}, {
-		a:   parse("@bar() @foo()"),
-		b:   parse("@foo() @bar()"),
-		out: parse("@bar() @foo()"),
-	}, {
-		a:   parse("@bar() @foo()"),
-		b:   parse("@foo() @baz()"),
-		out: parse("@bar() @baz() @foo()"),
-	}, {
-		a:   parse("@foo(ab)"),
-		b:   parse("@foo(cd)"),
-		err: `conflicting attributes for key "foo"`,
-	}}
-	for _, tc := range testdata {
-		t.Run("", func(t *testing.T) {
-			attrs, err := unifyAttrs(&context{}, baseValue{}, tc.a, tc.b)
-			if tc.err != "" {
-				if !strings.Contains(debugStr(&context{}, err), tc.err) {
-					t.Errorf("error was %v; want %v", err, tc.err)
-				}
-				return
-			}
-			if err != nil {
-				t.Fatal(err)
-			}
-			if !reflect.DeepEqual(attrs, tc.out) {
-				t.Errorf("\ngot:  %v;\nwant: %v", attrs, tc.out)
-			}
-		})
-	}
-}
diff --git a/cue/binop.go b/cue/binop.go
deleted file mode 100644
index a310bde..0000000
--- a/cue/binop.go
+++ /dev/null
@@ -1,1333 +0,0 @@
-// Copyright 2018 The 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 (
-	"bytes"
-	"fmt"
-	"math/big"
-	"regexp"
-	"sort"
-	"strings"
-	"time"
-
-	"github.com/cockroachdb/apd/v2"
-
-	"cuelang.org/go/cue/token"
-)
-
-// binSrc returns a baseValue representing a binary expression of the given
-// values.
-func binSrc(pos token.Pos, op op, a, b value) baseValue {
-	return baseValue{&computedSource{pos, op, a, b}}
-}
-
-func binOp(ctx *context, src source, op op, left, right evaluated) (result evaluated) {
-	_, isUnify := op.unifyType()
-	if b, ok := left.(*bottom); ok {
-		if isUnify && b.exprDepth == 0 && cycleError(b) != nil {
-			ctx.cycleErr = true
-			return right
-		}
-		return left
-	}
-	if b, ok := right.(*bottom); ok {
-		if isUnify && b.exprDepth == 0 && cycleError(b) != nil {
-			ctx.cycleErr = true
-			return left
-		}
-		return right
-	}
-
-	left = convertBuiltin(left)
-	right = convertBuiltin(right)
-
-	leftKind := left.Kind()
-	rightKind := right.Kind()
-	kind, invert, msg := matchBinOpKind(op, leftKind, rightKind)
-	if kind == bottomKind {
-		simplify := func(v, orig value) value {
-			switch x := v.(type) {
-			case *disjunction:
-				return orig
-			case *binaryExpr:
-				if x.Op == opDisjunction {
-					return orig
-				}
-			default:
-				return x
-			}
-			return v
-		}
-		var l, r value = left, right
-		if x, ok := src.(*binaryExpr); ok {
-			l = simplify(x.X, left)
-			r = simplify(x.Y, right)
-		}
-		return ctx.mkErr(src, msg, op, ctx.str(l), ctx.str(r), leftKind, rightKind)
-	}
-	if kind.hasReferences() {
-		panic("unexpected references in expression")
-	}
-	if invert {
-		left, right = right, left
-	}
-	if !isUnify {
-		// Any operation other than unification or disjunction must be on
-		// concrete types. Disjunction is handled separately.
-		if !leftKind.isGround() || !rightKind.isGround() {
-			return ctx.mkErr(src, codeIncomplete, "incomplete error")
-		}
-		ctx.incEvalDepth()
-		v := left.binOp(ctx, src, op, right) // may return incomplete
-		ctx.decEvalDepth()
-		return v
-	}
-
-	// isUnify
-
-	// TODO: unify type masks.
-	if left == right {
-		return left
-	}
-	if isTop(left) {
-		return right
-	}
-	if isTop(right) {
-		return left
-	}
-
-	if dl, ok := left.(*disjunction); ok {
-		return distribute(ctx, src, op, dl, right)
-	} else if dr, ok := right.(*disjunction); ok {
-		return distribute(ctx, src, op, dr, left)
-	}
-
-	if _, ok := right.(*unification); ok {
-		return right.binOp(ctx, src, op, left)
-	}
-
-	// TODO: value may be incomplete if there is a cycle. Instead of an error
-	// schedule an assert and return the atomic value, if applicable.
-	v := left.binOp(ctx, src, op, right)
-	if isBottom(v) {
-		v := right.binOp(ctx, src, op, left)
-		// Return the original failure if both fail, as this will result in
-		// better error messages.
-		if !isBottom(v) || isCustom(v) {
-			return v
-		}
-	}
-	return v
-}
-
-type mVal struct {
-	val  evaluated
-	mark bool
-}
-
-// distribute distributes a value over the element of a disjunction in a
-// unification operation.
-// TODO: this is an exponential algorithm. There is no reason to have to
-// resolve this early. Revise this to only do early pruning but not a full
-// evaluation.
-func distribute(ctx *context, src source, op op, x, y evaluated) evaluated {
-	dn := &disjunction{baseValue: src.base()}
-	dist(ctx, dn, false, op, mVal{x, true}, mVal{y, true})
-	return dn.normalize(ctx, src).val
-}
-
-func dist(ctx *context, d *disjunction, mark bool, op op, x, y mVal) {
-	if dx, ok := x.val.(*disjunction); ok {
-		if dx.HasDefaults {
-			mark = true
-			d.HasDefaults = true
-		}
-		for _, dxv := range dx.Values {
-			m := dxv.Default || !dx.HasDefaults
-			dist(ctx, d, mark, op, mVal{dxv.Val.evalPartial(ctx), m}, y)
-		}
-		return
-	}
-	if dy, ok := y.val.(*disjunction); ok {
-		if dy.HasDefaults {
-			mark = true
-			d.HasDefaults = true
-		}
-		for _, dxy := range dy.Values {
-			m := dxy.Default || !dy.HasDefaults
-			dist(ctx, d, mark, op, x, mVal{dxy.Val.evalPartial(ctx), m})
-		}
-		return
-	}
-	src := binSrc(token.NoPos, op, x.val, y.val)
-	d.add(ctx, binOp(ctx, src, op, x.val, y.val), mark && x.mark && y.mark)
-}
-
-func (x *disjunction) binOp(ctx *context, src source, op op, other evaluated) evaluated {
-	panic("unreachable: special-cased")
-}
-
-func (x *bottom) binOp(ctx *context, src source, op op, other evaluated) evaluated {
-	panic("unreachable: special-cased")
-}
-
-// add adds to a unification. Note that the value cannot be a struct and thus
-// there is no need to distinguish between checked and unchecked unification.
-func (x *unification) add(ctx *context, src source, v evaluated) evaluated {
-	for progress := true; progress; {
-		progress = false
-		k := 0
-
-		for i, vx := range x.Values {
-			a := binOp(ctx, src, opUnify, vx, v)
-			switch _, isUnify := a.(*unification); {
-			case isBottom(a):
-				if !isIncomplete(a) {
-					return a
-				}
-				fallthrough
-			case isUnify:
-				x.Values[k] = x.Values[i]
-				k++
-				continue
-			}
-			// k will not be raised in this iteration. So the outer loop
-			// will ultimately terminate as k reaches 0.
-			// In practice it is seems unlikely that there will be more than
-			// two iterations for any addition.
-			// progress = true
-			v = a
-		}
-		if k == 0 {
-			return v
-		}
-		x.Values = x.Values[:k]
-	}
-	x.Values = append(x.Values, v)
-	return nil
-}
-
-func (x *unification) binOp(ctx *context, src source, op op, other evaluated) evaluated {
-	if _, isUnify := op.unifyType(); isUnify {
-		// Cannot be checked unification.
-		u := &unification{baseValue: baseValue{src}}
-		u.Values = append(u.Values, x.Values...)
-		if y, ok := other.(*unification); ok {
-			for _, vy := range y.Values {
-				if v := u.add(ctx, src, vy); v != nil {
-					return v
-				}
-			}
-		} else if v := u.add(ctx, src, other); v != nil {
-			return v
-		}
-		return u
-	}
-	return ctx.mkIncompatible(src, op, x, other)
-}
-
-func (x *top) binOp(ctx *context, src source, op op, other evaluated) evaluated {
-	switch op {
-	case opUnify, opUnifyUnchecked:
-		return other
-	}
-	src = mkBin(ctx, src.Pos(), op, x, other)
-	return ctx.mkErr(src, codeIncomplete, "binary operation on (incomplete) top value")
-}
-
-func (x *basicType) binOp(ctx *context, src source, op op, other evaluated) evaluated {
-	k := unifyType(x.Kind(), other.Kind())
-	switch y := other.(type) {
-	case *basicType:
-		switch op {
-		// TODO: other types.
-		case opUnify, opUnifyUnchecked:
-			if k&typeKinds != bottomKind {
-				return &basicType{binSrc(src.Pos(), op, x, other), k & typeKinds}
-			}
-		}
-
-	case *bound:
-		src = mkBin(ctx, src.Pos(), op, x, other)
-		return ctx.mkErr(src, codeIncomplete, "%s with incomplete values", op)
-
-	case *numLit:
-		if op == opUnify || op == opUnifyUnchecked {
-			if k == y.K {
-				return y
-			}
-			return y.specialize(k)
-		}
-		src = mkBin(ctx, src.Pos(), op, x, other)
-		return ctx.mkErr(src, codeIncomplete, "%s with incomplete values", op)
-
-	default:
-		if k&typeKinds != bottomKind {
-			return other
-		}
-	}
-	return ctx.mkIncompatible(src, op, x, other)
-}
-
-func checkBounds(ctx *context, src source, r *bound, op op, a, b evaluated) evaluated {
-	v := binOp(ctx, src, op, a, b)
-	if isBottom(v) || !v.(*boolLit).B {
-		return errOutOfBounds(ctx, src.Pos(), r, a)
-	}
-	return nil
-}
-
-func errOutOfBounds(ctx *context, pos token.Pos, r *bound, v evaluated) *bottom {
-	if pos == token.NoPos {
-		pos = r.Pos()
-	}
-	e := mkBin(ctx, pos, opUnify, r, v)
-	msg := "invalid value %v (out of bound %v)"
-	switch r.Op {
-	case opNeq, opNMat:
-		msg = "invalid value %v (excluded by %v)"
-	case opMat:
-		msg = "invalid value %v (does not match %v)"
-	}
-	return ctx.mkErr(e, msg, ctx.str(v), ctx.str(r))
-}
-
-func opInfo(op op) (cmp op, norm int) {
-	switch op {
-	case opGtr:
-		return opGeq, 1
-	case opGeq:
-		return opGtr, 1
-	case opLss:
-		return opLeq, -1
-	case opLeq:
-		return opLss, -1
-	case opNeq:
-		return opNeq, 0
-	case opMat:
-		return opMat, 2
-	case opNMat:
-		return opNMat, 3
-	}
-	panic("cue: unreachable")
-}
-
-func (x *bound) binOp(ctx *context, src source, op op, other evaluated) evaluated {
-	xv := x.Expr.(evaluated)
-
-	newSrc := binSrc(src.Pos(), op, x, other)
-	switch op {
-	case opUnify, opUnifyUnchecked:
-		k, _, msg := matchBinOpKind(opUnify, x.Kind(), other.Kind())
-		if k == bottomKind {
-			return ctx.mkErr(src, msg, opUnify, ctx.str(x), ctx.str(other), x.Kind(), other.Kind())
-		}
-		switch y := other.(type) {
-		case *basicType:
-			k := unifyType(x.k, y.Kind())
-			if k == x.k {
-				return x
-			}
-			return newBound(ctx, newSrc.base(), x.Op, k, xv)
-
-		case *bound:
-			yv := y.Expr.(evaluated)
-			if !xv.Kind().isGround() || !yv.Kind().isGround() {
-				return ctx.mkErr(newSrc, codeIncomplete, "cannot add incomplete values")
-			}
-
-			cmp, xCat := opInfo(x.Op)
-			_, yCat := opInfo(y.Op)
-
-			switch {
-			case xCat == yCat:
-				if x.Op == opNeq || x.Op == opMat || x.Op == opNMat {
-					if test(ctx, x, opEql, xv, yv) {
-						return x
-					}
-					break // unify the two bounds
-				}
-
-				// xCat == yCat && x.op != opNeq
-				// > a & >= b
-				//    > a   if a >= b
-				//    >= b  if a <  b
-				// > a & > b
-				//    > a   if a >= b
-				//    > b   if a <  b
-				// >= a & > b
-				//    >= a   if a > b
-				//    > b    if a <= b
-				// >= a & >= b
-				//    >= a   if a > b
-				//    >= b   if a <= b
-				// inverse is true as well.
-
-				// Tighten bound.
-				if test(ctx, x, cmp, xv, yv) {
-					return x
-				}
-				return y
-
-			case xCat == -yCat:
-				if xCat == -1 {
-					x, y = y, x
-				}
-				a, aOK := x.Expr.(evaluated).(*numLit)
-				b, bOK := y.Expr.(evaluated).(*numLit)
-
-				if !aOK || !bOK {
-					break
-				}
-
-				var d, lo, hi apd.Decimal
-				lo.Set(&a.X)
-				hi.Set(&b.X)
-				if k&floatKind == 0 {
-					// Readjust bounds for integers.
-					if x.Op == opGeq {
-						// >=3.4  ==>  >=4
-						_, _ = apd.BaseContext.Ceil(&lo, &a.X)
-					} else {
-						// >3.4  ==>  >3
-						_, _ = apd.BaseContext.Floor(&lo, &a.X)
-					}
-					if y.Op == opLeq {
-						// <=2.3  ==>  <= 2
-						_, _ = apd.BaseContext.Floor(&hi, &b.X)
-					} else {
-						// <2.3   ==>  < 3
-						_, _ = apd.BaseContext.Ceil(&hi, &b.X)
-					}
-				}
-
-				cond, err := apd.BaseContext.Sub(&d, &hi, &lo)
-				if cond.Inexact() || err != nil {
-					break
-				}
-
-				// attempt simplification
-				// numbers
-				// >=a & <=b
-				//     a   if a == b
-				//     _|_ if a < b
-				// >=a & <b
-				//     _|_ if b <= a
-				// >a  & <=b
-				//     _|_ if b <= a
-				// >a  & <b
-				//     _|_ if b <= a
-
-				// integers
-				// >=a & <=b
-				//     a   if b-a == 0
-				//     _|_ if a < b
-				// >=a & <b
-				//     a   if b-a == 1
-				//     _|_ if b <= a
-				// >a  & <=b
-				//     b   if b-a == 1
-				//     _|_ if b <= a
-				// >a  & <b
-				//     a+1 if b-a == 2
-				//     _|_ if b <= a
-
-				n := newNum(src, k&numKind, a.rep|b.rep)
-				switch diff, err := d.Int64(); {
-				case err != nil:
-
-				case diff == 1:
-					if k&floatKind == 0 {
-						if x.Op == opGeq && y.Op == opLss {
-							return n.set(&lo)
-						}
-						if x.Op == opGtr && y.Op == opLeq {
-							return n.set(&hi)
-						}
-					}
-
-				case diff == 2:
-					if k&floatKind == 0 && x.Op == opGtr && y.Op == opLss {
-						_, _ = apd.BaseContext.Add(&d, d.SetInt64(1), &lo)
-						return n.set(&d)
-
-					}
-
-				case diff == 0:
-					if x.Op == opGeq && y.Op == opLeq {
-						return n.set(&lo)
-					}
-					fallthrough
-
-				case d.Negative:
-					return ctx.mkErr(newSrc, "conflicting bounds %v and %v",
-						ctx.str(x), ctx.str(y))
-				}
-
-			case x.Op == opNeq:
-				if !test(ctx, x, y.Op, xv, yv) {
-					return y
-				}
-
-			case y.Op == opNeq:
-				if !test(ctx, x, x.Op, yv, xv) {
-					return x
-				}
-			}
-			return &unification{newSrc, []evaluated{x, y}}
-
-		case *numLit:
-			if err := checkBounds(ctx, src, x, x.Op, y, xv); err != nil {
-				return err
-			}
-			// Narrow down number type.
-			if y.K != k {
-				return y.specialize(k)
-			}
-			return other
-
-		case *nullLit, *boolLit, *durationLit, *list, *structLit, *stringLit, *bytesLit:
-			// All remaining concrete types. This includes non-comparable types
-			// for comparison to null.
-			if err := checkBounds(ctx, src, x, x.Op, y, xv); err != nil {
-				return err
-			}
-			return y
-		}
-	}
-	return ctx.mkIncompatible(src, op, x, other)
-}
-
-func (x *customValidator) binOp(ctx *context, src source, op op, other evaluated) evaluated {
-	newSrc := binSrc(src.Pos(), op, x, other)
-	switch op {
-	case opUnify, opUnifyUnchecked:
-		k, _, msg := matchBinOpKind(opUnify, x.Kind(), other.Kind())
-		if k == bottomKind {
-			return ctx.mkErr(src, msg, op, ctx.str(x), ctx.str(other), x.Kind(), other.Kind())
-		}
-		switch y := other.(type) {
-		case *basicType:
-			k := unifyType(x.Kind(), y.Kind())
-			if k == x.Kind() {
-				return x
-			}
-			return &unification{newSrc, []evaluated{x, y}}
-
-		case *customValidator:
-			return &unification{newSrc, []evaluated{x, y}}
-
-		case *bound:
-			return &unification{newSrc, []evaluated{x, y}}
-
-		case *numLit:
-			if err := x.check(ctx, y); err != nil {
-				return err
-			}
-			// Narrow down number type.
-			if y.K != k {
-				return y.specialize(k)
-			}
-			return other
-
-		case *nullLit, *boolLit, *durationLit, *list, *structLit, *stringLit, *bytesLit:
-			// All remaining concrete types. This includes non-comparable types
-			// for comparison to null.
-			if err := x.check(ctx, y); err != nil {
-				return err
-			}
-			return y
-		}
-	}
-	return ctx.mkErr(src, "invalid operation %v and %v (operator not defined for custom validator)", ctx.str(x), ctx.str(other))
-}
-
-func (x *customValidator) check(ctx *context, v evaluated) evaluated {
-	args := make([]evaluated, 1+len(x.Args))
-	args[0] = v
-	for i, v := range x.Args {
-		args[1+i] = v.(evaluated)
-	}
-	res := x.Builtin.call(ctx, x, args...)
-	if isBottom(res) {
-		return res.(evaluated)
-	}
-	if b, ok := res.(*boolLit); !ok {
-		// should never reach here
-		return ctx.mkErr(x, "invalid custom validator")
-	} else if !b.B {
-		var buf bytes.Buffer
-		fmt.Fprintf(&buf, "%s.%s", ctx.LabelStr(x.Builtin.pkg), x.Builtin.Name)
-		buf.WriteString("(")
-		for _, a := range x.Args {
-			buf.WriteString(ctx.str(a))
-		}
-		buf.WriteString(")")
-		return ctx.mkErr(x, "invalid value %s (does not satisfy %s)", ctx.str(v), buf.String())
-	}
-	return nil
-}
-
-func evalLambda(ctx *context, a value, finalize bool) (l *lambdaExpr, err evaluated) {
-	if a == nil {
-		return nil, nil
-	}
-	// NOTE: the values of a lambda might still be a disjunction
-	e := ctx.manifest(a)
-	if isBottom(e) {
-		return nil, e
-	}
-	l, ok := e.(*lambdaExpr)
-	if !ok {
-		return nil, ctx.mkErr(a, "value must be lambda")
-	}
-	lambda := ctx.deref(l).(*lambdaExpr)
-	if finalize {
-		lambda.value = wrapFinalize(ctx, lambda.value)
-	}
-	return lambda, nil
-}
-
-func (x *structLit) binOp(ctx *context, src source, op op, other evaluated) evaluated {
-	y, ok := other.(*structLit)
-	unchecked, isUnify := op.unifyType()
-	if !ok || !isUnify {
-		return ctx.mkIncompatible(src, op, x, other)
-	}
-
-	// TODO: unify emit
-
-	x = ctx.deref(x).(*structLit)
-	y = ctx.deref(y).(*structLit)
-	if x == y {
-		return x
-	}
-	arcs := make(arcs, 0, len(x.Arcs)+len(y.Arcs))
-	var base baseValue
-	if src.computed() != nil {
-		base = baseValue{src.computed()}
-	} else {
-		base = binSrc(src.Pos(), op, x, other)
-	}
-	obj := &structLit{
-		base,                          // baseValue
-		x.emit,                        // emit
-		nil,                           // template
-		x.closeStatus | y.closeStatus, // closeStatus
-		nil,                           // comprehensions
-		arcs,                          // arcs
-		nil,                           // attributes
-	}
-	defer ctx.pushForwards(x, obj, y, obj).popForwards()
-
-	optionals, err := unifyOptionals(ctx, src, op, x, y)
-	if err != nil {
-		return err
-	}
-	obj.optionals = optionals
-
-	// If unifying with a closed struct that does not have a template,
-	// we need to apply the template to all elements.
-
-	sz := len(x.comprehensions) + len(y.comprehensions)
-	obj.comprehensions = make([]compValue, sz)
-	for i, c := range x.comprehensions {
-		obj.comprehensions[i] = compValue{
-			checked: c.checked || (!unchecked && y.isClosed()),
-			comp:    ctx.copy(c.comp),
-		}
-	}
-	for i, c := range y.comprehensions {
-		obj.comprehensions[i+len(x.comprehensions)] = compValue{
-			checked: c.checked || (!unchecked && x.isClosed()),
-			comp:    ctx.copy(c.comp),
-		}
-	}
-
-	for _, a := range x.Arcs {
-		found := false
-		for _, b := range y.Arcs {
-			if a.Label == b.Label {
-				found = true
-				break
-			}
-		}
-		if !unchecked && !found && !y.allows(ctx, a.Label) && !a.definition {
-			if a.optional {
-				continue
-			}
-			// TODO: pass position of key, not value. Currently does not have
-			// a position.
-			return ctx.mkErr(a.v, a.v, "field %q not allowed in closed struct",
-				ctx.LabelStr(a.Label))
-		}
-		cp := ctx.copy(a.v)
-		obj.Arcs = append(obj.Arcs,
-			arc{a.Label, a.optional, a.definition, cp, nil, a.attrs, a.docs})
-	}
-outer:
-	for _, a := range y.Arcs {
-		v := ctx.copy(a.v)
-		found := false
-		for i, b := range obj.Arcs {
-			if a.Label == b.Label {
-				found = true
-				if a.definition != b.definition {
-					src := binSrc(x.Pos(), op, a.v, b.v)
-					return ctx.mkErr(src, "field %q declared as definition and regular field",
-						ctx.LabelStr(a.Label))
-				}
-				w := b.v
-				if x.closeStatus.shouldFinalize() {
-					w = wrapFinalize(ctx, w)
-				}
-				if y.closeStatus.shouldFinalize() {
-					v = wrapFinalize(ctx, v)
-				}
-				v = mkBin(ctx, src.Pos(), op, w, v)
-				obj.Arcs[i].v = v
-				obj.Arcs[i].Value = nil
-				obj.Arcs[i].optional = a.optional && b.optional
-				obj.Arcs[i].docs = mergeDocs(a.docs, b.docs)
-				attrs, err := unifyAttrs(ctx, src, a.attrs, b.attrs)
-				if err != nil {
-					return err
-				}
-				obj.Arcs[i].attrs = attrs
-				continue outer
-			}
-		}
-		if !unchecked && !found && !x.allows(ctx, a.Label) && !a.definition {
-			if a.optional {
-				continue
-			}
-			// TODO: pass position of key, not value. Currently does not have a
-			// position.
-			return ctx.mkErr(a.v, x, "field %q not allowed in closed struct",
-				ctx.LabelStr(a.Label))
-		}
-		a.setValue(v)
-		obj.Arcs = append(obj.Arcs, a)
-	}
-	sort.Stable(obj)
-
-	if unchecked && obj.optionals.isFull() {
-		obj.closeStatus.unclose()
-	}
-
-	return obj
-}
-
-func (x *structLit) rewriteOpt(ctx *context) (*optionals, evaluated) {
-	fn := func(v value) value {
-		if l, ok := v.(*lambdaExpr); ok {
-			l, err := evalLambda(ctx, l, x.closeStatus.shouldFinalize())
-			if err != nil {
-				return err
-			}
-			v = l
-		}
-		return ctx.copy(v)
-	}
-	c, err := x.optionals.rewrite(fn)
-	if err != nil {
-		return c, err
-	}
-	return c, nil
-}
-
-func unifyOptionals(ctx *context, src source, op op, x, y *structLit) (o *optionals, err evaluated) {
-	if x.optionals == nil && y.optionals == nil {
-		return nil, nil
-	}
-	left, err := x.rewriteOpt(ctx)
-	if err != nil {
-		return left, err
-	}
-	right, err := y.rewriteOpt(ctx)
-	if err != nil {
-		return right, err
-	}
-
-	closeStatus := x.closeStatus | y.closeStatus
-	switch {
-	case left.isDotDotDot() && right.isDotDotDot():
-
-	case left == nil && (!x.closeStatus.isClosed() || op == opUnifyUnchecked):
-		return right, nil
-
-	case right == nil && (!y.closeStatus.isClosed() || op == opUnifyUnchecked):
-		return left, nil
-
-	case op == opUnify && closeStatus.isClosed(),
-		left != nil && (left.left != nil || left.right != nil),
-		right != nil && (right.left != nil || right.right != nil):
-		return &optionals{closeStatus, op, left, right, nil}, nil
-	}
-
-	// opUnify where both structs are open or opUnifyUnchecked
-	for _, f := range right.fields {
-		left.add(ctx, f.key, f.value)
-	}
-	return left, nil
-}
-
-func (x *nullLit) binOp(ctx *context, src source, op op, other evaluated) evaluated {
-	// TODO: consider using binSrc instead of src.base() for better traceability.
-	switch other.(type) {
-	case *nullLit:
-		switch op {
-		case opEql:
-			return &boolLit{baseValue: src.base(), B: true}
-		case opNeq:
-			return &boolLit{baseValue: src.base(), B: false}
-		case opUnify, opUnifyUnchecked:
-			return x
-		}
-
-	case *bound:
-		// Not strictly necessary, but handling this results in better error
-		// messages.
-		if op == opUnify || op == opUnifyUnchecked {
-			return other.binOp(ctx, src, opUnify, x)
-		}
-
-	default:
-		switch op {
-		case opEql:
-			return &boolLit{baseValue: src.base(), B: false}
-		case opNeq:
-			return &boolLit{baseValue: src.base(), B: true}
-		}
-	}
-	return ctx.mkIncompatible(src, op, x, other)
-}
-
-func (x *boolLit) binOp(ctx *context, src source, op op, other evaluated) evaluated {
-	switch y := other.(type) {
-	case *basicType:
-		// range math
-		return x
-
-	case *boolLit:
-		switch op {
-		case opUnify, opUnifyUnchecked:
-			if x.B != y.B {
-				return ctx.mkErr(x, "conflicting values %v and %v", x.B, y.B)
-			}
-			return x
-		case opLand:
-			return boolTonode(src, x.B && y.B)
-		case opLor:
-			return boolTonode(src, x.B || y.B)
-		case opEql:
-			return boolTonode(src, x.B == y.B)
-		case opNeq:
-			return boolTonode(src, x.B != y.B)
-		}
-	}
-	return ctx.mkIncompatible(src, op, x, other)
-}
-
-func (x *stringLit) binOp(ctx *context, src source, op op, other evaluated) evaluated {
-	switch y := other.(type) {
-	// case *basicType:
-	// 	return x
-
-	// TODO: rangelit
-
-	case *stringLit:
-		str := other.strValue()
-		switch op {
-		case opUnify, opUnifyUnchecked:
-			str := other.strValue()
-			if x.Str != str {
-				src := mkBin(ctx, src.Pos(), op, x, other)
-				return ctx.mkErr(src, "conflicting values %v and %v",
-					ctx.str(x), ctx.str(y))
-			}
-			return x
-		case opLss, opLeq, opEql, opNeq, opGeq, opGtr:
-			return cmpTonode(src, op, strings.Compare(x.Str, str))
-		case opAdd:
-			src := binSrc(src.Pos(), op, x, other)
-			return &stringLit{src, x.Str + str, nil}
-		case opMat:
-			if y.RE == nil {
-				// This really should not happen, but leave in for safety.
-				b, err := regexp.MatchString(str, x.Str)
-				if err != nil {
-					return ctx.mkErr(src, "error parsing regexp: %v", err)
-				}
-				return boolTonode(src, b)
-			}
-			return boolTonode(src, y.RE.MatchString(x.Str))
-		case opNMat:
-			if y.RE == nil {
-				// This really should not happen, but leave in for safety.
-				b, err := regexp.MatchString(str, x.Str)
-				if err != nil {
-					return ctx.mkErr(src, "error parsing regexp: %v", err)
-				}
-				return boolTonode(src, !b)
-			}
-			return boolTonode(src, !y.RE.MatchString(x.Str))
-		}
-	case *numLit:
-		switch op {
-		case opMul:
-			src := binSrc(src.Pos(), op, x, other)
-			return &stringLit{src, strings.Repeat(x.Str, y.intValue(ctx)), nil}
-		}
-	}
-	return ctx.mkIncompatible(src, op, x, other)
-}
-
-func (x *bytesLit) binOp(ctx *context, src source, op op, other evaluated) evaluated {
-	switch y := other.(type) {
-	// case *basicType:
-	// 	return x
-
-	// TODO: rangelit
-
-	case *bytesLit:
-		b := y.B
-		switch op {
-		case opUnify, opUnifyUnchecked:
-			if !bytes.Equal(x.B, b) {
-				return ctx.mkErr(x, "conflicting values %v and %v",
-					ctx.str(x), ctx.str(y))
-			}
-			return x
-		case opLss, opLeq, opEql, opNeq, opGeq, opGtr:
-			return cmpTonode(src, op, bytes.Compare(x.B, b))
-		case opAdd:
-			copy := append([]byte(nil), x.B...)
-			copy = append(copy, b...)
-			return &bytesLit{binSrc(src.Pos(), op, x, other), copy, nil}
-		}
-
-	case *numLit:
-		switch op {
-		case opMul:
-			src := binSrc(src.Pos(), op, x, other)
-			return &bytesLit{src, bytes.Repeat(x.B, y.intValue(ctx)), nil}
-		}
-	}
-	return ctx.mkIncompatible(src, op, x, other)
-}
-
-func test(ctx *context, src source, op op, a, b evaluated) bool {
-	v := binOp(ctx, src, op, a, b)
-	if isBottom(v) {
-		return false
-	}
-	return v.(*boolLit).B
-}
-
-func leq(ctx *context, src source, a, b evaluated) bool {
-	if isTop(a) || isTop(b) {
-		return true
-	}
-	v := binOp(ctx, src, opLeq, a, b)
-	if isBottom(v) {
-		return false
-	}
-	return v.(*boolLit).B
-}
-
-// TODO: should these go?
-func maxNum(v value) value {
-	switch x := v.(type) {
-	case *numLit:
-		return x
-	case *bound:
-		switch x.Op {
-		case opLeq:
-			return x.Expr
-		case opLss:
-			return &binaryExpr{x.baseValue, opSub, x.Expr, one}
-		}
-		return &basicType{x.baseValue, intKind}
-	}
-	return v
-}
-
-func minNum(v value) value {
-	switch x := v.(type) {
-	case *numLit:
-		return x
-	case *bound:
-		switch x.Op {
-		case opGeq:
-			return x.Expr
-		case opGtr:
-			return &binaryExpr{x.baseValue, opAdd, x.Expr, one}
-		}
-		return &basicType{x.baseValue, intKind}
-	}
-	return v
-}
-
-func cmpTonode(src source, op op, r int) evaluated {
-	result := false
-	switch op {
-	case opLss:
-		result = r == -1
-	case opLeq:
-		result = r != 1
-	case opEql, opUnify, opUnifyUnchecked:
-		result = r == 0
-	case opNeq:
-		result = r != 0
-	case opGeq:
-		result = r != -1
-	case opGtr:
-		result = r == 1
-	}
-	return boolTonode(src, result)
-}
-
-func (x *numLit) binOp(ctx *context, src source, op op, other evaluated) evaluated {
-	switch y := other.(type) {
-	case *basicType, *bound, *customValidator: // for better error reporting
-		if op == opUnify || op == opUnifyUnchecked {
-			return y.binOp(ctx, src, op, x)
-		}
-	case *numLit:
-		k, _, _ := matchBinOpKind(op, x.Kind(), y.Kind())
-		if k == bottomKind {
-			break
-		}
-		switch op {
-		case opLss, opLeq, opEql, opNeq, opGeq, opGtr:
-			return cmpTonode(src, op, x.X.Cmp(&y.X))
-		}
-		n := newNum(src.base(), k, x.rep|y.rep)
-		switch op {
-		case opUnify, opUnifyUnchecked:
-			if x.X.Cmp(&y.X) != 0 {
-				src = mkBin(ctx, src.Pos(), op, x, other)
-				return ctx.mkErr(src, "conflicting values %v and %v",
-					ctx.str(x), ctx.str(y))
-			}
-			if k != x.K {
-				n.X = x.X
-				return n
-			}
-			return x
-		case opAdd:
-			_, _ = ctx.Add(&n.X, &x.X, &y.X)
-		case opSub:
-			_, _ = ctx.Sub(&n.X, &x.X, &y.X)
-		case opMul:
-			_, _ = ctx.Mul(&n.X, &x.X, &y.X)
-		case opQuo:
-			cond, err := ctx.Quo(&n.X, &x.X, &y.X)
-			if err != nil {
-				return ctx.mkErr(src, err.Error())
-			}
-			if cond.DivisionByZero() {
-				return ctx.mkErr(src, "division by zero")
-			}
-			n.K = floatKind
-		case opIDiv:
-			if y.X.IsZero() {
-				return ctx.mkErr(src, "division by zero")
-			}
-			intOp(ctx, n, (*big.Int).Div, x, y)
-		case opIMod:
-			if y.X.IsZero() {
-				return ctx.mkErr(src, "division by zero")
-			}
-			intOp(ctx, n, (*big.Int).Mod, x, y)
-		case opIQuo:
-			if y.X.IsZero() {
-				return ctx.mkErr(src, "division by zero")
-			}
-			intOp(ctx, n, (*big.Int).Quo, x, y)
-		case opIRem:
-			if y.X.IsZero() {
-				return ctx.mkErr(src, "division by zero")
-			}
-			intOp(ctx, n, (*big.Int).Rem, x, y)
-		}
-		return n
-
-	case *durationLit:
-		if op == opMul {
-			fd := float64(y.d)
-			// TODO: check range
-			f, _ := x.X.Float64()
-			d := time.Duration(f * fd)
-			return &durationLit{binSrc(src.Pos(), op, x, other), d}
-		}
-	}
-	return ctx.mkIncompatible(src, op, x, other)
-}
-
-type intFunc func(z, x, y *big.Int) *big.Int
-
-func intOp(ctx *context, n *numLit, fn intFunc, a, b *numLit) {
-	var x, y apd.Decimal
-	_, _ = ctx.RoundToIntegralValue(&x, &a.X)
-	if x.Negative {
-		x.Coeff.Neg(&x.Coeff)
-	}
-	_, _ = ctx.RoundToIntegralValue(&y, &b.X)
-	if y.Negative {
-		y.Coeff.Neg(&y.Coeff)
-	}
-	fn(&n.X.Coeff, &x.Coeff, &y.Coeff)
-	if n.X.Coeff.Sign() < 0 {
-		n.X.Coeff.Neg(&n.X.Coeff)
-		n.X.Negative = true
-	}
-	n.K = intKind
-}
-
-// TODO: check overflow
-
-func (x *durationLit) binOp(ctx *context, src source, op op, other evaluated) evaluated {
-	switch y := other.(type) {
-	case *basicType:
-		// infinity math
-
-	case *durationLit:
-		switch op {
-		case opUnify, opUnifyUnchecked:
-			if x.d != y.d {
-				return ctx.mkIncompatible(src, op, x, other)
-			}
-			return other
-		case opLss:
-			return boolTonode(src, x.d < y.d)
-		case opLeq:
-			return boolTonode(src, x.d <= y.d)
-		case opEql:
-			return boolTonode(src, x.d == y.d)
-		case opNeq:
-			return boolTonode(src, x.d != y.d)
-		case opGeq:
-			return boolTonode(src, x.d >= y.d)
-		case opGtr:
-			return boolTonode(src, x.d > y.d)
-		case opAdd:
-			return &durationLit{binSrc(src.Pos(), op, x, other), x.d + y.d}
-		case opSub:
-			return &durationLit{binSrc(src.Pos(), op, x, other), x.d - y.d}
-		case opQuo:
-			n := newFloat(src.base(), base10).setInt64(int64(x.d))
-			d := apd.New(int64(y.d), 0)
-			// TODO: check result if this code becomes undead.
-			_, _ = ctx.Quo(&n.X, &n.X, d)
-			return n
-		case opIRem:
-			n := newInt(src.base(), base10).setInt64(int64(x.d % y.d))
-			n.X.Exponent = -9
-			return n
-		}
-
-	case *numLit:
-		switch op {
-		case opMul:
-			// TODO: check range
-			f, _ := y.X.Float64()
-			d := time.Duration(float64(x.d) * f)
-			return &durationLit{binSrc(src.Pos(), op, x, other), d}
-		case opQuo:
-			// TODO: check range
-			f, _ := y.X.Float64()
-			d := time.Duration(float64(x.d) * f)
-			return &durationLit{binSrc(src.Pos(), op, x, other), d}
-		case opIRem:
-			d := x.d % time.Duration(y.intValue(ctx))
-			return &durationLit{binSrc(src.Pos(), op, x, other), d}
-		}
-	}
-	return ctx.mkIncompatible(src, op, x, other)
-}
-
-func (x *list) binOp(ctx *context, src source, op op, other evaluated) evaluated {
-	switch op {
-	case opUnify, opUnifyUnchecked:
-		y, ok := other.(*list)
-		if !ok {
-			break
-		}
-
-		n := binOp(ctx, src, op, x.len.(evaluated), y.len.(evaluated))
-		if isBottom(n) {
-			src = mkBin(ctx, src.Pos(), op, x, other)
-			return ctx.mkErr(src, "conflicting list lengths: %v", n)
-		}
-		sx := x.elem.Arcs
-		xa := sx
-		sy := y.elem.Arcs
-		ya := sy
-		for len(xa) < len(ya) {
-			xa = append(xa, arc{Label: label(len(xa)), v: x.typ})
-		}
-		for len(ya) < len(xa) {
-			ya = append(ya, arc{Label: label(len(ya)), v: y.typ})
-		}
-
-		typ := x.typ
-		max, ok := n.(*numLit)
-		if !ok || len(xa) < max.intValue(ctx) {
-			typ = mkBin(ctx, src.Pos(), op, x.typ, y.typ)
-		}
-
-		// TODO: use forwarding instead of this mild hack.
-		x.elem.Arcs = xa
-		y.elem.Arcs = ya
-		s := binOp(ctx, src, op, x.elem, y.elem).(*structLit)
-		x.elem.Arcs = sx
-		y.elem.Arcs = sy
-
-		base := binSrc(src.Pos(), op, x, other)
-		return &list{baseValue: base, elem: s, typ: typ, len: n}
-
-	case opEql, opNeq:
-		y, ok := other.(*list)
-		if !ok {
-			break
-		}
-		if len(x.elem.Arcs) != len(y.elem.Arcs) {
-			return boolTonode(src, false)
-		}
-		for i := range x.elem.Arcs {
-			if !test(ctx, src, op, x.at(ctx, i), y.at(ctx, i)) {
-				return boolTonode(src, false)
-			}
-		}
-		return boolTonode(src, true)
-
-	case opAdd:
-		y, ok := other.(*list)
-		if !ok {
-			break
-		}
-		n := &list{baseValue: binSrc(src.Pos(), op, x, other), typ: y.typ}
-		arcs := []arc{}
-		for _, v := range x.elem.Arcs {
-			arcs = append(arcs, arc{Label: label(len(arcs)), v: v.v})
-		}
-		for _, v := range y.elem.Arcs {
-			arcs = append(arcs, arc{Label: label(len(arcs)), v: v.v})
-		}
-		switch v := y.len.(type) {
-		case *numLit:
-			// Closed list
-			n.len = newInt(v.base(), v.rep).setInt(len(arcs))
-		default:
-			// Open list
-			n.len = y.len // TODO: add length of x?
-		}
-		n.elem = &structLit{baseValue: n.baseValue, Arcs: arcs}
-		return n
-
-	case opMul:
-		k := other.Kind()
-		if !k.isAnyOf(intKind) {
-			panic("multiplication must be int type")
-		}
-		n := &list{baseValue: binSrc(src.Pos(), op, x, other), typ: x.typ}
-		arcs := []arc{}
-		if len(x.elem.Arcs) > 0 {
-			if !k.isGround() {
-				// should never reach here.
-				break
-			}
-			if ln := other.(*numLit).intValue(ctx); ln > 0 {
-				for i := 0; i < ln; i++ {
-					// TODO: copy values
-					for _, a := range x.elem.Arcs {
-						arcs = append(arcs, arc{Label: label(len(arcs)), v: a.v})
-					}
-				}
-			} else if ln < 0 {
-				return ctx.mkErr(src, "negative number %d multiplies list", ln)
-			}
-		}
-		switch v := x.len.(type) {
-		case *numLit:
-			// Closed list
-			n.len = newInt(v.base(), v.rep).setInt(len(arcs))
-		default:
-			// Open list
-			n.len = x.len // TODO: multiply length?
-		}
-		n.elem = &structLit{baseValue: n.baseValue, Arcs: arcs}
-		return n
-	}
-	return ctx.mkIncompatible(src, op, x, other)
-}
-
-func (x *lambdaExpr) binOp(ctx *context, src source, op op, other evaluated) evaluated {
-	if y, ok := other.(*lambdaExpr); ok && op == opUnify {
-		x = ctx.deref(x).(*lambdaExpr)
-		y = ctx.deref(y).(*lambdaExpr)
-		n, m := len(x.params.arcs), len(y.params.arcs)
-		if n != m {
-			src = mkBin(ctx, src.Pos(), op, x, other)
-			return ctx.mkErr(src, "number of params should match (%d != %d)", n, m)
-		}
-		arcs := make([]arc, len(x.arcs))
-		lambda := &lambdaExpr{binSrc(src.Pos(), op, x, other), &params{arcs}, nil}
-		defer ctx.pushForwards(x, lambda, y, lambda).popForwards()
-
-		xVal := ctx.copy(x.value)
-		yVal := ctx.copy(y.value)
-		lambda.value = mkBin(ctx, src.Pos(), opUnify, xVal, yVal)
-
-		for i := range arcs {
-			xArg := ctx.copy(x.at(ctx, i)).(evaluated)
-			yArg := ctx.copy(y.at(ctx, i)).(evaluated)
-			v := binOp(ctx, src, op, xArg, yArg)
-			if isBottom(v) {
-				return v
-			}
-			arcs[i] = arc{Label: x.arcs[i].Label, v: v}
-		}
-
-		return lambda
-	}
-	return ctx.mkIncompatible(src, op, x, other)
-}
-
-func (x *builtin) binOp(ctx *context, src source, op op, other evaluated) evaluated {
-	if _, isUnify := op.unifyType(); isUnify && evaluated(x) == other {
-		return x
-	}
-	return ctx.mkIncompatible(src, op, x, other)
-}
-
-func (x *feed) binOp(ctx *context, src source, op op, other evaluated) evaluated {
-	return ctx.mkIncompatible(src, op, x, other)
-}
-
-func (x *guard) binOp(ctx *context, src source, op op, other evaluated) evaluated {
-	return ctx.mkIncompatible(src, op, x, other)
-}
-
-func (x *yield) binOp(ctx *context, src source, op op, other evaluated) evaluated {
-	return ctx.mkIncompatible(src, op, x, other)
-}
-
-func (x *fieldComprehension) binOp(ctx *context, src source, op op, other evaluated) evaluated {
-	return ctx.mkIncompatible(src, op, x, other)
-}
diff --git a/cue/build.go b/cue/build.go
index d7849c9..65f0932 100644
--- a/cue/build.go
+++ b/cue/build.go
@@ -15,6 +15,7 @@
 package cue
 
 import (
+	"strings"
 	"sync"
 
 	"cuelang.org/go/cue/ast"
@@ -23,6 +24,8 @@
 	"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/compile"
 	"cuelang.org/go/internal/core/runtime"
 )
 
@@ -38,7 +41,7 @@
 }
 
 func init() {
-	internal.GetRuntimeOld = func(instance interface{}) interface{} {
+	internal.GetRuntimeNew = func(instance interface{}) interface{} {
 		switch x := instance.(type) {
 		case Value:
 			return &Runtime{idx: x.idx}
@@ -51,7 +54,7 @@
 		}
 	}
 
-	internal.CheckAndForkRuntimeOld = func(runtime, value interface{}) interface{} {
+	internal.CheckAndForkRuntimeNew = func(runtime, value interface{}) interface{} {
 		r := runtime.(*Runtime)
 		idx := value.(Value).ctx().index
 		if idx != r.idx {
@@ -59,6 +62,13 @@
 		}
 		return &Runtime{idx: newIndex(idx)}
 	}
+
+	internal.CoreValue = func(value interface{}) (runtime, vertex interface{}) {
+		if v, ok := value.(Value); ok && v.v != nil {
+			return v.idx.Index, v.v
+		}
+		return nil, nil
+	}
 }
 
 func dummyLoad(token.Pos, string) *build.Instance { return nil }
@@ -192,6 +202,7 @@
 //
 // All instances belonging to the same package should share this index.
 type index struct {
+	adt.Runtime
 	*runtime.Index
 
 	loaded map[*build.Instance]*Instance
@@ -201,16 +212,35 @@
 // sharedIndex is used for indexing builtins and any other labels common to
 // all instances.
 var sharedIndex = &index{
-	Index:  runtime.SharedIndex,
-	loaded: map[*build.Instance]*Instance{},
+	Runtime: runtime.SharedRuntimeNew,
+	Index:   runtime.SharedIndexNew,
+	loaded:  map[*build.Instance]*Instance{},
+}
+
+// NewRuntime creates a *runtime.Runtime with builtins preloaded.
+func NewRuntime() *runtime.Runtime {
+	idx := runtime.NewIndex(sharedIndex.Index)
+	r := runtime.NewWithIndex(idx)
+	i := &index{
+		Runtime: r,
+		Index:   idx,
+		loaded:  map[*build.Instance]*Instance{},
+	}
+	r.Data = i
+	return r
 }
 
 // newIndex creates a new index.
 func newIndex(parent *index) *index {
-	return &index{
-		Index:  runtime.NewIndex(parent.Index),
-		loaded: map[*build.Instance]*Instance{},
+	idx := runtime.NewIndex(parent.Index)
+	r := runtime.NewWithIndex(idx)
+	i := &index{
+		Runtime: r,
+		Index:   idx,
+		loaded:  map[*build.Instance]*Instance{},
 	}
+	r.Data = i
+	return i
 }
 
 func isBuiltin(s string) bool {
@@ -219,30 +249,93 @@
 }
 
 func (idx *index) loadInstance(p *build.Instance) *Instance {
-	if inst := idx.loaded[p]; inst != nil {
-		if !inst.complete {
-			// cycles should be detected by the builder and it should not be
-			// possible to construct a build.Instance that has them.
-			panic("cue: cycle")
+	_ = visitInstances(p, func(p *build.Instance, errs errors.Error) errors.Error {
+		if inst := idx.loaded[p]; inst != nil {
+			if !inst.complete {
+				// cycles should be detected by the builder and it should not be
+				// possible to construct a build.Instance that has them.
+				panic("cue: cycle")
+			}
+			return inst.Err
 		}
-		return inst
-	}
-	errs := runtime.ResolveFiles(idx.Index, p, isBuiltin)
-	files := p.Files
-	inst := newInstance(idx, p)
-	idx.loaded[p] = inst
 
-	if inst.Err == nil {
-		// inst.instance.index.state = s
-		// inst.instance.inst = p
+		err := runtime.ResolveFiles(idx.Index, p, isBuiltin)
+		errs = errors.Append(errs, err)
+
+		v, err := compile.Files(nil, idx.Runtime, p.Files...)
+		errs = errors.Append(errs, err)
+
+		inst := newInstance(idx, p, v)
+		idx.loaded[p] = inst
 		inst.Err = errs
-		for _, f := range files {
-			err := inst.insertFile(f)
-			inst.Err = errors.Append(inst.Err, err)
+
+		inst.ImportPath = p.ImportPath
+		inst.complete = true
+
+		return inst.Err
+	})
+
+	return idx.loaded[p]
+}
+
+// TODO: runtime.Runtime has a similar, much simpler, implementation. This
+// code should go.
+
+type visitFunc func(b *build.Instance, err errors.Error) (errs errors.Error)
+
+// visitInstances calls f for each transitive dependency.
+//
+// It passes any errors that occur in transitive dependencies to the visitFunc.
+// visitFunc must return the errors it is passed or return nil to ignore it.
+func visitInstances(b *build.Instance, f visitFunc) (errs errors.Error) {
+	v := visitor{b: b, f: f, errs: b.Err}
+	for _, file := range b.Files {
+		v.file(file)
+	}
+	return v.f(b, v.errs)
+}
+
+type visitor struct {
+	b    *build.Instance
+	f    visitFunc
+	errs errors.Error
+}
+
+func (v *visitor) addErr(e errors.Error) {
+	v.errs = errors.Append(v.errs, e)
+}
+
+func (v *visitor) file(file *ast.File) {
+	for _, d := range file.Decls {
+		switch x := d.(type) {
+		case *ast.Package:
+		case *ast.ImportDecl:
+			for _, s := range x.Specs {
+				v.spec(s)
+			}
+		case *ast.CommentGroup:
+		default:
+			return
 		}
 	}
-	inst.ImportPath = p.ImportPath
+}
 
-	inst.complete = true
-	return inst
+func (v *visitor) spec(spec *ast.ImportSpec) {
+	info, err := astutil.ParseImportSpec(spec)
+	if err != nil {
+		v.addErr(errors.Promote(err, "invalid import path"))
+		return
+	}
+
+	pkg := v.b.LookupImport(info.ID)
+	if pkg == nil {
+		if strings.Contains(info.ID, ".") {
+			v.addErr(errors.Newf(spec.Pos(),
+				"package %q imported but not defined in %s",
+				info.ID, v.b.ImportPath))
+		}
+		return
+	}
+
+	v.addErr(visitInstances(pkg, v.f))
 }
diff --git a/cue/build_test.go b/cue/build_test.go
index 7817ec7..4cf0ccb 100644
--- a/cue/build_test.go
+++ b/cue/build_test.go
@@ -16,12 +16,12 @@
 
 import (
 	"fmt"
-	"strings"
 	"testing"
 
 	"cuelang.org/go/cue/ast"
 	"cuelang.org/go/cue/build"
 	"cuelang.org/go/cue/token"
+	"cuelang.org/go/internal/core/debug"
 )
 
 func TestFromExpr(t *testing.T) {
@@ -36,7 +36,7 @@
 			ast.NewString("Hello"),
 			ast.NewString("World"),
 		),
-		out: `["Hello","World"]`,
+		out: `["Hello", "World"]`,
 	}}
 	for _, tc := range testCases {
 		t.Run("", func(t *testing.T) {
@@ -45,8 +45,7 @@
 			if err != nil {
 				t.Fatal(err)
 			}
-			ctx := inst.newContext()
-			if got := debugStr(ctx, inst.eval(ctx)); got != tc.out {
+			if got := fmt.Sprint(inst.Value()); got != tc.out {
 				t.Errorf("\n got: %v; want %v", got, tc.out)
 			}
 		})
@@ -86,7 +85,7 @@
 		emit      string
 	}{{
 		insts(&bimport{"", files(`test: "ok"`)}),
-		`{test: "ok"}`,
+		`{test:"ok"}`,
 	}, {
 		insts(&bimport{"",
 			files(
@@ -200,7 +199,8 @@
 			if err := insts[0].Err; err != nil {
 				got = err.Error()
 			} else {
-				got = strings.TrimSpace(fmt.Sprintf("%s\n", insts[0].Value()))
+				cfg := &debug.Config{Compact: true}
+				got = debug.NodeString(insts[0].Index, insts[0].Value().v, cfg)
 			}
 			if got != tc.emit {
 				t.Errorf("\n got: %s\nwant: %s", got, tc.emit)
diff --git a/cue/builtin.go b/cue/builtin.go
index 2da6821..9fa9fa1 100644
--- a/cue/builtin.go
+++ b/cue/builtin.go
@@ -12,6 +12,9 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+//go:generate go run golang.org/x/tools/cmd/goimports -w -local cuelang.org/go builtins.go
+//go:generate gofmt -s -w builtins.go
+
 package cue
 
 import (
@@ -21,6 +24,7 @@
 	"math/big"
 	"path"
 	"sort"
+	"strings"
 
 	"github.com/cockroachdb/apd/v2"
 
@@ -28,6 +32,10 @@
 	"cuelang.org/go/cue/parser"
 	"cuelang.org/go/cue/token"
 	"cuelang.org/go/internal"
+	"cuelang.org/go/internal/core/adt"
+	"cuelang.org/go/internal/core/compile"
+	"cuelang.org/go/internal/core/convert"
+	"cuelang.org/go/internal/core/runtime"
 )
 
 // A builtin is a builtin function or constant.
@@ -49,7 +57,6 @@
 //   map[string]T
 //
 type builtin struct {
-	baseValue
 	Name   string
 	pkg    label
 	Params []kind
@@ -64,21 +71,27 @@
 	cue    string
 }
 
-func mustCompileBuiltins(ctx *context, p *builtinPkg, pkgName string) *structLit {
-	obj := &structLit{}
+func mustCompileBuiltins(ctx *context, p *builtinPkg, pkgName string) *adt.Vertex {
+	obj := &adt.Vertex{}
 	pkgLabel := ctx.Label(pkgName, false)
+	st := &adt.StructLit{}
+	if len(p.native) > 0 {
+		obj.AddConjunct(adt.MakeConjunct(nil, st))
+	}
 	for _, b := range p.native {
 		b.pkg = pkgLabel
 
 		f := ctx.Label(b.Name, false) // never starts with _
 		// n := &node{baseValue: newBase(imp.Path)}
-		var v evaluated = b
+		var v adt.Expr = toBuiltin(ctx, b)
 		if b.Const != "" {
 			v = mustParseConstBuiltin(ctx, b.Name, b.Const)
 		}
-		obj.Arcs = append(obj.Arcs, arc{Label: f, v: v})
+		st.Decls = append(st.Decls, &adt.Field{
+			Label: f,
+			Value: v,
+		})
 	}
-	sort.Sort(obj)
 
 	// Parse builtin CUE
 	if p.cue != "" {
@@ -86,32 +99,77 @@
 		if err != nil {
 			panic(fmt.Errorf("could not parse %v: %v", p.cue, err))
 		}
-		v := newVisitor(ctx.index, nil, nil, nil, false)
-		value := v.walk(expr)
-		pkg := value.evalPartial(ctx).(*structLit)
-		for _, a := range pkg.Arcs {
-			// Discard option status and attributes at top level.
-			// TODO: filter on capitalized fields?
-			obj.insertValue(ctx, a.Label, false, false, a.v, nil, a.docs)
+		c, err := compile.Expr(nil, ctx.opCtx.Runtime, expr)
+		if err != nil {
+			panic(fmt.Errorf("could compile parse %v: %v", p.cue, err))
 		}
+		obj.AddConjunct(c)
+	}
+
+	// We could compile lazily, but this is easier for debugging.
+	obj.Finalize(ctx.opCtx)
+	if err := obj.Err(ctx.opCtx, adt.Finalized); err != nil {
+		panic(err.Err)
 	}
 
 	return obj
 }
 
+func toBuiltin(ctx *context, b *builtin) *adt.Builtin {
+	x := &adt.Builtin{
+		Params:  b.Params,
+		Result:  b.Result,
+		Package: b.pkg,
+		Name:    b.Name,
+	}
+	x.Func = func(ctx *adt.OpContext, args []adt.Value) (ret adt.Expr) {
+		runtime := ctx.Impl().(*runtime.Runtime)
+		index := runtime.Data.(*index)
+
+		// call, _ := ctx.Source().(*ast.CallExpr)
+		c := &callCtxt{
+			idx: index,
+			// src:  call,
+			ctx:     index.newContext(),
+			args:    args,
+			builtin: b,
+		}
+		defer func() {
+			var errVal interface{} = c.err
+			if err := recover(); err != nil {
+				errVal = err
+			}
+			ret = processErr(c, errVal, ret)
+		}()
+		b.Func(c)
+		switch v := c.ret.(type) {
+		case adt.Value:
+			return v
+		case *valueError:
+			return v.err
+		}
+		if c.err != nil {
+			return nil
+		}
+		return convert.GoValueToValue(ctx, c.ret, true)
+	}
+	return x
+}
+
 // newConstBuiltin parses and creates any CUE expression that does not have
 // fields.
-func mustParseConstBuiltin(ctx *context, name, val string) evaluated {
+func mustParseConstBuiltin(ctx *context, name, val string) adt.Expr {
 	expr, err := parser.ParseExpr("<builtin:"+name+">", val)
 	if err != nil {
 		panic(err)
 	}
-	v := newVisitor(ctx.index, nil, nil, nil, false)
-	value := v.walk(expr)
-	return value.evalPartial(ctx)
-}
+	c, err := compile.Expr(nil, ctx.Runtime, expr)
+	if err != nil {
+		panic(err)
+	}
+	return c.Expr()
 
-var _ caller = &builtin{}
+}
 
 var lenBuiltin = &builtin{
 	Name:   "len",
@@ -152,23 +210,39 @@
 			}
 			c.ret = len(s)
 		default:
-			c.ret = errors.Newf(token.NoPos,
-				"invalid argument type %v", k)
+			c.ret = c.ctx.opCtx.Newf("invalid argument type %v", k)
 		}
 	},
 }
 
+func pos(n adt.Node) (p token.Pos) {
+	if n == nil {
+		return
+	}
+	src := n.Source()
+	if src == nil {
+		return
+	}
+	return src.Pos()
+}
+
 var closeBuiltin = &builtin{
 	Name:   "close",
 	Params: []kind{structKind},
 	Result: structKind,
 	Func: func(c *callCtxt) {
-		s, ok := c.args[0].(*structLit)
+		s, ok := c.args[0].(*adt.Vertex)
 		if !ok {
-			c.ret = errors.Newf(c.args[0].Pos(), "struct argument must be concrete")
+			c.ret = errors.Newf(pos(c.args[0]), "struct argument must be concrete")
 			return
 		}
-		c.ret = s.close()
+		if s.IsClosed(c.ctx.opCtx) {
+			c.ret = s
+		} else {
+			v := *s
+			v.Closed = nil // TODO: set dedicated Closer.
+			c.ret = &v
+		}
 	},
 }
 
@@ -179,12 +253,12 @@
 	Func: func(c *callCtxt) {
 		iter := c.iter(0)
 		if !iter.Next() {
-			c.ret = &top{baseValue{c.src}}
+			c.ret = &top{}
 			return
 		}
-		u := iter.Value().v.v
+		var u adt.Expr = iter.Value().v
 		for iter.Next() {
-			u = mkBin(c.ctx, c.src.Pos(), opUnify, u, iter.Value().v.v)
+			u = &adt.BinaryExpr{Op: adt.AndOp, X: u, Y: iter.Value().v}
 		}
 		c.ret = u
 	},
@@ -196,11 +270,11 @@
 	Result: intKind,
 	Func: func(c *callCtxt) {
 		iter := c.iter(0)
-		d := []dValue{}
+		d := []adt.Disjunct{}
 		for iter.Next() {
-			d = append(d, dValue{iter.Value().v.v, false})
+			d = append(d, adt.Disjunct{iter.Value().v, false})
 		}
-		c.ret = &disjunction{baseValue{c.src}, d, nil, false}
+		c.ret = &adt.DisjunctionExpr{nil, d, false}
 		if len(d) == 0 {
 			// TODO(manifest): This should not be unconditionally incomplete,
 			// but it requires results from comprehensions and all to have
@@ -209,33 +283,14 @@
 			// an open list or struct. This would actually be exactly what
 			// that means. The error here could then only add an incomplete
 			// status if the source is open.
-			c.ret = c.ctx.mkErr(c.src, codeIncomplete, "empty list in call to or")
+			c.ret = &adt.Bottom{
+				Code: adt.IncompleteError,
+				Err:  errors.Newf(c.Pos(), "empty list in call to or"),
+			}
 		}
 	},
 }
 
-func (x *builtin) representedKind() kind {
-	if x.isValidator() {
-		return x.Params[0]
-	}
-	return x.Kind()
-}
-
-func (x *builtin) Kind() kind {
-	return lambdaKind
-}
-
-func (x *builtin) evalPartial(ctx *context) evaluated {
-	return x
-}
-
-func (x *builtin) subsumesImpl(s *subsumer, v value) bool {
-	if y, ok := v.(*builtin); ok {
-		return x == y
-	}
-	return false
-}
-
 func (x *builtin) name(ctx *context) string {
 	if x.pkg == 0 {
 		return x.Name
@@ -247,61 +302,9 @@
 	return len(x.Params) == 1 && x.Result == boolKind
 }
 
-func convertBuiltin(v evaluated) evaluated {
-	x, ok := v.(*builtin)
-	if ok && x.isValidator() {
-		return &customValidator{v.base(), x, []evaluated{}}
-	}
-	return v
-}
-
-func (x *builtin) call(ctx *context, src source, args ...evaluated) (ret value) {
-	if x.Func == nil {
-		return ctx.mkErr(x, "builtin %s is not a function", x.name(ctx))
-	}
-	if len(x.Params)-1 == len(args) && x.Result == boolKind {
-		// We have a custom builtin
-		return &customValidator{src.base(), x, args}
-	}
-	switch {
-	case len(x.Params) < len(args):
-		return ctx.mkErr(src, x, "too many arguments in call to %s (have %d, want %d)",
-			x.name(ctx), len(args), len(x.Params))
-	case len(x.Params) > len(args):
-		return ctx.mkErr(src, x, "not enough arguments in call to %s (have %d, want %d)",
-			x.name(ctx), len(args), len(x.Params))
-	}
-	for i, a := range args {
-		if x.Params[i] != bottomKind {
-			if unifyType(x.Params[i], a.Kind()) == bottomKind {
-				const msg = "cannot use %s (type %s) as %s in argument %d to %s"
-				return ctx.mkErr(src, x, msg, ctx.str(a), a.Kind(), x.Params[i], i+1, x.name(ctx))
-			}
-		}
-	}
-	call := callCtxt{src: src, ctx: ctx, builtin: x, args: args}
-	defer func() {
-		var errVal interface{} = call.err
-		if err := recover(); err != nil {
-			errVal = err
-		}
-		ret = processErr(&call, errVal, ret)
-	}()
-	x.Func(&call)
-	switch v := call.ret.(type) {
-	case value:
-		return v
-	case *valueError:
-		return v.err
-	}
-	return convertVal(ctx, x, true, call.ret)
-}
-
-func processErr(call *callCtxt, errVal interface{}, ret value) value {
+func processErr(call *callCtxt, errVal interface{}, ret adt.Expr) adt.Expr {
 	ctx := call.ctx
-	x := call.builtin
 	src := call.src
-	const msg = "error in call to %s: %v"
 	switch err := errVal.(type) {
 	case nil:
 	case *callError:
@@ -311,30 +314,92 @@
 			ret = err.b
 		}
 	case *marshalError:
-		ret = err.b
-		ret = ctx.mkErr(src, x, ret, msg, x.name(ctx), err)
+		ret = wrapCallErr(call, err.b)
 	case *valueError:
-		ret = err.err
-		ret = ctx.mkErr(src, x, ret, msg, x.name(ctx), err)
-	default:
+		ret = wrapCallErr(call, err.err)
+	case errors.Error:
+		ret = wrapCallErr(call, &adt.Bottom{Err: err})
+	case error:
 		if call.err == internal.ErrIncomplete {
 			ret = ctx.mkErr(src, codeIncomplete, "incomplete value")
 		} else {
 			// TODO: store the underlying error explicitly
-			ret = ctx.mkErr(src, x, msg, x.name(ctx), err)
+			ret = wrapCallErr(call, &adt.Bottom{Err: errors.Promote(err, "")})
 		}
+	default:
+		// Likely a string passed to panic.
+		ret = wrapCallErr(call, &adt.Bottom{
+			Err: errors.Newf(call.Pos(), "%s", err),
+		})
 	}
 	return ret
 }
 
+func wrapCallErr(c *callCtxt, b *adt.Bottom) *adt.Bottom {
+	pos := token.NoPos
+	if c.src != nil {
+		if src := c.src.Source(); src != nil {
+			pos = src.Pos()
+		}
+	}
+	const msg = "error in call to %s"
+	return &adt.Bottom{
+		Code: b.Code,
+		Err:  errors.Wrapf(b.Err, pos, msg, c.builtin.name(c.ctx)),
+	}
+}
+
+func (c *callCtxt) convertError(x interface{}, name string) *adt.Bottom {
+	var err errors.Error
+	switch v := x.(type) {
+	case nil:
+		return nil
+
+	case *adt.Bottom:
+		return v
+
+	case *json.MarshalerError:
+		err = errors.Promote(v, "marshal error")
+
+	case errors.Error:
+		err = v
+
+	case error:
+		if name != "" {
+			err = errors.Newf(c.Pos(), "%s: %v", name, v)
+		} else {
+			err = errors.Newf(c.Pos(), "error in call to %s: %v", c.name(), v)
+		}
+
+	default:
+		err = errors.Newf(token.NoPos, "%s", name)
+	}
+	if err != internal.ErrIncomplete {
+		return &adt.Bottom{
+			// Wrap to preserve position information.
+			Err: errors.Wrapf(err, c.Pos(), "error in call to %s", c.name()),
+		}
+	}
+	return &adt.Bottom{
+		Code: adt.IncompleteError,
+		Err:  errors.Newf(c.Pos(), "incomplete values in call to %s", c.name()),
+	}
+}
+
 // callCtxt is passed to builtin implementations.
 type callCtxt struct {
-	src     source
+	idx     *index
+	src     adt.Expr // *adt.CallExpr
 	ctx     *context
 	builtin *builtin
-	args    []evaluated
-	err     error
+	err     interface{}
 	ret     interface{}
+
+	args []adt.Value
+}
+
+func (c *callCtxt) Pos() token.Pos {
+	return c.ctx.opCtx.Pos()
 }
 
 func (c *callCtxt) name() string {
@@ -357,8 +422,7 @@
 		i := sharedIndex.addInst(&Instance{
 			ImportPath: k,
 			PkgName:    path.Base(k),
-			rootStruct: e,
-			rootValue:  e,
+			root:       e,
 		})
 
 		builtins[k] = i
@@ -375,7 +439,27 @@
 	if !ok {
 		return nil
 	}
-	return p.rootStruct
+	return p.root
+}
+
+func init() {
+	internal.UnifyBuiltin = func(val interface{}, kind string) interface{} {
+		v := val.(Value)
+		ctx := v.ctx()
+
+		p := strings.Split(kind, ".")
+		pkg, name := p[0], p[1]
+		s := getBuiltinPkg(ctx, pkg)
+		if s == nil {
+			return v
+		}
+		a := s.Lookup(ctx.Label(name, false))
+		if a == nil {
+			return v
+		}
+
+		return v.Unify(makeValue(v.idx, a))
+	}
 }
 
 // do returns whether the call should be done.
@@ -402,12 +486,21 @@
 	c.err = &callError{err}
 }
 
+func (c *callCtxt) errcf(src source, code adt.ErrorCode, format string, args ...interface{}) {
+	a := make([]interface{}, 0, 2+len(args))
+	a = append(a, code)
+	a = append(a, format)
+	a = append(a, args...)
+	err := c.ctx.mkErr(src, a...)
+	c.err = &callError{err}
+}
+
 func (c *callCtxt) value(i int) Value {
 	v := newValueRoot(c.ctx, c.args[i])
-	v, _ = v.Default()
+	// TODO: remove default
+	// v, _ = v.Default()
 	if !v.IsConcrete() {
-		c.errf(c.src, v.toErr(c.ctx.mkErr(c.src, codeIncomplete,
-			"non-concrete value")), "incomplete")
+		c.errcf(c.src, adt.IncompleteError, "non-concrete argument %d", i)
 	}
 	return v
 }
@@ -423,12 +516,26 @@
 }
 
 func (c *callCtxt) invalidArgType(arg value, i int, typ string, err error) {
+	if ve, ok := err.(*valueError); ok && ve.err.IsIncomplete() {
+		c.err = ve
+		return
+	}
+	v, ok := arg.(adt.Value)
+	// TODO: make these permanent errors if the value did not originate from
+	// a reference.
+	if !ok {
+		c.errf(c.src, nil,
+			"cannot use incomplete value %s as %s in argument %d to %s: %v",
+			c.ctx.str(arg), typ, i, c.name(), err)
+	}
 	if err != nil {
-		c.errf(c.src, err, "cannot use %s (type %s) as %s in argument %d to %s: %v",
-			c.ctx.str(arg), arg.Kind(), typ, i, c.name(), err)
+		c.errf(c.src, err,
+			"cannot use %s (type %s) as %s in argument %d to %s: %v",
+			c.ctx.str(arg), v.Kind(), typ, i, c.name(), err)
 	} else {
-		c.errf(c.src, nil, "cannot use %s (type %s) as %s in argument %d to %s",
-			c.ctx.str(arg), arg.Kind(), typ, i, c.name())
+		c.errf(c.src, err,
+			"cannot use %s (type %s) as %s in argument %d to %s",
+			c.ctx.str(arg), v.Kind(), typ, i, c.name())
 	}
 }
 
@@ -506,6 +613,8 @@
 	return n
 }
 
+var ten = big.NewInt(10)
+
 func (c *callCtxt) bigFloat(i int) *big.Float {
 	x := newValueRoot(c.ctx, c.args[i])
 	var mant big.Int
@@ -621,8 +730,8 @@
 	for j := 0; v.Next(); j++ {
 		str, err := v.Value().String()
 		if err != nil {
-			c.errf(c.src, err, "invalid list element %d in argument %d to %s: %v",
-				j, i, c.name(), err)
+			c.err = errors.Wrapf(err, c.Pos(),
+				"element %d of list argument %d", j, i)
 			break
 		}
 		a = append(a, str)
diff --git a/cue/builtin_test.go b/cue/builtin_test.go
index 1901d34..617235e 100644
--- a/cue/builtin_test.go
+++ b/cue/builtin_test.go
@@ -49,7 +49,7 @@
 		`3`,
 	}, {
 		test("math", "math.Pi(3)"),
-		`_|_(cannot call non-function Pi (type float))`,
+		`_|_(cannot call non-function math.Pi (type float))`,
 	}, {
 		test("math", "math.Floor(3, 5)"),
 		`_|_(too many arguments in call to math.Floor (have 2, want 1))`,
@@ -91,10 +91,10 @@
 		`'foo'`,
 	}, {
 		test("encoding/base64", `base64.Decode(null, "foo")`),
-		`_|_(error in call to encoding/base64.Decode: illegal base64 data at input byte 0)`,
+		`_|_(error in call to encoding/base64.Decode: illegal base64 data at input byte 0 (and 1 more errors))`,
 	}, {
 		test("encoding/base64", `base64.Decode({}, "foo")`),
-		`_|_(error in call to encoding/base64.Decode: base64: unsupported encoding: cannot use value {} (type struct) as null)`,
+		`_|_(error in call to encoding/base64.Decode: base64: unsupported encoding: cannot use value {} (type struct) as null (and 1 more errors))`,
 	}, {
 		test("encoding/hex", `hex.Encode("foo")`),
 		`"666f6f"`,
@@ -103,7 +103,7 @@
 		`'foo'`,
 	}, {
 		test("encoding/hex", `hex.Decode("foo")`),
-		`_|_(error in call to encoding/hex.Decode: encoding/hex: invalid byte: U+006F 'o')`,
+		`_|_(error in call to encoding/hex.Decode: encoding/hex: invalid byte: U+006F 'o' (and 1 more errors))`,
 	}, {
 		test("encoding/hex", `hex.Dump('foo')`),
 		`"00000000  66 6f 6f                                          |foo|\n"`,
@@ -112,19 +112,19 @@
 		`true`,
 	}, {
 		test("encoding/json", `json.Validate("{\"a\":10}", {a:<3})`),
-		`_|_(error in call to encoding/json.Validate: a: invalid value 10 (out of bound <3))`,
+		`_|_(error in call to encoding/json.Validate: a: invalid value 10 (out of bound <3) (and 1 more errors))`,
 	}, {
 		test("encoding/yaml", `yaml.Validate("a: 2\n---\na: 4", {a:<3})`),
-		`_|_(error in call to encoding/yaml.Validate: a: invalid value 4 (out of bound <3))`,
+		`_|_(error in call to encoding/yaml.Validate: a: invalid value 4 (out of bound <3) (and 1 more errors))`,
 	}, {
 		test("encoding/yaml", `yaml.Validate("a: 2\n---\na: 4", {a:<5})`),
 		`true`,
 	}, {
 		test("encoding/yaml", `yaml.Validate("a: 2\n", {a:<5, b:int})`),
-		`_|_(error in call to encoding/yaml.Validate: b: incomplete value (int))`,
+		`_|_(error in call to encoding/yaml.Validate: b: incomplete value int (and 1 more errors))`,
 	}, {
 		test("encoding/yaml", `yaml.ValidatePartial("a: 2\n---\na: 4", {a:<3})`),
-		`_|_(error in call to encoding/yaml.ValidatePartial: a: invalid value 4 (out of bound <3))`,
+		`_|_(error in call to encoding/yaml.ValidatePartial: a: invalid value 4 (out of bound <3) (and 1 more errors))`,
 	}, {
 		test("encoding/yaml", `yaml.ValidatePartial("a: 2\n---\na: 4", {a:<5})`),
 		`true`,
@@ -137,11 +137,11 @@
 	}, {
 		// Find a better alternative, as this call should go.
 		test("strconv", `strconv.FormatFloat(3.02, 300, 4, 64)`),
-		`_|_(int 300 overflows byte in argument 1 in call to strconv.FormatFloat)`,
+		`_|_(int 300 overflows byte in argument 1 in call to strconv.FormatFloat (and 1 more errors))`,
 	}, {
 		// Find a better alternative, as this call should go.
 		test("strconv", `strconv.FormatFloat(3.02, -1, 4, 64)`),
-		`_|_(cannot use -1 (type int) as byte in argument 1 to strconv.FormatFloat)`,
+		`_|_(cannot use -1 (type int) as byte in argument 1 to strconv.FormatFloat (and 1 more errors))`,
 	}, {
 		// Find a better alternative, as this call should go.
 		test("strconv", `strconv.FormatFloat(3.02, 1.0, 4, 64)`),
@@ -151,7 +151,7 @@
 		`2.5`,
 	}, {
 		test("list", `list.Avg([])`),
-		`_|_(error in call to list.Avg: empty list)`,
+		`_|_(error in call to list.Avg: empty list (and 1 more errors))`,
 	}, {
 		test("list", `list.Avg("foo")`),
 		`_|_(cannot use "foo" (type string) as list in argument 1 to list.Avg)`,
@@ -166,7 +166,7 @@
 		`[]`,
 	}, {
 		test("list", `list.Drop([1, 2, 3, 4], -1)`),
-		`_|_(error in call to list.Drop: negative index)`,
+		`_|_(error in call to list.Drop: negative index (and 1 more errors))`,
 	}, {
 		test("list", `list.FlattenN([1, [[2, 3], []], [4]], -1)`),
 		`[1,2,3,4]`,
@@ -184,7 +184,7 @@
 		`[]`,
 	}, {
 		test("list", `list.FlattenN("foo", 1)`),
-		`_|_(error in call to list.FlattenN: cannot use value "foo" (type string) as list)`,
+		`_|_(error in call to list.FlattenN: cannot use value "foo" (type string) as list (and 1 more errors))`,
 	}, {
 		test("list", `list.FlattenN([], "foo")`),
 		`_|_(cannot use "foo" (type string) as int in argument 2 to list.FlattenN)`,
@@ -193,7 +193,7 @@
 		`4`,
 	}, {
 		test("list", `list.Max([])`),
-		`_|_(error in call to list.Max: empty list)`,
+		`_|_(error in call to list.Max: empty list (and 1 more errors))`,
 	}, {
 		test("list", `list.Max("foo")`),
 		`_|_(cannot use "foo" (type string) as list in argument 1 to list.Max)`,
@@ -202,7 +202,7 @@
 		`1`,
 	}, {
 		test("list", `list.Min([])`),
-		`_|_(error in call to list.Min: empty list)`,
+		`_|_(error in call to list.Min: empty list (and 1 more errors))`,
 	}, {
 		test("list", `list.Min("foo")`),
 		`_|_(cannot use "foo" (type string) as list in argument 1 to list.Min)`,
@@ -217,13 +217,13 @@
 		`_|_(cannot use "foo" (type string) as list in argument 1 to list.Product)`,
 	}, {
 		test("list", `list.Range(0, 5, 0)`),
-		`_|_(error in call to list.Range: step must be non zero)`,
+		`_|_(error in call to list.Range: step must be non zero (and 1 more errors))`,
 	}, {
 		test("list", `list.Range(5, 0, 1)`),
-		`_|_(error in call to list.Range: end must be greater than start when step is positive)`,
+		`_|_(error in call to list.Range: end must be greater than start when step is positive (and 1 more errors))`,
 	}, {
 		test("list", `list.Range(0, 5, -1)`),
-		`_|_(error in call to list.Range: end must be less than start when step is negative)`,
+		`_|_(error in call to list.Range: end must be less than start when step is negative (and 1 more errors))`,
 	}, {
 		test("list", `list.Range(0, 5, 1)`),
 		`[0,1,2,3,4]`,
@@ -244,16 +244,16 @@
 		`[2,3]`,
 	}, {
 		test("list", `list.Slice([1, 2, 3, 4], -1, 3)`),
-		`_|_(error in call to list.Slice: negative index)`,
+		`_|_(error in call to list.Slice: negative index (and 1 more errors))`,
 	}, {
 		test("list", `list.Slice([1, 2, 3, 4], 3, 1)`),
-		`_|_(error in call to list.Slice: invalid index: 3 > 1)`,
+		`_|_(error in call to list.Slice: invalid index: 3 > 1 (and 1 more errors))`,
 	}, {
 		test("list", `list.Slice([1, 2, 3, 4], 5, 5)`),
-		`_|_(error in call to list.Slice: slice bounds out of range)`,
+		`_|_(error in call to list.Slice: slice bounds out of range (and 1 more errors))`,
 	}, {
 		test("list", `list.Slice([1, 2, 3, 4], 1, 5)`),
-		`_|_(error in call to list.Slice: slice bounds out of range)`,
+		`_|_(error in call to list.Slice: slice bounds out of range (and 1 more errors))`,
 	}, {
 		test("list", `list.Sort([], list.Ascending)`),
 		`[]`,
@@ -266,16 +266,17 @@
 			y:_,
 			less: (x.a < y.a)
 		})`),
-		`[{a: 1, v: 2},{a: 1, v: 3},{a: 2, v: 1}]`,
+		`[{a:1,v:2},{a:1,v:3},{a:2,v:1}]`,
 	}, {
 		test("list", `list.Sort([{a:1}, {b:2}], list.Ascending)`),
-		`_|_(error in call to list.Sort: less: conflicting values close(T, close(T)) and {b: 2} (mismatched types number|string and struct))`,
+		`_|_(error in call to list.Sort: x: conflicting values string and {b:2} (mismatched types string and struct) (and 1 more errors) (and 1 more errors))`,
 	}, {
 		test("list", `list.SortStrings(["b", "a"])`),
 		`["a","b"]`,
 	}, {
+		// TODO: path error. This should be done as part of builtin refactoring.
 		test("list", `list.SortStrings([1, 2])`),
-		`_|_(invalid list element 0 in argument 0 to list.SortStrings: 0: cannot use value 1 (type int) as string)`,
+		`_|_(error in call to list.SortStrings: element 0 of list argument 0: 0: cannot use value 1 (type int) as string (and 1 more errors))`,
 	}, {
 		test("list", `list.Sum([1, 2, 3, 4])`),
 		`10`,
@@ -296,7 +297,7 @@
 		`[1,2,3,4]`,
 	}, {
 		test("list", `list.Take([1, 2, 3, 4], -1)`),
-		`_|_(error in call to list.Take: negative index)`,
+		`_|_(error in call to list.Take: negative index (and 1 more errors))`,
 	}, {
 		test("list", `list.MinItems([1, 2, 3, 4], 2)`),
 		`true`,
@@ -312,20 +313,20 @@
 	}, {
 		// Panics
 		test("math", `math.Jacobi(1000, 2000)`),
-		`_|_(error in call to math.Jacobi: big: invalid 2nd argument to Int.Jacobi: need odd integer but got 2000)`,
+		`_|_(error in call to math.Jacobi: big: invalid 2nd argument to Int.Jacobi: need odd integer but got 2000 (and 1 more errors))`,
 	}, {
 		test("math", `math.Jacobi(1000, 201)`),
 		`1`,
 	}, {
 		test("math", `math.Asin(2.0e400)`),
-		`_|_(cannot use 2.0e+400 (type float) as float64 in argument 0 to math.Asin: value was rounded up)`,
+		`_|_(cannot use 2.0E+400 (type float) as float64 in argument 0 to math.Asin: value was rounded up (and 1 more errors))`,
 	}, {
 		test("math", `math.MultipleOf(4, 2)`), `true`,
 	}, {
 		test("math", `math.MultipleOf(5, 2)`), `false`,
 	}, {
 		test("math", `math.MultipleOf(5, 0)`),
-		`_|_(error in call to math.MultipleOf: division by zero)`,
+		`_|_(error in call to math.MultipleOf: division by zero (and 1 more errors))`,
 	}, {
 		test("math", `math.MultipleOf(100, 1.00001)`), `false`,
 	}, {
@@ -342,7 +343,7 @@
 		`"foo"`,
 	}, {
 		test("regexp", `regexp.Find(#"f\w\w"#, "bar")`),
-		`_|_(error in call to regexp.Find: no match)`,
+		`_|_(error in call to regexp.Find: no match (and 1 more errors))`,
 	}, {
 		test("regexp", `regexp.FindAll(#"f\w\w"#, "afoot afloat from", 2)`),
 		`["foo","flo"]`,
@@ -351,7 +352,7 @@
 		`["foo","flo"]`,
 	}, {
 		test("regexp", `regexp.FindAll(#"f\w\w"#, "bla bla", -1)`),
-		`_|_(error in call to regexp.FindAll: no match)`,
+		`_|_(error in call to regexp.FindAll: no match (and 1 more errors))`,
 	}, {
 		test("regexp", `regexp.FindSubmatch(#"f(\w)(\w)"#, "afloat afoot from")`),
 		`["flo","l","o"]`,
@@ -360,19 +361,19 @@
 		`[["flo","l","o"],["foo","o","o"],["fro","r","o"]]`,
 	}, {
 		test("regexp", `regexp.FindAllSubmatch(#"f(\w)(\w)"#, "aglom", -1)`),
-		`_|_(error in call to regexp.FindAllSubmatch: no match)`,
+		`_|_(error in call to regexp.FindAllSubmatch: no match (and 1 more errors))`,
 	}, {
 		test("regexp", `regexp.FindNamedSubmatch(#"f(?P<A>\w)(?P<B>\w)"#, "afloat afoot from")`),
-		`{A: "l", B: "o"}`,
+		`{A:"l",B:"o"}`,
 	}, {
 		test("regexp", `regexp.FindAllNamedSubmatch(#"f(?P<A>\w)(?P<B>\w)"#, "afloat afoot from", -1)`),
-		`[{A: "l", B: "o"},{A: "o", B: "o"},{A: "r", B: "o"}]`,
+		`[{A:"l",B:"o"},{A:"o",B:"o"},{A:"r",B:"o"}]`,
 	}, {
 		test("regexp", `regexp.FindAllNamedSubmatch(#"f(?P<A>optional)?"#, "fbla", -1)`),
-		`[{A: ""}]`,
+		`[{A:""}]`,
 	}, {
 		test("regexp", `regexp.FindAllNamedSubmatch(#"f(?P<A>\w)(?P<B>\w)"#, "aglom", -1)`),
-		`_|_(error in call to regexp.FindAllNamedSubmatch: no match)`,
+		`_|_(error in call to regexp.FindAllNamedSubmatch: no match (and 1 more errors))`,
 	}, {
 		test("regexp", `regexp.Valid & "valid"`),
 		`"valid"`,
@@ -387,7 +388,7 @@
 		`"Hello World!"`,
 	}, {
 		test("strings", `strings.Join([1, 2], " ")`),
-		`_|_(invalid list element 0 in argument 0 to strings.Join: 0: cannot use value 1 (type int) as string)`,
+		`_|_(error in call to strings.Join: element 0 of list argument 0: 0: cannot use value 1 (type int) as string (and 1 more errors))`,
 	}, {
 		test("strings", `strings.ByteAt("a", 0)`),
 		strconv.Itoa('a'),
@@ -432,7 +433,7 @@
 		`2`,
 	}, {
 		testExpr(`or([])`),
-		`_|_(empty list in call to or)`,
+		`_|_(empty list in call to or (and 1 more errors))`,
 	}, {
 		test("encoding/csv", `csv.Encode([[1,2,3],[4,5],[7,8,9]])`),
 		`"1,2,3\n4,5\n7,8,9\n"`,
@@ -459,7 +460,7 @@
 			x: int
 			y: json.Marshal({a: x})
 		}`),
-		`{x: int, y: Marshal ({a: x})}`,
+		`{x:int,y:_|_(cannot convert incomplete value "int" to JSON (and 1 more errors))}`,
 	}, {
 		test("encoding/yaml", `yaml.MarshalStream([{a: 1}, {b: 2}])`),
 		`"a: 1\n---\nb: 2\n"`,
@@ -482,14 +483,15 @@
 		test("net", `net.JoinHostPort([192,30,4,2], 80)`),
 		`"192.30.4.2:80"`,
 	}, {
-		test("net", `net.JoinHostPort([192,30,4], 80)`),
-		`_|_(error in call to net.JoinHostPort: invalid host [192,30,4])`,
+		// TODO: why is this not printing compactly?
+		test("net", `net.JoinHostPort([192, 30, 4], 80)`),
+		`_|_(error in call to net.JoinHostPort: invalid host [192, 30, 4] (and 1 more errors))`,
 	}, {
 		test("net", `net.IP("23.23.23.23")`),
 		`true`,
 	}, {
 		test("net", `net.IPv4 & "23.23.23.2333"`),
-		`_|_(invalid value "23.23.23.2333" (does not satisfy net.IPv4()))`,
+		`_|_(invalid value "23.23.23.2333" (does not satisfy net.IPv4))`,
 	}, {
 		test("net", `net.IP("23.23.23.23")`),
 		`true`,
@@ -501,7 +503,7 @@
 		`false`,
 	}, {
 		test("net", `net.IPv4() & "ff02::1:3"`),
-		`_|_(invalid value "ff02::1:3" (does not satisfy net.IPv4()))`,
+		`_|_(invalid value "ff02::1:3" (does not satisfy net.IPv4))`,
 	}, {
 		test("net", `net.LoopbackIP([127, 0, 0, 1])`),
 		`true`,
@@ -549,23 +551,23 @@
 		`_|_(invalid value "hello" (does not satisfy strings.MinRunes(10)))`,
 	}, {
 		test("struct", `struct.MinFields(0) & ""`),
-		`_|_(conflicting values MinFields (0) and "" (mismatched types struct and string))`,
+		`_|_(conflicting values struct.MinFields(0) and "" (mismatched types struct and string))`,
 	}, {
 		test("struct", `struct.MinFields(0) & {a: 1}`),
-		`{a: 1}`,
+		`{a:1}`,
 	}, {
 		test("struct", `struct.MinFields(2) & {a: 1}`),
-		`_|_(invalid value {a: 1} (does not satisfy struct.MinFields(2)))`,
+		`_|_(invalid value {a:1} (does not satisfy struct.MinFields(2)))`,
 	}, {
 		test("struct", `struct.MaxFields(0) & {a: 1}`),
-		`_|_(invalid value {a: 1} (does not satisfy struct.MaxFields(0)))`,
+		`_|_(invalid value {a:1} (does not satisfy struct.MaxFields(0)))`,
 	}, {
 		test("struct", `struct.MaxFields(2) & {a: 1}`),
-		`{a: 1}`,
+		`{a:1}`,
 	}, {
 		test("math", `math.Pow(8, 4)`), `4096`,
 	}, {
-		test("math", `math.Pow10(4)`), `10000`,
+		test("math", `math.Pow10(4)`), `1E+4`,
 	}, {
 		test("math", `math.Signbit(-4)`), `true`,
 	}, {
@@ -669,7 +671,41 @@
 			if err := insts[0].Err; err != nil {
 				t.Fatal(err)
 			}
-			got := strings.TrimSpace(fmt.Sprintf("%s\n", insts[0].Value()))
+			v := insts[0].Value()
+			ctx := v.ctx()
+			got := ctx.opCtx.Str(v.v)
+			if got != tc.emit {
+				t.Errorf("\n got: %s\nwant: %s", got, tc.emit)
+			}
+		})
+	}
+}
+
+// For debugging purposes. Do not remove.
+func TestSingleBuiltin(t *testing.T) {
+	t.Skip("error message")
+
+	test := func(pkg, expr string) []*bimport {
+		return []*bimport{{"",
+			[]string{fmt.Sprintf("import %q\n(%s)", pkg, expr)},
+		}}
+	}
+	testCases := []struct {
+		instances []*bimport
+		emit      string
+	}{{
+		test("list", `list.Sort([{a:1}, {b:2}], list.Ascending)`),
+		`_|_(error in call to list.Sort: less: invalid operands {b:2} and {a:1} to '<' (type struct and struct) (and 1 more errors))`,
+	}}
+	for i, tc := range testCases {
+		t.Run(fmt.Sprint(i), func(t *testing.T) {
+			insts := Build(makeInstances(tc.instances))
+			if err := insts[0].Err; err != nil {
+				t.Fatal(err)
+			}
+			v := insts[0].Value()
+			ctx := v.ctx()
+			got := ctx.opCtx.Str(v.v)
 			if got != tc.emit {
 				t.Errorf("\n got: %s\nwant: %s", got, tc.emit)
 			}
diff --git a/cue/builtins.go b/cue/builtins.go
index 7581fda..87ad902 100644
--- a/cue/builtins.go
+++ b/cue/builtins.go
@@ -148,9 +148,9 @@
 }
 
 var builtinPackages = map[string]*builtinPkg{
-	"": {
-		native: []*builtin{},
-	},
+	// "": {
+	// 	native: []*builtin{},
+	// },
 	"crypto/md5": {
 		native: []*builtin{{
 			Name:  "Size",
@@ -612,13 +612,15 @@
 						if !json.Valid(b) {
 							return false, fmt.Errorf("json: invalid JSON")
 						}
-						r := internal.GetRuntimeOld(v).(*Runtime)
+						r := internal.GetRuntimeNew(v).(*Runtime)
 						inst, err := r.Compile("json.Validate", b)
 						if err != nil {
 							return false, err
 						}
 
-						v = v.Unify(inst.Value())
+						t := inst.Value()
+
+						v = v.Unify(t)
 						if v.Err() != nil {
 							return false, v.Err()
 						}
@@ -709,7 +711,7 @@
 						if err != nil {
 							return false, err
 						}
-						r := internal.GetRuntimeOld(v).(*Runtime)
+						r := internal.GetRuntimeNew(v).(*Runtime)
 						for {
 							expr, err := d.Decode()
 							if err != nil {
@@ -748,7 +750,7 @@
 						if err != nil {
 							return false, err
 						}
-						r := internal.GetRuntimeOld(v).(*Runtime)
+						r := internal.GetRuntimeNew(v).(*Runtime)
 						for {
 							expr, err := d.Decode()
 							if err != nil {
diff --git a/cue/builtinutil.go b/cue/builtinutil.go
index df22d71..e226cfa 100644
--- a/cue/builtinutil.go
+++ b/cue/builtinutil.go
@@ -14,6 +14,11 @@
 
 package cue
 
+import (
+	"cuelang.org/go/internal/core/adt"
+	"cuelang.org/go/internal/core/convert"
+)
+
 // TODO: this code could be generated, but currently isn't.
 
 type valueSorter struct {
@@ -33,9 +38,12 @@
 func (s *valueSorter) Len() int      { return len(s.a) }
 func (s *valueSorter) Swap(i, j int) { s.a[i], s.a[j] = s.a[j], s.a[i] }
 func (s *valueSorter) Less(i, j int) bool {
-	x := fill(s.cmp, s.a[i], "x")
-	x = fill(x, s.a[j], "y")
-	isLess, err := x.Lookup("less").Bool()
+	ctx := s.cmp.ctx()
+	x := fill(ctx, s.cmp.v, s.a[i], "x")
+	x = fill(ctx, x, s.a[j], "y")
+	ctx.opCtx.Unify(ctx.opCtx, x, adt.Finalized) // TODO: remove.
+	v := Value{s.cmp.idx, x}
+	isLess, err := v.Lookup("less").Bool()
 	if err != nil && s.err == nil {
 		s.err = err
 		return true
@@ -45,13 +53,22 @@
 
 // fill creates a new value with the old value unified with the given value.
 // TODO: consider making this a method on Value.
-func fill(v Value, x interface{}, path ...string) Value {
-	ctx := v.ctx()
-	root := v.v.val()
+func fill(ctx *context, v *adt.Vertex, x interface{}, path ...string) *adt.Vertex {
 	for i := len(path) - 1; i >= 0; i-- {
 		x = map[string]interface{}{path[i]: x}
 	}
-	value := convertVal(ctx, root, false, x)
-	eval := binOp(ctx, baseValue{}, opUnify, root, value)
-	return newValueRoot(ctx, eval)
+	value := convertVal(ctx, v, false, x)
+
+	w := adt.ToVertex(value)
+	n := &adt.Vertex{Label: v.Label}
+	n.AddConjunct(adt.MakeConjunct(nil, v))
+	n.AddConjunct(adt.MakeConjunct(nil, w))
+
+	// n.Add(v)
+	// n.Add(w)
+	return n
+}
+
+func convertVal(ctx *context, src source, nullIsTop bool, x interface{}) adt.Value {
+	return convert.GoValueToValue(ctx.opCtx, x, nullIsTop)
 }
diff --git a/cue/context.go b/cue/context.go
index a63e3e9..3f00329 100644
--- a/cue/context.go
+++ b/cue/context.go
@@ -15,48 +15,17 @@
 package cue
 
 import (
+	"cuelang.org/go/internal/core/adt"
+	"cuelang.org/go/internal/core/debug"
+	"cuelang.org/go/internal/core/eval"
 	"github.com/cockroachdb/apd/v2"
 )
 
 // context manages evaluation state.
 type context struct {
+	opCtx *adt.OpContext
 	*apd.Context
-
 	*index
-
-	forwardMap []scope // pairs
-	oldSize    []int
-
-	// constraints are to be evaluated at the end values to be evaluated later.
-	constraints []*binaryExpr
-	evalStack   []bottom
-
-	inDefinition int
-	inSum        int
-	cycleErr     bool
-
-	// for debug strings
-	nodeRefs map[scope]string
-
-	// tracing
-	trace bool
-	level int
-
-	// TODO: replace with proper structural cycle detection/ occurs check.
-	// See Issue #29.
-	maxDepth int
-}
-
-func (c *context) incEvalDepth() {
-	if len(c.evalStack) > 0 {
-		c.evalStack[len(c.evalStack)-1].exprDepth++
-	}
-}
-
-func (c *context) decEvalDepth() {
-	if len(c.evalStack) > 0 {
-		c.evalStack[len(c.evalStack)-1].exprDepth--
-	}
 }
 
 var baseContext apd.Context
@@ -72,50 +41,56 @@
 		Context: &baseContext,
 		index:   idx,
 	}
+	if idx != nil {
+		c.opCtx = eval.NewContext(idx.Runtime, nil)
+	}
 	return c
 }
 
-// delayConstraint schedules constraint to be evaluated and returns ret. If
-// delaying constraints is currently not allowed, it returns an error instead.
-func (c *context) delayConstraint(ret evaluated, constraint *binaryExpr) evaluated {
-	c.cycleErr = true
-	c.constraints = append(c.constraints, constraint)
-	return ret
+func debugStr(ctx *context, v adt.Node) string {
+	return debug.NodeString(ctx.opCtx, v, nil)
 }
 
-func (c *context) processDelayedConstraints() evaluated {
-	cons := c.constraints
-	c.constraints = c.constraints[:0]
-	for _, dc := range cons {
-		v := binOp(c, dc, dc.Op, dc.X.evalPartial(c), dc.Y.evalPartial(c))
-		if isBottom(v) {
-			return v
-		}
+func (c *context) str(v adt.Node) string {
+	return debugStr(c, v)
+}
+
+func (c *context) mkErr(src source, args ...interface{}) *bottom {
+	return c.index.mkErr(src, args...)
+}
+
+func (c *context) vertex(v *adt.Vertex) *adt.Vertex {
+	return v
+}
+
+// vertex returns the evaluated vertex of v.
+func (v Value) vertex(ctx *context) *adt.Vertex {
+	return ctx.vertex(v.v)
+}
+
+// eval returns the evaluated value. This may not be the vertex.
+//
+// Deprecated: use ctx.value
+func (v Value) eval(ctx *context) adt.Value {
+	if v.v == nil {
+		panic("undefined value")
 	}
-	return nil
-}
-
-func (c *context) deref(f scope) scope {
-outer:
-	for {
-		for i := 0; i < len(c.forwardMap); i += 2 {
-			if c.forwardMap[i] == f {
-				f = c.forwardMap[i+1]
-				continue outer
-			}
-		}
-		return f
+	x := ctx.manifest(v.v)
+	switch x.Kind() {
+	case adt.StructKind, adt.ListKind:
+		return x
+	default:
+		return x.Value
 	}
 }
 
-func (c *context) pushForwards(pairs ...scope) *context {
-	c.oldSize = append(c.oldSize, len(c.forwardMap))
-	c.forwardMap = append(c.forwardMap, pairs...)
-	return c
-}
+// func (v Value) evalFull(u value) (Value, adt.Value) {
+// 	ctx := v.ctx()
+// 	x := ctx.manifest(u)
+// }
 
-func (c *context) popForwards() {
-	last := len(c.oldSize) - 1
-	c.forwardMap = c.forwardMap[:c.oldSize[last]]
-	c.oldSize = c.oldSize[:last]
+// TODO: change from Vertex to Vertex.
+func (c *context) manifest(v *adt.Vertex) *adt.Vertex {
+	v.Finalize(c.opCtx)
+	return v
 }
diff --git a/cue/copy.go b/cue/copy.go
deleted file mode 100644
index d60f18f..0000000
--- a/cue/copy.go
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright 2018 The 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
-
-func (c *context) copy(v value) value {
-	// return v.copy(c)
-	return rewrite(c, v, rewriteCopy)
-}
-
-func rewriteCopy(ctx *context, v value) (value, bool) {
-	switch x := v.(type) {
-	case *nodeRef:
-		node := ctx.deref(x.node)
-		if node == x.node {
-			return x, false
-		}
-		return &nodeRef{x.baseValue, node, x.label}, false
-
-	case *structLit:
-		arcs := make(arcs, len(x.Arcs))
-
-		obj := &structLit{x.baseValue, nil, nil, x.closeStatus, nil, arcs, nil}
-
-		defer ctx.pushForwards(x, obj).popForwards()
-
-		emit := x.emit
-		if emit != nil {
-			emit = ctx.copy(x.emit)
-		}
-		obj.emit = emit
-
-		fn := func(v value) value { return ctx.copy(v) }
-		o, err := x.optionals.rewrite(fn)
-		if err != nil {
-			return err, false
-		}
-		obj.optionals = o
-
-		for i, a := range x.Arcs {
-			a.setValue(ctx.copy(a.v))
-			arcs[i] = a
-		}
-
-		comp := make([]compValue, len(x.comprehensions))
-		for i, c := range x.comprehensions {
-			comp[i] = compValue{c.checked, ctx.copy(c.comp)}
-		}
-		obj.comprehensions = comp
-		return obj, false
-
-	case *lambdaExpr:
-		arcs := make([]arc, len(x.arcs))
-		for i, a := range x.arcs {
-			arcs[i] = arc{Label: a.Label, v: ctx.copy(a.v)}
-		}
-		lambda := &lambdaExpr{x.baseValue, &params{arcs}, nil}
-		defer ctx.pushForwards(x, lambda).popForwards()
-
-		lambda.value = ctx.copy(x.value)
-		return lambda, false
-	}
-	return v, true
-}
diff --git a/internal/legacy/cue/cue.go b/cue/cue.go
similarity index 100%
rename from internal/legacy/cue/cue.go
rename to cue/cue.go
diff --git a/cue/debug.go b/cue/debug.go
deleted file mode 100644
index 12cd4d9..0000000
--- a/cue/debug.go
+++ /dev/null
@@ -1,540 +0,0 @@
-// Copyright 2018 The 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 (
-	"bytes"
-	"fmt"
-	"strconv"
-	"strings"
-
-	"cuelang.org/go/cue/ast"
-)
-
-func debugStr(ctx *context, v value) string {
-	p := newPrinter(ctx)
-	p.showNodeRef = true
-	p.str(v)
-	return p.w.String()
-}
-
-func (c *context) str(v value) string {
-	p := newPrinter(c)
-	p.str(v)
-	return p.w.String()
-}
-
-func (c *context) ref(v scope) string {
-	v = c.deref(v)
-	if c.nodeRefs == nil {
-		c.nodeRefs = map[scope]string{}
-	}
-	ref, ok := c.nodeRefs[v]
-	if ok {
-		return ref
-	}
-	ref = strconv.Itoa(len(c.nodeRefs))
-	c.nodeRefs[v] = ref
-	return ref
-}
-
-func (c *context) indent() {
-	fmt.Print(strings.Repeat("    ", c.level))
-}
-
-func (c *context) debugPrint(args ...interface{}) {
-	if c.trace {
-		c.indent()
-		c.println(args...)
-	}
-}
-
-func (c *context) println(args ...interface{}) {
-	for i, a := range args {
-		if i != 0 {
-			fmt.Print(" ")
-		}
-		switch x := a.(type) {
-		case value:
-			fmt.Print(debugStr(c, x))
-		default:
-			fmt.Print(x)
-		}
-	}
-	fmt.Println()
-}
-
-// func trace(c *context, r rewriter, n *node) (*context, rewriter, *node) {
-// 	n = derefNode(n)
-// 	name := "evaluate"
-// 	if r != nil {
-// 		name = fmt.Sprintf("%T", r)
-// 	}
-// 	c.debugPrint("---", name, c.ref(n))
-// 	if n.obj != nil {
-// 		c.debugPrint("<<< node: ", debugStr(c, n.obj))
-// 	}
-// 	if n.expr != nil {
-// 		c.debugPrint("<<< expr: ", debugStr(c, n.expr))
-// 	}
-// 	if n.value != nil {
-// 		c.debugPrint("<<< value:", debugStr(c, n.value))
-// 	}
-// 	c.level++
-// 	return c, r, n
-// }
-
-// func un(c *context, r rewriter, n *node) {
-// 	n = derefNode(n)
-// 	c.level--
-// 	if n.expr != nil {
-// 		c.debugPrint(">>> expr:", debugStr(c, n.expr))
-// 	}
-// 	if n.value != nil {
-// 		c.debugPrint(">>> value:", debugStr(c, n.value))
-// 	}
-// 	if n.obj != nil {
-// 		c.debugPrint(">>> node: ", debugStr(c, n.obj))
-// 	}
-// }
-
-func indent(c *context, msg string, x value) (_ *context, m, v string) {
-	str := debugStr(c, x)
-	c.debugPrint("...", msg)
-	c.level++
-	c.debugPrint("in:", str)
-	return c, msg, str
-}
-
-func uni(c *context, msg, oldValue string) {
-	c.debugPrint("was:   ", oldValue)
-	c.level--
-	c.debugPrint("...", msg)
-}
-
-func newPrinter(ctx *context) *printer {
-	return &printer{
-		ctx: ctx,
-		w:   &bytes.Buffer{},
-	}
-}
-
-type printer struct {
-	ctx         *context
-	w           *bytes.Buffer
-	showNodeRef bool
-}
-
-func (p *printer) label(f label) string {
-	if p.ctx == nil {
-		return strconv.Itoa(int(f))
-	}
-
-	str := p.ctx.LabelStr(f)
-	if strings.HasPrefix(str, "#") && !f.IsDef() ||
-		strings.HasPrefix(str, "_") && !f.IsHidden() ||
-		!ast.IsValidIdent(str) {
-		return strconv.Quote(str)
-	}
-	return str
-}
-
-func (p *printer) writef(format string, args ...interface{}) {
-	fmt.Fprintf(p.w, format, args...)
-}
-
-func (p *printer) write(args ...interface{}) {
-	fmt.Fprint(p.w, args...)
-}
-
-func lambdaName(f label, v value) label {
-	switch x := v.(type) {
-	case *nodeRef:
-		return lambdaName(f, x.node)
-	case *lambdaExpr:
-		if f == 0 && len(x.params.arcs) == 1 {
-			return x.params.arcs[0].Label
-		}
-	}
-	return f
-}
-
-func (p *printer) str(v interface{}) {
-	writef := p.writef
-	write := p.write
-	switch x := v.(type) {
-	case nil:
-		write("*nil*")
-	case string:
-		write(x)
-	case *builtin:
-		write(x.name(p.ctx))
-	case *nodeRef:
-		if p.showNodeRef {
-			writef("<%s>", p.ctx.ref(x.node))
-		}
-	case *selectorExpr:
-		f := lambdaName(x.Sel, x.X)
-		if _, ok := x.X.(*nodeRef); ok && !p.showNodeRef {
-			write(p.label(f))
-		} else {
-			p.str(x.X)
-			writef(".%v", p.label(f))
-		}
-	case *indexExpr:
-		p.str(x.X)
-		write("[")
-		p.str(x.Index)
-		write("]")
-	case *sliceExpr:
-		p.str(x.X)
-		write("[")
-		if x.Lo != nil {
-			p.str(x.Lo)
-		}
-		write(":")
-		if x.Hi != nil {
-			p.str(x.Hi)
-		}
-		write("]")
-	case *callExpr:
-		p.str(x.Fun)
-		write(" (")
-		for i, a := range x.Args {
-			p.str(a)
-			if i < len(x.Args)-1 {
-				write(",")
-			}
-		}
-		write(")")
-	case *customValidator:
-		p.str(x.Builtin)
-		write(" (")
-		for i, a := range x.Args {
-			p.str(a)
-			if i < len(x.Args)-1 {
-				write(",")
-			}
-		}
-		write(")")
-	case *unaryExpr:
-		write(x.Op)
-		p.str(x.X)
-	case *binaryExpr:
-		if x.Op == opUnifyUnchecked {
-			p.str(x.X)
-			write(", ")
-			p.str(x.Y)
-			break
-		}
-		write("(")
-		p.str(x.X)
-		writef(" %v ", x.Op)
-		p.str(x.Y)
-		write(")")
-	case *unification:
-		write("(")
-		for i, v := range x.Values {
-			if i != 0 {
-				writef(" & ")
-			}
-			p.str(v)
-		}
-		write(")")
-	case *disjunction:
-		write("(")
-		for i, v := range x.Values {
-			if i != 0 {
-				writef(" | ")
-			}
-			if v.Default {
-				writef("*")
-			}
-			p.str(v.Val)
-		}
-		write(")")
-	case *lambdaExpr:
-		if p.showNodeRef {
-			writef("<%s>", p.ctx.ref(x))
-		}
-		write("(")
-		p.str(x.params.arcs)
-		write(")->")
-		v := x.value
-		// strip one layer of closeIf wrapper. Evaluation may cause one
-		// layer to have not yet been evaluated. This is fine.
-		if w, ok := v.(*closeIfStruct); ok {
-			v = w.value
-		}
-		p.str(v)
-
-	case *closeIfStruct:
-		write("close(")
-		p.str(x.value)
-		write(")")
-
-	case *optionals:
-		if x == nil {
-			break
-		}
-		wrap := func(v *optionals) {
-			if x.closed.isClosed() {
-				write("C{")
-			}
-			p.str(v)
-			if x.closed.isClosed() {
-				write("}")
-			}
-		}
-		switch {
-		case x.op == opUnify:
-			write("(")
-			wrap(x.left)
-			write(" & ")
-			wrap(x.right)
-			write(")")
-
-		case x.op == opUnifyUnchecked:
-			wrap(x.left)
-			write(", ")
-			wrap(x.right)
-
-		default:
-			for i, t := range x.fields {
-				if i > 0 {
-					write(", ")
-				}
-				write("[")
-				if t.key != nil {
-					p.str(t.key)
-				}
-				write("]: ")
-				p.str(t.value)
-			}
-		}
-
-	case *structLit:
-		if x == nil {
-			write("*nil node*")
-			break
-		}
-		if p.showNodeRef {
-			p.writef("<%s>", p.ctx.ref(x))
-		}
-		if x.closeStatus.shouldClose() {
-			write("C")
-		}
-		write("{")
-		topDefault := x.optionals.isDotDotDot()
-		if !topDefault && x.optionals != nil {
-			p.str(x.optionals)
-			write(", ")
-		}
-
-		if x.emit != nil {
-			p.str(x.emit)
-			write(", ")
-		}
-		p.str(x.Arcs)
-		for i, c := range x.comprehensions {
-			if c.checked {
-				p.write("c:")
-			}
-			p.str(c.comp)
-			if i < len(x.comprehensions)-1 {
-				p.write(", ")
-			}
-		}
-		if topDefault && !x.closeStatus.shouldClose() {
-			if len(x.Arcs) > 0 {
-				p.write(", ")
-			}
-			p.write("...")
-		}
-		write("}")
-
-	case []arc:
-		for i, a := range x {
-			p.str(a)
-
-			if i < len(x)-1 {
-				p.write(", ")
-			}
-		}
-
-	case arc:
-		n := x.v
-		str := p.label(x.Label)
-		p.writef(str)
-		if x.optional {
-			p.write("?")
-		}
-		if x.definition && !x.Label.IsDef() {
-			p.write(" :: ")
-		} else {
-			p.write(": ")
-		}
-		p.str(n)
-		if x.attrs != nil {
-			for _, a := range x.attrs.attr {
-				p.write(" ", a.text)
-			}
-		}
-
-	case *fieldComprehension:
-		p.str(x.key)
-		writef(": ")
-		p.str(x.val)
-
-	case *listComprehension:
-		writef("[")
-		p.str(x.clauses)
-		write(" ]")
-
-	case *structComprehension:
-		p.str(x.clauses)
-
-	case *yield:
-		writef(" yield ")
-		p.str(x.value)
-
-	case *feed:
-		writef(" <%s>for ", p.ctx.ref(x.fn))
-		a := x.fn.params.arcs[0]
-		p.writef(p.label(a.Label))
-		writef(", ")
-		a = x.fn.params.arcs[1]
-		p.writef(p.label(a.Label))
-		writef(" in ")
-		p.str(x.Src)
-		p.str(x.fn.value)
-
-	case *guard:
-		writef(" if ")
-		p.str(x.Condition)
-		p.str(x.Dst)
-
-	case *nullLit:
-		write("null")
-	case *boolLit:
-		writef("%v", x.B)
-	case *stringLit:
-		writef("%q", x.Str)
-	case *bytesLit:
-		str := strconv.Quote(string(x.B))
-		str = str[1 : len(str)-1]
-		writef("'%s'", str)
-	case *numLit:
-		write(x.String())
-	case *durationLit:
-		write(x.d.String())
-	case *bound:
-		switch x.k & numKind {
-		case intKind:
-			p.writef("int & ")
-		case floatKind:
-			p.writef("float & ")
-		}
-		p.writef("%v", x.Op)
-		p.str(x.Expr)
-	case *interpolation:
-		for i, e := range x.Parts {
-			if i != 0 {
-				write("+")
-			}
-			p.str(e)
-		}
-	case *list:
-		// TODO: do not evaluate
-		max := maxNum(x.len).evalPartial(p.ctx)
-		inCast := false
-		ellipsis := false
-		n, ok := max.(*numLit)
-		if !ok {
-			// TODO: do not evaluate
-			min := minNum(x.len).evalPartial(p.ctx)
-			n, _ = min.(*numLit)
-		}
-		ln := 0
-		if n != nil {
-			x, _ := n.X.Int64()
-			ln = int(x)
-		}
-		open := false
-		switch max.(type) {
-		case *top, *basicType:
-			open = true
-		}
-		if !ok || ln > len(x.elem.Arcs) {
-			if !open && !isTop(x.typ) {
-				p.str(x.len)
-				write("*[")
-				p.str(x.typ)
-				write("]")
-				if len(x.elem.Arcs) == 0 {
-					break
-				}
-				write("(")
-				inCast = true
-			}
-			ellipsis = true
-		}
-		write("[")
-		for i, a := range x.elem.Arcs {
-			p.str(a.v)
-			if i < len(x.elem.Arcs)-1 {
-				write(",")
-			}
-		}
-		if ellipsis {
-			write(", ...")
-			if !isTop(x.typ) {
-				p.str(x.typ)
-			}
-		}
-		write("]")
-		if inCast {
-			write(")")
-		}
-
-	case *bottom:
-		write("_|_")
-		if x.value != nil || x.format != "" {
-			write("(")
-			errs := x.sub
-			if errs == nil {
-				errs = []*bottom{x}
-			}
-			for i, x := range errs {
-				if i > 0 {
-					p.write(";")
-				}
-				if x.value != nil && p.showNodeRef {
-					p.str(x.value)
-					p.write(":")
-				}
-				write(x.msg())
-			}
-			write(")")
-		}
-	case *top:
-		write("_") // ⊤
-	case *basicType:
-		write(x.K.String())
-
-	default:
-		panic(fmt.Sprintf("unimplemented type %T", x))
-	}
-}
diff --git a/cue/doc.go b/cue/doc.go
deleted file mode 100644
index f91a2d3..0000000
--- a/cue/doc.go
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2018 The 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 creates, evaluates and manipulates CUE configurations.
-package cue // import "cuelang.org/go/cue"
diff --git a/cue/errors.go b/cue/errors.go
index 467254f..21ed886 100644
--- a/cue/errors.go
+++ b/cue/errors.go
@@ -18,63 +18,22 @@
 	"fmt"
 	"reflect"
 
-	"cuelang.org/go/cue/ast"
 	"cuelang.org/go/cue/errors"
 	"cuelang.org/go/cue/token"
 	"cuelang.org/go/internal/core/adt"
 )
 
-var _ errors.Error = &nodeError{}
-
-// A nodeError is an error associated with processing an AST node.
-type nodeError struct {
-	path []string // optional
-	n    ast.Node
-
-	errors.Message
-}
-
-func (n *nodeError) Error() string {
-	return errors.String(n)
-}
-
-func nodeErrorf(n ast.Node, format string, args ...interface{}) *nodeError {
-	return &nodeError{
-		n:       n,
-		Message: errors.NewMessage(format, args),
-	}
-}
-
-func (e *nodeError) Position() token.Pos {
-	return e.n.Pos()
-}
-
-func (e *nodeError) InputPositions() []token.Pos { return nil }
-
-func (e *nodeError) Path() []string {
-	return e.path
-}
-
 func (v Value) appendErr(err errors.Error, b *bottom) errors.Error {
-	switch {
-	case len(b.sub) > 0:
-		for _, b := range b.sub {
-			err = v.appendErr(err, b)
-		}
-		fallthrough
-	case b.err != nil:
-		err = errors.Append(err, b.err)
-	default:
-		err = errors.Append(err, &valueError{
-			v:   v,
-			err: b,
-		})
+	return &valueError{
+		v: v,
+		err: &adt.Bottom{
+			Err: errors.Append(err, b.Err),
+		},
 	}
-	return err
 }
 
 func (v Value) toErr(b *bottom) (err errors.Error) {
-	return v.appendErr(nil, b)
+	return &valueError{v: v, err: b}
 }
 
 var _ errors.Error = &valueError{}
@@ -90,23 +49,29 @@
 }
 
 func (e *valueError) Position() token.Pos {
-	return e.err.Pos()
+	src := e.err.Source()
+	if src == nil {
+		return token.NoPos
+	}
+	return src.Pos()
 }
 
 func (e *valueError) InputPositions() []token.Pos {
-	return e.err.Positions(e.v.ctx())
+	if e.err.Err == nil {
+		return nil
+	}
+	return e.err.Err.InputPositions()
 }
 
 func (e *valueError) Msg() (string, []interface{}) {
-	return e.err.Msg()
+	if e.err.Err == nil {
+		return "", nil
+	}
+	return e.err.Err.Msg()
 }
 
 func (e *valueError) Path() (a []string) {
-	if e.v.v == nil {
-		return nil
-	}
-	a, _ = e.v.v.appendPath(a, e.v.idx)
-	return a
+	return e.v.appendPath(nil)
 }
 
 type errCode = adt.ErrorCode
@@ -135,7 +100,10 @@
 	return false
 }
 
-var errNotExists = &bottom{Code: codeNotExist, format: "undefined value"}
+var errNotExists = &adt.Bottom{
+	Code: codeNotExist,
+	Err:  errors.Newf(token.NoPos, "undefined value"),
+}
 
 func exists(v value) bool {
 	if err, ok := v.(*bottom); ok {
@@ -144,126 +112,39 @@
 	return true
 }
 
-// bottom is the bottom of the value lattice. It is subsumed by all values.
-type bottom struct {
-	baseValue
-
-	index     *index
-	Code      errCode
-	exprDepth int
-	pos       source
-	format    string
-	args      []interface{}
-
-	err     errors.Error // pass-through from higher-level API
-	sub     []*bottom    // sub errors
-	value   value
-	wrapped *bottom
-}
-
-func (x *bottom) Kind() kind { return bottomKind }
-
-func (x *bottom) Positions(ctx *context) []token.Pos {
-	var a []token.Pos
-	if x.index != nil { // TODO: remove check?
-		a = appendPositions(ctx, nil, x.pos)
-	}
-	if w := x.wrapped; w != nil {
-		a = append(a, w.Positions(ctx)...)
-	}
-	for _, sub := range x.sub {
-		a = append(a, sub.Positions(ctx)...)
-	}
-	return a
-}
-
-func appendPositions(ctx *context, pos []token.Pos, src source) []token.Pos {
-	if len(pos) > 15 {
-		return pos
-	}
-	if src != nil {
-		if p := src.Pos(); p != token.NoPos {
-			pos = append(pos, src.Pos())
-		}
-		if c := src.computed(); c != nil {
-			pos = appendPositions(ctx, pos, c.x)
-			pos = appendPositions(ctx, pos, c.y)
-		}
-		switch x := src.(type) {
-		case evaluated:
-		case value:
-			pos = appendPositions(ctx, pos, x.evalPartial(ctx))
-		}
-	}
-	return pos
-}
-
-func (x *bottom) Msg() (format string, args []interface{}) {
-	ctx := x.index.newContext()
-	// We need to copy to avoid races.
-	args = make([]interface{}, len(x.args))
-	copy(args, x.args)
-	preEvalArgs(ctx, args)
-	return x.format, x.args
-}
-
-func (x *bottom) msg() string {
-	return fmt.Sprint(x)
-}
-
-func (x *bottom) Format(s fmt.State, verb rune) {
-	msg, args := x.Msg()
-	fmt.Fprintf(s, msg, args...)
-}
-
-func cycleError(v evaluated) *bottom {
-	if err, ok := v.(*bottom); ok && err.Code == codeCycle {
-		return err
-	}
-	return nil
-}
-
-func (c *context) mkIncompatible(src source, op op, a, b evaluated) evaluated {
-	if err := firstBottom(a, b); err != nil {
-		return err
-	}
-	e := mkBin(c, src.Pos(), op, a, b)
-	return c.mkErr(e, "invalid operation %s %s %s (mismatched types %s and %s)",
-		c.str(a), op, c.str(b), a.Kind(), b.Kind())
-}
-
 func (idx *index) mkErr(src source, args ...interface{}) *bottom {
-	e := &bottom{index: idx, pos: src}
-	if src != nil {
-		e.baseValue = src.base()
-	}
-	if v, ok := src.(value); ok {
-		e.value = v
-	}
+	var e *adt.Bottom
+	var code errCode = -1
 outer:
 	for i, a := range args {
 		switch x := a.(type) {
 		case errCode:
-			e.Code = x
+			code = x
 		case *bottom:
-			e.wrapped = x
+			e = adt.CombineErrors(nil, e, x)
 		case []*bottom:
-			e.sub = x
+			for _, b := range x {
+				e = adt.CombineErrors(nil, e, b)
+			}
 		case errors.Error:
-			e.err = x
+			e = adt.CombineErrors(nil, e, &adt.Bottom{Err: x})
 		case value:
 		case string:
-			e.format = x
-			e.args = args[i+1:]
+			args := args[i+1:]
 			// Do not expand message so that errors can be localized.
-			for i, a := range e.args {
-				e.args[i] = fixArg(idx, a)
+			pos := pos(src)
+			if code < 0 {
+				code = 0
 			}
+			e = adt.CombineErrors(nil, e, &adt.Bottom{
+				Code: code,
+				Err:  errors.Newf(pos, x, args...),
+			})
 			break outer
 		}
 	}
-	if e.Code == codeNone && e.wrapped != nil {
-		e.Code = e.wrapped.Code
+	if code >= 0 {
+		e.Code = code
 	}
 	return e
 }
@@ -283,22 +164,12 @@
 	return fmt.Sprint(x)
 }
 
-// preEvalArgs is used to expand value arguments just before printing.
-func preEvalArgs(ctx *context, args []interface{}) {
-	for i, a := range args {
-		switch v := a.(type) {
-		case *bottom:
-			args[i] = v.msg()
-		case value:
-			// TODO: convert to Go values so that localization frameworks
-			// can format values accordingly.
-			args[i] = ctx.str(v)
-		}
+func isBottom(x adt.Node) bool {
+	if x == nil {
+		return true
 	}
-}
-
-func isBottom(n value) bool {
-	return n.Kind() == bottomKind
+	b, _ := x.(*adt.Bottom)
+	return b != nil
 }
 
 func firstBottom(v ...value) *bottom {
diff --git a/cue/eval.go b/cue/eval.go
deleted file mode 100644
index b995a86..0000000
--- a/cue/eval.go
+++ /dev/null
@@ -1,693 +0,0 @@
-// Copyright 2018 The 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 (
-	"bytes"
-)
-
-type resolver interface {
-	reference(ctx *context) value
-}
-
-var _ resolver = &selectorExpr{}
-var _ resolver = &indexExpr{}
-
-// decycleRef rewrites a reference that resolves to an evaluation cycle to
-// an embedding that can be unified as is.
-func decycleRef(ctx *context, v value) (value, scope) {
-	switch x := v.(type) {
-	case *selectorExpr:
-		v, sc := decycleRef(ctx, x.X)
-		if v == nil {
-			e := x.evalPartial(ctx)
-			v = e
-			if cycleError(e) != nil {
-				sc = &structLit{baseValue: x.base()}
-				return &nodeRef{x.base(), sc, x.Sel}, sc
-			}
-			return nil, nil
-		}
-		return &selectorExpr{x.baseValue, v, x.Sel}, sc
-	case *indexExpr:
-		v, sc := decycleRef(ctx, x.X)
-		if v == x {
-			return nil, nil
-		}
-		return &indexExpr{x.baseValue, v, x.Index}, sc
-	case *nodeRef:
-		return nil, nil
-	}
-	return v, nil
-}
-
-func resolveReference(ctx *context, v value) evaluated {
-	if r, ok := v.(resolver); ok {
-		e := r.reference(ctx)
-		if st, ok := e.(*structLit); ok {
-			return st
-		}
-		if b, ok := e.(*bottom); ok {
-			if b := cycleError(b); b != nil {
-				// This is only called if we are unifying. The value referenced
-				// is either a struct or not. In case the other value is not a
-				// struct, we ensure an error by returning a struct. In case the
-				// value is a struct, we postpone the evaluation of this
-				// reference by creating an embedding for it (which are
-				// evaluated after evaluating the struct itself.)
-				if y, sc := decycleRef(ctx, v); y != v {
-					st := &structLit{baseValue: v.base()}
-					ctx.pushForwards(sc, st)
-					cp := ctx.copy(y)
-					ctx.popForwards()
-					st.comprehensions = []compValue{{comp: cp}}
-					return st
-				}
-				return b
-			}
-		}
-	}
-	return v.evalPartial(ctx)
-}
-
-func eval(idx *index, v value) evaluated {
-	ctx := idx.newContext()
-	return v.evalPartial(ctx)
-}
-
-func (x *nodeRef) evalPartial(ctx *context) (result evaluated) {
-	return x.node.evalPartial(ctx)
-}
-
-// Atoms
-
-func (x *top) evalPartial(ctx *context) evaluated    { return x }
-func (x *bottom) evalPartial(ctx *context) evaluated { return x }
-
-func (x *basicType) evalPartial(ctx *context) evaluated   { return x }
-func (x *nullLit) evalPartial(ctx *context) evaluated     { return x }
-func (x *boolLit) evalPartial(ctx *context) evaluated     { return x }
-func (x *stringLit) evalPartial(ctx *context) evaluated   { return x }
-func (x *bytesLit) evalPartial(ctx *context) evaluated    { return x }
-func (x *numLit) evalPartial(ctx *context) evaluated      { return x }
-func (x *durationLit) evalPartial(ctx *context) evaluated { return x }
-
-func (x *lambdaExpr) evalPartial(ctx *context) evaluated {
-	return ctx.deref(x).(*lambdaExpr)
-}
-
-func (x *selectorExpr) evalPartial(ctx *context) (result evaluated) {
-	if ctx.trace {
-		defer uni(indent(ctx, "selectorExpr", x))
-		defer func() { ctx.debugPrint("result:", result) }()
-	}
-
-	e := newEval(ctx, true)
-
-	const msgType = "invalid operation: %[5]s (type %[3]s does not support selection)"
-	v := e.eval(x.X, structKind|lambdaKind, msgType, x)
-
-	if e.is(v, structKind|lambdaKind, "") {
-		sc, ok := v.(scope)
-		if !ok {
-			return ctx.mkErr(x, "invalid subject to selector (found %v)", v.Kind())
-		}
-		n := sc.Lookup(ctx, x.Sel)
-		if n.optional {
-			field := ctx.LabelStr(x.Sel)
-			return ctx.mkErr(x, codeIncomplete, "field %q is optional", field)
-		}
-		if n.val() == nil {
-			field := ctx.LabelStr(x.Sel)
-			if st, ok := sc.(*structLit); ok && !st.isClosed() {
-				return ctx.mkErr(x, codeIncomplete, "undefined field %q", field)
-			}
-			//	m.foo undefined (type map[string]bool has no field or method foo)
-			// TODO: mention x.x in error message?
-			return ctx.mkErr(x, "undefined field %q", field)
-		}
-		return n.Value
-	}
-	return e.err(&selectorExpr{x.baseValue, v, x.Sel})
-}
-
-func (x *selectorExpr) reference(ctx *context) (result value) {
-	if ctx.trace {
-		defer uni(indent(ctx, "selectorExpr", x))
-		defer func() { ctx.debugPrint("result:", result) }()
-	}
-
-	e := newEval(ctx, true)
-
-	const msgType = "invalid operation: %[5]s (type %[3]s does not support selection)"
-	v := e.eval(x.X, structKind|lambdaKind, msgType, x)
-
-	if e.is(v, structKind|lambdaKind, "") {
-		sc, ok := v.(scope)
-		if !ok {
-			return ctx.mkErr(x, "invalid subject to selector (found %v)", v.Kind())
-		}
-		n := sc.Lookup(ctx, x.Sel)
-		if n.optional {
-			field := ctx.LabelStr(x.Sel)
-			return ctx.mkErr(x, codeIncomplete, "field %q is optional", field)
-		}
-		if n.val() == nil {
-			field := ctx.LabelStr(x.Sel)
-			if st, ok := sc.(*structLit); ok && !st.isClosed() {
-				return ctx.mkErr(x, codeIncomplete, "undefined field %q", field)
-			}
-			//	m.foo undefined (type map[string]bool has no field or method foo)
-			// TODO: mention x.x in error message?
-			return ctx.mkErr(x, "undefined field %q", field)
-		}
-		return n.v
-	}
-	return e.err(&selectorExpr{x.baseValue, v, x.Sel})
-}
-
-func (x *indexExpr) evalPartial(ctx *context) (result evaluated) {
-	if ctx.trace {
-		defer uni(indent(ctx, "indexExpr", x))
-		defer func() { ctx.debugPrint("result:", result) }()
-	}
-
-	e := newEval(ctx, true)
-
-	const msgType = "invalid operation: %[5]s (type %[3]s does not support indexing)"
-	const msgIndexType = "invalid %[5]s index %[1]s (type %[3]s)"
-
-	val := e.eval(x.X, listKind|structKind, msgType, x)
-	k := val.Kind()
-	index := e.eval(x.Index, stringKind|intKind, msgIndexType, k)
-
-	switch v := val.(type) {
-	case *structLit:
-		if e.is(index, stringKind, msgIndexType, k) {
-			s := index.strValue()
-			// TODO: must lookup
-			n := v.Lookup(ctx, ctx.StrLabel(s))
-			if n.definition {
-				return ctx.mkErr(x, index,
-					"field %q is a definition", s)
-			}
-			if n.optional {
-				return ctx.mkErr(x, index, codeIncomplete, "field %q is optional", s)
-			}
-			if n.val() == nil {
-				if !v.isClosed() {
-					return ctx.mkErr(x, index, codeIncomplete, "undefined field %q", s)
-				}
-				return ctx.mkErr(x, index, "undefined field %q", s)
-			}
-			return n.Value
-		}
-	case atter:
-		if e.is(index, intKind, msgIndexType, k) {
-			i := index.(*numLit).intValue(ctx)
-			if i < 0 {
-				const msg = "invalid %[4]s index %[1]s (index must be non-negative)"
-				return e.mkErr(x.Index, index, 0, k, msg)
-			}
-			return v.at(ctx, i)
-		}
-	}
-	return e.err(&indexExpr{x.baseValue, val, index})
-}
-
-func (x *indexExpr) reference(ctx *context) (result value) {
-	if ctx.trace {
-		defer uni(indent(ctx, "indexExpr", x))
-		defer func() { ctx.debugPrint("result:", result) }()
-	}
-
-	e := newEval(ctx, true)
-
-	const msgType = "invalid operation: %[5]s (type %[3]s does not support indexing)"
-	const msgIndexType = "invalid %[5]s index %[1]s (type %[3]s)"
-
-	val := e.eval(x.X, listKind|structKind, msgType, x)
-	k := val.Kind()
-	index := e.eval(x.Index, stringKind|intKind, msgIndexType, k)
-
-	switch v := val.(type) {
-	case *structLit:
-		if e.is(index, stringKind, msgIndexType, k) {
-			s := index.strValue()
-			// TODO: must lookup
-			n := v.Lookup(ctx, ctx.StrLabel(s))
-			if n.definition {
-				return ctx.mkErr(x, index,
-					"field %q is a definition", s)
-			}
-			if n.optional {
-				return ctx.mkErr(x, index, codeIncomplete, "field %q is optional", s)
-			}
-			if n.val() == nil {
-				if !v.isClosed() {
-					return ctx.mkErr(x, index, codeIncomplete, "undefined field %q", s)
-				}
-				return ctx.mkErr(x, index, "undefined field %q", s)
-			}
-			return n.v
-		}
-	case *list:
-		if e.is(index, intKind, msgIndexType, k) {
-			i := index.(*numLit).intValue(ctx)
-			if i < 0 {
-				const msg = "invalid %[4]s index %[1]s (index must be non-negative)"
-				return e.mkErr(x.Index, index, 0, k, msg)
-			}
-			return v.iterAt(ctx, i).v
-		}
-
-	case atter:
-		if e.is(index, intKind, msgIndexType, k) {
-			i := index.(*numLit).intValue(ctx)
-			if i < 0 {
-				const msg = "invalid %[4]s index %[1]s (index must be non-negative)"
-				return e.mkErr(x.Index, index, 0, k, msg)
-			}
-			return v.at(ctx, i)
-		}
-	}
-	return e.err(&indexExpr{x.baseValue, val, index})
-}
-
-// Composit
-
-func (x *sliceExpr) evalPartial(ctx *context) (result evaluated) {
-	if ctx.trace {
-		defer uni(indent(ctx, "sliceExpr", x))
-		defer func() { ctx.debugPrint("result:", result) }()
-	}
-
-	e := newEval(ctx, true)
-	const msgType = "cannot slice %[2]s (type %[3]s)"
-	const msgInvalidIndex = "invalid slice index %[1]s (type %[3]s)"
-	val := e.eval(x.X, listKind, msgType)
-	lo := e.evalAllowNil(x.Lo, intKind, msgInvalidIndex)
-	hi := e.evalAllowNil(x.Hi, intKind, msgInvalidIndex)
-	var low, high *numLit
-	if lo != nil && e.is(lo, intKind, msgInvalidIndex) {
-		low = lo.(*numLit)
-	}
-	if hi != nil && e.is(hi, intKind, msgInvalidIndex) {
-		high = hi.(*numLit)
-	}
-	if !e.hasErr() {
-		switch x := val.(type) {
-		case *list:
-			return x.slice(ctx, low, high)
-		case *stringLit:
-			return x.slice(ctx, low, high)
-		}
-	}
-	return e.err(&sliceExpr{x.baseValue, val, lo, hi})
-}
-
-// TODO: make a callExpr a binary expression
-func (x *callExpr) evalPartial(ctx *context) (result evaluated) {
-	if ctx.trace {
-		defer uni(indent(ctx, "callExpr", x))
-		defer func() {
-			ctx.debugPrint("result:", result)
-		}()
-	}
-
-	e := newEval(ctx, true)
-
-	fn := e.eval(x.Fun, lambdaKind, "cannot call non-function %[2]s (type %[3]s)")
-	args := make([]evaluated, len(x.Args))
-	for i, a := range x.Args {
-		args[i] = e.evalPartial(a, typeKinds, "never triggers")
-	}
-	if !e.hasErr() {
-		// If we have a template expression, it is either already copied it as
-		// result of a references, or it is a literal, in which case it is
-		// trivially fully evaluated.
-		return fn.(caller).call(ctx, x, args...).evalPartial(ctx)
-	}
-	// Construct a simplified call for reporting purposes.
-	err := &callExpr{x.baseValue, fn, nil}
-	for _, a := range args {
-		err.Args = append(err.Args, a)
-	}
-	return e.err(err)
-}
-
-func (x *customValidator) evalPartial(ctx *context) (result evaluated) {
-	if ctx.trace {
-		defer uni(indent(ctx, "custom", x))
-		defer func() { ctx.debugPrint("result:", result) }()
-	}
-	return x
-}
-
-func (x *bound) evalPartial(ctx *context) (result evaluated) {
-	if ctx.trace {
-		defer uni(indent(ctx, "bound", x))
-		defer func() { ctx.debugPrint("result:", result) }()
-	}
-	v := x.Expr.evalPartial(ctx)
-	if isBottom(v) {
-		if isIncomplete(v) {
-			return v
-		}
-		return ctx.mkErr(x, v, "error evaluating bound")
-	}
-	if v == x.Expr {
-		return x
-	}
-	return newBound(ctx, x.baseValue, x.Op, x.k, v)
-}
-
-func (x *interpolation) evalPartial(ctx *context) (result evaluated) {
-	if ctx.trace {
-		defer uni(indent(ctx, "interpolation", x))
-		defer func() { ctx.debugPrint("result:", result) }()
-	}
-	buf := bytes.Buffer{}
-	var incomplete value
-	for _, v := range x.Parts {
-		switch e := ctx.manifest(v).(type) {
-		case *bottom:
-			return e
-		case *stringLit, *numLit, *durationLit:
-			buf.WriteString(e.strValue())
-		default:
-			k := e.Kind()
-			if k&stringableKind == bottomKind {
-				return ctx.mkErr(e, "expression in interpolation must evaluate to a number kind or string (found %v)", k)
-			}
-			if !k.isGround() {
-				incomplete = v
-			}
-		}
-	}
-	if incomplete != nil {
-		return ctx.mkErr(incomplete, codeIncomplete,
-			"incomplete value '%s' in interpolation", ctx.str(incomplete))
-	}
-	return &stringLit{x.baseValue, buf.String(), nil}
-}
-
-func (x *list) evalPartial(ctx *context) (result evaluated) {
-	if ctx.trace {
-		defer uni(indent(ctx, "list", x))
-		defer func() { ctx.debugPrint("result:", result) }()
-	}
-	n := x.len.evalPartial(ctx)
-	if isBottom(n) {
-		return n
-	}
-	s := x.elem.evalPartial(ctx).(*structLit)
-	if s == x.elem && n == x.len {
-		return x
-	}
-	return &list{x.baseValue, s, x.typ, n}
-}
-
-func (x *listComprehension) evalPartial(ctx *context) evaluated {
-	s := &structLit{baseValue: x.baseValue}
-	list := &list{baseValue: x.baseValue, elem: s}
-	err := x.clauses.yield(ctx, func(v evaluated) *bottom {
-		list.elem.Arcs = append(list.elem.Arcs, arc{
-			Label: label(len(list.elem.Arcs)),
-			v:     v.evalPartial(ctx),
-		})
-		return nil
-	})
-	if err != nil {
-		return err
-	}
-	list.initLit()
-	return list
-}
-
-func (x *structComprehension) evalPartial(ctx *context) evaluated {
-	var st evaluated = &structLit{baseValue: x.baseValue}
-	err := x.clauses.yield(ctx, func(v evaluated) *bottom {
-		embed := v.evalPartial(ctx)
-		if st, ok := embed.(*structLit); ok {
-			x, err := st.expandFields(ctx)
-			if err != nil {
-				return err
-			}
-			embed = x
-		}
-		res := binOp(ctx, x, opUnify, st, embed)
-		if b, ok := res.(*bottom); ok {
-			return b
-		}
-		st = res
-		return nil
-	})
-	if err != nil {
-		return err
-	}
-	return st
-}
-
-func (x *feed) evalPartial(ctx *context) evaluated  { return x }
-func (x *guard) evalPartial(ctx *context) evaluated { return x }
-func (x *yield) evalPartial(ctx *context) evaluated { return x }
-
-func (x *fieldComprehension) evalPartial(ctx *context) evaluated {
-	k := x.key.evalPartial(ctx)
-	v := x.val
-	if err := firstBottom(k, v); err != nil {
-		return err
-	}
-	if !k.Kind().isAnyOf(stringKind) {
-		return ctx.mkErr(k, "key must be of type string")
-	}
-	f := ctx.Label(k.strValue(), true)
-	st := &structLit{baseValue: x.baseValue}
-	st.insertValue(ctx, f, x.opt, x.def, v, x.attrs, x.doc)
-	return st
-}
-
-func (x *closeIfStruct) evalPartial(ctx *context) evaluated {
-	v := x.value.evalPartial(ctx)
-	v = updateCloseStatus(ctx, v)
-	return v
-}
-
-func (x *structLit) evalPartial(ctx *context) (result evaluated) {
-	if ctx.trace {
-		defer uni(indent(ctx, "struct eval", x))
-		defer func() { ctx.debugPrint("result:", result) }()
-	}
-	x = ctx.deref(x).(*structLit)
-
-	// TODO: Handle cycle?
-
-	// TODO: would be great to be able to expand fields here. But would need
-	// some careful consideration regarding dereferencing.
-
-	return x
-}
-
-func (x *unification) evalPartial(ctx *context) (result evaluated) {
-	// By definition, all of the values in this type are already evaluated.
-	return x
-}
-
-func (x *disjunction) evalPartial(ctx *context) (result evaluated) {
-	if ctx.trace {
-		defer uni(indent(ctx, "disjunction", x))
-		defer func() { ctx.debugPrint("result:", result) }()
-	}
-
-	// decSum := false
-	if len(ctx.evalStack) > 1 {
-		ctx.inSum++
-	}
-	dn := &disjunction{
-		x.baseValue,
-		make([]dValue, 0, len(x.Values)),
-		make([]*bottom, 0, len(x.errors)),
-		x.HasDefaults,
-	}
-	changed := false
-	for _, v := range x.Values {
-		n := v.Val.evalPartial(ctx)
-		changed = changed || n != v.Val
-		// Including elements of disjunctions recursively makes default handling
-		// associative (*a | (*b|c)) == ((*a|*b) | c).
-		if d, ok := n.(*disjunction); ok {
-			changed = true
-			for _, dv := range d.Values {
-				dn.add(ctx, dv.Val, dv.Default)
-			}
-		} else {
-			dn.add(ctx, n, v.Default)
-		}
-	}
-	if !changed {
-		dn = x
-	}
-	if len(ctx.evalStack) > 1 {
-		ctx.inSum--
-	}
-	return dn.normalize(ctx, x).val
-}
-
-func (x *disjunction) manifest(ctx *context) (result evaluated) {
-	values := make([]dValue, 0, len(x.Values))
-	validValue := false
-	for _, dv := range x.Values {
-		switch {
-		case isBottom(dv.Val):
-		case dv.Default:
-			values = append(values, dv)
-		default:
-			validValue = true
-		}
-	}
-
-	switch {
-	case len(values) > 0:
-		// values contains all the valid defaults
-	case !validValue:
-		return x
-	default:
-		for _, dv := range x.Values {
-			dv.Default = false
-			values = append(values, dv)
-		}
-	}
-
-	switch len(values) {
-	case 0:
-		return x
-
-	case 1:
-		return values[0].Val.evalPartial(ctx)
-	}
-
-	x = &disjunction{x.baseValue, values, x.errors, true}
-	return x.normalize(ctx, x).val
-}
-
-func (x *binaryExpr) evalPartial(ctx *context) (result evaluated) {
-	if ctx.trace {
-		defer uni(indent(ctx, "binaryExpr", x))
-		defer func() { ctx.debugPrint("result:", result) }()
-	}
-	var left, right evaluated
-
-	if _, isUnify := x.Op.unifyType(); !isUnify {
-		ctx.incEvalDepth()
-		left = ctx.manifest(x.X)
-		right = ctx.manifest(x.Y)
-		ctx.decEvalDepth()
-
-		// TODO: allow comparing to a literal bottom only. Find something more
-		// principled perhaps. One should especially take care that two values
-		// evaluating to bottom don't evaluate to true. For now we check for
-		// bottom here and require that one of the values be a bottom literal.
-		if isLiteralBottom(x.X) || isLiteralBottom(x.Y) {
-			if b := validate(ctx, left); b != nil {
-				left = b
-			}
-			if b := validate(ctx, right); b != nil {
-				right = b
-			}
-			leftBottom := isBottom(left)
-			rightBottom := isBottom(right)
-			switch x.Op {
-			case opEql:
-				return &boolLit{x.baseValue, leftBottom == rightBottom}
-			case opNeq:
-				return &boolLit{x.baseValue, leftBottom != rightBottom}
-			}
-		}
-	} else {
-		left = resolveReference(ctx, x.X)
-		right = resolveReference(ctx, x.Y)
-
-		if err := cycleError(left); err != nil && ctx.inSum == 0 && right.Kind().isAtom() {
-			return ctx.delayConstraint(right, x)
-		}
-		if err := cycleError(right); err != nil && ctx.inSum == 0 && left.Kind().isAtom() {
-			return ctx.delayConstraint(left, x)
-		}
-
-		// check if it is a cycle that can be unwrapped.
-		// If other value is a cycle or list, return the original forwarded,
-		// but ensure the value is not cached. Object/list error?
-	}
-	return binOp(ctx, x, x.Op, left, right)
-}
-
-func (x *unaryExpr) evalPartial(ctx *context) (result evaluated) {
-	if ctx.trace {
-		defer uni(indent(ctx, "unaryExpr", x))
-		defer func() { ctx.debugPrint("result:", result) }()
-	}
-
-	return evalUnary(ctx, x, x.Op, x.X)
-}
-
-func evalUnary(ctx *context, src source, op op, x value) evaluated {
-	v := ctx.manifest(x)
-
-	const numeric = numKind | durationKind
-	kind := v.Kind()
-	switch op {
-	case opSub:
-		if kind&numeric == bottomKind {
-			return ctx.mkErr(src, "invalid operation -%s (- %s)", ctx.str(x), kind)
-		}
-		switch v := v.(type) {
-		case *numLit:
-			f := *v
-			f.X.Neg(&v.X)
-			return &f
-		case *durationLit:
-			d := *v
-			d.d = -d.d
-			return &d
-		}
-		return ctx.mkErr(src, codeIncomplete, "operand %s of '-' not concrete (was %s)", ctx.str(x), kind)
-
-	case opAdd:
-		if kind&numeric == bottomKind {
-			return ctx.mkErr(src, "invalid operation +%s (+ %s)", ctx.str(x), kind)
-		}
-		switch v := v.(type) {
-		case *numLit, *durationLit:
-			return v
-		case *top:
-			return &basicType{v.baseValue, numeric | nonGround}
-		case *basicType:
-			return &basicType{v.baseValue, (v.K & numeric) | nonGround}
-		}
-		return ctx.mkErr(src, codeIncomplete, "operand %s of '+' not concrete (was %s)", ctx.str(x), kind)
-
-	case opNot:
-		if kind&boolKind == bottomKind {
-			return ctx.mkErr(src, "invalid operation !%s (! %s)", ctx.str(x), kind)
-		}
-		switch v := v.(type) {
-		case *boolLit:
-			return &boolLit{src.base(), !v.B}
-		}
-		return ctx.mkErr(src, codeIncomplete, "operand %s of '!' not concrete (was %s)", ctx.str(x), kind)
-	}
-	return ctx.mkErr(src, "invalid operation %s%s (%s %s)", op, ctx.str(x), op, kind)
-}
diff --git a/cue/evaluator.go b/cue/evaluator.go
deleted file mode 100644
index ccdc429..0000000
--- a/cue/evaluator.go
+++ /dev/null
@@ -1,146 +0,0 @@
-// Copyright 2018 The 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
-
-func (c *context) manifest(v value) evaluated {
-	evaluated := v.evalPartial(c)
-outer:
-	switch x := evaluated.(type) {
-	case *disjunction:
-		evaluated = x.manifest(c)
-
-	case *list:
-		return x.manifest(c)
-
-	default:
-		break outer
-	}
-	return evaluated
-}
-
-type evaluator struct {
-	ctx    *context
-	bottom []*bottom
-}
-
-const (
-	// (fmt, evaluated, orig, gotKind, wantKind)
-	// "invalid [string index] -1 (index must be non-negative)"
-	// "invalid operation: %[1]s (type %[3] does not support indexing)"
-	// msgType   = "invalid %s %s (must be type %s)"
-	msgGround = "invalid non-ground value %[1]s (must be concrete %[4]s)"
-)
-
-func newEval(ctx *context, manifest bool) evaluator {
-	return evaluator{ctx: ctx}
-}
-
-func (e *evaluator) hasErr() bool {
-	return len(e.bottom) > 0
-}
-
-func (e *evaluator) mkErr(orig, eval value, code errCode, want kind, desc string, args ...interface{}) (err *bottom) {
-	args = append([]interface{}{
-		eval,
-		code,
-		desc,        // format string
-		eval,        // 1
-		orig,        // 2
-		eval.Kind(), // 3
-		want},       // 4
-		args...)
-	for i := 3; i < len(args); i++ {
-		switch v := args[i].(type) {
-		case value:
-			args[i] = e.ctx.str(v)
-		}
-	}
-	err = e.ctx.mkErr(orig, args...)
-	// TODO: maybe replace with more specific type error.
-	for i, old := range e.bottom {
-		if old == eval {
-			e.bottom[i] = err
-			return err
-		}
-	}
-	e.bottom = append(e.bottom, err)
-	return err
-}
-
-func (e *evaluator) eval(v value, want kind, desc string, extraArgs ...interface{}) evaluated {
-	eval := e.ctx.manifest(v)
-
-	if isBottom(eval) {
-		e.bottom = append(e.bottom, eval.(*bottom))
-		return eval
-	}
-	got := eval.Kind()
-	if got&want == bottomKind {
-		return e.mkErr(v, eval, codeTypeError, want, desc, extraArgs...)
-	}
-	if !got.isGround() {
-		return e.mkErr(v, eval, codeIncomplete, want, msgGround, extraArgs...)
-	}
-	return eval
-}
-
-func (e *evaluator) evalPartial(v value, want kind, desc string, extraArgs ...interface{}) evaluated {
-	eval := v.evalPartial(e.ctx)
-	if isBottom(eval) {
-		// handle incomplete errors separately?
-		e.bottom = append(e.bottom, eval.(*bottom))
-		return eval
-	}
-	got := eval.Kind()
-	if got&want == bottomKind {
-		return e.mkErr(v, eval, codeTypeError, want, desc, extraArgs...)
-	}
-	return eval
-}
-
-func (e *evaluator) evalAllowNil(v value, want kind, desc string, extraArgs ...interface{}) evaluated {
-	if v == nil {
-		return nil
-	}
-	return e.eval(v, want, desc, extraArgs...)
-}
-
-func (e *evaluator) is(v value, want kind, desc string, args ...interface{}) bool {
-	if isBottom(v) {
-		// Even though errors are ground, we treat them as not allowed.
-		return false
-	}
-	got := v.Kind()
-	if got&want == bottomKind {
-		e.mkErr(v, v, codeTypeError, want, desc, args...)
-		return false
-	}
-	// groundness must already have been checked.
-	return true
-}
-
-func (e *evaluator) err(v value) evaluated {
-	// if bottom is a fatal (not incomplete) error, return that.
-	// otherwise, try to extract a fatal error from the given value.
-	// otherwise return an incomplete error with the given value as offending.
-	for _, b := range e.bottom {
-		if b.Code != codeIncomplete {
-			return b
-		}
-	}
-	b := *e.bottom[0]
-	b.Code = codeIncomplete
-	return &b
-}
diff --git a/cue/examples_test.go b/cue/examples_test.go
deleted file mode 100644
index 889fdf1..0000000
--- a/cue/examples_test.go
+++ /dev/null
@@ -1,117 +0,0 @@
-// Copyright 2019 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_test
-
-import (
-	"fmt"
-	"log"
-
-	"cuelang.org/go/cue"
-)
-
-func ExampleRuntime_Parse() {
-	const config = `
-	msg:   "Hello \(place)!"
-	place: string | *"world"
-	`
-
-	var r cue.Runtime
-
-	instance, err := r.Compile("test", config)
-	if err != nil {
-		// handle error
-	}
-
-	str, _ := instance.Lookup("msg").String()
-	fmt.Println(str)
-
-	instance, _ = instance.Fill("you", "place")
-	str, _ = instance.Lookup("msg").String()
-	fmt.Println(str)
-
-	// Output:
-	// Hello world!
-	// Hello you!
-}
-
-func ExampleValue_Decode() {
-	type ab struct{ A, B int }
-
-	var x ab
-
-	var r cue.Runtime
-
-	i, _ := r.Compile("test", `{A: 2, B: 4}`)
-	_ = i.Value().Decode(&x)
-	fmt.Println(x)
-
-	i, _ = r.Compile("test", `{B: "foo"}`)
-	err := i.Value().Decode(&x)
-	fmt.Println(err)
-
-	// Output:
-	// {2 4}
-	// json: cannot unmarshal string into Go struct field ab.B of type int
-}
-
-func ExampleValue_Subsume() {
-	// Check compatibility of successive APIs.
-	var r cue.Runtime
-
-	inst, err := r.Compile("apis", `
-	// Release notes:
-	// - You can now specify your age and your hobby!
-	#V1: {
-		age:   >=0 & <=100
-		hobby: string
-	}
-
-	// Release notes:
-	// - People get to be older than 100, so we relaxed it.
-	// - It seems not many people have a hobby, so we made it optional.
-	#V2: {
-		age:    >=0 & <=150 // people get older now
-		hobby?: string      // some people don't have a hobby
-	}
-
-	// Release notes:
-	// - Actually no one seems to have a hobby nowadays anymore,
-	//   so we dropped the field.
-	#V3: {
-		age: >=0 & <=150
-	}`)
-
-	if err != nil {
-		fmt.Println(err)
-		// handle error
-	}
-	v1, err1 := inst.Value().FieldByName("#V1", true)
-	v2, err2 := inst.Value().FieldByName("#V2", true)
-	v3, err3 := inst.Value().FieldByName("#V3", true)
-	if err1 != nil || err2 != nil || err3 != nil {
-		log.Println(err1, err2, err3)
-	}
-
-	// Is V2 backwards compatible with V1? In other words, does V2 subsume V1?
-	err = v2.Value.Subsume(v1.Value)
-	fmt.Println("V2 is backwards compatible with V1:", err)
-
-	err = v3.Value.Subsume(v2.Value)
-	fmt.Println("V3 is backwards compatible with V2:", err)
-
-	// Output:
-	// V2 is backwards compatible with V1: <nil>
-	// V3 is backwards compatible with V2: #V2: conflicting values <=150 and string (mismatched types number and string)
-}
diff --git a/cue/export.go b/cue/export.go
deleted file mode 100644
index a581a27..0000000
--- a/cue/export.go
+++ /dev/null
@@ -1,1302 +0,0 @@
-// Copyright 2018 The 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 (
-	"fmt"
-	"math/rand"
-	"sort"
-	"strconv"
-	"strings"
-	"unicode/utf8"
-
-	"github.com/cockroachdb/apd/v2"
-
-	"cuelang.org/go/cue/ast"
-	"cuelang.org/go/cue/token"
-	"cuelang.org/go/internal"
-)
-
-func doEval(m options) bool {
-	return !m.raw
-}
-
-func exportFile(ctx *context, inst *Instance, v value, m options) (f *ast.File, imports []string) {
-	e := exporter{ctx, m, nil, map[label]bool{}, map[string]importInfo{}, false, nil}
-	top, ok := v.evalPartial(ctx).(*structLit)
-	if ok {
-		top, err := top.expandFields(ctx)
-		if err != nil {
-			v = err
-		} else {
-			for _, a := range top.Arcs {
-				e.top[a.Label] = true
-			}
-		}
-	}
-
-	value := e.expr(v)
-	return e.toFile(inst, value, m)
-}
-
-func export(ctx *context, inst *Instance, v value, m options) (n ast.Node, imports []string) {
-	e := exporter{ctx, m, nil, map[label]bool{}, map[string]importInfo{}, false, nil}
-	top, ok := v.evalPartial(ctx).(*structLit)
-	if ok {
-		top, err := top.expandFields(ctx)
-		if err != nil {
-			v = err
-		} else {
-			for _, a := range top.Arcs {
-				e.top[a.Label] = true
-			}
-		}
-	}
-
-	value := e.expr(v)
-	if len(e.imports) == 0 && inst == nil {
-		// TODO: unwrap structs?
-		return value, nil
-	}
-	return e.toFile(inst, value, m)
-}
-
-func (e *exporter) toFile(inst *Instance, value ast.Expr, m options) (n *ast.File, imports []string) {
-	file := &ast.File{}
-	if inst != nil {
-		if inst.PkgName != "" {
-			p := &ast.Package{Name: ast.NewIdent(inst.PkgName)}
-			file.Decls = append(file.Decls, p)
-			if m.docs {
-				for _, d := range inst.Doc() {
-					p.AddComment(d)
-					break
-				}
-			}
-		}
-	}
-
-	imports = make([]string, 0, len(e.imports))
-	for k := range e.imports {
-		imports = append(imports, k)
-	}
-	sort.Strings(imports)
-
-	if len(imports) > 0 {
-		importDecl := &ast.ImportDecl{}
-		file.Decls = append(file.Decls, importDecl)
-
-		for _, k := range imports {
-			info := e.imports[k]
-			ident := (*ast.Ident)(nil)
-			if info.name != "" {
-				ident = ast.NewIdent(info.name)
-			}
-			if info.alias != "" {
-				file.Decls = append(file.Decls, &ast.LetClause{
-					Ident: ast.NewIdent(info.alias),
-					Expr:  ast.NewIdent(info.short),
-				})
-			}
-			importDecl.Specs = append(importDecl.Specs, ast.NewImport(ident, k))
-		}
-	}
-
-	if obj, ok := value.(*ast.StructLit); ok {
-		file.Decls = append(file.Decls, obj.Elts...)
-	} else {
-		file.Decls = append(file.Decls, &ast.EmbedDecl{Expr: value})
-	}
-
-	// resolve the file.
-	return file, imports
-}
-
-type exporter struct {
-	ctx     *context
-	mode    options
-	stack   []remap
-	top     map[label]bool        // label to alias or ""
-	imports map[string]importInfo // pkg path to info
-	inDef   bool                  // TODO(recclose):use count instead
-
-	incomplete []source
-}
-
-func (p *exporter) addIncomplete(v value) {
-	// TODO: process incomplete values
-}
-
-type importInfo struct {
-	name  string
-	short string
-	alias string
-}
-
-type remap struct {
-	key  scope // structLit or params
-	from label
-	to   *ast.Ident
-	syn  *ast.StructLit
-}
-
-func (p *exporter) unique(s string) string {
-	s = strings.ToUpper(s)
-	lab := s
-	for {
-		if !p.ctx.HasLabel(lab) {
-			p.ctx.Label(lab, true)
-			break
-		}
-		lab = s + fmt.Sprintf("%0.6x", rand.Intn(1<<24))
-	}
-	return lab
-}
-
-func (p *exporter) label(f label) ast.Label {
-	str := p.ctx.LabelStr(f)
-	if strings.HasPrefix(str, "#") && !f.IsDef() ||
-		strings.HasPrefix(str, "_") && !f.IsHidden() ||
-		!ast.IsValidIdent(str) {
-		return ast.NewLit(token.STRING, strconv.Quote(str))
-	}
-	return &ast.Ident{Name: str}
-}
-
-func (p *exporter) identifier(f label) *ast.Ident {
-	str := p.ctx.LabelStr(f)
-	return &ast.Ident{Name: str}
-}
-
-func (p *exporter) ident(str string) *ast.Ident {
-	return &ast.Ident{Name: str}
-}
-
-func (p *exporter) clause(v value) (n ast.Clause, next yielder) {
-	switch x := v.(type) {
-	case *feed:
-		feed := &ast.ForClause{
-			Value:  p.identifier(x.fn.params.arcs[1].Label),
-			Source: p.expr(x.Src),
-		}
-		key := x.fn.params.arcs[0]
-		if p.ctx.LabelStr(key.Label) != "_" {
-			feed.Key = p.identifier(key.Label)
-		}
-		return feed, x.fn.value.(yielder)
-
-	case *guard:
-		return &ast.IfClause{Condition: p.expr(x.Condition)}, x.Dst
-	}
-	panic(fmt.Sprintf("unsupported clause type %T", v))
-}
-
-func (p *exporter) shortName(inst *Instance, preferred, pkg string) string {
-	info, ok := p.imports[pkg]
-	short := info.short
-	if !ok {
-		short = inst.PkgName
-		if _, ok := p.top[p.ctx.Label(short, true)]; ok && preferred != "" {
-			short = preferred
-			info.name = short
-		}
-		for {
-			if _, ok := p.top[p.ctx.Label(short, true)]; !ok {
-				break
-			}
-			short += "x"
-			info.name = short
-		}
-		info.short = short
-		p.top[p.ctx.Label(short, true)] = true
-		p.imports[pkg] = info
-	}
-	f := p.ctx.Label(short, true)
-	for _, e := range p.stack {
-		if e.from == f {
-			if info.alias == "" {
-				info.alias = p.unique(short)
-				p.imports[pkg] = info
-			}
-			short = info.alias
-			break
-		}
-	}
-	return short
-}
-
-func (p *exporter) mkTemplate(v value, n *ast.Ident) ast.Label {
-	var expr ast.Expr
-	if v != nil {
-		expr = p.expr(v)
-	} else {
-		expr = ast.NewIdent("string")
-	}
-	switch n.Name {
-	case "", "_":
-	default:
-		expr = &ast.Alias{Ident: n, Expr: ast.NewIdent("string")}
-	}
-	return ast.NewList(expr)
-}
-
-func hasTemplate(s *ast.StructLit) bool {
-	for _, e := range s.Elts {
-		switch f := e.(type) {
-		case *ast.Ellipsis:
-			return true
-
-		case *ast.EmbedDecl:
-			if st, ok := f.Expr.(*ast.StructLit); ok && hasTemplate(st) {
-				return true
-			}
-		case *ast.Field:
-			label := f.Label
-			if _, ok := label.(*ast.TemplateLabel); ok {
-				return true
-			}
-			if a, ok := label.(*ast.Alias); ok {
-				label, ok = a.Expr.(ast.Label)
-				if !ok {
-					return false
-				}
-			}
-			if l, ok := label.(*ast.ListLit); ok {
-				if len(l.Elts) != 1 {
-					return false
-				}
-				expr := l.Elts[0]
-				if a, ok := expr.(*ast.Alias); ok {
-					expr = a.Expr
-				}
-				if i, ok := expr.(*ast.Ident); ok {
-					if i.Name == "_" || i.Name == "string" {
-						return true
-					}
-				}
-			}
-		}
-	}
-	return false
-}
-
-func (p *exporter) showOptional() bool {
-	return !p.mode.omitOptional && !p.mode.concrete
-}
-
-func (p *exporter) closeOrOpen(s *ast.StructLit, isClosed bool) ast.Expr {
-	// Note, there is no point in printing close if we are dropping optional
-	// fields, as by this the meaning of close will change anyway.
-	if !p.showOptional() || p.mode.final {
-		return s
-	}
-	if isClosed && !p.inDef && !hasTemplate(s) {
-		return ast.NewCall(ast.NewIdent("close"), s)
-	}
-	if !isClosed && p.inDef && !hasTemplate(s) {
-		s.Elts = append(s.Elts, &ast.Ellipsis{})
-	}
-	return s
-}
-
-func (p *exporter) isComplete(v value, all bool) bool {
-	switch x := v.(type) {
-	case *numLit, *stringLit, *bytesLit, *nullLit, *boolLit:
-		return true
-	case *list:
-		if p.mode.final || !all {
-			return true
-		}
-		if x.isOpen() {
-			return false
-		}
-		for i := range x.elem.Arcs {
-			if !p.isComplete(x.at(p.ctx, i), all) {
-				return false
-			}
-		}
-		return true
-	case *structLit:
-		return !all && p.mode.final
-	case *bottom:
-		return !isIncomplete(x)
-	case *closeIfStruct:
-		return p.isComplete(x.value, all)
-	}
-	return false
-}
-
-func isDisjunction(v value) bool {
-	switch x := v.(type) {
-	case *disjunction:
-		return true
-	case *closeIfStruct:
-		return isDisjunction(x.value)
-	}
-	return false
-}
-
-func (p *exporter) recExpr(v value, e evaluated, optional bool) ast.Expr {
-	var m evaluated
-	if !p.mode.final {
-		m = e.evalPartial(p.ctx)
-	} else {
-		m = p.ctx.manifest(e)
-	}
-	isComplete := p.isComplete(m, false)
-	if optional || (!isComplete && !p.mode.concrete) {
-		if !p.mode.final {
-			// Schema mode.
-
-			// Print references as they are, if applicable.
-			//
-			// TODO: We probably should not allow resolving references in
-			// schema mode, or at most allow resolving _some_ references, like
-			// those defined outside of packages.
-			noResolve := !p.mode.resolveReferences
-			if optional {
-				// Don't resolve references when a field is optional.
-				// This may break some unnecessary cycles.
-				noResolve = true
-			}
-			if isBottom(e) || (v.Kind().hasReferences() && noResolve) {
-				return p.expr(v)
-			}
-		} else {
-			// Data mode.
-
-			if p.mode.concrete && !m.Kind().isGround() {
-				p.addIncomplete(v)
-			}
-			// TODO: do something more principled than this hack.
-			// This likely requires disjunctions to keep track of original
-			// values (so using arcs instead of values).
-			opts := options{concrete: true, raw: true}
-			p := &exporter{p.ctx, opts, p.stack, p.top, p.imports, p.inDef, nil}
-			if isDisjunction(v) || isBottom(e) {
-				return p.expr(v)
-			}
-			if v.Kind()&structKind == 0 {
-				return p.expr(e)
-			}
-			if optional || isDisjunction(e) {
-				// Break cycles: final and resolveReferences really should not be
-				// used with optional.
-				p.mode.resolveReferences = false
-				p.mode.final = false
-				return p.expr(v)
-			}
-		}
-	}
-	return p.expr(e)
-}
-
-func (p *exporter) isClosed(x *structLit) bool {
-	return x.closeStatus.shouldClose()
-}
-
-func (p *exporter) badf(msg string, args ...interface{}) ast.Expr {
-	msg = fmt.Sprintf(msg, args...)
-	bad := &ast.BadExpr{}
-	bad.AddComment(&ast.CommentGroup{
-		Doc:  true,
-		List: []*ast.Comment{{Text: "// " + msg}},
-	})
-	return bad
-}
-
-func (p *exporter) expr(v value) ast.Expr {
-	// TODO: use the raw expression for convert incomplete errors downstream
-	// as well.
-	if doEval(p.mode) || p.mode.concrete {
-		e := v.evalPartial(p.ctx)
-		x := e
-		if p.mode.final {
-			x = p.ctx.manifest(e)
-		}
-
-		if !p.isComplete(x, true) {
-			if p.mode.concrete && !x.Kind().isGround() {
-				p.addIncomplete(v)
-			}
-			switch {
-			case isBottom(e):
-				if p.mode.concrete {
-					p.addIncomplete(v)
-				}
-				p = &exporter{p.ctx, options{raw: true}, p.stack, p.top, p.imports, p.inDef, nil}
-				return p.expr(v)
-			case v.Kind().hasReferences() && !p.mode.resolveReferences:
-			case doEval(p.mode):
-				v = e
-			}
-		} else {
-			v = x
-		}
-	}
-
-	old := p.stack
-	defer func() { p.stack = old }()
-
-	// TODO: also add position information.
-	switch x := v.(type) {
-	case *builtin:
-		if x.pkg == 0 {
-			return ast.NewIdent(x.Name)
-		}
-		pkg := p.ctx.LabelStr(x.pkg)
-		inst := builtins[pkg]
-		short := p.shortName(inst, "", pkg)
-		return ast.NewSel(ast.NewIdent(short), x.Name)
-
-	case *nodeRef:
-		if x.label == 0 {
-			// NOTE: this nodeRef is used within a selector.
-			return nil
-		}
-		short := p.ctx.LabelStr(x.label)
-
-		if inst := p.ctx.getImportFromNode(x.node); inst != nil {
-			return ast.NewIdent(p.shortName(inst, short, inst.ImportPath))
-		}
-
-		// fix shadowed label.
-		return ast.NewIdent(short)
-
-	case *selectorExpr:
-		n := p.expr(x.X)
-		if n != nil {
-			return ast.NewSel(n, p.ctx.LabelStr(x.Sel))
-		}
-		f := x.Sel
-		ident := p.identifier(f)
-		node, ok := x.X.(*nodeRef)
-		if !ok {
-			return p.badf("selector without node")
-		}
-		if l, ok := node.node.(*lambdaExpr); ok && len(l.arcs) == 1 {
-			f = l.params.arcs[0].Label
-			// TODO: ensure it is shadowed.
-			ident = p.identifier(f)
-			return ident
-		}
-
-		// TODO: nodes may have been shadowed. Use different algorithm.
-		conflict := false
-		for i := len(p.stack) - 1; i >= 0; i-- {
-			e := &p.stack[i]
-			if e.from != f {
-				continue
-			}
-			if e.key != node.node {
-				conflict = true
-				continue
-			}
-			if conflict {
-				ident = e.to
-				if e.to == nil {
-					name := p.unique(p.ctx.LabelStr(f))
-					e.syn.Elts = append(e.syn.Elts, &ast.Alias{
-						Ident: p.ident(name),
-						Expr:  p.identifier(f),
-					})
-					ident = p.ident(name)
-					e.to = ident
-				}
-			}
-			break
-		}
-		return ident
-
-	case *indexExpr:
-		return &ast.IndexExpr{X: p.expr(x.X), Index: p.expr(x.Index)}
-
-	case *sliceExpr:
-		return &ast.SliceExpr{
-			X:    p.expr(x.X),
-			Low:  p.expr(x.Lo),
-			High: p.expr(x.Hi),
-		}
-
-	case *callExpr:
-		call := &ast.CallExpr{}
-		b := x.Fun.evalPartial(p.ctx)
-		if b, ok := b.(*builtin); ok {
-			call.Fun = p.expr(b)
-		} else {
-			call.Fun = p.expr(x.Fun)
-		}
-		for _, a := range x.Args {
-			call.Args = append(call.Args, p.expr(a))
-		}
-		return call
-
-	case *customValidator:
-		call := ast.NewCall(p.expr(x.Builtin))
-		for _, a := range x.Args {
-			call.Args = append(call.Args, p.expr(a))
-		}
-		return call
-
-	case *unaryExpr:
-		return &ast.UnaryExpr{Op: opMap[x.Op], X: p.expr(x.X)}
-
-	case *binaryExpr:
-		// opUnifyUnchecked: represented as embedding. The two arguments must
-		// be structs.
-		if x.Op == opUnifyUnchecked {
-			s := ast.NewStruct()
-			return p.closeOrOpen(s, p.embedding(s, x))
-		}
-		return ast.NewBinExpr(opMap[x.Op], p.expr(x.X), p.expr(x.Y))
-
-	case *bound:
-		return &ast.UnaryExpr{Op: opMap[x.Op], X: p.expr(x.Expr)}
-
-	case *unification:
-		b := boundSimplifier{p: p}
-		vals := make([]evaluated, 0, 3)
-		for _, v := range x.Values {
-			if !b.add(v) {
-				vals = append(vals, v)
-			}
-		}
-		e := b.expr(p.ctx)
-		for _, v := range vals {
-			e = wrapBin(e, p.expr(v), opUnify)
-		}
-		return e
-
-	case *disjunction:
-		if len(x.Values) == 1 {
-			return p.expr(x.Values[0].Val)
-		}
-		expr := func(v dValue) ast.Expr {
-			e := p.expr(v.Val)
-			if v.Default {
-				e = &ast.UnaryExpr{Op: token.MUL, X: e}
-			}
-			return e
-		}
-		bin := expr(x.Values[0])
-		for _, v := range x.Values[1:] {
-			bin = ast.NewBinExpr(token.OR, bin, expr(v))
-		}
-		return bin
-
-	case *closeIfStruct:
-		return p.expr(x.value)
-
-	case *structLit:
-		st, err := p.structure(x, !p.isClosed(x))
-		if err != nil {
-			return p.expr(err)
-		}
-		expr := p.closeOrOpen(st, p.isClosed(x))
-		switch {
-		// If a template is non-nil, we only show it if printing of
-		// optional fields is requested. If a struct is not closed it was
-		// already generated before. Furthermore, if if we are in evaluation
-		// mode, the struct is already unified, so there is no need to print it.
-		case p.showOptional() && p.isClosed(x) && !doEval(p.mode):
-			if x.optionals == nil {
-				break
-			}
-			p.optionals(len(x.Arcs) > 0, st, x.optionals)
-		}
-		return expr
-
-	case *fieldComprehension:
-		panic("should be handled in structLit")
-
-	case *listComprehension:
-		var clauses []ast.Clause
-		for y, next := p.clause(x.clauses); ; y, next = p.clause(next) {
-			clauses = append(clauses, y)
-			if yield, ok := next.(*yield); ok {
-				return &ast.ListComprehension{
-					Expr:    p.expr(yield.value),
-					Clauses: clauses,
-				}
-			}
-		}
-
-	case *nullLit:
-		return ast.NewNull()
-
-	case *boolLit:
-		return ast.NewBool(x.B)
-
-	case *stringLit:
-		return &ast.BasicLit{
-			Kind:  token.STRING,
-			Value: quote(x.Str, '"'),
-		}
-
-	case *bytesLit:
-		return &ast.BasicLit{
-			Kind:  token.STRING,
-			Value: quote(string(x.B), '\''),
-		}
-
-	case *numLit:
-		kind := token.FLOAT
-		if x.K&intKind != 0 {
-			kind = token.INT
-		}
-		return &ast.BasicLit{Kind: kind, Value: x.String()}
-
-	case *durationLit:
-		panic("unimplemented")
-
-	case *interpolation:
-		t := &ast.Interpolation{}
-		multiline := false
-		// TODO: mark formatting in interpolation itself.
-		for i := 0; i < len(x.Parts); i += 2 {
-			str := x.Parts[i].(*stringLit).Str
-			if strings.IndexByte(str, '\n') >= 0 {
-				multiline = true
-				break
-			}
-		}
-		quote := `"`
-		if multiline {
-			quote = `"""`
-		}
-		prefix := quote
-		suffix := `\(`
-		for i, e := range x.Parts {
-			if i%2 == 1 {
-				t.Elts = append(t.Elts, p.expr(e))
-			} else {
-				buf := []byte(prefix)
-				if i == len(x.Parts)-1 {
-					suffix = quote
-				}
-				str := e.(*stringLit).Str
-				if multiline {
-					buf = appendEscapeMulti(buf, str, '"')
-				} else {
-					buf = appendEscaped(buf, str, '"', true)
-				}
-				buf = append(buf, suffix...)
-				t.Elts = append(t.Elts, &ast.BasicLit{
-					Kind:  token.STRING,
-					Value: string(buf),
-				})
-			}
-			prefix = ")"
-		}
-		return t
-
-	case *list:
-		list := &ast.ListLit{}
-		var expr ast.Expr = list
-		for i, a := range x.elem.Arcs {
-			if !doEval(p.mode) {
-				list.Elts = append(list.Elts, p.expr(a.v))
-			} else {
-				e := x.elem.at(p.ctx, i)
-				list.Elts = append(list.Elts, p.recExpr(a.v, e, false))
-			}
-		}
-		max := maxNum(x.len)
-		num, ok := max.(*numLit)
-		if !ok {
-			min := minNum(x.len)
-			num, _ = min.(*numLit)
-		}
-		ln := 0
-		if num != nil {
-			x, _ := num.X.Int64()
-			ln = int(x)
-		}
-		open := false
-		switch max.(type) {
-		case *top, *basicType:
-			open = true
-		}
-		if !ok || ln > len(x.elem.Arcs) {
-			list.Elts = append(list.Elts, &ast.Ellipsis{Type: p.expr(x.typ)})
-			if !open && !isTop(x.typ) {
-				expr = ast.NewBinExpr(
-					token.AND,
-					ast.NewBinExpr(
-						token.MUL,
-						p.expr(x.len),
-						ast.NewList(p.expr(x.typ))),
-					list,
-				)
-
-			}
-		}
-		return expr
-
-	case *bottom:
-		err := &ast.BottomLit{}
-		if x.format != "" {
-			msg := x.msg()
-			if len(x.sub) > 0 {
-				buf := strings.Builder{}
-				for i, b := range x.sub {
-					if i > 0 {
-						buf.WriteString("; ")
-						buf.WriteString(b.msg())
-					}
-				}
-				msg = buf.String()
-			}
-			comment := &ast.Comment{Text: "// " + msg}
-			err.AddComment(&ast.CommentGroup{
-				Line:     true,
-				Position: 2,
-				List:     []*ast.Comment{comment},
-			})
-		}
-		return err
-
-	case *top:
-		return p.ident("_")
-
-	case *basicType:
-		return p.ident(x.K.String())
-
-	case *lambdaExpr:
-		return p.ident("TODO: LAMBDA")
-
-	default:
-		panic(fmt.Sprintf("unimplemented type %T", x))
-	}
-}
-
-func (p *exporter) optionalsExpr(x *optionals, isClosed bool) ast.Expr {
-	st := ast.NewStruct()
-	// An empty struct has meaning in case of closed structs, where they
-	// indicate no other fields may be added. Non-closed empty structs should
-	// have been optimized away. In case they are not, it is just a no-op.
-	if x != nil {
-		p.optionals(false, st, x)
-	}
-	if isClosed {
-		return ast.NewCall(ast.NewIdent("close"), st)
-	}
-	return st
-}
-
-func (p *exporter) optionals(wrap bool, st *ast.StructLit, x *optionals) (skippedEllipsis bool) {
-	wrap = wrap || len(x.fields) > 1
-	switch x.op {
-	default:
-		for _, t := range x.fields {
-			l, ok := t.value.evalPartial(p.ctx).(*lambdaExpr)
-			if !ok {
-				// Really should not happen.
-				continue
-			}
-			v := l.value
-			if c, ok := v.(*closeIfStruct); ok {
-				v = c.value
-			}
-			f := &ast.Field{
-				Label: p.mkTemplate(t.key, p.identifier(l.params.arcs[0].Label)),
-				Value: p.expr(l.value),
-			}
-			if internal.IsEllipsis(f) {
-				skippedEllipsis = true
-				continue
-			}
-			if !wrap {
-				st.Elts = append(st.Elts, f)
-				continue
-			}
-			st.Elts = append(st.Elts, internal.EmbedStruct(ast.NewStruct(f)))
-		}
-
-	case opUnify:
-		// Optional constraints added with normal unification are embedded as an
-		// expression. This relies on the fact that a struct embedding a closed
-		// struct will itself be closed.
-		st.Elts = append(st.Elts, &ast.EmbedDecl{Expr: &ast.BinaryExpr{
-			X:  p.optionalsExpr(x.left, x.left.isClosed()),
-			Op: token.AND,
-			Y:  p.optionalsExpr(x.right, x.right.isClosed()),
-		}})
-
-	case opUnifyUnchecked:
-		// Constraints added with unchecked unification are embedded
-		// individually. It doesn't matter here whether this originated from
-		// regular unification of open structs or embedded closed structs.
-		// The result in each case is unchecked unification.
-		left := p.optionalsExpr(x.left, false)
-		right := p.optionalsExpr(x.right, false)
-		st.Elts = append(st.Elts, &ast.EmbedDecl{Expr: left})
-		st.Elts = append(st.Elts, &ast.EmbedDecl{Expr: right})
-	}
-	return skippedEllipsis
-}
-
-func (p *exporter) structure(x *structLit, addTempl bool) (ret *ast.StructLit, err *bottom) {
-	obj := ast.NewStruct()
-	if doEval(p.mode) {
-		x, err = x.expandFields(p.ctx)
-		if err != nil {
-			return nil, err
-		}
-	}
-
-	for _, a := range x.Arcs {
-		p.stack = append(p.stack, remap{
-			key:  x,
-			from: a.Label,
-			to:   nil,
-			syn:  obj,
-		})
-	}
-	if x.emit != nil {
-		obj.Elts = append(obj.Elts, &ast.EmbedDecl{Expr: p.expr(x.emit)})
-	}
-	hasEllipsis := false
-	if p.showOptional() && x.optionals != nil &&
-		// Optional field constraints may be omitted if they were already
-		// applied and no more new fields may be added.
-		!(doEval(p.mode) && x.optionals.isEmpty() && p.isClosed(x)) {
-		hasEllipsis = p.optionals(len(x.Arcs) > 0, obj, x.optionals)
-	}
-	for i, a := range x.Arcs {
-		f := &ast.Field{
-			Label: p.label(a.Label),
-		}
-		// TODO: allow the removal of hidden fields. However, hidden fields
-		// that still used in incomplete expressions should not be removed
-		// (unless RequireConcrete is requested).
-		if a.optional {
-			// Optional fields are almost never concrete. We omit them in
-			// concrete mode to allow the user to use the -a option in eval
-			// without getting many errors.
-			if p.mode.omitOptional || p.mode.concrete {
-				continue
-			}
-			f.Optional = token.NoSpace.Pos()
-		}
-		if a.definition {
-			if p.mode.omitDefinitions || p.mode.concrete {
-				continue
-			}
-			if !internal.IsDefinition(f.Label) {
-				f.Token = token.ISA
-			}
-		}
-		if a.Label.IsHidden() && p.mode.concrete && p.mode.omitHidden {
-			continue
-		}
-		oldInDef := p.inDef
-		p.inDef = a.definition || p.inDef
-		if !doEval(p.mode) {
-			f.Value = p.expr(a.v)
-		} else {
-			f.Value = p.recExpr(a.v, x.at(p.ctx, i), a.optional)
-		}
-		p.inDef = oldInDef
-		if a.attrs != nil && !p.mode.omitAttrs {
-			for _, at := range a.attrs.attr {
-				f.Attrs = append(f.Attrs, &ast.Attribute{Text: at.text})
-			}
-		}
-		if p.mode.docs {
-			for _, d := range a.docs.appendDocs(nil) {
-				ast.AddComment(f, d)
-				break
-			}
-		}
-		obj.Elts = append(obj.Elts, f)
-	}
-
-	if !p.mode.concrete {
-		for _, v := range x.comprehensions {
-			switch c := v.comp.(type) {
-			case *fieldComprehension:
-				l := p.expr(c.key)
-				label, _ := l.(ast.Label)
-				opt := token.NoPos
-				if c.opt {
-					opt = token.NoSpace.Pos() // anything but token.NoPos
-				}
-				tok := token.COLON
-				if c.def && !internal.IsDefinition(label) {
-					tok = token.ISA
-				}
-				f := &ast.Field{
-					Label:    label,
-					Optional: opt,
-					Token:    tok,
-					Value:    p.expr(c.val),
-				}
-				obj.Elts = append(obj.Elts, f)
-
-			case *structComprehension:
-				var clauses []ast.Clause
-				next := c.clauses
-				for {
-					if yield, ok := next.(*yield); ok {
-						obj.Elts = append(obj.Elts, &ast.Comprehension{
-							Clauses: clauses,
-							Value:   p.expr(yield.value),
-						})
-						break
-					}
-
-					var y ast.Clause
-					y, next = p.clause(next)
-					clauses = append(clauses, y)
-				}
-			}
-		}
-	}
-
-	if hasEllipsis {
-		obj.Elts = append(obj.Elts, &ast.Ellipsis{})
-	}
-	return obj, nil
-}
-
-func hasBulk(a []ast.Decl) bool {
-	for _, d := range a {
-		if internal.IsBulkField(d) {
-			return true
-		}
-	}
-	return false
-}
-
-func (p *exporter) embedding(s *ast.StructLit, n value) (closed bool) {
-	switch x := n.(type) {
-	case *structLit:
-		st, err := p.structure(x, true)
-		if err != nil {
-			n = err
-			break
-		}
-		if hasBulk(st.Elts) {
-			s.Elts = append(s.Elts, internal.EmbedStruct(st))
-		} else {
-			s.Elts = append(s.Elts, st.Elts...)
-		}
-		return p.isClosed(x)
-
-	case *binaryExpr:
-		if x.Op != opUnifyUnchecked {
-			// should not happen
-			s.Elts = append(s.Elts, &ast.EmbedDecl{Expr: p.expr(x)})
-			return false
-		}
-		leftClosed := p.embedding(s, x.X)
-		rightClosed := p.embedding(s, x.Y)
-		return leftClosed || rightClosed
-	}
-	s.Elts = append(s.Elts, &ast.EmbedDecl{Expr: p.expr(n)})
-	return false
-}
-
-// quote quotes the given string.
-func quote(str string, quote byte) string {
-	if strings.IndexByte(str, '\n') < 0 {
-		buf := []byte{quote}
-		buf = appendEscaped(buf, str, quote, true)
-		buf = append(buf, quote)
-		return string(buf)
-	}
-	buf := []byte{quote, quote, quote}
-	buf = append(buf, multiSep...)
-	buf = appendEscapeMulti(buf, str, quote)
-	buf = append(buf, quote, quote, quote)
-	return string(buf)
-}
-
-// TODO: consider the best indent strategy.
-const multiSep = "\n        "
-
-func appendEscapeMulti(buf []byte, str string, quote byte) []byte {
-	// TODO(perf)
-	a := strings.Split(str, "\n")
-	for _, s := range a {
-		buf = appendEscaped(buf, s, quote, true)
-		buf = append(buf, multiSep...)
-	}
-	return buf
-}
-
-const lowerhex = "0123456789abcdef"
-
-func appendEscaped(buf []byte, s string, quote byte, graphicOnly bool) []byte {
-	for width := 0; len(s) > 0; s = s[width:] {
-		r := rune(s[0])
-		width = 1
-		if r >= utf8.RuneSelf {
-			r, width = utf8.DecodeRuneInString(s)
-		}
-		if width == 1 && r == utf8.RuneError {
-			buf = append(buf, `\x`...)
-			buf = append(buf, lowerhex[s[0]>>4])
-			buf = append(buf, lowerhex[s[0]&0xF])
-			continue
-		}
-		buf = appendEscapedRune(buf, r, quote, graphicOnly)
-	}
-	return buf
-}
-
-func appendEscapedRune(buf []byte, r rune, quote byte, graphicOnly bool) []byte {
-	var runeTmp [utf8.UTFMax]byte
-	if r == rune(quote) || r == '\\' { // always backslashed
-		buf = append(buf, '\\')
-		buf = append(buf, byte(r))
-		return buf
-	}
-	// TODO(perf): IsGraphic calls IsPrint.
-	if strconv.IsPrint(r) || graphicOnly && strconv.IsGraphic(r) {
-		n := utf8.EncodeRune(runeTmp[:], r)
-		buf = append(buf, runeTmp[:n]...)
-		return buf
-	}
-	switch r {
-	case '\a':
-		buf = append(buf, `\a`...)
-	case '\b':
-		buf = append(buf, `\b`...)
-	case '\f':
-		buf = append(buf, `\f`...)
-	case '\n':
-		buf = append(buf, `\n`...)
-	case '\r':
-		buf = append(buf, `\r`...)
-	case '\t':
-		buf = append(buf, `\t`...)
-	case '\v':
-		buf = append(buf, `\v`...)
-	default:
-		switch {
-		case r < ' ':
-			// Invalid for strings, only bytes.
-			buf = append(buf, `\x`...)
-			buf = append(buf, lowerhex[byte(r)>>4])
-			buf = append(buf, lowerhex[byte(r)&0xF])
-		case r > utf8.MaxRune:
-			r = 0xFFFD
-			fallthrough
-		case r < 0x10000:
-			buf = append(buf, `\u`...)
-			for s := 12; s >= 0; s -= 4 {
-				buf = append(buf, lowerhex[r>>uint(s)&0xF])
-			}
-		default:
-			buf = append(buf, `\U`...)
-			for s := 28; s >= 0; s -= 4 {
-				buf = append(buf, lowerhex[r>>uint(s)&0xF])
-			}
-		}
-	}
-	return buf
-}
-
-type boundSimplifier struct {
-	p *exporter
-
-	isInt  bool
-	min    *bound
-	minNum *numLit
-	max    *bound
-	maxNum *numLit
-}
-
-func (s *boundSimplifier) add(v value) (used bool) {
-	switch x := v.(type) {
-	case *basicType:
-		switch x.K & scalarKinds {
-		case intKind:
-			s.isInt = true
-			return true
-		}
-
-	case *bound:
-		if x.k&concreteKind == intKind {
-			s.isInt = true
-		}
-		switch x.Op {
-		case opGtr:
-			if n, ok := x.Expr.(*numLit); ok {
-				if s.min == nil || s.minNum.X.Cmp(&n.X) != 1 {
-					s.min = x
-					s.minNum = n
-				}
-				return true
-			}
-
-		case opGeq:
-			if n, ok := x.Expr.(*numLit); ok {
-				if s.min == nil || s.minNum.X.Cmp(&n.X) == -1 {
-					s.min = x
-					s.minNum = n
-				}
-				return true
-			}
-
-		case opLss:
-			if n, ok := x.Expr.(*numLit); ok {
-				if s.max == nil || s.maxNum.X.Cmp(&n.X) != -1 {
-					s.max = x
-					s.maxNum = n
-				}
-				return true
-			}
-
-		case opLeq:
-			if n, ok := x.Expr.(*numLit); ok {
-				if s.max == nil || s.maxNum.X.Cmp(&n.X) == 1 {
-					s.max = x
-					s.maxNum = n
-				}
-				return true
-			}
-		}
-	}
-
-	return false
-}
-
-type builtinRange struct {
-	typ string
-	lo  *apd.Decimal
-	hi  *apd.Decimal
-}
-
-func makeDec(s string) *apd.Decimal {
-	d, _, err := apd.NewFromString(s)
-	if err != nil {
-		panic(err)
-	}
-	return d
-}
-
-func (s *boundSimplifier) expr(ctx *context) (e ast.Expr) {
-	if s.min == nil || s.max == nil {
-		return nil
-	}
-	switch {
-	case s.isInt:
-		t := s.matchRange(intRanges)
-		if t != "" {
-			e = ast.NewIdent(t)
-			break
-		}
-		if sign := s.minNum.X.Sign(); sign == -1 {
-			e = ast.NewIdent("int")
-
-		} else {
-			e = ast.NewIdent("uint")
-			if sign == 0 && s.min.Op == opGeq {
-				s.min = nil
-				break
-			}
-		}
-		fallthrough
-	default:
-		t := s.matchRange(floatRanges)
-		if t != "" {
-			e = wrapBin(e, ast.NewIdent(t), opUnify)
-		}
-	}
-
-	if s.min != nil {
-		e = wrapBin(e, s.p.expr(s.min), opUnify)
-	}
-	if s.max != nil {
-		e = wrapBin(e, s.p.expr(s.max), opUnify)
-	}
-	return e
-}
-
-func (s *boundSimplifier) matchRange(ranges []builtinRange) (t string) {
-	for _, r := range ranges {
-		if !s.minNum.X.IsZero() && s.min.Op == opGeq && s.minNum.X.Cmp(r.lo) == 0 {
-			switch s.maxNum.X.Cmp(r.hi) {
-			case 0:
-				if s.max.Op == opLeq {
-					s.max = nil
-				}
-				s.min = nil
-				return r.typ
-			case -1:
-				if !s.minNum.X.IsZero() {
-					s.min = nil
-					return r.typ
-				}
-			case 1:
-			}
-		} else if s.max.Op == opLeq && s.maxNum.X.Cmp(r.hi) == 0 {
-			switch s.minNum.X.Cmp(r.lo) {
-			case -1:
-			case 0:
-				if s.min.Op == opGeq {
-					s.min = nil
-				}
-				fallthrough
-			case 1:
-				s.max = nil
-				return r.typ
-			}
-		}
-	}
-	return ""
-}
-
-var intRanges = []builtinRange{
-	{"int8", makeDec("-128"), makeDec("127")},
-	{"int16", makeDec("-32768"), makeDec("32767")},
-	{"int32", makeDec("-2147483648"), makeDec("2147483647")},
-	{"int64", makeDec("-9223372036854775808"), makeDec("9223372036854775807")},
-	{"int128", makeDec("-170141183460469231731687303715884105728"),
-		makeDec("170141183460469231731687303715884105727")},
-
-	{"uint8", makeDec("0"), makeDec("255")},
-	{"uint16", makeDec("0"), makeDec("65535")},
-	{"uint32", makeDec("0"), makeDec("4294967295")},
-	{"uint64", makeDec("0"), makeDec("18446744073709551615")},
-	{"uint128", makeDec("0"), makeDec("340282366920938463463374607431768211455")},
-
-	// {"rune", makeDec("0"), makeDec(strconv.Itoa(0x10FFFF))},
-}
-
-var floatRanges = []builtinRange{
-	// 2**127 * (2**24 - 1) / 2**23
-	{"float32",
-		makeDec("-3.40282346638528859811704183484516925440e+38"),
-		makeDec("+3.40282346638528859811704183484516925440e+38")},
-
-	// 2**1023 * (2**53 - 1) / 2**52
-	{"float64",
-		makeDec("-1.797693134862315708145274237317043567981e+308"),
-		makeDec("+1.797693134862315708145274237317043567981e+308")},
-}
-
-func wrapBin(a, b ast.Expr, op op) ast.Expr {
-	if a == nil {
-		return b
-	}
-	if b == nil {
-		return a
-	}
-	return ast.NewBinExpr(opMap[op], a, b)
-}
diff --git a/cue/export_test.go b/cue/export_test.go
deleted file mode 100644
index 96771bb..0000000
--- a/cue/export_test.go
+++ /dev/null
@@ -1,1205 +0,0 @@
-// Copyright 2018 The 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 (
-	"fmt"
-	"log"
-	"strings"
-	"testing"
-
-	"cuelang.org/go/cue/format"
-)
-
-func TestExport(t *testing.T) {
-	// Do not inline: the named struct is used as a marker in
-	// testdata/gen.go.
-	type exportTest struct {
-		raw     bool // skip evaluation the root, fully raw
-		eval    bool // evaluate the full export
-		noOpt   bool
-		in, out string
-	}
-	testCases := []exportTest{{
-		in:  `"hello"`,
-		out: `"hello"`,
-	}, {
-		in:  `'hello'`,
-		out: `'hello'`,
-	}, {
-		in: `'hello\nworld'`,
-		out: "'''" +
-			multiSep + "hello" +
-			multiSep + "world" +
-			multiSep + "'''",
-	}, {
-		in: `"hello\nworld"`,
-		out: `"""` +
-			multiSep + "hello" +
-			multiSep + "world" +
-			multiSep + `"""`,
-	}, {
-		in: `{
-			$type: 3
-			"_": int
-			"_foo": int
-			_bar: int
-		}`,
-		out: unindent(`
-		{
-			$type:  3
-			"_":    int
-			"_foo": int
-			_bar:   int
-		}`),
-	}, {
-		in: "{ a: 1, b: a + 2, c: null, d: true, e: _, f: string }",
-		out: unindent(`
-			{
-				a: 1
-				b: 3
-				c: null
-				d: true
-				e: _
-				f: string
-			}`),
-	}, {
-		// Here the failed lookups are not considered permanent
-		// failures, as the structs are open.
-		in: `{ a: { b: 2.0, s: "abc" }, b: a.b, c: a.c, d: a["d"], e: a.t[2:3] }`,
-		out: unindent(`
-			{
-				a: {
-					b: 2.0
-					s: "abc"
-				}
-				b: 2.0
-				c: a.c
-				d: a["d"]
-				e: a.t[2:3]
-			}`),
-	}, {
-		// Here the failed lookups are permanent failures as the structs are
-		// closed.
-		in: `{ #a: { b: 2.0, s: "abc" }, b: #a.b, c: #a.c, d: #a["d"], e: #a.t[2:3] }`,
-		out: unindent(`
-			{
-				#a: {
-					b: 2.0
-					s: "abc"
-				}
-				b: 2.0
-				c: _|_ // undefined field "c"
-				d: _|_ // undefined field "d"
-				e: _|_ // undefined field "t"
-			}`),
-	}, {
-		// Insert comma between error and inserted message.
-		in: `{ a: [ 3&4] }`,
-		out: unindent(`
-		{
-			a: [_|_, // conflicting values 3 and 4
-			]
-		}`),
-	}, {
-		in: `{
-			a: 5*[int]
-			a: [1, 2, ...]
-			b: <=5*[int]
-			b: [1, 2, ...]
-			c: (>=3 & <=5)*[int]
-			c: [1, 2, ...]
-			d: >=2*[int]
-			d: [1, 2, ...]
-			e: [...int]
-			e: [1, 2, ...]
-			f: [1, 2, ...]
-		}`,
-		out: unindent(`
-		{
-			a: [1, 2, int, int, int]
-			b: <=5*[int] & [1, 2, ...]
-			c: (>=3 & <=5)*[int] & [1, 2, ...]
-			d: >=2*[int] & [1, 2, ...]
-			e: [1, 2]
-			f: [1, 2]
-		}`),
-	}, {
-		raw: true,
-		in: `{
-			a: 5*[int]
-			a: [1, 2, ...]
-			b: <=5*[int]
-			b: [1, 2, ...]
-			c: (>=3 & <=5)*[int]
-			c: [1, 2, ...]
-			d: >=2*[int]
-			d: [1, 2, ...]
-			e: [...int]
-			e: [1, 2, ...]
-			f: [1, 2, ...]
-		}`,
-		out: unindent(`
-		{
-			a: 5*[int] & [1, 2, ...]
-			b: <=5*[int] & [1, 2, ...]
-			c: (>=3 & <=5)*[int] & [1, 2, ...]
-			d: >=2*[int] & [1, 2, ...]
-			e: [...int] & [1, 2, ...]
-			f: [1, 2, ...]
-		}`),
-	}, {
-		raw: true,
-		in:  `{ a: { b: [] }, c: a.b, d: a["b"] }`,
-		out: unindent(`
-			{
-				a: b: []
-				c: a.b
-				d: a["b"]
-			}`),
-	}, {
-		raw: true,
-		in:  `{ a: *"foo" | *"bar" | *string | int, b: a[2:3] }`,
-		out: unindent(`
-			{
-				a: *"foo" | *"bar" | *string | int
-				b: a[2:3]
-			}`),
-	}, {
-		in: `{
-			a: >=0 & <=10 & !=1
-		}`,
-		out: unindent(`
-			{
-				a: >=0 & <=10 & !=1
-			}`),
-	}, {
-		raw: true,
-		in: `{
-				a: >=0 & <=10 & !=1
-			}`,
-		out: unindent(`
-			{
-				a: >=0 & <=10 & !=1
-			}`),
-	}, {
-		raw:  true,
-		eval: true,
-		in: `{
-				a: (*1 | 2) & (1 | *2)
-				b: [(*1 | 2) & (1 | *2)]
-			}`,
-		out: unindent(`
-			{
-				a: 1 | 2 | *_|_
-				b: [1 | 2 | *_|_]
-			}`),
-	}, {
-		raw:  true,
-		eval: true,
-		in: `{
-				u16: int & >=0 & <=65535
-				u32: uint32
-				u64: uint64
-				u128: uint128
-				u8: uint8
-				ua: uint16 & >0
-				us: >=0 & <10_000 & int
-				i16: >=-32768 & int & <=32767
-				i32: int32 & > 0
-				i64:  int64
-				i128: int128
-				f64:  float64
-				fi:  float64 & int
-			}`,
-		out: unindent(`
-			{
-				u16:  uint16
-				u32:  uint32
-				u64:  uint64
-				u128: uint128
-				u8:   uint8
-				ua:   uint16 & >0
-				us:   uint & <10000
-				i16:  int16
-				i32:  int32 & >0
-				i64:  int64
-				i128: int128
-				f64:  float64
-				fi:   int & float64
-			}`),
-	}, {
-		raw: true,
-		in:  `{ a: [1, 2], b: { for k, v in a if v > 1 { "\(k)": v } } }`,
-		out: unindent(`
-			{
-				a: [1, 2]
-				b: {
-					for k, v in a if v > 1 {
-						"\(k)": v
-					}
-				}
-			}`),
-	}, {
-		raw: true,
-		in:  `{ a: [1, 2], b: [ for k, v in a { v }] }`,
-		out: unindent(`
-			{
-				a: [1, 2]
-				b: [ for k, v in a { v } ]
-			}`),
-	}, {
-		raw: true,
-		in:  `{ a: >=0 & <=10, b: "Count: \(a) times" }`,
-		out: unindent(`
-			{
-				a: >=0 & <=10
-				b: "Count: \(a) times"
-			}`),
-	}, {
-		raw: true,
-		in:  `{ a: "", b: len(a) }`,
-		out: unindent(`
-				{
-					a: ""
-					b: len(a)
-				}`),
-	}, {
-		raw:  true,
-		eval: true,
-		in: `{
-			b: {
-				idx: a[str]
-				str: string
-			}
-			b: a: b: 4
-			a: b: 3
-		}`,
-		// reference to a must be redirected to outer a through alias
-		out: unindent(`
-		{
-			A = a
-			b: {
-				idx: A[str]
-				a: b: 4
-				str: string
-			}
-			a: b: 3
-		}`),
-	}, {
-		raw:   true,
-		eval:  true,
-		noOpt: true,
-		in: `{
-			job: [Name=_]: {
-				name:     Name
-				replicas: uint | *1 @protobuf(10)
-				command:  string
-			}
-
-			job: list: command: "ls"
-
-			job: nginx: {
-				command:  "nginx"
-				replicas: 2
-			}
-		}`,
-		out: unindent(`
-		{
-			job: {
-				list: {
-					name:     "list"
-					replicas: >=0 | *1 @protobuf(10)
-					command:  "ls"
-				}
-				nginx: {
-					name:     "nginx"
-					replicas: 2 @protobuf(10)
-					command:  "nginx"
-				}
-			}
-		}`),
-	}, {
-		// TODO: positions of embedded structs is not preserved. Use some kind
-		// of topological sort to preserve order.
-		raw: true,
-		in: `{
-			#emb: {
-				a: 1
-
-				sub: {
-					f: 3
-				}
-			}
-			#def: {
-				#emb
-
-				b: 2
-			}
-			#f: a: 10
-			#e: {
-				#f
-
-				b: int
-				[_]: <100
-				{[_]: <300}
-			}
-		}`,
-		out: unindent(`
-		{
-			#emb: {
-				a: 1
-				sub: f: 3
-			}
-			#def: {
-				b: 2
-				#emb
-			}
-			#f: {
-				a: 10
-			}
-			#e: {
-				{[string]: <100}
-				b: int
-				#f
-				{[string]: <300}
-			}
-		}`),
-	}, {
-		raw:   true,
-		eval:  true,
-		noOpt: true,
-		in: `{
-				reg: { foo: 1, bar: { baz: 3 } }
-				#def: {
-					a: 1
-
-					sub: reg
-				}
-				val: #def
-				#def2: {
-					a: { b: int }
-				}
-				val2: #def2
-			}`,
-		out: unindent(`
-		{
-			reg: {
-				foo: 1
-				bar: baz: 3
-			}
-			#def: {
-				a:   1
-				sub: reg
-			}
-			val: #def
-			#def2: {
-				a: b: int
-			}
-			val2: #def2
-		}`),
-	}, {
-		raw:  true,
-		eval: true,
-		in: `{
-			b: [{
-				[X=_]: int
-				if a > 4 {
-					f: 4
-				}
-			}][a]
-			a: int
-			c: *1 | 2
-		}`,
-		// reference to a must be redirected to outer a through alias
-		out: unindent(`
-		{
-			b: [{
-				[X=string]: int
-				if a > 4 {
-					f: 4
-				}
-			}][a]
-			a: int
-			c: *1 | 2
-		}`),
-	}, {
-		raw: true,
-		in: `{
-			if false {
-				{ a: 1 } | { b: 1 }
-			}
-		}`,
-		// reference to a must be redirected to outer a through alias
-		out: unindent(`
-		{
-			if false {
-				{
-					a: 1
-				} | {
-					b: 1
-				}
-			}
-		}`),
-	}, {
-		raw:  true,
-		eval: true,
-		in: `{
-			#Foo: {
-			#Bar: #Foo | string
-			}
-		}`,
-		out: unindent(`
-		{
-			#Foo: {
-				#Bar: #Foo | string
-			}
-		}`),
-	}, {
-		raw:  true,
-		eval: true,
-		in: `{
-				#FindInMap: {
-					#: "Fn::FindInMap": [string | #FindInMap]
-				}
-				a: [...string]
-			}`,
-		out: unindent(`
-			{
-				#FindInMap: {
-					#: {
-						"Fn::FindInMap": [string | #FindInMap]
-					}
-				}
-				a: [...string]
-			}`),
-	}, {
-		raw:   true,
-		eval:  true,
-		noOpt: true,
-		in: `{
-				#And: {
-					#: "Fn::And": [...(3 | #And)]
-				}
-				#Ands: #And & {
-					#: "Fn::And" : [_]
-				}
-			}`,
-		out: unindent(`
-			{
-				#And: {
-					#: {
-						"Fn::And": [...3 | #And]
-					}
-				}
-				#Ands: #And & {
-					#: {
-						"Fn::And": [_]
-					}
-				}
-			}`),
-	}, {
-		raw:  true,
-		eval: true,
-		in: `{
-			#Foo: {
-				sgl: #Bar
-				ref: null | #Foo
-				ext: #Bar | null
-				ref: null | #Foo
-				ref2: null | #Foo.sgl
-				...
-			}
-			#Foo: {
-				"#Foo": 2
-				...
-			}
-			#Bar: string
-		}`,
-		out: unindent(`
-		{
-			#Foo: {
-				"#Foo": 2
-				sgl:    #Bar
-				ref:    (null | #Foo) & (null | #Foo)
-				ext:    #Bar | null
-				ref2:   null | #Foo.sgl
-				...
-			}
-			#Bar: string
-		}`),
-	}, {
-		raw:  true,
-		eval: true,
-		in: `{
-			A: [uint]
-			B: A & ([10] | [192])
-		}`,
-		out: unindent(`
-		{
-			A: [>=0]
-			B: A & ([10] | [192])
-		}`),
-	}, {
-		in: `{
-			[string]: _
-			foo: 3
-		}`,
-		out: unindent(`
-		{
-			foo: 3
-			...
-		}`),
-	}}
-	for _, tc := range testCases {
-		t.Run("", func(t *testing.T) {
-			body := fmt.Sprintf("Test: %s", tc.in)
-			ctx, obj := compileFile(t, body)
-			ctx.trace = *traceOn
-			var root value = obj
-			if !tc.raw {
-				root = testResolve(ctx, obj, evalFull)
-			}
-			t.Log(debugStr(ctx, root))
-
-			n := root.(*structLit).Arcs[0].v
-			v := newValueRoot(ctx, n)
-
-			opts := options{raw: !tc.eval, omitOptional: tc.noOpt}
-			node, _ := export(ctx, nil, v.eval(ctx), opts)
-			b, err := format.Node(node, format.Simplify())
-			if err != nil {
-				log.Fatal(err)
-			}
-			if got := string(b); got != tc.out {
-				t.Errorf("\ngot  %v;\nwant %v", got, tc.out)
-			}
-		})
-	}
-}
-
-func TestExportFile(t *testing.T) {
-	testCases := []struct {
-		eval    bool // evaluate the full export
-		in, out string
-		opts    []Option
-	}{{
-		eval: true,
-		opts: []Option{Docs(true)},
-		in: `
-		// Hello foo
-		package foo
-
-		import "strings"
-
-		a: strings.ContainsAny("c")
-		`,
-		out: unindent(`
-		// Hello foo
-		package foo
-
-		import "strings"
-
-		a: strings.ContainsAny("c")`),
-	}, {
-		eval: true,
-		in: `
-		// Drop this comment
-		package foo
-
-		import "time"
-
-		a: time.Time
-		`,
-		out: unindent(`
-		package foo
-
-		import "time"
-
-		a: time.Time`),
-	}, {
-		in: `
-		import "time"
-
-		{
-			a: time.Time
-		} & {
-			time: int
-		}		`,
-		out: unindent(`
-		import timex "time"
-
-		time: int
-		a:    timex.Time`),
-	}, {
-		in: `
-		import time2 "time"
-
-		a:    time2.Time`,
-		out: unindent(`
-		import "time"
-
-		a: time.Time`),
-	}, {
-		in: `
-		import time2 "time"
-
-		time: int
-		a:    time2.Time`,
-		out: unindent(`
-		import time2 "time"
-
-		time: int
-		a:    time2.Time`),
-	}, {
-		in: `
-		import "strings"
-
-		a: strings.TrimSpace("  c  ")
-		`,
-		out: unindent(`
-		import "strings"
-
-		a: strings.TrimSpace("  c  ")`),
-	}, {
-		in: `
-		import "strings"
-
-		let stringsx = strings
-
-		a: {
-			strings: stringsx.ContainsAny("c")
-		}
-		`,
-		out: unindent(`
-		import "strings"
-
-		let STRINGS = strings
-		a: strings: STRINGS.ContainsAny("c")`),
-	}, {
-		in: `
-			a: b - 100
-			b: a + 100
-		`,
-		out: unindent(`
-		a: b - 100
-		b: a + 100`),
-	}, {
-		in: `A: {
-			[_]: B
-		} @protobuf(1,"test")
-
-		B: {}
-		B: {a: int} | {b: int}
-
-		#C: [#D]: int
-		#D: string
-		`,
-		out: unindent(`
-		A: {
-			[string]: B
-		} @protobuf(1,"test")
-		B: {} & ({
-			a: int
-		} | {
-			b: int
-		})
-		#C: {
-			[#D]: int
-			[#D]: int
-		}
-		#D: string`),
-	}, {
-		in: `
-		a: {
-			foo: 3
-			[=~"foo"]: int
-		}
-		`,
-		out: unindent(`
-		a: {
-			{[=~"foo"]: int}
-			foo: 3
-		}`),
-	}, {
-		in: `
-		import "time"
-
-		a: { b: time.Duration } | { c: time.Duration }
-		`,
-		out: unindent(`
-		import "time"
-
-		a: {
-			b: time.Duration
-		} | {
-			c: time.Duration
-		}`),
-	}, {
-		// a closed struct unified with a struct with a template restrictions is
-		// exported as a conjunction of two structs.
-		eval: true,
-		opts: []Option{ResolveReferences(true)},
-		in: `
-		#A: { b: int }
-		a: #A & { [string]: <10 }
-		#B: a
-		`,
-		out: unindent(`
-		#A: {
-			b: int
-		}
-		a: close({
-			b: <10
-		})
-		#B: {
-			b: <10
-		}`),
-	}, {
-		eval: true,
-		opts: []Option{Final()},
-		in: `{
-			reg: { foo: 1, bar: { baz: 3 } }
-			#def: {
-				a: 1
-
-				sub: reg
-			}
-			val: #def
-		}`,
-		out: unindent(`
-		{
-			reg: {
-				foo: 1
-				bar: baz: 3
-			}
-			val: {
-				a: 1
-				sub: {
-					foo: 1
-					bar: baz: 3
-				}
-			}
-		}`),
-	}, {
-		eval: true,
-		opts: []Option{ResolveReferences(true)},
-		in: `
-			#T: {
-				[_]: int64
-			}
-			#X: {
-				x: int
-			} & #T
-			x: #X
-			`,
-		out: unindent(`
-		x: {
-			{[string]: int64}
-			x: int64
-		}
-		#T: {
-			[string]: int64
-		}
-		#X: {
-			{[string]: int64}
-			x: int64
-		}`),
-	}, {
-		eval: true,
-		opts: []Option{Optional(false), ResolveReferences(true)},
-		in: `
-		#T: {
-			[_]: int64
-		}
-		#X: {
-			x: int
-		} & #T
-		x: #X
-		`,
-		out: unindent(`
-		x: x: int64
-		#T: {}
-		#X: {
-			x: int64
-		}`),
-	}, {
-		eval: true,
-		opts: []Option{ResolveReferences(true)},
-		in: `{
-				reg: { foo: 1, bar: { baz: 3 } }
-				#def: {
-					a: 1
-
-					sub: reg
-				}
-				val: #def
-				#def2: {
-					a: { b: int }
-				}
-				val2: #def2
-			}`,
-		out: unindent(`
-			{
-				reg: {
-					foo: 1
-					bar: baz: 3
-				}
-				#def: {
-					a: 1
-					sub: {
-						foo: 1
-						bar: {
-							baz: 3
-							...
-						}
-						...
-					}
-				}
-				val: close({
-					a: 1
-					sub: {
-						foo: 1
-						bar: baz: 3
-					}
-				})
-				#def2: {
-					a: b: int
-				}
-				val2: close({
-					a: close({
-						b: int
-					})
-				})
-			}`),
-	}, {
-		eval: true,
-		in: `
-				a?: 1
-				b?: 2
-				b?: 2
-				c?: 3
-				c: 3`,
-		out: unindent(`
-		a?: 1
-		b?: 2
-		c:  3`),
-	}, {
-		eval: true,
-		opts: []Option{ResolveReferences(true)},
-		in: `
-		#A: {
-			[=~"^[a-s]*$"]: int
-		}
-		#B: {
-			[=~"^[m-z]+"]: int
-		}
-		C: {#A & #B}
-		#D: {#A & #B}
-		`,
-		// TODO: the outer close of C could be optimized away.
-		out: unindent(`
-		#A: {
-			[=~"^[a-s]*$"]: int
-		}
-		#B: {
-			[=~"^[m-z]+"]: int
-		}
-		C: close({
-			close({
-				[=~"^[a-s]*$"]: int
-			}) & close({
-				[=~"^[m-z]+"]: int
-			})
-		})
-		#D: {
-			close({
-				[=~"^[a-s]*$"]: int
-			}) & close({
-				[=~"^[m-z]+"]: int
-			})
-		}`),
-	}, {
-		eval: true,
-		opts: []Option{Docs(true)},
-		in: `
-		// Definition
-		#A: {
-			// TODO: support
-			[string]: int
-		}
-		// Field
-		a: #A
-
-		// Pick first comment only.
-		a: _
-		`,
-		out: unindent(`
-		// Definition
-		#A: {
-			[string]: int
-		}
-
-		// Field
-		a: #A`),
-	}, {
-		eval: true,
-		opts: []Option{Docs(true)},
-		// It is okay to allow bulk-optional fields along-side definitions.
-		in: `
-		"#A": {
-			{[string]: int}
-			"#B": 4
-		}
-		// Definition
-		#A: {
-			{[string]: int}
-			#B: 4
-		}
-		a: #A.#B
-		`,
-		out: unindent(`
-		"#A": {
-			{[string]: int}
-			"#B": 4
-		}
-		// Definition
-		#A: {
-			{[string]: int}
-			#B: 4
-		}
-		a: 4`),
-	}, {
-		in: `
-		#A: {
-			#B: 4
-		}
-		a: #A.#B
-		`,
-		out: unindent(`
-		#A: {
-			#B: 4
-		}
-		a: #A.#B`),
-	}, {
-		eval: true,
-		in: `
-		x: [string]: int
-		a: [P=string]: {
-			b: x[P]
-			c: P
-			e: len(P)
-		}
-		`,
-		out: unindent(`
-		x: [string]: int
-		a: [P=string]: {
-			b: x[P]
-			c: P
-			e: len(P)
-		}`),
-	}, {
-		eval: true,
-		in: `
-		list: [...string]
-		foo: 1 | 2 | *3
-		foo: int
-		`,
-		out: unindent(`
-		list: [...string]
-		foo: 1 | 2 | *3`),
-	}, {
-		eval: true,
-		opts: []Option{Final()},
-		in: `
-		list: [...string]
-		foo: 1 | 2 | *3
-		foo: int
-		`,
-		out: unindent(`
-		{
-			list: []
-			foo: 3
-		}`),
-	}, {
-		// Expand final values, not values that may still be incomplete.
-		eval: true,
-		in: `
-		import "math"
-		import "tool/exec"
-
-		#A: {
-			b: 3
-		}
-
-		a:   #A
-		pi:  math.Pi
-		run: exec.Run
-		`,
-		out: unindent(`
-		import "tool/exec"
-
-		#A: {
-			b: 3
-		}
-		a:   #A
-		pi:  3.14159265358979323846264338327950288419716939937510582097494459
-		run: exec.Run`),
-	}, {
-		// Change mode midway to break cycle.
-		eval: true,
-		opts: []Option{Final(), Optional(true)},
-		in: `
-		Foo: {
-			foo?: Foo
-			bar:  string
-			baz:  bar + "2"
-		}
-
-		foo: Foo & {
-			foo: {
-				bar: "barNested"
-			}
-			bar: "barParent"
-		}`,
-		out: unindent(`
-		{
-			Foo: {
-				foo?: Foo
-				bar:  string
-				baz:  bar + "2"
-			}
-			foo: {
-				foo: {
-					foo?: Foo
-					bar:  "barNested"
-					baz:  "barNested2"
-				}
-				bar: "barParent"
-				baz: "barParent2"
-			}
-		}`),
-	}, {
-		eval: true,
-		opts: []Option{Final(), Definitions(true)},
-		in: `
-		package tst
-
-		x: {
-			a: #A
-			b: #A
-		}
-		#A: string | [#A]
-
-		`,
-		out: unindent(`
-		{
-			x: {
-				a: #A
-				b: #A
-			}
-			#A: string | [#A]
-		}`),
-	}, {
-		eval: true,
-		opts: []Option{Definitions(true)},
-		in: `
-		body?: {
-			a: int
-			b?: string
-		}
-		`,
-		out: unindent(`
-		body?: {
-			a:  int
-			b?: string
-		}`),
-	}, {
-		// Drop comprehensions in final mode.
-		eval: true,
-		opts: []Option{Final(), Concrete(true)},
-		in: `
-		foo: _
-		a: {
-			if len(foo.bar) > 0 {
-				command: ["envoy-lifecycle", string]
-			}
-		}
-		`,
-		out: unindent(`
-		{
-			foo: _
-			a: {}
-		}`),
-	}, {
-		// Don't output hidden fields in concrete and final mode.
-		eval: true,
-		opts: []Option{Final(), Concrete(true)},
-		in: `
-			_foo: _
-			`,
-		out: `{}`,
-	}, {
-		eval: true,
-		in: `
-		#A: {
-			foo: int @tag2(2)
-		} @tag2(1)
-
-		#A: {
-			foo: 2 @tag(2)
-		} @tag(1)
-
-		`,
-		out: `#A: {
-	foo: 2 @tag(2) @tag2(2)
-} @tag(1) @tag2(1)`,
-	}}
-	for _, tc := range testCases {
-		t.Run("", func(t *testing.T) {
-			var r Runtime
-			inst, err := r.Compile("test", tc.in)
-			if err != nil {
-				t.Fatal(err)
-			}
-			opts := tc.opts
-			if !tc.eval {
-				opts = []Option{Raw()}
-			}
-			b, err := format.Node(inst.Value().Syntax(opts...), format.Simplify())
-			if err != nil {
-				log.Fatal(err)
-			}
-			if got := strings.TrimSpace(string(b)); got != tc.out {
-				t.Errorf("\ngot:\n%v\nwant:\n%v", got, tc.out)
-			}
-		})
-	}
-}
-
-func unindent(s string) string {
-	lines := strings.Split(s, "\n")[1:]
-	ws := lines[0][:len(lines[0])-len(strings.TrimLeft(lines[0], " \t"))]
-	for i, s := range lines {
-		if s == "" {
-			continue
-		}
-		if !strings.HasPrefix(s, ws) {
-			panic("invalid indentation")
-		}
-		lines[i] = lines[i][len(ws):]
-	}
-	return strings.Join(lines, "\n")
-}
diff --git a/cue/gen.go b/cue/gen.go
deleted file mode 100644
index 0dcf198..0000000
--- a/cue/gen.go
+++ /dev/null
@@ -1,460 +0,0 @@
-// Copyright 2018 The 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.
-
-// +build ignore
-
-package main
-
-import (
-	"bytes"
-	"flag"
-	"fmt"
-	"go/ast"
-	"go/constant"
-	"go/format"
-	"go/parser"
-	"go/printer"
-	"go/token"
-	"io"
-	"io/ioutil"
-	"log"
-	"math/big"
-	"os"
-	"path"
-	"path/filepath"
-	"sort"
-	"strconv"
-	"strings"
-
-	"cuelang.org/go/cue"
-	"cuelang.org/go/cue/errors"
-	cueformat "cuelang.org/go/cue/format"
-	"cuelang.org/go/cue/load"
-	"cuelang.org/go/internal"
-)
-
-const prefix = "../pkg/"
-
-const header = `// Code generated by go generate. DO NOT EDIT.
-
-package cue
-
-`
-
-const initFunc = `
-func init() {
-	initBuiltins(builtinPackages)
-}
-
-var _ io.Reader
-`
-
-func main() {
-	flag.Parse()
-	log.SetFlags(log.Lshortfile)
-	log.SetOutput(os.Stdout)
-
-	g := generator{
-		w:     &bytes.Buffer{},
-		decls: &bytes.Buffer{},
-		fset:  token.NewFileSet(),
-	}
-
-	fmt.Fprintln(g.w, "var builtinPackages = map[string]*builtinPkg{")
-	filepath.Walk(prefix, func(dir string, info os.FileInfo, err error) error {
-		if err != nil {
-			log.Fatal(err)
-		}
-		if info.Name() == "testdata" {
-			return filepath.SkipDir
-		}
-		if info.IsDir() {
-			g.processDir(dir)
-		}
-		return nil
-	})
-	fmt.Fprintln(g.w, "}")
-
-	w := &bytes.Buffer{}
-	fmt.Fprintln(w, header)
-
-	m := map[string]*ast.ImportSpec{}
-	keys := []string{}
-	for _, spec := range g.imports {
-		if spec.Path.Value == `"cuelang.org/go/cue"` {
-			// Don't add this package.
-			continue
-		}
-		if prev, ok := m[spec.Path.Value]; ok {
-			if importName(prev) != importName(spec) {
-				log.Fatalf("inconsistent name for import %s: %q != %q",
-					spec.Path.Value, importName(prev), importName(spec))
-			}
-			continue
-		}
-		m[spec.Path.Value] = spec
-		keys = append(keys, spec.Path.Value)
-	}
-	fmt.Fprintln(w, "import (")
-	sort.Strings(keys)
-	for _, k := range keys {
-		printer.Fprint(w, g.fset, m[k])
-		fmt.Fprintln(w)
-	}
-	fmt.Fprintln(w, ")")
-	fmt.Fprintln(w, initFunc)
-	io.Copy(w, g.decls)
-	io.Copy(w, g.w)
-
-	b, err := format.Source(w.Bytes())
-	if err != nil {
-		b = w.Bytes() // write the unformatted source
-	}
-	// TODO: do this in a more principled way. The best is probably to
-	// put all builtins in a separate package.
-	b = bytes.Replace(b, []byte("cue."), []byte(""), -1)
-	b = bytes.Replace(b, []byte("{{}}"), []byte("{}"), -1)
-
-	if err := ioutil.WriteFile("builtins.go", b, 0644); err != nil {
-		log.Fatal(err)
-	}
-	if err != nil {
-		log.Fatal(err)
-	}
-}
-
-type generator struct {
-	w          *bytes.Buffer
-	decls      *bytes.Buffer
-	name       string
-	fset       *token.FileSet
-	defaultPkg string
-	first      bool
-	iota       int
-
-	imports []*ast.ImportSpec
-}
-
-func (g *generator) processDir(dir string) {
-	goFiles, err := filepath.Glob(filepath.Join(dir, "*.go"))
-	if err != nil {
-		log.Fatal(err)
-	}
-
-	cueFiles, err := filepath.Glob(filepath.Join(dir, "*.cue"))
-	if err != nil {
-		log.Fatal(err)
-	}
-
-	if len(goFiles)+len(cueFiles) == 0 {
-		return
-	}
-
-	pkg := dir[len(prefix):]
-	fmt.Fprintf(g.w, "%q: &builtinPkg{\nnative: []*builtin{{\n", pkg)
-	g.first = true
-	for _, filename := range goFiles {
-		g.processGo(filename)
-	}
-	fmt.Fprintf(g.w, "}},\n")
-	g.processCUE(dir)
-	fmt.Fprintf(g.w, "},\n")
-}
-
-func (g *generator) sep() {
-	if g.first {
-		g.first = false
-		return
-	}
-	fmt.Fprintln(g.w, "}, {")
-}
-
-func importName(s *ast.ImportSpec) string {
-	if s.Name != nil {
-		return s.Name.Name
-	}
-	pkg, err := strconv.Unquote(s.Path.Value)
-	if err != nil {
-		log.Fatal(err)
-	}
-	return path.Base(pkg)
-}
-
-// processCUE mixes in CUE definitions defined in the package directory.
-func (g *generator) processCUE(dir string) {
-	instances := cue.Build(load.Instances([]string{dir}, &load.Config{
-		StdRoot: "../pkg",
-	}))
-
-	if err := instances[0].Err; err != nil {
-		if !strings.Contains(err.Error(), "no CUE files") {
-			errors.Print(os.Stderr, err, nil)
-			log.Fatalf("error processing %s: %v", dir, err)
-		}
-		return
-	}
-
-	n := internal.ToExpr(instances[0].Value().Syntax(cue.Raw()))
-	b, err := cueformat.Node(n)
-	if err != nil {
-		log.Fatal(err)
-	}
-	b = bytes.ReplaceAll(b, []byte("\n\n"), []byte("\n"))
-	// body = strings.ReplaceAll(body, "\t", "")
-	// TODO: escape backtick
-	fmt.Fprintf(g.w, "cue: `%s`,\n", string(b))
-}
-
-func (g *generator) processGo(filename string) {
-	if strings.HasSuffix(filename, "_test.go") {
-		return
-	}
-	f, err := parser.ParseFile(g.fset, filename, nil, parser.ParseComments)
-	if err != nil {
-		log.Fatal(err)
-	}
-	g.defaultPkg = ""
-	g.name = f.Name.Name
-	if g.name == "structs" {
-		g.name = "struct"
-	}
-
-	for _, d := range f.Decls {
-		switch x := d.(type) {
-		case *ast.GenDecl:
-			switch x.Tok {
-			case token.CONST:
-				for _, spec := range x.Specs {
-					if !ast.IsExported(spec.(*ast.ValueSpec).Names[0].Name) {
-						continue
-					}
-					g.genConst(spec.(*ast.ValueSpec))
-				}
-			case token.IMPORT:
-				for _, s := range x.Specs {
-					spec := s.(*ast.ImportSpec)
-					g.imports = append(g.imports, spec)
-				}
-				if g.defaultPkg == "" {
-					g.defaultPkg = importName(x.Specs[0].(*ast.ImportSpec))
-				}
-			case token.VAR:
-				for _, spec := range x.Specs {
-					if ast.IsExported(spec.(*ast.ValueSpec).Names[0].Name) {
-						log.Fatal("gen %s: var declarations not supported", filename)
-					}
-				}
-				printer.Fprint(g.decls, g.fset, x)
-				fmt.Fprint(g.decls, "\n\n")
-				continue
-			case token.TYPE:
-				// TODO: support type declarations.
-				for _, spec := range x.Specs {
-					if ast.IsExported(spec.(*ast.TypeSpec).Name.Name) {
-						log.Fatal("gen %s: type declarations not supported", filename)
-					}
-				}
-				continue
-			default:
-				log.Fatalf("gen %s: unexpected spec of type %s", filename, x.Tok)
-			}
-		case *ast.FuncDecl:
-			g.genFun(x)
-		}
-	}
-}
-
-func (g *generator) genConst(spec *ast.ValueSpec) {
-	name := spec.Names[0].Name
-	value := ""
-	switch v := g.toValue(spec.Values[0]); v.Kind() {
-	case constant.Bool, constant.Int, constant.String:
-		// TODO: convert octal numbers
-		value = v.ExactString()
-	case constant.Float:
-		var rat big.Rat
-		rat.SetString(v.ExactString())
-		var float big.Float
-		float.SetRat(&rat)
-		value = float.Text('g', -1)
-	default:
-		fmt.Printf("Dropped entry %s.%s (%T: %v)\n", g.defaultPkg, name, v.Kind(), v.ExactString())
-		return
-	}
-	g.sep()
-	fmt.Fprintf(g.w, "Name: %q,\n Const: %q,\n", name, value)
-}
-
-func (g *generator) toValue(x ast.Expr) constant.Value {
-	switch x := x.(type) {
-	case *ast.BasicLit:
-		return constant.MakeFromLiteral(x.Value, x.Kind, 0)
-	case *ast.BinaryExpr:
-		return constant.BinaryOp(g.toValue(x.X), x.Op, g.toValue(x.Y))
-	case *ast.UnaryExpr:
-		return constant.UnaryOp(x.Op, g.toValue(x.X), 0)
-	default:
-		log.Fatalf("%s: unsupported expression type %T: %#v", g.defaultPkg, x, x)
-	}
-	return constant.MakeUnknown()
-}
-
-func (g *generator) genFun(x *ast.FuncDecl) {
-	if x.Body == nil {
-		return
-	}
-	types := []string{}
-	if x.Type.Results != nil {
-		for _, f := range x.Type.Results.List {
-			if len(f.Names) > 0 {
-				for range f.Names {
-					types = append(types, g.goKind(f.Type))
-				}
-			} else {
-				types = append(types, g.goKind(f.Type))
-			}
-		}
-	}
-	if n := len(types); n != 1 && (n != 2 || types[1] != "error") {
-		fmt.Printf("Dropped func %s.%s: must have one return value or a value and an error %v\n", g.defaultPkg, x.Name.Name, types)
-		return
-	}
-
-	if !ast.IsExported(x.Name.Name) || x.Recv != nil {
-		if strings.HasPrefix(x.Name.Name, g.name) {
-			printer.Fprint(g.decls, g.fset, x)
-			fmt.Fprint(g.decls, "\n\n")
-		}
-		return
-	}
-
-	g.sep()
-	fmt.Fprintf(g.w, "Name: %q,\n", x.Name.Name)
-
-	args := []string{}
-	vals := []string{}
-	kind := []string{}
-	for _, f := range x.Type.Params.List {
-		for _, name := range f.Names {
-			typ := g.goKind(f.Type)
-			argKind := g.goToCUE(f.Type)
-			vals = append(vals, fmt.Sprintf("c.%s(%d)", typ, len(args)))
-			args = append(args, name.Name)
-			kind = append(kind, argKind)
-		}
-	}
-
-	fmt.Fprintf(g.w, "Params: []kind{%s},\n", strings.Join(kind, ", "))
-	result := g.goToCUE(x.Type.Results.List[0].Type)
-	fmt.Fprintf(g.w, "Result: %s,\n", result)
-	argList := strings.Join(args, ", ")
-	valList := strings.Join(vals, ", ")
-	init := ""
-	if len(args) > 0 {
-		init = fmt.Sprintf("%s := %s", argList, valList)
-	}
-
-	fmt.Fprintf(g.w, "Func: func(c *callCtxt) {")
-	defer fmt.Fprintln(g.w, "},")
-	fmt.Fprintln(g.w)
-	if init != "" {
-		fmt.Fprintln(g.w, init)
-	}
-	fmt.Fprintln(g.w, "if c.do() {")
-	defer fmt.Fprintln(g.w, "}")
-	if len(types) == 1 {
-		fmt.Fprint(g.w, "c.ret = func() interface{} ")
-	} else {
-		fmt.Fprint(g.w, "c.ret, c.err = func() (interface{}, error) ")
-	}
-	printer.Fprint(g.w, g.fset, x.Body)
-	fmt.Fprintln(g.w, "()")
-}
-
-func (g *generator) goKind(expr ast.Expr) string {
-	if star, isStar := expr.(*ast.StarExpr); isStar {
-		expr = star.X
-	}
-	w := &bytes.Buffer{}
-	printer.Fprint(w, g.fset, expr)
-	switch str := w.String(); str {
-	case "big.Int":
-		return "bigInt"
-	case "big.Float":
-		return "bigFloat"
-	case "big.Rat":
-		return "bigRat"
-	case "internal.Decimal":
-		return "decimal"
-	case "[]*internal.Decimal":
-		return "decimalList"
-	case "cue.Struct":
-		return "structVal"
-	case "cue.Value":
-		return "value"
-	case "cue.List":
-		return "list"
-	case "[]string":
-		return "strList"
-	case "[]byte":
-		return "bytes"
-	case "[]cue.Value":
-		return "list"
-	case "io.Reader":
-		return "reader"
-	case "time.Time":
-		return "string"
-	default:
-		return str
-	}
-}
-
-func (g *generator) goToCUE(expr ast.Expr) (cueKind string) {
-	// TODO: detect list and structs types for return values.
-	switch k := g.goKind(expr); k {
-	case "error":
-		cueKind += "bottomKind"
-	case "bool":
-		cueKind += "boolKind"
-	case "bytes", "reader":
-		cueKind += "bytesKind|stringKind"
-	case "string":
-		cueKind += "stringKind"
-	case "int", "int8", "int16", "int32", "rune", "int64",
-		"uint", "byte", "uint8", "uint16", "uint32", "uint64",
-		"bigInt":
-		cueKind += "intKind"
-	case "float64", "bigRat", "bigFloat", "decimal":
-		cueKind += "numKind"
-	case "list", "decimalList", "strList":
-		cueKind += "listKind"
-	case "structVal":
-		cueKind += "structKind"
-	case "value":
-		// Must use callCtxt.value method for these types and resolve manually.
-		cueKind += "topKind" // TODO: can be more precise
-	default:
-		switch {
-		case strings.HasPrefix(k, "[]"):
-			cueKind += "listKind"
-		case strings.HasPrefix(k, "map["):
-			cueKind += "structKind"
-		default:
-			// log.Println("Unknown type:", k)
-			// Must use callCtxt.value method for these types and resolve manually.
-			cueKind += "topKind" // TODO: can be more precise
-		}
-	}
-	return cueKind
-}
diff --git a/cue/go.go b/cue/go.go
index ae41b4b..28399d9 100644
--- a/cue/go.go
+++ b/cue/go.go
@@ -1,4 +1,4 @@
-// Copyright 2019 CUE Authors
+// 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.
@@ -15,684 +15,32 @@
 package cue
 
 import (
-	"encoding"
-	"encoding/json"
-	"fmt"
-	"math/big"
-	"reflect"
-	"sort"
-	"strings"
-	"unicode/utf8"
-
-	"github.com/cockroachdb/apd/v2"
-
-	"cuelang.org/go/cue/ast"
-	"cuelang.org/go/cue/parser"
-	"cuelang.org/go/cue/token"
 	"cuelang.org/go/internal"
+	"cuelang.org/go/internal/core/adt"
+	"cuelang.org/go/internal/core/convert"
+	"cuelang.org/go/internal/core/eval"
 )
 
-// This file contains functionality for converting Go to CUE.
-//
-// The code in this file is a prototype implementation and is far from
-// optimized.
-
 func init() {
 	internal.FromGoValue = func(runtime, x interface{}, nilIsTop bool) interface{} {
-		return convertValue(runtime.(*Runtime), x, nilIsTop)
+		r := runtime.(*Runtime)
+		ctx := eval.NewContext(r.index().Runtime, nil)
+		v := convert.GoValueToValue(ctx, x, nilIsTop)
+		n := adt.ToVertex(v)
+		return Value{r.idx, n}
 	}
 
 	internal.FromGoType = func(runtime, x interface{}) interface{} {
-		return convertType(runtime.(*Runtime), x)
-	}
-}
-
-func convertValue(r *Runtime, x interface{}, nilIsTop bool) Value {
-	ctx := r.index().newContext()
-	v := convertVal(ctx, baseValue{}, nilIsTop, x)
-	return newValueRoot(ctx, v)
-}
-
-func convertType(r *Runtime, x interface{}) Value {
-	ctx := r.index().newContext()
-	v := convertGoType(r, reflect.TypeOf(x))
-	return newValueRoot(ctx, v)
-
-}
-
-// parseTag parses a CUE expression from a cue tag.
-func parseTag(ctx *context, obj *structLit, field label, tag string) value {
-	if p := strings.Index(tag, ","); p >= 0 {
-		tag = tag[:p]
-	}
-	if tag == "" {
-		return &top{}
-	}
-	expr, err := parser.ParseExpr("<field:>", tag)
-	if err != nil {
-		field := ctx.LabelStr(field)
-		return ctx.mkErr(baseValue{}, "invalid tag %q for field %q: %v", tag, field, err)
-	}
-	v := newVisitor(ctx.index, nil, nil, obj, true)
-	return v.walk(expr)
-}
-
-// TODO: should we allow mapping names in cue tags? This only seems like a good
-// idea if we ever want to allow mapping CUE to a different name than JSON.
-var tagsWithNames = []string{"json", "yaml", "protobuf"}
-
-func getName(f *reflect.StructField) string {
-	name := f.Name
-	for _, s := range tagsWithNames {
-		if tag, ok := f.Tag.Lookup(s); ok {
-			if p := strings.Index(tag, ","); p >= 0 {
-				tag = tag[:p]
-			}
-			if tag != "" {
-				name = tag
-				break
-			}
-		}
-	}
-	return name
-}
-
-// isOptional indicates whether a field should be marked as optional.
-func isOptional(f *reflect.StructField) bool {
-	isOptional := false
-	switch f.Type.Kind() {
-	case reflect.Ptr, reflect.Map, reflect.Chan, reflect.Interface, reflect.Slice:
-		// Note: it may be confusing to distinguish between an empty slice and
-		// a nil slice. However, it is also surprising to not be able to specify
-		// a default value for a slice. So for now we will allow it.
-		isOptional = true
-	}
-	if tag, ok := f.Tag.Lookup("cue"); ok {
-		// TODO: only if first field is not empty.
-		isOptional = false
-		for _, f := range strings.Split(tag, ",")[1:] {
-			switch f {
-			case "opt":
-				isOptional = true
-			case "req":
-				return false
-			}
-		}
-	} else if tag, ok = f.Tag.Lookup("json"); ok {
-		isOptional = false
-		for _, f := range strings.Split(tag, ",")[1:] {
-			if f == "omitempty" {
-				return true
-			}
-		}
-	}
-	return isOptional
-}
-
-// isOmitEmpty means that the zero value is interpreted as undefined.
-func isOmitEmpty(f *reflect.StructField) bool {
-	isOmitEmpty := false
-	switch f.Type.Kind() {
-	case reflect.Ptr, reflect.Map, reflect.Chan, reflect.Interface, reflect.Slice:
-		// Note: it may be confusing to distinguish between an empty slice and
-		// a nil slice. However, it is also surprising to not be able to specify
-		// a default value for a slice. So for now we will allow it.
-		isOmitEmpty = true
-
-	default:
-		// TODO: we can also infer omit empty if a type cannot be nil if there
-		// is a constraint that unconditionally disallows the zero value.
-	}
-	tag, ok := f.Tag.Lookup("json")
-	if ok {
-		isOmitEmpty = false
-		for _, f := range strings.Split(tag, ",")[1:] {
-			if f == "omitempty" {
-				return true
-			}
-		}
-	}
-	return isOmitEmpty
-}
-
-// parseJSON parses JSON into a CUE value. b must be valid JSON.
-func parseJSON(ctx *context, b []byte) evaluated {
-	expr, err := parser.ParseExpr("json", b)
-	if err != nil {
-		panic(err) // cannot happen
-	}
-	v := newVisitor(ctx.index, nil, nil, nil, false)
-	return v.walk(expr).evalPartial(ctx)
-}
-
-func isZero(v reflect.Value) bool {
-	x := v.Interface()
-	if x == nil {
-		return true
-	}
-	switch k := v.Kind(); k {
-	case reflect.Struct, reflect.Array:
-		// we never allow optional values for these types.
-		return false
-
-	case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map,
-		reflect.Slice:
-		// Note that for maps we preserve the distinction between a nil map and
-		// an empty map.
-		return v.IsNil()
-
-	case reflect.String:
-		return v.Len() == 0
-
-	default:
-		return x == reflect.Zero(v.Type()).Interface()
-	}
-}
-
-func convertVal(ctx *context, src source, nilIsTop bool, x interface{}) evaluated {
-	v := convertRec(ctx, src, nilIsTop, x)
-	if v == nil {
-		return ctx.mkErr(baseValue{}, "unsupported Go type (%v)", v)
-	}
-	return v
-}
-
-func isNil(x reflect.Value) bool {
-	switch x.Kind() {
-	// Only check for supported types; ignore func and chan.
-	case reflect.Ptr, reflect.Map, reflect.Slice, reflect.Interface:
-		return x.IsNil()
-	}
-	return false
-}
-
-func convertRec(ctx *context, src source, nilIsTop bool, x interface{}) evaluated {
-	switch v := x.(type) {
-	case nil:
-		if nilIsTop {
-			return &top{src.base()}
-		}
-		return &nullLit{src.base()}
-
-	case Value:
-		if ctx.index != v.ctx().index {
-			panic("value of type Value is not created with same Runtime as Instance")
-		}
-		return v.eval(ctx)
-
-	case *ast.File:
-		x := newVisitorCtx(ctx, nil, nil, nil, false)
-		return ctx.manifest(x.walk(v))
-
-	case ast.Expr:
-		x := newVisitorCtx(ctx, nil, nil, nil, false)
-		return ctx.manifest(x.walk(v))
-
-	case *big.Int:
-		n := newInt(src.base(), 0)
-		n.X.Coeff.Set(v)
-		if v.Sign() < 0 {
-			n.X.Coeff.Neg(&n.X.Coeff)
-			n.X.Negative = true
-		}
-		return n
-
-	case *big.Rat:
-		// should we represent this as a binary operation?
-		n := newNum(src, numKind, 0)
-		_, err := ctx.Quo(&n.X, apd.NewWithBigInt(v.Num(), 0), apd.NewWithBigInt(v.Denom(), 0))
+		r := runtime.(*Runtime)
+		ctx := eval.NewContext(r.index().Runtime, nil)
+		expr, err := convert.GoTypeToExpr(ctx, x)
 		if err != nil {
-			return ctx.mkErr(src, err)
+			expr = &adt.Bottom{Err: err}
 		}
-		if !v.IsInt() {
-			n.K = floatKind
-		}
-		return n
+		n := &adt.Vertex{}
+		n.AddConjunct(adt.MakeConjunct(nil, expr))
+		return Value{r.idx, n}
 
-	case *big.Float:
-		return newFloat(src, 0).setString(v.String())
-
-	case *apd.Decimal:
-		n := newNum(src, numKind, 0).set(v)
-		if !n.isInt(ctx) {
-			n.K = floatKind
-		}
-		return n
-
-	case json.Marshaler:
-		b, err := v.MarshalJSON()
-		if err != nil {
-			return ctx.mkErr(src, err)
-		}
-
-		return parseJSON(ctx, b)
-
-	case encoding.TextMarshaler:
-		b, err := v.MarshalText()
-		if err != nil {
-			return ctx.mkErr(src, err)
-		}
-		b, err = json.Marshal(string(b))
-		if err != nil {
-			return ctx.mkErr(src, err)
-		}
-		return parseJSON(ctx, b)
-
-	case error:
-		return ctx.mkErr(src, v.Error())
-	case bool:
-		return &boolLit{src.base(), v}
-	case string:
-		if !utf8.ValidString(v) {
-			return ctx.mkErr(src,
-				"cannot convert result to string: invalid UTF-8")
-		}
-		return &stringLit{src.base(), v, nil}
-	case []byte:
-		return &bytesLit{src.base(), v, nil}
-	case int:
-		return toInt(ctx, src, int64(v))
-	case int8:
-		return toInt(ctx, src, int64(v))
-	case int16:
-		return toInt(ctx, src, int64(v))
-	case int32:
-		return toInt(ctx, src, int64(v))
-	case int64:
-		return toInt(ctx, src, int64(v))
-	case uint:
-		return toUint(ctx, src, uint64(v))
-	case uint8:
-		return toUint(ctx, src, uint64(v))
-	case uint16:
-		return toUint(ctx, src, uint64(v))
-	case uint32:
-		return toUint(ctx, src, uint64(v))
-	case uint64:
-		return toUint(ctx, src, uint64(v))
-	case uintptr:
-		return toUint(ctx, src, uint64(v))
-	case float64:
-		return newFloat(src, 0).setString(fmt.Sprintf("%g", v))
-	case float32:
-		return newFloat(src, 0).setString(fmt.Sprintf("%g", v))
-
-	case reflect.Value:
-		if v.CanInterface() {
-			return convertRec(ctx, src, nilIsTop, v.Interface())
-		}
-
-	default:
-		value := reflect.ValueOf(v)
-		switch value.Kind() {
-		case reflect.Bool:
-			return &boolLit{src.base(), value.Bool()}
-
-		case reflect.String:
-			str := value.String()
-			if !utf8.ValidString(str) {
-				return ctx.mkErr(src,
-					"cannot convert result to string: invalid UTF-8")
-			}
-			return &stringLit{src.base(), str, nil}
-
-		case reflect.Int, reflect.Int8, reflect.Int16,
-			reflect.Int32, reflect.Int64:
-			return toInt(ctx, src, value.Int())
-
-		case reflect.Uint, reflect.Uint8, reflect.Uint16,
-			reflect.Uint32, reflect.Uint64, reflect.Uintptr:
-			return toUint(ctx, src, value.Uint())
-
-		case reflect.Float32, reflect.Float64:
-			return convertRec(ctx, src, nilIsTop, value.Float())
-
-		case reflect.Ptr:
-			if value.IsNil() {
-				if nilIsTop {
-					return &top{src.base()}
-				}
-				return &nullLit{src.base()}
-			}
-			return convertRec(ctx, src, nilIsTop, value.Elem().Interface())
-
-		case reflect.Struct:
-			obj := newStruct(src)
-			t := value.Type()
-			for i := 0; i < value.NumField(); i++ {
-				t := t.Field(i)
-				if t.PkgPath != "" {
-					continue
-				}
-				val := value.Field(i)
-				if !nilIsTop && isNil(val) {
-					continue
-				}
-				if tag, _ := t.Tag.Lookup("json"); tag == "-" {
-					continue
-				}
-				if isOmitEmpty(&t) && isZero(val) {
-					continue
-				}
-				sub := convertRec(ctx, src, nilIsTop, val.Interface())
-				if sub == nil {
-					// mimic behavior of encoding/json: skip fields of unsupported types
-					continue
-				}
-				if isBottom(sub) {
-					return sub
-				}
-
-				// leave errors like we do during normal evaluation or do we
-				// want to return the error?
-				name := getName(&t)
-				if name == "-" {
-					continue
-				}
-				f := ctx.StrLabel(name)
-				obj.Arcs = append(obj.Arcs, arc{Label: f, v: sub})
-			}
-			sort.Sort(obj)
-			return obj
-
-		case reflect.Map:
-			obj := newStruct(src)
-
-			sorted := []string{}
-			keys := []string{}
-			t := value.Type()
-			switch key := t.Key(); key.Kind() {
-			case reflect.String,
-				reflect.Int, reflect.Int8, reflect.Int16,
-				reflect.Int32, reflect.Int64,
-				reflect.Uint, reflect.Uint8, reflect.Uint16,
-				reflect.Uint32, reflect.Uint64, reflect.Uintptr:
-				for _, k := range value.MapKeys() {
-					val := value.MapIndex(k)
-					// if isNil(val) {
-					// 	continue
-					// }
-
-					sub := convertRec(ctx, src, nilIsTop, val.Interface())
-					// mimic behavior of encoding/json: report error of
-					// unsupported type.
-					if sub == nil {
-						return ctx.mkErr(baseValue{}, "unsupported Go type (%v)", val)
-					}
-					if isBottom(sub) {
-						return sub
-					}
-
-					s := fmt.Sprint(k)
-					keys = append(keys, s)
-					sorted = append(sorted, s)
-
-					// Set feature later.
-					obj.Arcs = append(obj.Arcs, arc{Label: 0, v: sub})
-				}
-
-			default:
-				return ctx.mkErr(baseValue{}, "unsupported Go type for map key (%v)", key)
-			}
-
-			// Assign label in normalized order.
-			sort.Strings(sorted)
-			for _, k := range sorted {
-				ctx.StrLabel(k)
-			}
-
-			// Now assign the labels to the arcs.
-			for i, k := range keys {
-				obj.Arcs[i].Label = ctx.StrLabel(k)
-			}
-			sort.Sort(obj)
-			return obj
-
-		case reflect.Slice, reflect.Array:
-			list := &list{baseValue: src.base()}
-			arcs := []arc{}
-			for i := 0; i < value.Len(); i++ {
-				val := value.Index(i)
-				x := convertRec(ctx, src, nilIsTop, val.Interface())
-				if x == nil {
-					return ctx.mkErr(baseValue{}, "unsupported Go type (%v)", val)
-				}
-				if isBottom(x) {
-					return x
-				}
-				arcs = append(arcs, arc{Label: label(len(arcs)), v: x})
-			}
-			list.elem = &structLit{baseValue: list.baseValue, Arcs: arcs}
-			list.initLit()
-			// There is no need to set the type of the list, as the list will
-			// be of fixed size and all elements will already have a defined
-			// value.
-			return list
-		}
-	}
-	return nil
-}
-
-func toInt(ctx *context, src source, x int64) evaluated {
-	return newInt(src, 0).setInt64(x)
-}
-
-func toUint(ctx *context, src source, x uint64) evaluated {
-	return newInt(src, 0).setUInt64(x)
-}
-
-func convertGoType(r *Runtime, t reflect.Type) value {
-	ctx := r.index().newContext()
-	// TODO: this can be much more efficient.
-	ctx.mutex.Lock()
-	defer ctx.mutex.Unlock()
-	return goTypeToValue(ctx, true, t)
-}
-
-var (
-	jsonMarshaler = reflect.TypeOf(new(json.Marshaler)).Elem()
-	textMarshaler = reflect.TypeOf(new(encoding.TextMarshaler)).Elem()
-	topSentinel   = &top{}
-)
-
-// goTypeToValue converts a Go Type to a value.
-//
-// TODO: if this value will always be unified with a concrete type in Go, then
-// many of the fields may be omitted.
-func goTypeToValue(ctx *context, allowNullDefault bool, t reflect.Type) value {
-	v := goTypeToValueRec(ctx, allowNullDefault, t)
-	if v == nil {
-		return ctx.mkErr(baseValue{}, "unsupported Go type (%v)", t)
-	}
-	return v
-}
-
-func goTypeToValueRec(ctx *context, allowNullDefault bool, t reflect.Type) (e value) {
-	if e, ok := ctx.LoadType(t); ok {
-		return e.(value)
-	}
-
-	switch reflect.Zero(t).Interface().(type) {
-	case *big.Int, big.Int:
-		e = &basicType{K: intKind}
-		goto store
-
-	case *big.Float, big.Float, *big.Rat, big.Rat:
-		e = &basicType{K: numKind}
-		goto store
-
-	case *apd.Decimal, apd.Decimal:
-		e = &basicType{K: numKind}
-		goto store
-	}
-
-	// Even if this is for types that we know cast to a certain type, it can't
-	// hurt to return top, as in these cases the concrete values will be
-	// strict instances and there cannot be any tags that further constrain
-	// the values.
-	if t.Implements(jsonMarshaler) || t.Implements(textMarshaler) {
-		return topSentinel
-	}
-
-	switch k := t.Kind(); k {
-	case reflect.Ptr:
-		elem := t.Elem()
-		for elem.Kind() == reflect.Ptr {
-			elem = elem.Elem()
-		}
-		e = goTypeToValueRec(ctx, false, elem)
-		if allowNullDefault {
-			e = wrapOrNull(e)
-		}
-
-	case reflect.Interface:
-		switch t.Name() {
-		case "error":
-			// This is really null | _|_. There is no error if the error is null.
-			e = &nullLit{} // null
-		default:
-			e = topSentinel // `_`
-		}
-
-	case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
-		reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
-		e = predefinedRanges[t.Kind().String()]
-
-	case reflect.Uint, reflect.Uintptr:
-		e = predefinedRanges["uint64"]
-
-	case reflect.Int:
-		e = predefinedRanges["int64"]
-
-	case reflect.String:
-		e = &basicType{K: stringKind}
-
-	case reflect.Bool:
-		e = &basicType{K: boolKind}
-
-	case reflect.Float32, reflect.Float64:
-		e = &basicType{K: floatKind}
-
-	case reflect.Struct:
-		// First iterate to create struct, then iterate another time to
-		// resolve field tags to allow field tags to refer to the struct fields.
-		tags := map[label]string{}
-		obj := newStruct(baseValue{})
-		ctx.StoreType(t, obj)
-
-		for i := 0; i < t.NumField(); i++ {
-			f := t.Field(i)
-			if f.PkgPath != "" {
-				continue
-			}
-			_, ok := f.Tag.Lookup("cue")
-			elem := goTypeToValueRec(ctx, !ok, f.Type)
-			if elem == nil || isBottom(elem) {
-				continue // Ignore fields for unsupported types
-			}
-
-			// leave errors like we do during normal evaluation or do we
-			// want to return the error?
-			name := getName(&f)
-			if name == "-" {
-				continue
-			}
-			l := ctx.StrLabel(name)
-			obj.Arcs = append(obj.Arcs, arc{
-				Label: l,
-				// The GO JSON decoder always allows a value to be undefined.
-				optional: isOptional(&f),
-				v:        elem,
-			})
-
-			if tag, ok := f.Tag.Lookup("cue"); ok {
-				tags[l] = tag
-			}
-		}
-		sort.Sort(obj)
-
-		for label, tag := range tags {
-			v := parseTag(ctx, obj, label, tag)
-			if isBottom(v) {
-				return v
-			}
-			for i, a := range obj.Arcs {
-				if a.Label == label {
-					// Instead of unifying with the existing type, we substitute
-					// with the constraints from the tags. The type constraints
-					// will be implied when unified with a concrete value.
-					obj.Arcs[i].v = mkBin(ctx, token.NoPos, opUnify, a.v, v)
-				}
-			}
-		}
-
-		return obj
-
-	case reflect.Array, reflect.Slice:
-		if t.Elem().Kind() == reflect.Uint8 {
-			e = &basicType{K: bytesKind}
-		} else {
-			elem := goTypeToValueRec(ctx, allowNullDefault, t.Elem())
-			if elem == nil {
-				return ctx.mkErr(baseValue{}, "unsupported Go type (%v)", t.Elem())
-			}
-
-			var ln value = &top{}
-			if t.Kind() == reflect.Array {
-				ln = toInt(ctx, baseValue{}, int64(t.Len()))
-			}
-			e = &list{elem: &structLit{}, typ: elem, len: ln}
-		}
-		if k == reflect.Slice {
-			e = wrapOrNull(e)
-		}
-
-	case reflect.Map:
-		switch key := t.Key(); key.Kind() {
-		case reflect.String, reflect.Int, reflect.Int8, reflect.Int16,
-			reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8,
-			reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
-		default:
-			return ctx.mkErr(baseValue{}, "unsupported Go type for map key (%v)", key)
-		}
-
-		obj := newStruct(baseValue{})
-		sig := &params{}
-		sig.add(ctx.Label("_", true), &basicType{K: stringKind})
-		v := goTypeToValueRec(ctx, allowNullDefault, t.Elem())
-		if v == nil {
-			return ctx.mkErr(baseValue{}, "unsupported Go type (%v)", t.Elem())
-		}
-		if isBottom(v) {
-			return v
-		}
-		obj.optionals = newOptional(nil, &lambdaExpr{params: sig, value: v})
-
-		e = wrapOrNull(obj)
-	}
-
-store:
-	// TODO: store error if not nil?
-	if e != nil {
-		ctx.StoreType(t, e)
-	}
-	return e
-}
-
-func wrapOrNull(e value) value {
-	if e == nil || isBottom(e) || e.Kind().isAnyOf(nullKind) {
-		return e
-	}
-	return makeNullable(e, true)
-}
-
-func makeNullable(e value, nullIsDefault bool) value {
-	return &disjunction{
-		baseValue: baseValue{e},
-		Values: []dValue{
-			{Val: &nullLit{}, Default: nullIsDefault},
-			{Val: e}},
-		errors:      nil,
-		HasDefaults: nullIsDefault,
+		// return convertType(runtime.(*Runtime), x)
 	}
 }
diff --git a/cue/go_test.go b/cue/go_test.go
deleted file mode 100644
index fd5a03f..0000000
--- a/cue/go_test.go
+++ /dev/null
@@ -1,265 +0,0 @@
-// Copyright 2019 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 (
-	"math/big"
-	"reflect"
-	"testing"
-	"time"
-
-	"github.com/cockroachdb/apd/v2"
-
-	"cuelang.org/go/cue/ast"
-	"cuelang.org/go/cue/errors"
-)
-
-func mkBigInt(a int64) (v apd.Decimal) { v.SetInt64(a); return }
-
-func TestConvert(t *testing.T) {
-	i34 := big.NewInt(34)
-	d34 := mkBigInt(34)
-	n34 := mkBigInt(-34)
-	f34 := big.NewFloat(34.0000)
-	testCases := []struct {
-		goVal interface{}
-		want  string
-	}{{
-		nil, "_",
-	}, {
-		true, "true",
-	}, {
-		false, "false",
-	}, {
-		errors.New("oh noes"), "_|_(oh noes)",
-	}, {
-		"foo", `"foo"`,
-	}, {
-		"\x80", `_|_(cannot convert result to string: invalid UTF-8)`,
-	}, {
-		3, "3",
-	}, {
-		uint(3), "3",
-	}, {
-		uint8(3), "3",
-	}, {
-		uint16(3), "3",
-	}, {
-		uint32(3), "3",
-	}, {
-		uint64(3), "3",
-	}, {
-		int8(-3), "-3",
-	}, {
-		int16(-3), "-3",
-	}, {
-		int32(-3), "-3",
-	}, {
-		int64(-3), "-3",
-	}, {
-		float64(3.1), "3.1",
-	}, {
-		float32(3.1), "3.1",
-	}, {
-		uintptr(3), "3",
-	}, {
-		&i34, "34",
-	}, {
-		&f34, "34",
-	}, {
-		&d34, "34",
-	}, {
-		&n34, "-34",
-	}, {
-		[]int{1, 2, 3, 4}, "[1,2,3,4]",
-	}, {
-		struct {
-			A int
-			B *int
-		}{3, nil},
-		"<0>{A: 3}",
-	}, {
-		[]interface{}{}, "[]",
-	}, {
-		[]interface{}{nil}, "[_]",
-	}, {
-		map[string]interface{}{"a": 1, "x": nil}, "<0>{x: _, a: 1}",
-	}, {
-		map[string][]int{
-			"a": {1},
-			"b": {3, 4},
-		}, "<0>{a: [1], b: [3,4]}",
-	}, {
-		map[bool]int{}, "_|_(unsupported Go type for map key (bool))",
-	}, {
-		map[struct{}]int{{}: 2}, "_|_(unsupported Go type for map key (struct {}))",
-	}, {
-		map[int]int{1: 2}, `<0>{"1": 2}`,
-	}, {
-		struct {
-			a int
-			b int
-		}{3, 4},
-		"<0>{}",
-	}, {
-		struct {
-			A int
-			B int `json:"-"`
-			C int `json:",omitempty"`
-		}{3, 4, 0},
-		"<0>{A: 3}",
-	}, {
-		struct {
-			A int
-			B int
-		}{3, 4},
-		"<0>{A: 3, B: 4}",
-	}, {
-		struct {
-			A int `json:"a"`
-			B int `yaml:"b"`
-		}{3, 4},
-		"<0>{a: 3, b: 4}",
-	}, {
-		struct {
-			A int `json:"" yaml:"" protobuf:"aa"`
-			B int `yaml:"cc" json:"bb" protobuf:"aa"`
-		}{3, 4},
-		"<0>{aa: 3, bb: 4}",
-	}, {
-		&struct{ A int }{3}, "<0>{A: 3}",
-	}, {
-		(*struct{ A int })(nil), "_",
-	}, {
-		reflect.ValueOf(3), "3",
-	}, {
-		time.Date(2019, 4, 1, 0, 0, 0, 0, time.UTC), `"2019-04-01T00:00:00Z"`,
-	}}
-	inst := getInstance(t, "{}")
-	b := ast.NewIdent("dummy")
-	for _, tc := range testCases {
-		ctx := inst.newContext()
-		t.Run("", func(t *testing.T) {
-			v := convertVal(ctx, newNode(b), true, tc.goVal)
-			got := debugStr(ctx, v)
-			if got != tc.want {
-				t.Errorf("got %q; want %q", got, tc.want)
-			}
-		})
-	}
-}
-
-func TestConvertType(t *testing.T) {
-	testCases := []struct {
-		goTyp interface{}
-		want  string
-	}{{
-		struct {
-			A int      `cue:">=0&<100"`
-			B *big.Int `cue:">=0"`
-			C *big.Int
-			D big.Int
-			F *big.Float
-		}{},
-		// TODO: indicate that B is explicitly an int only.
-		`<0>{A: ((int & >=-9223372036854775808 & int & <=9223372036854775807) & (>=0 & <100)), ` +
-			`B: (int & >=0), ` +
-			`C?: int, ` +
-			`D: int, ` +
-			`F?: number}`,
-	}, {
-		&struct {
-			A int16 `cue:">=0&<100"`
-			B error `json:"b,"`
-			C string
-			D bool
-			F float64
-			L []byte
-			T time.Time
-			G func()
-		}{},
-		`(*null | <0>{T: _, ` +
-			`A: ((int & >=-32768 & int & <=32767) & (>=0 & <100)), ` +
-			`C: string, ` +
-			`D: bool, ` +
-			`F: float, ` +
-			`b: null, ` +
-			`L?: (*null | bytes)})`,
-	}, {
-		struct {
-			A int `cue:"<"` // invalid
-		}{},
-		"_|_(invalid tag \"<\" for field \"A\": expected operand, found 'EOF')",
-	}, {
-		struct {
-			A int `json:"-"` // skip
-			D *apd.Decimal
-			P ***apd.Decimal
-			I interface{ Foo() }
-			T string `cue:""` // allowed
-			h int
-		}{},
-		"<0>{T: string, D?: number, P?: (*null | number), I?: _}",
-	}, {
-		struct {
-			A int8 `cue:"C-B"`
-			B int8 `cue:"C-A,opt"`
-			C int8 `cue:"A+B"`
-		}{},
-		// TODO: should B be marked as optional?
-		`<0>{A: ((int & >=-128 & int & <=127) & (<0>.C - <0>.B)), ` +
-			`B?: ((int & >=-128 & int & <=127) & (<0>.C - <0>.A)), ` +
-			`C: ((int & >=-128 & int & <=127) & (<0>.A + <0>.B))}`,
-	}, {
-		[]string{},
-		`(*null | [, ...string])`,
-	}, {
-		[4]string{},
-		`4*[string]`,
-	}, {
-		[]func(){},
-		"_|_(unsupported Go type (func()))",
-	}, {
-		map[string]struct{ A map[string]uint }{},
-		`(*null | ` +
-			`<0>{[]: <1>(_: string)-><2>{` +
-			`A?: (*null | ` +
-			`<3>{[]: <4>(_: string)->(int & >=0 & int & <=18446744073709551615), })}, })`,
-	}, {
-		map[float32]int{},
-		`_|_(unsupported Go type for map key (float32))`,
-	}, {
-		map[int]map[float32]int{},
-		`_|_(unsupported Go type for map key (float32))`,
-	}, {
-		map[int]func(){},
-		`_|_(unsupported Go type (func()))`,
-	}, {
-		time.Now, // a function
-		"_|_(unsupported Go type (func() time.Time))",
-	}}
-	inst := getInstance(t, "{}")
-
-	for _, tc := range testCases {
-		ctx := inst.newContext()
-		t.Run("", func(t *testing.T) {
-			v := goTypeToValue(ctx, true, reflect.TypeOf(tc.goTyp))
-			got := debugStr(ctx, v)
-			if got != tc.want {
-				t.Errorf("\n got %q;\nwant %q", got, tc.want)
-			}
-		})
-	}
-}
diff --git a/cue/instance.go b/cue/instance.go
index a779041..5b954ea 100644
--- a/cue/instance.go
+++ b/cue/instance.go
@@ -18,8 +18,11 @@
 	"cuelang.org/go/cue/ast"
 	"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/compile"
+	"cuelang.org/go/internal/core/convert"
+	"cuelang.org/go/internal/core/eval"
 	"cuelang.org/go/internal/core/runtime"
 )
 
@@ -28,12 +31,7 @@
 type Instance struct {
 	*index
 
-	rootStruct *structLit // the struct to insert root values into
-	rootValue  value      // the value to evaluate: may add comprehensions
-
-	// scope is used as an additional top-level scope between the package scope
-	// and the predeclared identifiers.
-	scope *structLit
+	root *adt.Vertex
 
 	ImportPath  string
 	Dir         string
@@ -49,12 +47,12 @@
 }
 
 func (x *index) addInst(p *Instance) *Instance {
-	x.Index.AddInst(p.ImportPath, p.rootStruct, p)
+	x.Index.AddInst(p.ImportPath, p.root, p)
 	p.index = x
 	return p
 }
 
-func (x *index) getImportFromNode(v value) *Instance {
+func (x *index) getImportFromNode(v *adt.Vertex) *Instance {
 	p := x.Index.GetImportFromNode(v)
 	if p == nil {
 		return nil
@@ -74,25 +72,23 @@
 	internal.MakeInstance = func(value interface{}) interface{} {
 		v := value.(Value)
 		x := v.eval(v.ctx())
-		st, ok := x.(*structLit)
+		st, ok := x.(*adt.Vertex)
 		if !ok {
-			st = &structLit{baseValue: x.base(), emit: x}
+			st = &adt.Vertex{}
+			st.AddConjunct(adt.MakeConjunct(nil, x))
 		}
 		return v.ctx().index.addInst(&Instance{
-			rootStruct: st,
-			rootValue:  v.v.v,
+			root: st,
 		})
 	}
 }
 
 // newInstance creates a new instance. Use Insert to populate the instance.
-func newInstance(x *index, p *build.Instance) *Instance {
+func newInstance(x *index, p *build.Instance, v *adt.Vertex) *Instance {
 	// TODO: associate root source with structLit.
-	st := &structLit{baseValue: baseValue{nil}}
 	i := &Instance{
-		rootStruct: st,
-		rootValue:  st,
-		inst:       p,
+		root: v,
+		inst: p,
 	}
 	if p != nil {
 		i.ImportPath = p.ImportPath
@@ -118,28 +114,7 @@
 
 func (inst *Instance) eval(ctx *context) evaluated {
 	// TODO: remove manifest here?
-	v := ctx.manifest(inst.rootValue)
-	if s, ok := v.(*structLit); ok && s.emit != nil {
-		e := s.emit.evalPartial(ctx)
-		src := binSrc(token.NoPos, opUnify, v, e)
-	outer:
-		switch e.(type) {
-		case *structLit, *top:
-			v = binOp(ctx, src, opUnifyUnchecked, v, e)
-			if s, ok := v.(*structLit); ok {
-				s.emit = nil
-			}
-
-		default:
-			for _, a := range s.Arcs {
-				if !a.definition {
-					v = binOp(ctx, src, opUnify, v, e)
-					break outer
-				}
-			}
-			return e
-		}
-	}
+	v := ctx.manifest(inst.root)
 	return v
 }
 
@@ -148,20 +123,63 @@
 		v := value.(Value)
 		e := expr.(ast.Expr)
 		ctx := v.idx.newContext()
-		return newValueRoot(ctx, evalExpr(ctx, v.eval(ctx), e))
+		return newValueRoot(ctx, evalExpr(ctx, v.vertex(ctx), e))
 	}
 }
 
-func evalExpr(ctx *context, x value, expr ast.Expr) evaluated {
-	if isBottom(x) {
-		return ctx.mkErr(x, "error evaluating instance: %v", x)
+// evalExpr evaluates expr within scope.
+func evalExpr(ctx *context, scope *adt.Vertex, expr ast.Expr) evaluated {
+	cfg := &compile.Config{
+		Scope: scope,
+		Imports: func(x *ast.Ident) (pkgPath string) {
+			if _, ok := builtins[x.Name]; !ok {
+				return ""
+			}
+			return x.Name
+		},
 	}
-	obj, ok := x.(*structLit)
-	if !ok {
-		return ctx.mkErr(x, "instance is not a struct, found %s", x.Kind())
+
+	c, err := compile.Expr(cfg, ctx.opCtx, expr)
+	if err != nil {
+		return &adt.Bottom{Err: err}
 	}
-	v := newVisitor(ctx.index, nil, nil, obj, true)
-	return v.walk(expr).evalPartial(ctx)
+	return adt.Resolve(ctx.opCtx, c)
+
+	// scope.Finalize(ctx.opCtx) // 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.opCtx
+
+	// 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))
 }
 
 // Doc returns the package comments for this instance.
@@ -183,7 +201,8 @@
 // top-level values.
 func (inst *Instance) Value() Value {
 	ctx := inst.newContext()
-	return newValueRoot(ctx, inst.eval(ctx))
+	inst.root.Finalize(ctx.opCtx)
+	return newVertexRoot(ctx, inst.root)
 }
 
 // Eval evaluates an expression within an existing instance.
@@ -191,7 +210,9 @@
 // Expressions may refer to builtin packages if they can be uniquely identified.
 func (inst *Instance) Eval(expr ast.Expr) Value {
 	ctx := inst.newContext()
-	result := evalExpr(ctx, inst.eval(ctx), expr)
+	v := inst.root
+	v.Finalize(ctx.opCtx)
+	result := evalExpr(ctx, v, expr)
 	return newValueRoot(ctx, result)
 }
 
@@ -201,33 +222,22 @@
 // that these will only surface during manifestation. This allows
 // non-conflicting parts to be used.
 func Merge(inst ...*Instance) *Instance {
-	switch len(inst) {
-	case 0:
-		return nil
-	case 1:
-		return inst[0]
-	}
+	v := &adt.Vertex{}
 
-	values := []value{}
+	i := inst[0]
+	ctx := i.index.newContext().opCtx
+
+	// TODO: interesting test: use actual unification and then on K8s corpus.
+
 	for _, i := range inst {
-		if i.Err != nil {
-			return i
-		}
-		values = append(values, i.rootValue)
+		w := i.Value()
+		v.AddConjunct(adt.MakeConjunct(nil, w.v.ToDataAll()))
 	}
-	merged := &mergedValues{values: values}
+	v.Finalize(ctx)
 
-	ctx := inst[0].newContext()
-
-	st, ok := ctx.manifest(merged).(*structLit)
-	if !ok {
-		return nil
-	}
-
-	p := ctx.index.addInst(&Instance{
-		rootStruct: st,
-		rootValue:  merged,
-		complete:   true,
+	p := i.index.addInst(&Instance{
+		root:     v,
+		complete: true,
 	})
 	return p
 }
@@ -239,37 +249,33 @@
 	p.Complete()
 
 	idx := inst.index
+	r := inst.index.Runtime
 
-	i := newInstance(idx, p)
+	rErr := runtime.ResolveFiles(idx.Index, p, isBuiltin)
+
+	v, err := compile.Files(&compile.Config{Scope: inst.root}, r, p.Files...)
+
+	v.AddConjunct(adt.MakeConjunct(nil, inst.root))
+
+	i := newInstance(idx, p, v)
+	if rErr != nil {
+		i.setListOrError(err)
+	}
 	if i.Err != nil {
-		return i
+		i.setListOrError(err)
 	}
 
-	ctx := inst.newContext()
-	val := newValueRoot(ctx, inst.rootValue)
-	v, err := val.structValFull(ctx)
 	if err != nil {
-		i.setError(val.toErr(err))
-		return i
+		i.setListOrError(err)
 	}
-	i.scope = v.obj
 
-	if err := runtime.ResolveFiles(idx.Index, p, isBuiltin); err != nil {
-		i.setError(err)
-		return i
-	}
-	for _, f := range p.Files {
-		if err := i.insertFile(f); err != nil {
-			i.setListOrError(err)
-		}
-	}
 	i.complete = true
 
 	return i
 }
 
 func (inst *Instance) value() Value {
-	return newValueRoot(inst.newContext(), inst.rootValue)
+	return newVertexRoot(inst.newContext(), inst.root)
 }
 
 // Lookup reports the value at a path starting from the top level struct. The
@@ -322,44 +328,36 @@
 // a Value. In the latter case, it will panic if the Value is not from the same
 // Runtime.
 func (inst *Instance) Fill(x interface{}, path ...string) (*Instance, error) {
-	ctx := inst.newContext()
-	root := ctx.manifest(inst.rootValue)
 	for i := len(path) - 1; i >= 0; i-- {
 		x = map[string]interface{}{path[i]: x}
 	}
-	value := convertVal(ctx, root, true, x)
-	eval := binOp(ctx, baseValue{}, opUnify, root, value)
-	// TODO: validate recursively?
-	err := inst.Err
-	var st *structLit
-	var stVal evaluated
-	switch x := eval.(type) {
-	case *structLit:
-		st = x
-		stVal = x
-	default:
-		// This should not happen.
-		b := ctx.mkErr(eval, "error filling struct")
-		err = inst.Value().toErr(b)
-		st = &structLit{emit: b}
-		stVal = b
-	case *bottom:
-		err = inst.Value().toErr(x)
-		st = &structLit{emit: x}
-		stVal = x
+	a := make([]adt.Conjunct, len(inst.root.Conjuncts))
+	copy(a, inst.root.Conjuncts)
+	u := &adt.Vertex{Conjuncts: a}
+
+	if v, ok := x.(Value); ok {
+		if inst.index != v.idx {
+			panic("value of type Value is not created with same Runtime as Instance")
+		}
+		for _, c := range v.v.Conjuncts {
+			u.AddConjunct(c)
+		}
+	} else {
+		ctx := eval.NewContext(inst.index.Runtime, nil)
+		expr := convert.GoValueToExpr(ctx, true, x)
+		u.AddConjunct(adt.MakeConjunct(nil, expr))
+		u.Finalize(ctx)
 	}
 	inst = inst.index.addInst(&Instance{
-		rootStruct: st,
-		rootValue:  stVal,
-		inst:       nil,
+		root: u,
+		inst: nil,
 
 		// Omit ImportPath to indicate this is not an importable package.
 		Dir:        inst.Dir,
 		PkgName:    inst.PkgName,
 		Incomplete: inst.Incomplete,
-		Err:        err,
 
-		complete: err != nil,
+		complete: true,
 	})
-	return inst, err
+	return inst, nil
 }
diff --git a/cue/instance_test.go b/cue/instance_test.go
deleted file mode 100644
index e11cbf6..0000000
--- a/cue/instance_test.go
+++ /dev/null
@@ -1,162 +0,0 @@
-// Copyright 2018 The 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 (
-	"strings"
-	"testing"
-
-	"cuelang.org/go/cue/build"
-)
-
-func toString(t *testing.T, v Value) string {
-	t.Helper()
-
-	b, err := v.MarshalJSON()
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	return strings.Replace(string(b), `"`, "", -1)
-}
-
-func TestMerge(t *testing.T) {
-	insts := func(s ...string) []string { return s }
-	testCases := []struct {
-		desc      string
-		instances []string
-		out       string
-		isErr     bool
-	}{{
-		desc:      "single",
-		instances: insts(`a: 1, b: 2`),
-		out:       `{a:1,b:2}`,
-	}, {
-		desc: "multiple",
-		instances: insts(
-			`a: 1`,
-			`b: 2`,
-			`a: int`,
-		),
-		out: `{a:1,b:2}`,
-	}, {
-		desc: "templates",
-		instances: insts(`
-			obj: [string]: { a: "A" }
-			obj: alpha: { b: 2 }
-			`,
-			`
-			obj: [string]: { a: "B" }
-			obj: beta: { b: 3 }
-			`,
-		),
-		out: `{obj:{alpha:{a:A,b:2},beta:{a:B,b:3}}}`,
-	}, {
-		// Structs that are shared in templates may have conflicting results.
-		// However, this is not an issue as long as these value are not
-		// referenced during evaluation. For generating JSON this is not an
-		// issue as such fields are typically hidden.
-		desc: "shared struct",
-		instances: insts(`
-			_shared: { a: "A" }
-			obj: [string]: _shared & {}
-			obj: alpha: { b: 2 }
-			`,
-			`
-			_shared: { a: "B" }
-			obj: [string]: _shared & {}
-			obj: beta: { b: 3 }
-			`,
-		),
-		out: `{obj:{alpha:{a:A,b:2},beta:{a:B,b:3}}}`,
-	}, {
-		desc: "top-level comprehensions",
-		instances: insts(`
-			t: { for k, x in s {"\(k)": 10} }
-			s: [string]: {}
-			s: foo: a: 1
-			`,
-			`
-			t: { for k, x in s {"\(k)": 10 } }
-			s: [string]: {}
-			s: bar: b: 2
-			`,
-		),
-		out: `{t:{foo:10,bar:10},s:{foo:{a:1},bar:{b:2}}}`,
-	}, {
-		desc:      "error",
-		instances: insts(`a:`),
-		out:       `{}`,
-		isErr:     true,
-	}}
-
-	for _, tc := range testCases {
-		t.Run(tc.desc, func(t *testing.T) {
-			ctx := build.NewContext()
-			in := []*build.Instance{}
-			for _, str := range tc.instances {
-				bi := ctx.NewInstance("dir", nil) // no packages
-				_ = bi.AddFile("file", str)
-				in = append(in, bi)
-			}
-			merged := Merge(Build(in)...)
-			if err := merged.Err; err != nil {
-				if !tc.isErr {
-					t.Fatal(err)
-				}
-			}
-
-			if got := toString(t, merged.Value()); got != tc.out {
-				t.Errorf("\n got: %s\nwant: %s", got, tc.out)
-			}
-		})
-	}
-}
-
-func TestInstance_Build(t *testing.T) {
-	testCases := []struct {
-		desc     string
-		instance string
-		overlay  string
-		out      string
-	}{{
-		desc:     "single",
-		instance: `a: {b: 1, c: 2}`,
-		overlay:  `res: a`,
-		out:      `{res:{b:1,c:2}}`,
-	}}
-
-	for _, tc := range testCases {
-		t.Run(tc.desc, func(t *testing.T) {
-			ctx := build.NewContext()
-
-			bi := ctx.NewInstance("main", nil) // no packages
-			_ = bi.AddFile("file", tc.instance)
-			main := Build([]*build.Instance{bi})
-			if err := main[0].Err; err != nil {
-				t.Fatal(err)
-			}
-
-			bi = ctx.NewInstance("overlay", nil) // no packages
-			_ = bi.AddFile("file", tc.overlay)
-
-			overlay := main[0].Build(bi)
-
-			if got := toString(t, overlay.Value()); got != tc.out {
-				t.Errorf("\n got: %s\nwant: %s", got, tc.out)
-			}
-		})
-	}
-}
diff --git a/cue/kind.go b/cue/kind.go
deleted file mode 100644
index 1f95d00..0000000
--- a/cue/kind.go
+++ /dev/null
@@ -1,314 +0,0 @@
-// Copyright 2018 The 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 (
-	"fmt"
-)
-
-func unifyType(a, b kind) kind {
-	const mask = topKind
-	isRef := (a &^ mask) | (b &^ mask)
-	return isRef | (a & b)
-}
-
-type kind uint16
-
-const (
-	unknownKind kind = (1 << iota)
-	nullKind
-	boolKind
-	intKind
-	floatKind
-	stringKind
-	bytesKind
-	durationKind
-	listKind
-	structKind
-
-	lambdaKind
-	// customKind
-
-	// nonGround means that a value is not specific enough to be emitted.
-	// Structs and lists are indicated as ground even when their values are not.
-	nonGround
-
-	// TODO: distinguish beteween nonGround and disjunctions?
-
-	// a referenceKind is typically top and nonGround, but is indicated with an
-	// additional bit. If reference is set and nonGround is not, it is possible
-	// to move the reference to an assertion clause.
-	referenceKind
-
-	atomKind     = (listKind - 1) &^ unknownKind
-	addableKind  = (structKind - 1) &^ unknownKind
-	concreteKind = (lambdaKind - 1) &^ unknownKind
-
-	// doneKind indicates a value can not further develop on its own (i.e. not a
-	// reference). If doneKind is not set, but the result is ground, it
-	// typically possible to hoist the reference out of a unification operation.
-
-	// For rational numbers, typically both intKind and floatKind are set,
-	// unless the range is restricted by a root type.
-	numKind = intKind | floatKind
-
-	comparableKind = (listKind - 1) &^ unknownKind
-	stringableKind = scalarKinds | stringKind
-	topKind        = (referenceKind - 1) // all kinds, but not references
-	typeKinds      = (nonGround - 1) &^ unknownKind
-	okKinds        = typeKinds &^ bottomKind
-	fixedKinds     = okKinds &^ (structKind | lambdaKind)
-	scalarKinds    = numKind | durationKind
-
-	bottomKind = 0
-)
-
-func isTop(v value) bool {
-	_, ok := v.(*top)
-	return ok
-}
-
-func isCustom(v value) bool {
-	_, ok := v.(*customValidator)
-	return ok
-}
-
-// isDone means that the value will not evaluate further.
-func (k kind) isDone() bool        { return k&referenceKind == bottomKind }
-func (k kind) hasReferences() bool { return k&referenceKind != bottomKind }
-func (k kind) isConcrete() bool    { return k&^(lambdaKind-1) == bottomKind }
-func (k kind) isGround() bool      { return k&^(nonGround-1) == bottomKind }
-func (k kind) isAtom() bool        { return k.isGround() && k&atomKind != bottomKind }
-func (k kind) isAnyOf(of kind) bool {
-	return k&of != bottomKind
-}
-func (k kind) stringable() bool {
-	return k.isGround() && k&stringKind|scalarKinds != bottomKind
-}
-
-func (k kind) String() string {
-	str := ""
-	if k&topKind == topKind {
-		str = "_"
-		goto finalize
-	}
-	for i := kind(1); i < referenceKind; i <<= 1 {
-		t := ""
-		switch k & i {
-		case bottomKind:
-			continue
-		case nullKind:
-			t = "null"
-		case boolKind:
-			t = "bool"
-		case intKind:
-			if k&floatKind != 0 {
-				t = "number"
-			} else {
-				t = "int"
-			}
-		case floatKind:
-			if k&intKind != 0 {
-				continue
-			}
-			t = "float"
-		case stringKind:
-			t = "string"
-		case bytesKind:
-			t = "bytes"
-		case durationKind:
-			t = "duration"
-		case listKind:
-			t = "list"
-		case structKind:
-			t = "struct"
-		case lambdaKind:
-			t = "lambda"
-		case nonGround, referenceKind:
-			continue
-		default:
-			t = fmt.Sprintf("<unknown> %x", int(i))
-		}
-		if str != "" {
-			str += "|"
-		}
-		str += t
-	}
-finalize:
-	if str == "" {
-		return "_|_"
-	}
-	return str
-}
-
-// matchBinOpKind returns the result kind of applying the given op to operands with
-// the given kinds. The operation is disallowed if the return value is bottomKind. If
-// the second return value is true, the operands should be swapped before evaluation.
-//
-// Evaluating binary expressions uses this to
-// - fail incompatible operations early, even if the concrete types are
-//   not known,
-// - check the result type of unification,
-//
-// Secondary goals:
-// - keep type compatibility mapped at a central place
-// - reduce the amount op type switching.
-// - simplifies testing
-func matchBinOpKind(op op, a, b kind) (k kind, swap bool, msg string) {
-	if op == opDisjunction {
-		return a | b, false, ""
-	}
-	u := unifyType(a, b)
-	valBits := u & typeKinds
-	catBits := u &^ typeKinds
-	aGround := a&nonGround == 0
-	bGround := b&nonGround == 0
-	a = a & typeKinds
-	b = b & typeKinds
-	if valBits == bottomKind {
-		msg := "invalid operation %[2]s %[1]s %[3]s (mismatched types %[4]s and %[5]s)"
-		k := nullKind
-		switch op {
-		case opLss, opLeq, opGtr, opGeq:
-			if a.isAnyOf(numKind) && b.isAnyOf(numKind) {
-				return boolKind, false, ""
-			}
-		case opEql, opNeq:
-			if a.isAnyOf(numKind) && b.isAnyOf(numKind) {
-				return boolKind, false, ""
-			}
-			if a&nullKind != 0 {
-				return k, false, ""
-			}
-			if b&nullKind != 0 {
-				return k, true, ""
-			}
-			return bottomKind, false, msg
-		case opUnify, opUnifyUnchecked:
-			if a&nullKind != 0 {
-				return k, false, ""
-			}
-			if b&nullKind != 0 {
-				return k, true, ""
-			}
-			switch {
-			case a.isGround() && !b.isGround():
-				msg = "invalid value %[2]s (must be %[5]s)"
-			case !a.isGround() && b.isGround():
-				msg = "invalid value %[3]s (must be %[4]s)"
-			default:
-				msg = "conflicting values %[2]s and %[3]s (mismatched types %[4]s and %[5]s)"
-			}
-			return bottomKind, false, msg
-		case opRem, opQuo, opMul, opAdd, opSub:
-			if a.isAnyOf(numKind) && b.isAnyOf(numKind) {
-				return floatKind, false, ""
-			}
-		}
-		if op == opMul {
-			if a.isAnyOf(listKind|stringKind|bytesKind) && b.isAnyOf(intKind) {
-				return a | catBits, false, ""
-			}
-			if b.isAnyOf(listKind|stringKind|bytesKind) && a.isAnyOf(intKind) {
-				return b | catBits, true, ""
-			}
-		}
-		// non-overlapping types
-		if a&scalarKinds == 0 || b&scalarKinds == 0 {
-			return bottomKind, false, msg
-		}
-		// a and b have different numeric types.
-		switch {
-		case b.isAnyOf(durationKind):
-			// a must be a numeric, non-duration type.
-			if op == opMul {
-				return durationKind | catBits, true, msg
-			}
-		case a.isAnyOf(durationKind):
-			if opIn(op, opMul, opQuo, opRem) {
-				return durationKind | catBits, false, msg
-			}
-		case op.isCmp():
-			return boolKind, false, ""
-		}
-		return bottomKind, false, msg
-	}
-	switch {
-	case aGround && bGround:
-		// both ground values: nothing to do
-
-	case op != opUnify && op != opLand && op != opLor && op != opNeq:
-
-	default:
-		swap = aGround && !bGround
-	}
-	// a and b have overlapping types.
-	switch op {
-	case opUnify, opUnifyUnchecked:
-		// Increase likelihood of unification succeeding on first try.
-		return u, swap, ""
-
-	case opLand, opLor:
-		if u.isAnyOf(boolKind) {
-			return boolKind | catBits, swap, ""
-		}
-	case opMat, opNMat:
-		if u.isAnyOf(stringKind | bytesKind) {
-			return boolKind | catBits, false, ""
-		}
-	case opEql, opNeq:
-		if u.isAnyOf(fixedKinds) {
-			return boolKind | catBits, false, ""
-		}
-	case opLss, opLeq, opGeq, opGtr:
-		if u.isAnyOf(fixedKinds) {
-			return boolKind | catBits, false, ""
-		}
-	case opAdd:
-		if u.isAnyOf(addableKind) {
-			return u&(addableKind) | catBits, false, ""
-		}
-	case opSub:
-		if u.isAnyOf(scalarKinds) {
-			return u&scalarKinds | catBits, false, ""
-		}
-	case opRem:
-		if u.isAnyOf(numKind) {
-			return floatKind | catBits, false, ""
-		}
-	case opQuo:
-		if u.isAnyOf(numKind) {
-			return floatKind | catBits, false, ""
-		}
-	case opIRem, opIMod:
-		if u.isAnyOf(intKind) {
-			return u&(intKind) | catBits, false, ""
-		}
-	case opIQuo, opIDiv:
-		if u.isAnyOf(intKind) {
-			return intKind | catBits, false, ""
-		}
-	case opMul:
-		if u.isAnyOf(numKind) {
-			return u&numKind | catBits, false, ""
-		}
-	default:
-		panic("unimplemented")
-	}
-	// TODO: localize
-	msg = "invalid operation %[2]s %[1]s %[3]s"
-	msg += fmt.Sprintf(" (operator '%s' not defined on %s)", op, valBits)
-	return bottomKind, false, msg
-}
diff --git a/cue/kind_test.go b/cue/kind_test.go
deleted file mode 100644
index 48f48db..0000000
--- a/cue/kind_test.go
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright 2018 The 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 (
-	"fmt"
-	"testing"
-)
-
-func TestMatchBinOpKind(t *testing.T) {
-	testCases := []struct {
-		op   op
-		a    kind
-		b    kind
-		want kind
-	}{{
-		op:   opMul,
-		a:    floatKind,
-		b:    numKind,
-		want: floatKind,
-	}, {
-		op:   opMul,
-		a:    intKind,
-		b:    numKind,
-		want: intKind,
-	}, {
-		op:   opMul,
-		a:    floatKind,
-		b:    intKind,
-		want: floatKind,
-	}, {
-		op:   opMul,
-		a:    listKind,
-		b:    intKind,
-		want: listKind,
-	}, {
-		op:   opMul,
-		a:    intKind,
-		b:    listKind,
-		want: listKind,
-	}}
-	for _, tc := range testCases {
-		key := fmt.Sprintf("%s(%v, %v)", tc.op, tc.a, tc.b)
-		t.Run(key, func(t *testing.T) {
-			got, _, _ := matchBinOpKind(tc.op, tc.a, tc.b)
-			if got != tc.want {
-				t.Errorf("got %v, want %v", got, tc.want)
-			}
-		})
-	}
-}
diff --git a/cue/lit.go b/cue/lit.go
deleted file mode 100644
index 2d2c778..0000000
--- a/cue/lit.go
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright 2018 The 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/cue/ast"
-	"cuelang.org/go/cue/literal"
-	"cuelang.org/go/cue/token"
-)
-
-const base10 literal.Multiplier = 100
-
-type litParser struct {
-	ctx *context
-	num literal.NumInfo
-}
-
-func (p *litParser) parse(l *ast.BasicLit) (n value) {
-	ctx := p.ctx
-	s := l.Value
-	if s == "" {
-		return p.ctx.mkErr(newNode(l), "invalid literal %q", s)
-	}
-	switch l.Kind {
-	case token.STRING:
-		info, nStart, _, err := literal.ParseQuotes(s, s)
-		if err != nil {
-			return ctx.mkErr(newNode(l), err.Error())
-		}
-		s := s[nStart:]
-		return parseString(ctx, l, info, s)
-
-	case token.FLOAT, token.INT:
-		err := literal.ParseNum(s, &p.num)
-		if err != nil {
-			return ctx.mkErr(newNode(l), err)
-		}
-		kind := floatKind
-		if p.num.IsInt() {
-			kind = intKind
-		}
-		n := newNum(newExpr(l), kind, 0)
-		if err = p.num.Decimal(&n.X); err != nil {
-			return ctx.mkErr(newNode(l), err)
-		}
-		return n
-
-	case token.TRUE:
-		return &boolLit{newExpr(l), true}
-	case token.FALSE:
-		return &boolLit{newExpr(l), false}
-	case token.NULL:
-		return &nullLit{newExpr(l)}
-	default:
-		return ctx.mkErr(newExpr(l), "unknown literal type")
-	}
-}
-
-// parseString decodes a string without the starting and ending quotes.
-func parseString(ctx *context, node ast.Expr, q literal.QuoteInfo, s string) (n value) {
-	src := newExpr(node)
-	str, err := q.Unquote(s)
-	if err != nil {
-		return ctx.mkErr(src, "invalid string: %v", err)
-	}
-	if q.IsDouble() {
-		return &stringLit{src, str, nil}
-	}
-	return &bytesLit{src, []byte(str), nil}
-}
diff --git a/cue/lit_test.go b/cue/lit_test.go
deleted file mode 100644
index 9cf25cf..0000000
--- a/cue/lit_test.go
+++ /dev/null
@@ -1,199 +0,0 @@
-// Copyright 2018 The 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 (
-	"fmt"
-	"math/big"
-	"testing"
-
-	"github.com/cockroachdb/apd/v2"
-	"github.com/google/go-cmp/cmp"
-	"github.com/google/go-cmp/cmp/cmpopts"
-
-	"cuelang.org/go/cue/ast"
-	"cuelang.org/go/cue/literal"
-	"cuelang.org/go/cue/token"
-)
-
-var testBase = newExpr(&ast.BasicLit{})
-
-func mkInt(a int64) *numLit {
-	return newInt(testBase, base10).setInt64(a)
-}
-func mkIntString(a string) *numLit {
-	return newInt(testBase, base10).setString(a)
-}
-func mkFloat(a string) *numLit {
-	return newFloat(testBase, base10).setString(a)
-}
-
-var diffOpts = []cmp.Option{
-	cmp.Comparer(func(x, y big.Rat) bool {
-		return x.String() == y.String()
-	}),
-	cmp.Comparer(func(x, y big.Int) bool {
-		return x.String() == y.String()
-	}),
-	cmp.AllowUnexported(
-		nullLit{},
-		boolLit{},
-		stringLit{},
-		bytesLit{},
-		numLit{},
-	),
-	cmpopts.IgnoreUnexported(
-		bottom{},
-		baseValue{},
-		baseValue{},
-	),
-}
-
-var (
-	nullSentinel  = &nullLit{}
-	trueSentinel  = &boolLit{B: true}
-	falseSentinel = &boolLit{B: false}
-)
-
-func TestLiterals(t *testing.T) {
-	t.Skip()
-	mkMul := func(x int64, m literal.Multiplier, base int) *numLit {
-		return newInt(testBase, m).setInt64(x)
-	}
-	hk := newInt(testBase, 0).setInt64(100000)
-	testCases := []struct {
-		lit  string
-		node value
-	}{
-		{"0", mkInt(0)},
-		{"null", nullSentinel},
-		{"true", trueSentinel},
-		{"false", falseSentinel},
-		{"fls", &bottom{}},
-		{`"foo"`, &stringLit{Str: "foo"}},
-		{`#"foo"#`, &stringLit{Str: "foo"}},
-		{`#""foo"#`, &stringLit{Str: `"foo`}},
-		{`#" ""#`, &stringLit{Str: ` "`}},
-		{`"\"foo\""`, &stringLit{Str: `"foo"`}},
-		{`"foo\u0032"`, &stringLit{Str: `foo2`}},
-		{`"foo\U00000033"`, &stringLit{Str: `foo3`}},
-		{`"foo\U0001f499"`, &stringLit{Str: `foo💙`}},
-		{`"\a\b\f\n\r\t\v"`, &stringLit{Str: "\a\b\f\n\r\t\v"}},
-		{`"""
-		"""`, &stringLit{Str: ""}},
-		{`"""
-			abc
-			"""`, &stringLit{Str: "abc"}},
-		{`"""
-			abc
-			def
-			"""`, &stringLit{Str: "abc\ndef"}},
-		{`"""
-			abc
-				def
-			"""`, &stringLit{Str: "abc\n\tdef"}},
-		{`'\xff'`, &bytesLit{B: []byte("\xff")}},
-		{"1", mkInt(1)},
-		{"100_000", hk},
-		{"1.", mkFloat("1")},
-		{"0.0", mkFloat("0.0")},
-		{".0", mkFloat(".0")},
-		{"012.34", mkFloat("012.34")},
-		{".01", mkFloat(".01")},
-		{".01e2", mkFloat("1")},
-		{"0.", mkFloat("0.")},
-		{"1K", mkMul(1000, literal.K, 10)},
-		{".5K", mkMul(500, literal.K, 10)},
-		{"1Mi", mkMul(1024*1024, literal.Mi, 10)},
-		{"1.5Mi", mkMul((1024+512)*1024, literal.Mi, 10)},
-		{"1.3Mi", &bottom{}}, // Cannot be accurately represented.
-		{"1.3G", mkMul(1300000000, literal.G, 10)},
-		{"1.3e+20", mkFloat("1.3e+20")},
-		{"1.3e20", mkFloat("1.3e+20")},
-		{"1.3e-5", mkFloat("1.3e-5")},
-		{".3e-1", mkFloat("0.3e-1")},
-		{"0e-5", mkFloat("0e-5")},
-		{"0E-5", mkFloat("0e-5")},
-		{"5e-5", mkFloat("5e-5")},
-		{"5E-5", mkFloat("5e-5")},
-		{"0x1234", mkMul(0x1234, 0, 16)},
-		{"0xABCD", mkMul(0xABCD, 0, 16)},
-		{"-0xABCD", mkMul(0xABCD, 0, 16)},
-		{"0b11001000", mkMul(0xc8, 0, 2)},
-		{"0b1", mkMul(1, 0, 2)},
-		{"0o755", mkMul(0755, 0, 8)},
-		{"0755", mkMul(0755, 0, 8)},
-	}
-	p := litParser{
-		ctx: &context{Context: &apd.BaseContext},
-	}
-	for i, tc := range testCases {
-		t.Run(fmt.Sprintf("%d/%+q", i, tc.lit), func(t *testing.T) {
-			got := p.parse(&ast.BasicLit{Value: tc.lit})
-			if !cmp.Equal(got, tc.node, diffOpts...) {
-				t.Error(cmp.Diff(got, tc.node, diffOpts...))
-				t.Errorf("%#v, %#v\n", got, tc.node)
-			}
-		})
-	}
-}
-
-func TestLiteralErrors(t *testing.T) {
-	testCases := []struct {
-		kind token.Token
-		lit  string
-	}{
-		{token.STRING, `"foo\u"`},
-		{token.STRING, `"foo\u003"`},
-		{token.STRING, `"foo\U1234567"`},
-		{token.STRING, `"foo\U12345678"`},
-		{token.STRING, `"foo\Ug"`},
-		{token.STRING, `"\xff"`},
-		// not allowed in string literal, only binary
-		{token.STRING, `"foo\x00"`},
-		{token.INT, `0x`},
-		{token.INT, `0o`},
-		{token.INT, `0b`},
-		{token.INT, `0_`},
-		{token.INT, "0128"},
-		{token.STRING, ``},
-		{token.STRING, `"`},
-		{token.STRING, `"a`},
-		// wrong indentation
-		{token.STRING, `"""
-			abc
-		def
-			"""`},
-		// non-matching quotes
-		{token.STRING, `"""
-			abc
-			'''`},
-		{token.STRING, `"""
-			abc
-			"`},
-		{token.STRING, `"abc \( foo "`},
-	}
-	p := litParser{
-		ctx: &context{Context: &apd.BaseContext},
-	}
-	for _, tc := range testCases {
-		t.Run(fmt.Sprintf("%+q", tc.lit), func(t *testing.T) {
-			got := p.parse(&ast.BasicLit{Kind: tc.kind, Value: tc.lit})
-			if _, ok := got.(*bottom); !ok {
-				t.Fatalf("expected error but found none")
-			}
-		})
-	}
-}
diff --git a/cue/load/loader_test.go b/cue/load/loader_test.go
index a77936c..f3c4ec0 100644
--- a/cue/load/loader_test.go
+++ b/cue/load/loader_test.go
@@ -26,8 +26,8 @@
 
 	"github.com/kylelemons/godebug/diff"
 
+	"cuelang.org/go/cue"
 	"cuelang.org/go/cue/format"
-	"cuelang.org/go/internal/legacy/cue"
 	"cuelang.org/go/internal/str"
 )
 
diff --git a/cue/marshal.go b/cue/marshal.go
index fd3cbe1..c48d136 100644
--- a/cue/marshal.go
+++ b/cue/marshal.go
@@ -28,6 +28,7 @@
 	"cuelang.org/go/cue/format"
 	"cuelang.org/go/cue/token"
 	"cuelang.org/go/internal"
+	"cuelang.org/go/internal/core/export"
 )
 
 // root.
@@ -141,7 +142,7 @@
 			return p
 		}
 		// TODO: support exporting instance
-		file, _ := exportFile(ctx, nil, i.rootValue, options{raw: true})
+		file, _ := export.Def(r.idx.Runtime, i.root)
 		imports := []string{}
 		for _, i := range internal.Imports(file) {
 			for _, spec := range i.(*ast.ImportDecl).Specs {
@@ -151,8 +152,15 @@
 		}
 
 		if i.PkgName != "" {
-			pkg := &ast.Package{Name: ast.NewIdent(i.PkgName)}
-			file.Decls = append([]ast.Decl{pkg}, file.Decls...)
+			p, name, _ := internal.PackageInfo(file)
+			if p == nil {
+				pkg := &ast.Package{Name: ast.NewIdent(i.PkgName)}
+				file.Decls = append([]ast.Decl{pkg}, file.Decls...)
+			} else if name != i.PkgName {
+				// p is guaranteed to be generated by Def, so it is "safe" to
+				// modify.
+				p.Name = ast.NewIdent(i.PkgName)
+			}
 		}
 
 		b, err := format.Node(file)
diff --git a/cue/marshal_test.go b/cue/marshal_test.go
index b380b1a..64775aa 100644
--- a/cue/marshal_test.go
+++ b/cue/marshal_test.go
@@ -100,7 +100,7 @@
 	insts := func(i ...*instanceData) []*instanceData { return i }
 	pkg1 := &instanceData{
 		true,
-		"pkg1",
+		"example.com/foo/pkg1",
 		files(`
 		package pkg1
 
@@ -137,7 +137,7 @@
 			files(
 				`package test
 
-			import "pkg1"
+			import "example.com/foo/pkg1"
 
 			"Hello \(pkg1.Object)!"`),
 		}),
@@ -147,7 +147,7 @@
 			files(
 				`package test
 
-		import pkg2 "pkg1"
+		import pkg2 "example.com/foo/pkg1"
 		pkg1: pkg2.Object
 
 		"Hello \(pkg1)!"`),
diff --git a/cue/resolve_test.go b/cue/resolve_test.go
index e7480da..b9ad808 100644
--- a/cue/resolve_test.go
+++ b/cue/resolve_test.go
@@ -15,3031 +15,12 @@
 package cue
 
 import (
-	"flag"
 	"strings"
 	"testing"
+
+	"cuelang.org/go/internal/core/adt"
 )
 
-var traceOn = flag.Bool("debug", false, "enable tracing")
-
-func compileFileWithErrors(t *testing.T, body string) (*context, *structLit, error) {
-	t.Helper()
-	ctx, inst, err := compileInstance(t, body)
-	return ctx, inst.rootValue.evalPartial(ctx).(*structLit), err
-}
-
-func compileFile(t *testing.T, body string) (*context, *structLit) {
-	t.Helper()
-	ctx, inst, errs := compileInstance(t, body)
-	if errs != nil {
-		t.Fatal(errs)
-	}
-	return ctx, inst.rootValue.evalPartial(ctx).(*structLit)
-}
-
-func compileInstance(t *testing.T, body string) (*context, *Instance, error) {
-	var r Runtime
-	inst, err := r.Compile("test", body)
-
-	if err != nil {
-		x := newInstance(newIndex(sharedIndex), nil)
-		ctx := x.newContext()
-		return ctx, x, err
-	}
-
-	return r.index().newContext(), inst, nil
-}
-
-func rewriteHelper(t *testing.T, cases []testCase, r rewriteMode) {
-	for _, tc := range cases {
-		t.Run(tc.desc, func(t *testing.T) {
-			ctx, obj := compileFile(t, tc.in)
-			ctx.trace = *traceOn
-			root := testResolve(ctx, obj, r)
-
-			got := debugStr(ctx, root)
-
-			// Copy the result
-			if got != tc.out {
-				fn := t.Errorf
-				if tc.skip {
-					fn = t.Skipf
-				}
-				fn("output differs:\ngot  %s\nwant %s", got, tc.out)
-			}
-		})
-	}
-}
-
-type testCase struct {
-	desc string
-	in   string
-	out  string
-	skip bool
-}
-
-func TestBasicRewrite(t *testing.T) {
-	testCases := []testCase{{
-		desc: "errors",
-		in: `
-			a: _|_ & _|_
-			b: null & _|_
-			c: b.a == _|_
-			d: _|_ != b.a
-			e: _|_ == _|_
-			`,
-		out: `<0>{a: _|_(from source), b: _|_(from source), c: true, d: false, e: true}`,
-	}, {
-		desc: "regexp",
-		in: `
-			c1: "a" =~ "a"
-			c2: "foo" =~ "[a-z]{3}"
-			c3: "foo" =~ "[a-z]{4}"
-			c4: "foo" !~ "[a-z]{4}"
-
-			b1: =~ "a"
-			b1: "a"
-			b2: =~ "[a-z]{3}"
-			b2: "foo"
-			b3: =~ "[a-z]{4}"
-			b3: "foo"
-			b4: !~ "[a-z]{4}"
-			b4: "foo"
-
-			s1: != "b" & =~"c"      // =~"c"
-			s2: != "b" & =~"[a-z]"  // != "b" & =~"[a-z]"
-
-			e1: "foo" =~ 1
-			e2: "foo" !~ true
-			e3: != "a" & <5
-		`,
-		out: `<0>{c1: true, ` +
-			`c2: true, ` +
-			`c3: false, ` +
-			`c4: true, ` +
-
-			`b1: "a", ` +
-			`b2: "foo", ` +
-			`b3: _|_((=~"[a-z]{4}" & "foo"):invalid value "foo" (does not match =~"[a-z]{4}")), ` +
-			`b4: "foo", ` +
-
-			`s1: =~"c", ` +
-			`s2: (!="b" & =~"[a-z]"), ` +
-
-			`e1: _|_(("foo" =~ 1):invalid operation "foo" =~ 1 (mismatched types string and int)), ` +
-			`e2: _|_(("foo" !~ true):invalid operation "foo" !~ true (mismatched types string and bool)), ` +
-			`e3: _|_((!="a" & <5):conflicting values !="a" and <5 (mismatched types string and number))}`,
-	}, {
-		desc: "arithmetic",
-		in: `
-			i1: 1 & int
-			i2: 2 & int
-
-			sum: -1 + +2        // 1
-			div1: 2.0 / 3 * 6   // 4
-			div2: 2 / 3 * 6     // 4
-			div3: 1.00 / 1.00
-			divZero: 1.0 / 0
-			div00: 0 / 0
-			b: 1 != 4
-			add: div1 + 1.0
-
-			idiv00: 0 div 0
-			imod00: 0 mod 0
-			iquo00: 0 quo 0
-			irem00: 0 rem 0
-
-			v1: 1.0T/2.0
-			v2: 2.0 == 2
-			v3: 2.0/3.0
-			v5: i1 div i2
-
-			e0: 2 + "a"
-			// these are now all alloweed
-			// e1: 2.0 / i1
-			// e2: i1 / 2.0
-			// e3: 3.0 % i2
-			// e4: i1 % 2.0
-			e5: 1.0 div 2
-			e6: 2 rem 2.0
-			e7: 2 quo 2.0
-			e8: 1.0 mod 1
-			`,
-		out: `<0>{i1: 1, i2: 2, ` +
-			`sum: 1, ` +
-			`div1: 4.00000000000000000000000, ` +
-			`div2: 4.00000000000000000000000, ` +
-			`div3: 1., ` +
-			`divZero: _|_((1.0 / 0):division by zero), ` +
-			`div00: _|_((0 / 0):division undefined), ` +
-			`b: true, ` +
-			`add: 5.00000000000000000000000, ` +
-			`idiv00: _|_((0 div 0):division by zero), ` +
-			`imod00: _|_((0 mod 0):division by zero), ` +
-			`iquo00: _|_((0 quo 0):division by zero), ` +
-			`irem00: _|_((0 rem 0):division by zero), ` +
-			`v1: 5.0000000000e+11, ` +
-			`v2: true, ` +
-			`v3: 0.666666666666666666666667, ` +
-			`v5: 0, ` +
-
-			`e0: _|_((2 + "a"):invalid operation 2 + "a" (mismatched types int and string)), ` +
-			// `e1: _|_((2.0 / 1):unsupported op /(float, int)), ` +
-			// `e2: _|_((1 / 2.0):unsupported op /(int, float)), ` +
-			// `e3: _|_((3.0 % 2):unsupported op %(float, int)), ` +
-			// `e4: _|_((1 % 2.0):unsupported op %(int, float)), ` +
-			`e5: _|_((1.0 div 2):invalid operation 1.0 div 2 (mismatched types float and int)), ` +
-			`e6: _|_((2 rem 2.0):invalid operation 2 rem 2.0 (mismatched types int and float)), ` +
-			`e7: _|_((2 quo 2.0):invalid operation 2 quo 2.0 (mismatched types int and float)), ` +
-			`e8: _|_((1.0 mod 1):invalid operation 1.0 mod 1 (mismatched types float and int))}`,
-	}, {
-		desc: "integer-specific arithmetic",
-		in: `
-			q1: 5 quo 2    // 2
-			q2: 5 quo -2   // -2
-			q3: -5 quo 2   // -2
-			q4: -5 quo -2  // 2
-			qe1: 2.0 quo 1
-			qe2: 2 quo 1.0
-
-			r1: 5 rem 2    // 1
-			r2: 5 rem -2   // 1
-			r3: -5 rem 2   // -1
-			r4: -5 rem -2  // -1
-			re1: 2.0 rem 1
-			re2: 2 rem 1.0
-
-			d1: 5 div 2    // 2
-			d2: 5 div -2   // -2
-			d3: -5 div 2   // -3
-			d4: -5 div -2  // 3
-			de1: 2.0 div 1
-			de2: 2 div 1.0
-
-			m1: 5 mod 2    // 1
-			m2: 5 mod -2   // 1
-			m3: -5 mod 2   // 1
-			m4: -5 mod -2  // 1
-			me1: 2.0 mod 1
-			me2: 2 mod 1.0
-			`,
-		out: `<0>{q1: 2, q2: -2, q3: -2, q4: 2, ` +
-			`qe1: _|_((2.0 quo 1):invalid operation 2.0 quo 1 (mismatched types float and int)), ` +
-			`qe2: _|_((2 quo 1.0):invalid operation 2 quo 1.0 (mismatched types int and float)), ` +
-			`r1: 1, r2: 1, r3: -1, r4: -1, ` +
-			`re1: _|_((2.0 rem 1):invalid operation 2.0 rem 1 (mismatched types float and int)), ` +
-			`re2: _|_((2 rem 1.0):invalid operation 2 rem 1.0 (mismatched types int and float)), ` +
-			`d1: 2, d2: -2, d3: -3, d4: 3, ` +
-			`de1: _|_((2.0 div 1):invalid operation 2.0 div 1 (mismatched types float and int)), ` +
-			`de2: _|_((2 div 1.0):invalid operation 2 div 1.0 (mismatched types int and float)), ` +
-			`m1: 1, m2: 1, m3: 1, m4: 1, ` +
-			`me1: _|_((2.0 mod 1):invalid operation 2.0 mod 1 (mismatched types float and int)), ` +
-			`me2: _|_((2 mod 1.0):invalid operation 2 mod 1.0 (mismatched types int and float))}`,
-	}, {
-		desc: "booleans",
-		in: `
-			t: true
-			t: !false
-			f: false
-			f: !t
-			e: true
-			e: !true
-			`,
-		out: "<0>{t: true, f: false, e: _|_(true:conflicting values true and false)}",
-	}, {
-		desc: "boolean arithmetic",
-		in: `
-			a: true && true
-			b: true || false
-			c: false == true
-			d: false != true
-			e: true & true
-			f: true & false
-			`,
-		out: "<0>{a: true, b: true, c: false, d: true, e: true, f: _|_(true:conflicting values true and false)}",
-	}, {
-		desc: "basic type",
-		in: `
-			a: 1 & int
-			b: number & 1
-			c: 1.0
-			c: float
-			d: int & float // _|_
-			e: "4" & string
-			f: true
-			f: bool
-			`,
-		out: `<0>{a: 1, b: 1, c: 1.0, d: _|_((int & float):conflicting values int and float (mismatched types int and float)), e: "4", f: true}`, // TODO: eliminate redundancy
-	}, {
-		desc: "strings and bytes",
-		in: `
-			s0: "foo" + "bar"
-			s1: 3 * "abc"
-			s2: "abc" * 2
-
-			b0: 'foo' + 'bar'
-			b1: 3 * 'abc'
-			b2: 'abc' * 2
-
-			// TODO: consider the semantics of this and perhaps allow this.
-			e0: "a" + ''
-			e1: 'b' + "c"
-		`,
-		out: `<0>{` +
-			`s0: "foobar", ` +
-			`s1: "abcabcabc", ` +
-			`s2: "abcabc", ` +
-			`b0: 'foobar', ` +
-			`b1: 'abcabcabc', ` +
-			`b2: 'abcabc', ` +
-
-			`e0: _|_(("a" + ''):invalid operation "a" + '' (mismatched types string and bytes)), ` +
-			`e1: _|_(('b' + "c"):invalid operation 'b' + "c" (mismatched types bytes and string))` +
-			`}`,
-	}, {
-		desc: "escaping",
-
-		in: `
-			a: "foo\nbar",
-			b: a,
-
-			// TODO: mimic http://exploringjs.com/es6/ch_template-literals.html#sec_introduction-template-literals
-		`,
-		out: `<0>{a: "foo\nbar", b: "foo\nbar"}`,
-		// out: `<0>{a: "foo\nbar", b: <0>.a}`,
-	}, {
-		desc: "reference",
-		in: `
-			a: b
-			b: 2
-			d: {
-				d: 3
-				e: d
-			}
-			e: {
-				e: {
-					v: 1
-				}
-				f: {
-					v: e.v
-				}
-			}
-			`,
-		out: "<0>{a: 2, b: 2, d: <1>{d: 3, e: 3}, e: <2>{e: <3>{v: 1}, f: <4>{v: 1}}}",
-	}, {
-		desc: "lists",
-		in: `
-			list: [1,2,3]
-			index: [1,2,3][1]
-			unify: [1,2,3] & [_,2,3]
-			e: [] & 4
-			e2: [3]["d"]
-			e3: [3][-1]
-			e4: [1, 2, ...>=4 & <=5] & [1, 2, 4, 8]
-			e5: [1, 2, 4, 8] & [1, 2, ...>=4 & <=5]
-			`,
-		out: `<0>{list: [1,2,3], index: 2, unify: [1,2,3], e: _|_(([] & 4):conflicting values [] and 4 (mismatched types list and int)), e2: _|_("d":invalid list index "d" (type string)), e3: _|_(-1:invalid list index -1 (index must be non-negative)), e4: [1,2,4,_|_((<=5 & 8):invalid value 8 (out of bound <=5))], e5: [1,2,4,_|_((<=5 & 8):invalid value 8 (out of bound <=5))]}`,
-	}, {
-		desc: "list arithmetic",
-		in: `
-			list: [1,2,3]
-			mul0: list*0
-			mul1: list*1
-			mul2: 2*list
-			list1: [1]
-		    mul1_0: list1*0
-			mul1_1: 1*list1
-			mul1_2: list1*2
-			e: list*-1
-			`,
-		out: `<0>{list: [1,2,3], ` +
-			`mul0: [], ` +
-			`mul1: [1,2,3], ` +
-			`mul2: [1,2,3,1,2,3], ` +
-			`list1: [1], ` +
-			`mul1_0: [], ` +
-			`mul1_1: [1], ` +
-			`mul1_2: [1,1], ` +
-			`e: _|_((<1>.list * -1):negative number -1 multiplies list)}`,
-	}, {
-		desc: "selecting",
-		in: `
-			obj: {a: 1, b: 2}
-			index: {a: 1, b: 2}["b"]
-			mulidx: {a: 1, b: {a:1, b: 3}}["b"]["b"]
-			e: {a: 1}[4]
-			f: {a: 1}.b
-			g: {a: 1}["b"]
-			h: [3].b
-			`,
-		out: `<0>{obj: <1>{a: 1, b: 2}, index: 2, mulidx: 3, e: _|_(4:invalid struct index 4 (type int)), f: <2>{a: 1}.b, g: <3>{a: 1}["b"], h: _|_([3]:invalid operation: [3].b (type list does not support selection))}`,
-	}, {
-		desc: "obj unify",
-		in: `
-			o1: {a: 1 } & { b: 2}      // {a:1,b:2}
-			o2: {a: 1, b:2 } & { b: 2} // {a:1,b:2}
-			o3: {a: 1 } & { a:1, b: 2} // {a:1,b:2}
-			o4: {a: 1 } & { b: 2}      // {a:1,b:2}
-			o4: {a: 1, b:2 } & { b: 2}
-			o4: {a: 1 } & { a:1, b: 2}
-			e: 1                       // 1 & {a:3}
-			e: {a:3}
-			`,
-		out: "<0>{o1: <1>{a: 1, b: 2}, o2: <2>{a: 1, b: 2}, o3: <3>{a: 1, b: 2}, o4: <4>{a: 1, b: 2}, e: _|_((1 & <5>{a: 3}):conflicting values 1 and {a: 3} (mismatched types int and struct))}",
-	}, {
-		desc: "disjunctions",
-		in: `
-			o1: 1 | 2 | 3
-			o2: (1 | 2 | 3) & 1
-			o3: 2 & (1 | *2 | 3)
-			o4: (1 | *2 | 3) & (1 | 2 | *3)
-			o5: (1 | *2 | 3) & (3 | *2 | 1)
-			o6: (1 | 2 | 3) & (3 | 1 | 2)
-			o7: (1 | 2 | 3) & (2 | 3)
-			o8: (1 | 2 | 3) & (3 | 2)
-			o9: (2 | 3) & (1 | 2 | 3)
-			o10: (3 | 2) & (1 | *2 | 3)
-
-			m1: (*1 | (*2 | 3)) & (>=2 & <=3)
-			m2: (*1 | (*2 | 3)) & (2 | 3)
-			m3: (*1 | *(*2 | 3)) & (2 | 3)
-			m4: (2 | 3) & (*2 | 3)
-			m5: (*2 | 3) & (2 | 3)
-
-			// (*2 | 3) & (2 | 3)
-			// (2 | 3) & (*2 | 3)
-			// 2&(*2 | 3) | 3&(*2 | 3)
-			// (*1 | (*2 | 3)) & (2 | 3)
-			// *1& (2 | 3) | (*2 | 3)&(2 | 3)
-			// *2&(2 | 3) | 3&(2 | 3)
-
-			// (2 | 3)&(*1 | (*2 | 3))
-			// 2&(*1 | (*2 | 3)) | 3&(*1 | (*2 | 3))
-			// *1&2 | (*2 | 3)&2 | *1&3 | (*2 | 3)&3
-			// (*2 | 3)&2 | (*2 | 3)&3
-			// *2 | 3
-
-
-			// All errors are treated the same as per the unification model.
-			i1: [1, 2][3] | "c"
-			`,
-		out: `<0>{o1: (1 | 2 | 3), o2: 1, o3: 2, o4: (1 | 2 | 3 | *_|_), o5: (1 | *2 | 3), o6: (1 | 2 | 3), o7: (2 | 3), o8: (2 | 3), o9: (2 | 3), o10: (3 | *2), m1: (*2 | 3), m2: (*2 | 3), m3: (*2 | 3), m4: (*2 | 3), m5: (*2 | 3), i1: "c"}`,
-	}, {
-		desc: "types",
-		in: `
-			i: int
-			j: int & 3
-			s: string
-			t: "s" & string
-			e: int & string
-			e2: 1 & string
-			b: !int
-			p: +true
-			m: -false
-		`,
-		out: `<0>{i: int, j: 3, s: string, t: "s", e: _|_((int & string):conflicting values int and string (mismatched types int and string)), e2: _|_((1 & string):conflicting values 1 and string (mismatched types int and string)), b: _|_(!int:invalid operation !int (! int)), p: _|_(+true:invalid operation +true (+ bool)), m: _|_(-false:invalid operation -false (- bool))}`,
-	}, {
-		desc: "comparison",
-		in: `
-			lss: 1 < 2
-			leq: 1 <= 1.0
-			leq: 2.0 <= 3
-			eql: 1 == 1.0
-			neq: 1.0 == 1
-			gtr: !(2 > 3)
-			geq: 2.0 >= 2
-			seq: "a" + "b" == "ab"
-			err: 2 == "s"
-		`,
-		out: `<0>{lss: true, leq: true, eql: true, neq: true, gtr: true, geq: true, seq: true, err: _|_((2 == "s"):invalid operation 2 == "s" (mismatched types int and string))}`,
-	}, {
-		desc: "null",
-		in: `
-			eql: null == null
-			neq: null != null
-			unf: null & null
-
-			// errors
-			eq1: null == 1
-			eq2: 1 == null
-			ne1: "s" != null
-			call: null()
-		`,
-		out: `<0>{eql: true, neq: false, unf: null, eq1: false, eq2: false, ne1: true, call: _|_(null:cannot call non-function null (type null))}`,
-	}, {
-		desc: "self-reference cycles",
-		in: `
-			a: b - 100
-			b: a + 100
-
-			c: [c[1], c[0]]
-		`,
-		out: `<0>{a: (<1>.b - 100), ` +
-			`b: (<1>.a + 100), ` +
-			`c: [<1>.c[1],<1>.c[0]]}`,
-	}, {
-		desc: "resolved self-reference cycles",
-		in: `
-			a: b - 100
-			b: a + 100
-			b: 200
-
-			c: [c[1], a]
-
-			s1: s2 & {a: 1}
-			s2: s3 & {b: 2}
-			s3: s1 & {c: 3}
-		`,
-		out: `<0>{a: 100, b: 200, c: [100,100], s1: <1>{a: 1, b: 2, c: 3}, s2: <2>{a: 1, b: 2, c: 3}, s3: <3>{a: 1, b: 2, c: 3}}`,
-	}, {
-		desc: "resolved self-reference cycles: Issue 19",
-		in: `
-			// CUE knows how to resolve the following:
-			x: y + 100
-			y: x - 100
-			x: 200
-
-			z1: z2 + 1
-			z2: z3 + 2
-			z3: z1 - 3
-			z3: 8
-
-			// TODO: extensive tests with disjunctions.
-		`,
-		out: `<0>{x: 200, y: 100, z1: 11, z2: 10, z3: 8}`,
-	}, {
-		desc: "delayed constraint failure",
-		in: `
-			a: b - 100
-			b: a + 110
-			b: 200
-
-			x: 100
-			x: x + 1
-		`,
-		out: `<0>{` +
-			`x: _|_((100 & 101):conflicting values 100 and 101), ` +
-			`a: _|_((210 & 200):conflicting values 210 and 200), ` +
-			`b: _|_((210 & 200):conflicting values 210 and 200)}`,
-		// TODO: find a way to mark error in data.
-	}}
-	rewriteHelper(t, testCases, evalPartial)
-}
-
-func TestChooseDefault(t *testing.T) {
-	testCases := []testCase{{
-		desc: "pick first",
-		in: `
-		a: *5 | "a" | true
-		b: c: *{
-			a: 2
-		} | {
-			a : 3
-		}
-		`,
-		out: "<0>{a: 5, b: <1>{c: <2>{a: 2}}}",
-	}, {
-		// In this test, default results to bottom, meaning that the non-default
-		// value remains.
-		desc: "simple disambiguation conflict",
-		in: `
-			a: *"a" | "b"
-			b: *"b" | "a"
-			c: a & b
-			`,
-		out: `<0>{a: "a", b: "b", c: ("a" | "b")}`,
-	}, {
-		desc: "associativity of defaults",
-		in: `
-			a: *"a" | ("b" | "c")
-			b: (*"a" | "b") | "c"
-			c: *"a" | (*"b" | "c")
-			x: a & b
-			y: b & c
-			`,
-		out: `<0>{x: "a", y: (*"a" | *"b"), a: "a", b: "a", c: (*"a" | *"b")}`,
-	}}
-	rewriteHelper(t, testCases, evalFull)
-}
-
-func TestResolve(t *testing.T) {
-	testCases := []testCase{{
-		desc: "convert _ to top",
-		in:   `a: { [_]: _ }`,
-		out:  `<0>{a: <1>{...}}`,
-	}, {
-		in: `
-			a: b.c.d
-			b: c: { d: 3 }
-			c: { c: d.d, }
-			d: { d: 2 }
-			`,
-		out: "<0>{a: 3, b: <1>{c: <2>{d: 3}}, c: <3>{c: 2}, d: <4>{d: 2}}",
-	}, {
-		in:  "`foo-bar`: 3\n x: `foo-bar`,",
-		out: `<0>{x: 3, "foo-bar": 3}`,
-	}, {
-		desc: "resolution of quoted identifiers",
-		in: `
-		package foo
-
-` + "`foo-bar`" + `: 2
-"baz":     ` + "`foo-bar`" + `
-
-a: {
-	qux:        3
-	` + "`qux-quux`" + `: qux
-	"qaz":      ` + "`qux-quux`" + `
-}`,
-		out: `<0>{"foo-bar": 2, baz: 2, a: <1>{qux: 3, "qux-quux": 3, qaz: 3}}`,
-	}, {
-		in: `
-			a: _
-			b: a
-			a: { d: 1, d: _ }
-			b: _
-			`,
-		out: `<0>{a: <1>{d: 1}, b: <2>{d: 1}}`,
-	}, {
-		desc: "JSON",
-		in: `
-			a="a": 3
-			b: a
-			o: { "a\nb": 2 } // TODO: use $ for root?
-			c: o["a\nb"]
-		`,
-		out: `<0>{a: 3, b: 3, o: <1>{"a\nb": 2}, c: 2}`,
-	}, {
-		desc: "arithmetic",
-		in: `
-				v1: 1.0T/2.0
-				v2: 2.0 == 2
-				n1: 1
-				v5: 2.0 / n1
-				v6: 1.0 / 1.0
-				e2: int & 4.0/2.0
-				`,
-		out: `<0>{v1: 5.0000000000e+11, v2: true, n1: 1, v5: 2.0, v6: 1., e2: _|_((int & (4.0 / 2.0)):conflicting values int and (4.0 / 2.0) (mismatched types int and float))}`,
-	}, {
-		desc: "inequality",
-		in: `
-			a: 1 != 2
-			b: 1 != null
-			c: true == null
-			d: null != {}
-			e: null == []
-			f: 0 == 0.0    // types are unified first TODO: make this consistent
-		`,
-		out: `<0>{a: true, b: true, c: false, d: true, e: false, f: true}`,
-	}, {
-		desc: "attributes",
-		in: `
-			a: { foo: 1 @foo() @baz(1) }
-			b: { foo: 1 @bar() @foo() }
-			c: a & b
-
-			e: a & { foo: 1 @foo(other) }
-		`,
-		out: `<0>{a: <1>{foo: 1 @baz(1) @foo()}, ` +
-			`b: <2>{foo: 1 @bar() @foo()}, ` +
-			`c: <3>{foo: 1 @bar() @baz(1) @foo()}, ` +
-			`e: _|_((<4>.a & <5>{foo: 1 @foo(other)}):conflicting attributes for key "foo")}`,
-	}, {
-		desc: "optional field unification",
-		in: `
-			a: { foo?: string }
-			b: { foo: "foo" }
-			c: a & b
-			d: a & { "foo"?: "bar" }
-
-			g1: 1
-			"g\(1)"?: 1
-			"g\(2)"?: 2
-		`,
-		out: `<0>{a: <1>{foo?: string}, ` +
-			`b: <2>{foo: "foo"}, ` +
-			`c: <3>{foo: "foo"}, ` +
-			`d: <4>{foo?: "bar"}, ` +
-			`g1: 1, ` +
-			`g2?: 2}`,
-	}, {
-		desc: "optional field resolves to incomplete",
-		in: `
-		r: {
-			a?: 3
-			b: a
-			c: r["a"]
-		}
-	`,
-		out: `<0>{r: <1>{a?: 3, b: <2>.a, c: <3>.r["a"]}}`,
-		// TODO(#152): should be
-		// out: `<0>{r: <1>{a?: 3, b: <2>.a, c: <2>["a"]}}`,
-	}, {
-		desc: "bounds",
-		in: `
-			i1: >1 & 5
-			i2: (>=0 & <=10) & 5
-			i3: !=null & []
-			i4: !=2 & !=4
-
-
-			s1: >=0 & <=10 & !=1        // no simplification
-			s2: >=0 & <=10 & !=11       // >=0 & <=10
-			s3: >5 & !=5                // >5
-			s4: <10 & !=10              // <10
-			s5: !=2 & !=2
-
-			// TODO: could change inequality
-			s6: !=2 & >=2
-			s7: >=2 & !=2
-
-			s8: !=5 & >5
-
-			s10: >=0 & <=10 & <12 & >1   // >1  & <=10
-			s11: >0 & >=0 & <=12 & <12   // >0  & <12
-
-			s20: >=10 & <=10             // 10
-
-			s22:  >5 & <=6               // no simplification
-			s22a: >5 & (<=6 & int)       // 6
-			s22b: (int & >5) & <=6       // 6
-			s22c: >=5 & (<6 & int)       // 5
-			s22d: (int & >=5) & <6       // 5
-			s22e: (>=5 & <6) & int       // 5
-			s22f: int & (>=5 & <6)       // 5
-
-			s23: >0 & <2                 // no simplification
-			s23a: (>0 & <2) & int        // int & 1
-			s23b: int & (>0 & <2)        // int & 1
-			s23c: (int & >0) & <2        // int & 1
-			s23d: >0 & (int & <2)        // int & 1
-			s23e: >0.0 & <2.0            // no simplification
-
-			s30: >0 & int
-
-			e1: null & !=null
-			e2: !=null & null
-			e3: >1 & 1
-			e4: <0 & 0
-			e5: >1 & <0
-			e6: >11 & <11
-			e7: >=11 & <11
-			e8: >11 & <=11
-			e9: >"a" & <1
-		`,
-		out: `<0>{i1: 5, i2: 5, i3: [], i4: (!=2 & !=4), ` +
-
-			`s1: (>=0 & <=10 & !=1), ` +
-			`s2: (>=0 & <=10), ` +
-			`s3: >5, ` +
-			`s4: <10, ` +
-			`s5: !=2, ` +
-
-			`s6: (!=2 & >=2), ` +
-			`s7: (>=2 & !=2), ` +
-
-			`s8: >5, ` +
-
-			`s10: (<=10 & >1), ` +
-			`s11: (>0 & <12), ` +
-
-			`s20: 10, ` +
-
-			`s22: (>5 & <=6), ` +
-			`s22a: 6, ` +
-			`s22b: 6, ` +
-			`s22c: 5, ` +
-			`s22d: 5, ` +
-			`s22e: 5, ` +
-			`s22f: 5, ` +
-
-			`s23: (>0 & <2), ` +
-			`s23a: 1, ` +
-			`s23b: 1, ` +
-			`s23c: 1, ` +
-			`s23d: 1, ` +
-			`s23e: (>0.0 & <2.0), ` +
-
-			`s30: int & >0, ` +
-
-			`e1: _|_((!=null & null):invalid value null (excluded by !=null)), ` +
-			`e2: _|_((!=null & null):invalid value null (excluded by !=null)), ` +
-			`e3: _|_((>1 & 1):invalid value 1 (out of bound >1)), ` +
-			`e4: _|_((<0 & 0):invalid value 0 (out of bound <0)), ` +
-			`e5: _|_(conflicting bounds >1 and <0), ` +
-			`e6: _|_(conflicting bounds >11 and <11), ` +
-			`e7: _|_(conflicting bounds >=11 and <11), ` +
-			`e8: _|_(conflicting bounds >11 and <=11), ` +
-			`e9: _|_((>"a" & <1):conflicting values >"a" and <1 (mismatched types string and number))}`,
-	}, {
-		desc: "bound conversions",
-		in: `
-		r0: int & >0.1 &  <=1.9
-		r1: int & >0.1 & <1.9
-		r2: int & >=0.1 & <1.9
-		r3: int & >=-1.9 & <=-0.1
-		r4: int & >-1.9 & <=-0.1
-
-		r5: >=1.1 & <=1.1
-		r6: r5 & 1.1
-
-		c1: (1.2 & >1.3) & <2
-		c2: 1.2 & (>1.3 & <2)
-
-		c3: 1.2 & (>=1 & <2)
-		c4: 1.2 & (>=1 & <2 & int)
-		`,
-		out: `<0>{` +
-			`r0: 1, ` +
-			`r1: 1, ` +
-			`r2: 1, ` +
-			`r3: -1, ` +
-			`r4: -1, ` +
-			`r5: 1.1, ` +
-			`r6: 1.1, ` +
-			`c1: _|_((>1.3 & 1.2):invalid value 1.2 (out of bound >1.3)), ` +
-			`c2: _|_((>1.3 & 1.2):invalid value 1.2 (out of bound >1.3)), ` +
-			`c3: 1.2, ` +
-			`c4: _|_((1.2 & ((>=1 & <2) & int)):conflicting values 1.2 and ((>=1 & <2) & int) (mismatched types float and int))}`,
-	}, {
-		desc: "custom validators",
-		in: `
-		import "strings"
-
-		a: strings.ContainsAny("ab")
-		a: "after"
-
-		b: strings.ContainsAny("c")
-		b: "dog"
-
-		c: strings.ContainsAny("d") & strings.ContainsAny("g")
-		c: "dog"
-		`,
-		out: `<0>{` +
-			`a: "after", ` +
-			`b: _|_(strings.ContainsAny ("c"):invalid value "dog" (does not satisfy strings.ContainsAny("c"))), ` +
-			`c: "dog"` +
-			`}`,
-	}, {
-		desc: "null coalescing",
-		in: `
-			a: null
-			b: a.x | "b"
-			c: a["x"] | "c"
-			`,
-		out: `<0>{a: null, b: "b", c: "c"}`,
-	}, {
-		desc: "reference across tuples and back",
-		// Tests that it is okay to partially evaluate structs.
-		in: `
-			a: { c: b.e, d: b.f }
-			b: { e: 3, f: a.c }
-			`,
-		out: "<0>{a: <1>{c: 3, d: 3}, b: <2>{e: 3, f: 3}}",
-	}, {
-		desc: "index",
-		in: `
-			a: [2][0]
-			b: {foo:"bar"}["foo"]
-			c: (*l|{"3":3})["3"]
-			d: (*[]|[1])[0]
-			l: []
-			e1: [2][""]
-			e2: 2[2]
-			e3: [][true]
-			e4: [1,2,3][3]
-			e5: [1,2,3][-1]
-			e6: (*[]|{})[1]
-			def: {
-				a: 1
-				#b: 3
-			}
-			e7: def["b"]
-		`,
-		out: `<0>{a: 2, b: "bar", c: _|_("3":invalid list index "3" (type string)), l: [], d: _|_([]:index 0 out of bounds), e1: _|_("":invalid list index "" (type string)), e2: _|_(2:invalid operation: 2[2] (type int does not support indexing)), e3: _|_(true:invalid list index true (type bool)), e4: _|_([1,2,3]:index 3 out of bounds), e5: _|_(-1:invalid list index -1 (index must be non-negative)), e6: _|_([]:index 1 out of bounds), def: <1>{a: 1, #b: 3}, e7: <2>.def["b"]}`,
-		// }, {
-		// NOTE: string indexing no longer supported.
-		// Keeping it around until this is no longer an experiment.
-		// 	desc: "string index",
-		// 	in: `
-		// 		a0: "abc"[0]
-		// 		a1: "abc"[1]
-		// 		a2: "abc"[2]
-		// 		a3: "abc"[3]
-		// 		a4: "abc"[-1]
-
-		// 		b: "zoëven"[2]
-		// 	`,
-		// 	out: `<0>{a0: "a", a1: "b", a2: "c", a3: _|_("abc":index 3 out of bounds), a4: _|_(-1:invalid string index -1 (index must be non-negative)), b: "ë"}`,
-	}, {
-		desc: "disjunctions of lists",
-		in: `
-			l: [ int, int ] | [ string, string ]
-
-			l1: [ "a", "b" ]
-			l2: l & [ "c", "d" ]
-			`,
-		out: `<0>{l: ([int,int] | [string,string]), l1: ["a","b"], l2: ["c","d"]}`,
-	}, {
-		desc: "slice",
-		in: `
-			a: [2][0:0]
-			b: [0][1:1]
-			e1: [][1:1]
-			e2: [0][-1:0]
-			e3: [0][1:0]
-			e4: [0][1:2]
-			e5: 4[1:2]
-			e6: [2]["":]
-			e7: [2][:"9"]
-
-		`,
-		out: `<0>{a: [], b: [], e1: _|_(1:slice bounds out of range), e2: _|_([0]:negative slice index), e3: _|_([0]:invalid slice index: 1 > 0), e4: _|_(2:slice bounds out of range), e5: _|_(4:cannot slice 4 (type int)), e6: _|_("":invalid slice index "" (type string)), e7: _|_("9":invalid slice index "9" (type string))}`,
-		// }, {
-		// NOTE: string indexing no longer supported.
-		// Keeping it around until this is no longer an experiment.
-		// 	desc: "string slice",
-		// 	in: `
-		// 		a0: ""[0:0]
-		// 		a1: ""[:]
-		// 		a2: ""[0:]
-		// 		a3: ""[:0]
-		// 		b0: "abc"[0:0]
-		// 		b1: "abc"[0:1]
-		// 		b2: "abc"[0:2]
-		// 		b3: "abc"[0:3]
-		// 		b4: "abc"[3:3]
-		// 		b5: "abc"[1:]
-		// 		b6: "abc"[:2]
-
-		// 		// TODO: supported extended graphemes, instead of just runes.
-		// 		u: "Spaß"[3:4]
-		// 	`,
-		// 	out: `<0>{a0: "", a1: "", a2: "", a3: "", b0: "", b1: "a", b2: "ab", b3: "abc", b4: "", b5: "bc", b6: "ab", u: "ß"}`,
-	}, {
-		desc: "list types",
-		in: `
-			l0: 3*[int]
-			l0: [1, 2, 3]
-			l2: [...{ a: int }]
-			l2: [{a: 1}, {a: 2, b: 3}]
-
-			// TODO: work out a decent way to specify length ranges of lists.
-			// l3: <=10*[int]
-			// l3: [1, 2, 3, ...]
-
-			s1: (6*[int])[2:3]
-			s2: [0,2,3][1:2]
-
-			i1: (6*[int])[2]
-			i2: [0,2,3][2]
-
-			t0: [...{a: 8}]
-			t0: [{}]
-			t1: [...]
-			t1: [...int]
-
-			e0: 2*[{}]
-			e0: [{}]
-			e1: [...int]
-			e1: [...float]
-			`,
-		out: `<0>{` +
-			`l0: [1,2,3], ` +
-			`l2: [<1>{a: 1},<2>{a: 2, b: 3}], ` +
-			`s1: [int], ` +
-			`s2: [2], ` +
-			`i1: int, ` +
-			`i2: 3, ` +
-			`t0: [<3>{a: 8}], ` +
-			`t1: [, ...int], ` +
-			`e0: _|_(([<4>{},<4>{}] & [<5>{}]):conflicting list lengths: conflicting values 2 and 1), ` +
-			`e1: [, ..._|_((int & float):conflicting values int and float (mismatched types int and float))]` +
-			`}`,
-	}, {
-		// TODO: consider removing list arithmetic altogether. It is no longer
-		// needed to indicate the allowed capacity of a list and that didn't
-		// work anyway.
-		desc: "list arithmetic",
-		in: `
-			l0: 3*[1, 2, 3]
-			l1: 0*[1, 2, 3]
-			l2: 10*[]
-			l3: <=2*[]
-			l4: <=2*[int]
-			l5: <=2*(int*[int])
-			l6: 3*[...int]
-			l7: 3*[1, ...int]
-			l8: 3*[1, 2, ...int]
-
-			s0: [] + []
-			s1: [1] + []
-			s2: [] + [2]
-			s3: [1] + [2]
-			s4: [1,2] + []
-			s5: [] + [1,2]
-			s6: [1] + [1,2]
-			s7: [1,2] + [1]
-			s8: [1,2] + [1,2]
-			s9: [] + [...]
-			s10: [1] + [...]
-			s11: [] + [2, ...]
-			s12: [1] + [2, ...]
-			s13: [1,2] + [...]
-			s14: [] + [1,2, ...]
-			s15: [1] + [1,2, ...]
-			s16: [1,2] + [1, ...]
-			s17: [1,2] + [1,2, ...]
-
-			s18: [...] + []
-			s19: [1, ...] + []
-			s20: [...] + [2]
-			s21: [1, ...] + [2]
-			s22: [1,2, ...] + []
-			s23: [...] + [1,2]
-			s24: [1, ...] + [1,2]
-			s25: [1,2, ...] + [1]
-			s26: [1,2, ...] + [1,2]
-			s27: [...] + [...]
-			s28: [1, ...] + [...]
-			s29: [...] + [2, ...]
-			s30: [1, ...] + [2, ...]
-			s31: [1,2, ...] + [...]
-			s32: [...] + [1,2, ...]
-			s33: [1, ...] + [1,2, ...]
-			s34: [1,2, ...] + [1, ...]
-			s35: [1,2, ...] + [1,2, ...]
-			`,
-		out: `<0>{l0: [1,2,3,1,2,3,1,2,3], ` +
-			`l1: [], ` +
-			`l2: [], ` +
-			`l3: (<=2 * []), ` +
-			`l4: (<=2 * [int]), ` +
-			`l5: (<=2 * (int * [int])), ` +
-			`l6: [], ` +
-			`l7: [1,1,1], ` +
-			`l8: [1,2,1,2,1,2], ` +
-
-			`s0: [], ` +
-			`s1: [1], ` +
-			`s2: [2], ` +
-			`s3: [1,2], ` +
-			`s4: [1,2], ` +
-			`s5: [1,2], ` +
-			`s6: [1,1,2], ` +
-			`s7: [1,2,1], ` +
-			`s8: [1,2,1,2], ` +
-			`s9: [], ` +
-			`s10: [1], ` +
-			`s11: [2], ` +
-			`s12: [1,2], ` +
-			`s13: [1,2], ` +
-			`s14: [1,2], ` +
-			`s15: [1,1,2], ` +
-			`s16: [1,2,1], ` +
-			`s17: [1,2,1,2], ` +
-
-			`s18: [], ` +
-			`s19: [1], ` +
-			`s20: [2], ` +
-			`s21: [1,2], ` +
-			`s22: [1,2], ` +
-			`s23: [1,2], ` +
-			`s24: [1,1,2], ` +
-			`s25: [1,2,1], ` +
-			`s26: [1,2,1,2], ` +
-			`s27: [], ` +
-			`s28: [1], ` +
-			`s29: [2], ` +
-			`s30: [1,2], ` +
-			`s31: [1,2], ` +
-			`s32: [1,2], ` +
-			`s33: [1,1,2], ` +
-			`s34: [1,2,1], ` +
-			`s35: [1,2,1,2]` +
-
-			`}`,
-	}, {
-		desc: "list equality",
-		in: `
-		eq0: [] == []
-		eq1: [...] == []
-		eq2: [] == [...]
-		eq3: [...] == [...]
-
-		eq4: [1] == [1]
-		eq5: [1, ...] == [1]
-		eq6: [1] == [1, ...]
-		eq7: [1, ...] == [1, ...]
-
-		eq8: [1, 2] == [1, 2]
-		eq9: [1, 2, ...] == [1, 2]
-		eq10: [1, 2] == [1, 2, ...]
-		eq11: [1, 2, ...] == [1, 2, ...]
-
-		ne0: [] != []
-		ne1: [...] != []
-		ne2: [] != [...]
-		ne3: [...] != [...]
-
-		ne4: [1] != [1]
-		ne5: [1, ...] != [1]
-		ne6: [1] != [1, ...]
-		ne7: [1, ...] != [1, ...]
-
-		ne8: [1, 2] != [1, 2]
-		ne9: [1, 2, ...] != [1, 2]
-		ne10: [1, 2] != [1, 2, ...]
-		ne11: [1, 2, ...] != [1, 2, ...]
-
-		feq0: [] == [1]
-		feq1: [...] == [1]
-		feq2: [] == [1, ...]
-		feq3: [...] == [1, ...]
-
-		feq4: [1] == []
-		feq5: [1, ...] == []
-		feq6: [1] == [...]
-		feq7: [1, ...] == [...]
-
-		feq8: [1, 2] == [1]
-		feq9: [1, ...] == [1, 2]
-		feq10: [1, 2] == [1, ...]
-		feq11: [1, ...] == [1, 2, ...]
-
-		fne0: [] != [1]
-		fne1: [...] != [1]
-		fne2: [] != [1, ...]
-		fne3: [1, ...] != [1, ...]
-
-		fne4: [1] != []
-		fne5: [1, ...] != []
-		fne6: [1] != [...]
-		fne7: [1, ...] != [...]
-
-		fne8: [1, 2] != [1]
-		fne9: [1, ...] != [1, 2]
-		fne10: [1, 2] != [1, ...]
-		fne11: [1, ...] != [1, 2, ...]
-		`,
-		out: `<0>{` +
-			`eq0: true, eq1: true, eq2: true, eq3: true, eq4: true, eq5: true, eq6: true, eq7: true, eq8: true, eq9: true, eq10: true, eq11: true, ` +
-			`ne0: true, ne1: true, ne2: true, ne3: true, ne4: false, ne5: false, ne6: false, ne7: false, ne8: false, ne9: false, ne10: false, ne11: false, ` +
-			`feq0: false, feq1: false, feq2: false, feq3: false, feq4: false, feq5: false, feq6: false, feq7: false, feq8: false, feq9: false, feq10: false, feq11: false, ` +
-			`fne0: false, fne1: false, fne2: false, fne3: false, fne4: false, fne5: false, fne6: false, fne7: false, fne8: false, fne9: false, fne10: false, fne11: false}`,
-	}, {
-		desc: "list unification",
-		in: `
-		a: { l: ["foo", v], v: l[1] }
-		b: a & { l: [_, "bar"] }
-		`,
-		out: `<0>{` +
-			`a: <1>{l: ["foo",<2>.v], ` +
-			`v: <2>.l[1]}, ` +
-			`b: <3>{l: ["foo","bar"], v: "bar"}}`,
-	}, {
-		desc: "correct error messages",
-		// Tests that it is okay to partially evaluate structs.
-		in: `
-			a: "a" & 1
-			`,
-		out: `<0>{a: _|_(("a" & 1):conflicting values "a" and 1 (mismatched types string and int))}`,
-	}, {
-		desc: "structs",
-		in: `
-			a: t & { c: 5 }             // {c:5,d:15}
-			b: ti & { c: 7 }            // {c:7,d:21}
-			t: { c: number, d: c * 3 }  // {c:number,d:number*3}
-			ti: t & { c: int }
-			`,
-		out: `<0>{a: <1>{c: 5, d: 15}, t: <2>{c: number, d: (<3>.c * 3)}, b: <4>{c: 7, d: 21}, ti: <5>{c: int, d: (<6>.c * 3)}}`,
-	}, {
-		desc: "definitions",
-		in: `
-			#Foo: {
-				field: int
-				recursive: {
-					field: string
-				}
-			}
-
-			// Allowed
-			#Foo1: { field: int }
-			#Foo1: { field2: string }
-
-			foo: #Foo
-			foo: { feild: 2 }
-
-			foo1: #Foo
-			foo1: {
-				field: 2
-				recursive: {
-					feild: 2 // Not caught as per spec. TODO: change?
-				}
-			}
-
-			#Bar: {
-				field: int
-				{[A=_]:   int}
-			}
-			bar: #Bar
-			bar: { feild: 2 }
-
-			#Mixed: string
-			Mixed: string
-
-			mixedRec: { #Mixed: string }
-			mixedRec: { Mixed: string }
-			`,
-		out: `<0>{` +
-			`#Foo: <1>C{field: int, recursive: <2>C{field: string}}, ` +
-			`#Foo1: <3>C{field: int, field2: string}, ` +
-			`foo: _|_(2:field "feild" not allowed in closed struct), ` +
-			`foo1: <4>C{field: 2, recursive: _|_(2:field "feild" not allowed in closed struct)}, ` +
-			`#Bar: <5>{[]: <6>(A: string)->int, field: int}, ` +
-			`bar: <7>{[]: <8>(A: string)->int, field: int, feild: 2}, ` +
-			`#Mixed: string, ` +
-			`Mixed: string, ` +
-			`mixedRec: <9>{#Mixed: string, Mixed: string}}`,
-	}, {
-		desc: "combined definitions",
-		in: `
-			// Allow combining of structs within a definition
-			#D1: {
-				env: a: "A"
-				env: b: "B"
-				#def: {a: "A"}
-				#def: {b: "B"}
-			}
-
-			d1: #D1 & { env: c: "C" }
-
-			#D2: {
-				a: int
-			}
-			#D2: {
-				b: int
-			}
-
-			#D3: {
-				env: a: "A"
-			}
-			#D3: {
-				env: b: "B"
-			}
-
-			#D4: {
-				env: #DC
-				env: b: int
-			}
-
-			#DC: { a: int }
-					`,
-		out: `<0>{` +
-			`#D1: <1>C{env: <2>C{a: "A", b: "B"}, #def: <3>C{a: "A", b: "B"}}, ` +
-			`d1: <4>C{env: _|_("C":field "c" not allowed in closed struct), #def: <5>C{a: "A", b: "B"}}, ` +
-			`#D2: <6>C{a: int, b: int}, ` +
-			`#D3: <7>C{env: <8>C{a: "A", b: "B"}}, ` +
-			`#D4: <9>C{env: _|_(int:field "b" not allowed in closed struct)}, ` +
-			`#DC: <10>C{a: int}` +
-			`}`,
-	}, {
-		desc: "new-style definitions",
-		in: `
-		#Foo: {
-			a: 1
-			b: int
-		}
-		"#Foo": #Foo & {b: 1}
-
-		bulk: {[string]: string} & {
-			#def: 4 // Different namespace, so bulk option does not apply.
-			_hid: 3
-			a: "foo"
-		}
-		`,
-		out: `<0>{` +
-			`"#Foo": <1>C{a: 1, b: 1}, ` +
-			`#Foo: <2>C{a: 1, b: int}, ` +
-			`bulk: <3>{[]: <4>(_: string)->string, a: "foo", #def: 4, _hid: 3}` +
-			`}`,
-	}, {
-		desc: "recursive closing starting at non-definition",
-		in: `
-			z: a: {
-				#B: {
-					c: d: 1
-					c: f: 1
-				}
-			}
-			A: z & { a: { #B: { c: e: 2 } } }
-			`,
-		out: `<0>{z: <1>{a: <2>{#B: <3>C{c: <4>C{d: 1, f: 1}}}}, A: <5>{a: <6>{#B: <7>C{c: _|_(2:field "e" not allowed in closed struct)}}}}`,
-	}, {
-		desc: "non-closed definition carries over closedness to enclosed template",
-		in: `
-		#S: {
-			[string]: { a: int }
-		}
-		a: #S & {
-			v: { b: int }
-		}
-		#Q: {
-			[string]: { a: int } | { b: int }
-		}
-		b: #Q & {
-			w: { c: int }
-		}
-		#R: {
-			[string]: [{ a: int }, { b: int }]
-		}
-		c: #R & {
-			w: [{ d: int }, ...]
-		}
-		`,
-		out: `<0>{` +
-			`#S: <1>{[]: <2>(_: string)-><3>C{a: int}, }, ` +
-			`a: <4>{[]: <5>(_: string)-><6>C{a: int}, v: _|_(int:field "b" not allowed in closed struct)}, ` +
-			`b: <7>{[]: <8>(_: string)->(<9>C{a: int} | <10>C{b: int}), w: _|_(int:empty disjunction: field "c" not allowed in closed struct)}, ` +
-			`#Q: <11>{[]: <12>(_: string)->(<13>C{a: int} | <14>C{b: int}), }, ` +
-			`c: <15>{[]: <16>(_: string)->[<17>C{a: int},<18>C{b: int}], w: [_|_(int:field "d" not allowed in closed struct),<19>C{b: int}]}, ` +
-			`#R: <20>{[]: <21>(_: string)->[<22>C{a: int},<23>C{b: int}], }}`,
-	}, {
-		desc: "definitions with disjunctions",
-		in: `
-			#Foo: {
-				field: int
-
-				{ a: 1 } |
-				{ b: 2 }
-			}
-
-			foo: #Foo
-			foo: { a: 1 }
-
-			bar: #Foo
-			bar: { c: 2 }
-
-			baz: #Foo
-			baz: { b: 2 }
-			`,
-		out: `<0>{` +
-			`#Foo: (<1>C{field: int, a: 1} | <2>C{field: int, b: 2}), ` +
-			`foo: <3>C{field: int, a: 1}, ` +
-			`bar: _|_(2:empty disjunction: field "c" not allowed in closed struct), ` +
-			`baz: <4>C{field: int, b: 2}}`,
-	}, {
-		desc: "definitions with disjunctions recurisive",
-		in: `
-			#Foo: {
-				x: {
-					field: int
-
-					{ a: 1 } |
-					{ b: 2 }
-				}
-				x: c: 3
-			}
-					`,
-		out: `<0>{` +
-			`#Foo: <1>C{x: (<2>C{field: int, a: 1, c: 3} | <3>C{field: int, b: 2, c: 3})}` +
-			`}`,
-	}, {
-		desc: "definitions with embedding",
-		in: `
-		#E: {
-			a: { b: int }
-		}
-
-		#S: {
-			#E
-			a: { c: int }
-			b: 3
-		}
-
-		// adding a field to a nested struct that is closed.
-		#e1: #S & { a: d: 4 }
-		// literal struct not closed until after unification.
-		#v1: #S & { a: c: 4 }
-		`,
-		out: `<0>{` +
-			`#E: <1>C{a: <2>C{b: int}}, ` +
-			`#S: <3>C{a: <4>C{b: int, c: int}, b: 3}, ` +
-			`#e1: <5>C{a: _|_(4:field "d" not allowed in closed struct), b: 3}, ` +
-			`#v1: <6>C{a: <7>C{b: int, c: 4}, b: 3}}`,
-	}, {
-		desc: "top-level definition with struct and disjunction",
-		in: `
-		#def: {
-			Type: string
-			Text: string
-			Size: int
-		}
-
-		#def: {
-			Type: "B"
-			Size: 0
-		} | {
-			Type: "A"
-			Size: 1
-		}`,
-		out: `<0>{` +
-			`#def: (<1>C{Size: (0 & int), Type: ("B" & string), Text: string} | ` +
-			`<2>C{Size: (1 & int), Type: ("A" & string), Text: string})` +
-			`}`,
-	}, {
-		desc: "closing structs",
-		in: `
-		op: {x: int}             // {x: int}
-		ot: {x: int, ...}        // {x: int, ...}
-		cp: close({x: int})      // closed({x: int})
-		ct: close({x: int, ...}) // {x: int, ...}
-
-		opot: op & ot  // {x: int, ...}
-		otop: ot & op  // {x: int, ...}
-		opcp: op & cp  // closed({x: int})
-		cpop: cp & op  // closed({x: int})
-		opct: op & ct  // {x: int, ...}
-		ctop: ct & op  // {x: int, ...}
-		otcp: ot & cp  // closed({x: int})
-		cpot: cp & ot  // closed({x: int})
-		otct: ot & ct  // {x: int, ...}
-		ctot: ct & ot  // {x: int, ...}
-		cpct: cp & ct  // closed({x: int})
-		ctcp: ct & cp  // closed({x: int})
-		ctct: ct & ct  // {x: int, ...}
-		`,
-		out: `<0>{` +
-			`op: <1>{x: int}, ` +
-			`ot: <2>{x: int, ...}, ` +
-			`cp: <3>C{x: int}, ` +
-			`ct: <4>{x: int, ...}, ` +
-			`opot: <5>{x: int, ...}, ` +
-			`otop: <6>{x: int, ...}, ` +
-			`opcp: <7>C{x: int}, ` +
-			`cpop: <8>C{x: int}, ` +
-			`opct: <9>{x: int, ...}, ` +
-			`ctop: <10>{x: int, ...}, ` +
-			`otcp: <11>C{x: int}, ` +
-			`cpot: <12>C{x: int}, ` +
-			`otct: <13>{x: int, ...}, ` +
-			`ctot: <14>{x: int, ...}, ` +
-			`cpct: <15>C{x: int}, ` +
-			`ctcp: <16>C{x: int}, ` +
-			`ctct: <17>{x: int, ...}}`,
-	}, {
-		desc: "excluded embedding from closing",
-		in: `
-		#S: {
-			a: { c: int }
-			{
-				c: { d: int }
-			}
-			B = { open: int }
-			b: B
-		}
-		V: #S & {
-			c: e: int
-			b: extra: int
-		}
-		`,
-		out: `<0>{` +
-			`#S: <1>C{` +
-			`a: <2>C{c: int}, ` +
-			`c: <3>{d: int}, ` +
-			`b: <4>{open: int}}, ` +
-			`V: <5>C{` +
-			`a: <6>C{c: int}, ` +
-			`c: <7>{d: int, e: int}, ` +
-			`b: <8>{open: int, extra: int}}}`,
-	}, {
-		desc: "closing with failed optional",
-		in: `
-		#k1: {a: int, b?: int} & #A // closed({a: int})
-		#k2: #A & {a: int, b?: int} // closed({a: int})
-
-		o1: {a?: 3} & {a?: 4} // {a?: _|_}
-
-		// Optional fields with error values can be elimintated when closing
-		#o2: {a?: 3} & {a?: 4} // close({})
-
-		#d1: {a?: 2, b: 4} | {a?: 3, c: 5}
-		v1: #d1 & {a?: 3, b: 4}  // close({b: 4})
-
-		#A: {a: int}
-		`,
-		out: `<0>{` +
-			`#k1: <1>C{a: int}, ` +
-			`#A: <2>C{a: int}, ` +
-			`#k2: <3>C{a: int}, ` +
-			`o1: <4>{a?: _|_((3 & 4):conflicting values 3 and 4)}, ` +
-			`#o2: <5>C{a?: _|_((3 & 4):conflicting values 3 and 4)}, ` +
-			`#d1: (<6>C{a?: 2, b: 4} | <7>C{a?: 3, c: 5}), ` +
-			`v1: <8>C{a?: _|_((2 & 3):conflicting values 2 and 3), b: 4}` +
-			`}`,
-	}, {
-		desc: "closing with comprehensions",
-		in: `
-		#A: {f1: int, f2: int}
-
-		for k, v in {f3 : int} {
-			a: #A & { "\(k)": v }
-		}
-
-		#B: {
-			for k, v in {f1: int} {
-				"\(k)": v
-			}
-		}
-
-		#C: {
-			f1: _
-			for k, v in {f1: int} {
-				"\(k)": v
-			}
-		}
-
-		#D: {
-			for k, v in {f1: int} {
-				"\(k)": v
-			}
-			...
-		}
-
-		#E: #A & {
-			for k, v in { f3: int } {
-				"\(k)": v
-			}
-		}
-		`,
-		out: `<0>{` +
-			`#A: <1>C{f1: int, f2: int}, ` +
-			`a: _|_(<2>.v:field "f3" not allowed in closed struct), ` +
-			`#B: <3>C{f1: int}, ` +
-			`#C: <4>C{f1: int}, ` +
-			`#D: <5>{f1: int, ...}, ` +
-			`#E: _|_(<6>.v:field "f3" not allowed in closed struct)` +
-			`}`,
-	}, {
-		desc: "incomplete comprehensions",
-		in: `
-		A: {
-			for v in src {
-				"\(v)": v
-			}
-			src: _
-			if true {
-				baz: "baz"
-			}
-		}
-		B: A & {
-			src: ["foo", "bar"]
-		}
-		`,
-		out: `<0>{` +
-			`A: <1>{src: _, baz: "baz" <2>for _, v in <3>.src yield <4>{""+<2>.v+"": <2>.v}}, ` +
-			`B: <5>{src: ["foo","bar"], baz: "baz", foo: "foo", bar: "bar"}}`,
-	}, {
-		desc: "reference to root",
-		in: `
-			a: { b: int }
-			c: a & {
-				b: 100
-				d: a.b + 3 // do not resolve as c != a.
-			}
-			x: {
-				b: int
-				c: b + 5
-			}
-			y: x & {
-				b: 100
-				// c should resolve to 105
-			}
-			v: {
-				b: int
-				c: v.b + 5 // reference starting from copied node.
-			}
-			w: v & { b: 100 }
-			wp: v & { b: 100 }
-			`,
-		out: `<0>{x: <1>{b: int, c: (<2>.b + 5)}, y: <3>{b: 100, c: 105}, a: <4>{b: int}, c: <5>{b: 100, d: (<6>.a.b + 3)}, v: <7>{b: int, c: (<6>.v.b + 5)}, w: <8>{b: 100, c: (<6>.v.b + 5)}, wp: <9>{b: 100, c: (<6>.v.b + 5)}}`,
-		// TODO(#152): should be
-		// out: `<0>{a: <1>{b: int}, c: <2>{b: 100, d: (<3>.a.b + 3)}, x: <4>{b: int, c: (<5>.b + 5)}, y: <6>{b: 100, c: 105}, v: <7>{b: int, c: (<8>.b + 5)}, w: <9>{b: 100, c: 105}, wp: <10>{b: 100, c: 105}}`,
-	}, {
-		desc: "references from template to concrete",
-		in: `
-			res: [t]
-			t: [X=string]: {
-				a: c + b.str
-				b: str: string
-				c: "X"
-			}
-			t: x: { b: str: "DDDD" }
-			`,
-		out: `<0>{res: [<1>{[]: <2>(X: string)-><3>{a: (<3>.c + <3>.b.str), c: "X", b: <4>{str: string}}, x: <5>{a: "XDDDD", c: "X", b: <6>{str: "DDDD"}}}], t: <7>{[]: <2>(X: string)-><3>{a: (<3>.c + <3>.b.str), c: "X", b: <4>{str: string}}, x: <8>{a: "XDDDD", c: "X", b: <9>{str: "DDDD"}}}}`,
-	}, {
-		desc: "interpolation",
-		in: `
-			a: "\(4)"
-			b: "one \(a) two \(  a + c  )"
-			c: "one"
-			d: "\(r)"
-			u: "\(_)"
-			r: _
-			e: "\([])"`,
-		out: `<0>{a: "4", b: "one 4 two 4one", c: "one", d: ""+<1>.r+"", r: _, u: ""+_+"", e: _|_([]:expression in interpolation must evaluate to a number kind or string (found list))}`,
-	}, {
-		desc: "multiline interpolation",
-		in: `
-			a1: """
-			before
-			\(4)
-			after
-			"""
-			a2: """
-			before
-			\(4)
-
-			"""
-			a3: """
-
-			\(4)
-			after
-			"""
-			a4: """
-
-			\(4)
-
-			"""
-			m1: """
-			before
-			\(
-				4)
-			after
-			"""
-			m2: """
-			before
-			\(
-	4)
-
-			"""
-			m3: """
-
-			\(
-
-				4)
-			after
-			"""
-			m4: """
-
-			\(
-	4)
-
-			"""
-			`,
-		out: `<0>{` +
-			`a1: "before\n4\nafter", a2: "before\n4\n", a3: "\n4\nafter", a4: "\n4\n", ` +
-			`m1: "before\n4\nafter", m2: "before\n4\n", m3: "\n4\nafter", m4: "\n4\n"` +
-			`}`,
-	}, {
-		desc: "diamond-shaped constraints",
-		in: `
-		S: {
-			A: {
-				a: 1,
-			},
-			B: A & {
-				b: 2,
-			}
-		},
-		T: S & { // S == { A: { a:1 }, B: { a:1, b:2 } }
-			A: {
-				c: 3,
-			},
-			B: { // S.B & A
-				d: 4, // Combines constraints S.A, S.B, T.A, and T.B
-			}
-		}`,
-		out: "<0>{T: <1>{A: <2>{a: 1, c: 3}, B: <3>{a: 1, b: 2, c: 3, d: 4}}, S: <4>{A: <5>{a: 1}, B: <6>{a: 1, b: 2}}}",
-	}, {
-		desc: "field templates",
-		in: `
-			a: {
-				{[name=_]: int}
-				k: 1
-			}
-			b: {
-				{[X=_]: { x: 0, y: *1 | int }}
-				v: {}
-				w: { x: 0 }
-			}
-			b: { [y=_]: {} }
-			c: {
-				{[Name=_]: { name: Name, y: 1 }}
-				foo: {}
-				bar: _
-			}
-			`,
-		out: `<0>{a: <1>{[]: <2>(name: string)->int, k: 1}, b: <3>{[]: <4>(X: string)->(<5>{x: 0, y: (*1 | int)} & <6>{}), v: <7>{x: 0, y: (*1 | int)}, w: <8>{x: 0, y: (*1 | int)}}, c: <9>{[]: <10>(Name: string)-><11>{y: 1, name: <10>.Name}, foo: <12>{y: 1, name: "foo"}, bar: <13>{y: 1, name: "bar"}}}`,
-	}, {
-		desc: "range unification",
-		in: `
-			// with concrete values
-			a1: >=1 & <=5 & 3
-			a2: >=1 & <=5 & 1
-			a3: >=1 & <=5 & 5
-			a4: >=1 & <=5 & 6
-			a5: >=1 & <=5 & 0
-
-			a6: 3 & >=1 & <=5
-			a7: 1 & >=1 & <=5
-			a8: 5 & >=1 & <=5
-			a9: 6 & >=1 & <=5
-			a10: 0 & >=1 & <=5
-
-			// with ranges
-			b1: >=1 & <=5 & >=1 & <=5
-			b2: >=1 & <=5 & >=1 & <=1
-			b3: >=1 & <=5 & >=5 & <=5
-			b4: >=1 & <=5 & >=2 & <=3
-			b5: >=1 & <=5 & >=3 & <=9
-			b6: >=1 & <=5 & >=5 & <=9
-			b7: >=1 & <=5 & >=6 & <=9
-
-			b8: >=1 & <=5 & >=1 & <=5
-			b9: >=1 & <=1 & >=1 & <=5
-			b10: >=5 & <=5 & >=1 & <=5
-			b11: >=2 & <=3 & >=1 & <=5
-			b12: >=3 & <=9 & >=1 & <=5
-			b13: >=5 & <=9 & >=1 & <=5
-			b14: >=6 & <=9 & >=1 & <=5
-
-			// ranges with more general types
-			c1: int & >=1 & <=5
-			c2: >=1 & <=5 & int
-			c3: string & >=1 & <=5
-			c4: >=1 & <=5 & string
-
-			// other types
-			s1: >="d" & <="z" & "e"
-			s2: >="d" & <="z" & "ee"
-
-			n1: number & >=1 & <=2
-			n2: int & >=1.1 & <=1.3
-			n3: >=1.0 & <=3.0 & 2
-			n4: >=0.0 & <=0.1 & 0.09999
-			n5: >=1 & <=5 & 2.5
-			`,
-		out: `<0>{` +
-			`a1: 3, ` +
-			`a2: 1, ` +
-			`a3: 5, ` +
-			`a4: _|_((<=5 & 6):invalid value 6 (out of bound <=5)), ` +
-			`a5: _|_((>=1 & 0):invalid value 0 (out of bound >=1)), ` +
-			`a6: 3, ` +
-			`a7: 1, ` +
-			`a8: 5, ` +
-
-			`a9: _|_((<=5 & 6):invalid value 6 (out of bound <=5)), ` +
-			`a10: _|_((>=1 & 0):invalid value 0 (out of bound >=1)), ` +
-
-			`b1: (>=1 & <=5), ` +
-			`b2: 1, ` +
-			`b3: 5, ` +
-			`b4: (>=2 & <=3), ` +
-			`b5: (>=3 & <=5), ` +
-			`b6: 5, ` +
-			`b7: _|_(conflicting bounds >=6 and <=5), ` +
-			`b8: (>=1 & <=5), ` +
-			`b9: 1, ` +
-			`b10: 5, ` +
-			`b11: (>=2 & <=3), ` +
-			`b12: (>=3 & <=5), ` +
-			`b13: 5, ` +
-			`b14: _|_(conflicting bounds >=6 and <=5), ` +
-			`c1: (int & >=1 & <=5), ` +
-			`c2: (<=5 & int & >=1), ` +
-			`c3: _|_((string & >=1):conflicting values string and >=1 (mismatched types string and number)), ` +
-			`c4: _|_(((>=1 & <=5) & string):conflicting values (>=1 & <=5) and string (mismatched types number and string)), ` +
-			`s1: "e", ` +
-			`s2: "ee", ` +
-			`n1: (>=1 & <=2), ` +
-			`n2: _|_(conflicting bounds int & >=1.1 and <=1.3), ` +
-			`n3: 2, ` +
-			`n4: 0.09999, ` +
-			`n5: 2.5}`,
-	}, {
-		desc: "predefined ranges",
-		in: `
-			k1: int8
-			k1: 44
-
-			k2: int64
-			k2: -8_000_000_000
-
-			e1: int16
-			e1: 100_000
-		`,
-		out: `<0>{k1: 44, k2: -8000000000, ` +
-			`e1: _|_((int & <=32767 & 100000):invalid value 100000 (out of bound int & <=32767))}`,
-	}, {
-		desc: "struct comprehensions",
-		in: `
-			obj: foo: a: "bar"
-			obj: [Name=string]: {
-				a: *"dummy" | string
-				if true {
-					sub: as: a
-				}
-			}
-
-			for k, v in { #def: 1, opt?: 2, _hid: 3, reg: 4 } {
-				"\(k)": v
-			}
-		`,
-		out: `<0>{obj: <1>{[]: <2>(Name: string)-><3>{a: (*"dummy" | string) if true yield <4>{sub: <5>{as: <3>.a}}}, foo: <6>{a: "bar", sub: <7>{as: "bar"}}}, reg: 4}`,
-	}, {
-		desc: "builtins",
-		in: `
-		a1: {
-			a: and([b, c])
-			b: =~"oo"
-			c: =~"fo"
-		}
-		a2: a1 & { a: "foo" }
-		a3: a1 & { a: "bar" }
-
-		o1: {
-			a: or([b, c])
-			b: string
-			c: "bar"
-		}
-		o2: o1 & { a: "foo" }
-		o3: o1 & { a: "foo", b: "baz" }
-		`,
-		out: `<0>{` +
-			`a1: <1>{a: (=~"oo" & =~"fo"), b: =~"oo", c: =~"fo"}, ` +
-			`a2: <2>{a: "foo", b: =~"oo", c: =~"fo"}, ` +
-			`a3: <3>{a: _|_((=~"oo" & "bar"):invalid value "bar" (does not match =~"oo")), b: =~"oo", c: =~"fo"}, ` +
-			`o1: <4>{a: string, b: string, c: "bar"}, ` +
-			`o2: <5>{a: "foo", b: string, c: "bar"}, ` +
-			`o3: <6>{a: _|_(("baz" & "foo"):empty disjunction: conflicting values "baz" and "foo";("bar" & "foo"):empty disjunction: conflicting values "bar" and "foo"), b: "baz", c: "bar"}}`,
-	}, {
-		desc: "self-reference cycles conflicts with strings",
-		in: `
-			a: {
-				x: y+"?"
-				y: x+"!"
-			}
-			a: x: "hey"
-		`,
-		out: `<0>{a: <1>{x: _|_(("hey!?" & "hey"):conflicting values "hey!?" and "hey"), y: "hey!"}}`,
-	}, {
-		desc: "resolved self-reference cycles with disjunctions",
-		in: `
-			a: b&{x:1} | {y:1}  // {x:1,y:3,z:2} | {y:1}
-			b: {x:2} | c&{z:2}  // {x:2} | {x:1,y:3,z:2}
-			c: a&{y:3} | {z:3}  // {x:1,y:3,z:2} | {z:3}
-		`,
-		out: `<0>{a: (<1>{x: 1, y: 3, z: 2} | <2>{y: 1}), b: (<3>{x: 2} | <4>{x: 1, y: 3, z: 2}), c: (<5>{x: 1, y: 3, z: 2} | <6>{z: 3})}`,
-	}, {
-		// We take a very conservative stance on delaying arithmetic
-		// expressions within disjunctions. It should remain resolvable, though,
-		// once the user specifies one.
-		desc: "resolved self-reference cycles with disjunction",
-		in: `
-			// The second disjunct in xa1 is not resolvable and can be
-			// eliminated:
-			//   xa4 & 9
-			//   (xa2 + 2) & 9
-			//   ((xa3 + 2) + 2) & 9
-			//   (((6 & xa1-2) + 2) + 2) & 9
-			//   ((6 + 2) + 2) & 9 // 6 == xa1-2
-			//   10 & 9 => _|_
-			// The remaining values resolve.
-			xa1: (xa2 & 8) | (xa4 & 9)
-			xa2: xa3 + 2
-			xa3: 6 & xa1-2
-			xa4: xa2 + 2
-
-			// The second disjunct in xb4 can be eliminated as both disjuncts
-			// of xb3 result in an incompatible sum when substituted.
-			xb1: (xb2 & 8) | (xb4 & 9)
-			xb2: xb3 + 2
-			xb3: (6 & (xb1-2)) | (xb4 & 9)
-			xb4: xb2 + 2
-
-			// Another variant with more disjunctions. xc1 remains with two
-			// possibilities. Technically, only the first value is valid.
-			// However, to fully determine that, all options of the remaining
-			// disjunction will have to be evaluated algebraically, which is
-			// not done.
-			xc1: xc2 & 8 | xc4 & 9 | xc5 & 9
-			xc2: xc3 + 2
-			xc3: 6 & xc1-2
-			xc4: xc2 + 1
-			xc5: xc2 + 2
-
-			// The above is resolved by setting xd1 explicitly.
-			xd1: xd2 & 8 | xd4 & 9 | xd5 & 9
-			xd2: xd3 + 2
-			xd3: 6 & xd1-2
-			xd4: xd2 + 1
-			xd5: xd2 + 2
-			xd1: 8
-
-			// The above is resolved by setting xd1 explicitly to the wrong
-			// value, resulting in an error.
-			xe1: xe2 & 8 | xe4 & 9 | xe5 & 9
-			xe2: xe3 + 2
-			xe3: 6 & xe1-2
-			xe4: xe2 + 1
-			xe5: xe2 + 2
-			xe1: 9
-
-			// Only one solution.
-			xf1: xf2 & 8 | xf4 & 9
-			xf2: xf3 + 2
-			xf3: 6 & xf1-2 | xf4 & 9
-			xf4: xf2 + 2
-
-			z1: z2 + 1 | z3 + 5
-			z2: z3 + 2
-			z3: z1 - 3
-			z3: 8
-		`,
-		out: `<0>{` +
-			`xa1: 8, ` +
-			`xa2: 8, ` +
-			`xa4: 10, ` +
-			`xa3: 6, ` +
-
-			`xb1: 8, ` +
-			`xb2: 8, ` +
-			`xb4: 10, ` +
-			`xb3: 6, ` +
-
-			`xc1: ((<1>.xc2 & 8) | (<1>.xc4 & 9) | (<1>.xc5 & 9)), ` +
-			`xc2: (<1>.xc3 + 2), ` +
-			`xc4: (<1>.xc2 + 1), ` +
-			`xc5: (<1>.xc2 + 2), ` +
-			`xc3: (6 & (<1>.xc1 - 2)), ` +
-
-			`xd1: 8, ` +
-			`xd2: 8, ` +
-			`xd4: 9, ` +
-			`xd5: 10, ` +
-			`xd3: 6, ` +
-
-			`xe1: _|_((6 & 7):conflicting values 6 and 7), ` +
-			`xe2: _|_((6 & 7):conflicting values 6 and 7), ` +
-			`xe4: _|_((6 & 7):conflicting values 6 and 7), ` +
-			`xe5: _|_((6 & 7):conflicting values 6 and 7), ` +
-			`xe3: _|_((6 & 7):conflicting values 6 and 7), ` +
-
-			`xf1: 8, ` +
-			`xf2: 8, ` +
-			`xf4: 10, ` +
-			`xf3: 6, ` +
-
-			`z1: ((<1>.z2 + 1) | (<1>.z3 + 5)), ` +
-			`z2: (<1>.z3 + 2), ` +
-			`z3: ((<1>.z1 - 3) & 8)}`,
-	}, {
-		// Defaults should not alter the result of the above disjunctions.
-		// The results may differ, but errors and resolution should be roughly
-		// the same.
-		desc: "resolved self-reference cycles with disjunction with defaults",
-		in: `
-			// The disjunction in xa could be resolved, but as disjunctions
-			// are not resolved for expression, it remains unresolved.
-			xa1: (xa2 & 8) | *(xa4 & 9)
-			xa2: xa3 + 2
-			xa3: 6 & xa1-2
-			xa4: xa2 + 2
-
-			// As xb3 is a disjunction, xb2 cannot be resolved and evaluating
-			// the cycle completely is broken. However, it is not an error
-			// as the user might still resolve the disjunction.
-			xb1: *(xb2 & 8) | (xb4 & 9)
-			xb2: xb3 + 2
-			xb3: *(6 & (xb1-2)) | (xb4 & 9)
-			xb4: xb2 + 2
-
-			// Another variant with more disjunctions. xc1 remains with two
-			// possibilities. Technically, only the first value is valid.
-			// However, to fully determine that, all options of the remaining
-			// disjunction will have to be evaluated algebraically, which is
-			// not done.
-			xc1: *(xc2 & 8) | (xc4 & 9) | (xc5 & 9)
-			xc2: xc3 + 2
-			xc3: 6 & xc1-2
-			xc4: xc2 + 1
-			xc5: xc2 + 2
-
-			// The above is resolved by setting xd1 explicitly.
-			xd1: *(xd2 & 8) | xd4 & 9 | xd5 & 9
-			xd2: xd3 + 2
-			xd3: 6 & xd1-2
-			xd4: xd2 + 1
-			xd5: xd2 + 2
-
-			// The above is resolved by setting xd1 explicitly to the wrong
-			// value, resulting in an error.
-			xe1: *(xe2 & 8) | xe4 & 9 | xe5 & 9
-			xe2: xe3 + 2
-			xe3: 6 & xe1-2
-			xe4: xe2 + 1
-			xe5: xe2 + 2
-			xe1: 9
-
-			z1: *(z2 + 1) | z3 + 5
-			z2: z3 + 2
-			z3: z1 - 3
-			z3: 8
-		`,
-		out: `<0>{` +
-			`xa1: 8, ` +
-			`xa2: 8, ` +
-			`xa4: 10, ` +
-			`xa3: 6, ` +
-
-			`xb1: 8, ` +
-			`xb2: 8, ` +
-			`xb4: 10, ` +
-			`xb3: 6, ` +
-
-			`xc1: (*8 | 9), ` + // not resolved because we use evalPartial
-			`xc2: 8, ` +
-			`xc4: 9, ` +
-			`xc5: 10, ` +
-			`xc3: 6, ` +
-
-			`xd1: (*8 | 9), ` + // TODO: eliminate 9?
-			`xd2: 8, ` +
-			`xd4: 9, ` +
-			`xd5: 10, ` +
-			`xd3: 6, ` +
-
-			`xe1: _|_((6 & 7):conflicting values 6 and 7), ` +
-			`xe2: _|_((6 & 7):conflicting values 6 and 7), ` +
-			`xe4: _|_((6 & 7):conflicting values 6 and 7), ` +
-			`xe5: _|_((6 & 7):conflicting values 6 and 7), ` +
-			`xe3: _|_((6 & 7):conflicting values 6 and 7), ` +
-
-			`z1: (*11 | 13), ` + // 13 is eliminated with evalFull
-			`z2: 10, ` +
-			`z3: 8}`,
-	}}
-	rewriteHelper(t, testCases, evalPartial)
-}
-
-func TestFullEval(t *testing.T) {
-	testCases := []testCase{{
-		desc: "detect conflicting value",
-		in: `
-				a: 8000.9
-				a: 7080 | int`,
-		out: `<0>{a: _|_((8000.9 & (int | int)):conflicting values 8000.9 and int (mismatched types float and int))}`, // TODO: fix repetition
-	}, {
-		desc: "conflicts in optional fields are okay ",
-		in: `
-			d: {a: 1, b?: 3} | {a: 2}
-
-			// the following conjunction should not eliminate any disjuncts
-			c: d & {b?:4}
-		`,
-		out: `<0>{d: (<1>{a: 1, b?: 3} | <2>{a: 2}), c: (<3>{a: 1, b?: (3 & 4)} | <4>{a: 2, b?: 4})}`,
-	}, {
-		desc: "resolve all disjunctions",
-		in: `
-			service: [Name=string]: {
-				name: string | *Name
-				port: int | *7080
-			}
-			service: foo: _
-			service: bar: { port: 8000 }
-			service: baz: { name: "foobar" }
-			`,
-		out: `<0>{service: <1>{[]: <2>(Name: string)-><3>{name: (string | *<2>.Name), port: (int | *7080)}, foo: <4>{name: "foo", port: 7080}, bar: <5>{name: "bar", port: 8000}, baz: <6>{name: "foobar", port: 7080}}}`,
-	}, {
-		desc: "field templates",
-		in: `
-			a: {
-				[name=_]: int
-				k: 1
-			}
-			b: {
-				[X=_]: { x: 0, y: *1 | int }
-				v: {}
-				w: { y: 0 }
-			}
-			b: { [y=_]: {} } // TODO: allow different name
-			c: {
-				[Name=_]: { name: Name, y: 1 }
-				foo: {}
-				bar: _
-			}
-			`,
-		out: `<0>{a: <1>{[]: <2>(name: string)->int, k: 1}, b: <3>{[]: <4>(X: string)->(<5>{x: 0, y: (*1 | int)} & <6>{}), v: <7>{x: 0, y: 1}, w: <8>{x: 0, y: 0}}, c: <9>{[]: <10>(Name: string)-><11>{y: 1, name: <10>.Name}, foo: <12>{y: 1, name: "foo"}, bar: <13>{y: 1, name: "bar"}}}`,
-	}, {
-		desc: "field comprehension",
-		in: `
-			a: {
-				for k, v in b
-				if k < "d"
-				if v > b.a {
-					"\(k)": v
-				}
-			}
-			b: {
-				a: 1
-				b: 2
-				c: 3
-				d: 4
-			}
-			c: {
-				for k, v in b
-				if k < "d"
-				if v > b.a {
-					"\(k)": v
-				}
-			}
-			`,
-		out: `<0>{a: <1>{b: 2, c: 3}, b: <2>{a: 1, b: 2, c: 3, d: 4}, c: <3>{b: 2, c: 3}}`,
-	}, {
-		desc: "conditional field",
-		in: `
-			if b {
-				a: "foo"
-			}
-			b: true
-			c: {
-				a: 3
-				if a > 1 {
-					a: 3
-				}
-			}
-			d: {
-				a: int
-				if a > 1 {
-					a: 3
-				}
-			}
-		`,
-		// NOTE: the node numbers are not correct here, but this is an artifact
-		// of the testing code.
-		out: `<0>{b: true, a: "foo", c: <1>{a: 3}, d: <2>{a: int if (<3>.a > 1) yield <4>{a: 3}}}`,
-	}, {
-		desc: "referencing field in field comprehension",
-		in: `
-		a: { b: c: 4 }
-		a: {
-			b: d: 5
-			for k, v in b {
-				"\(k)": v
-			}
-		}
-		`,
-		out: `<0>{a: <1>{b: <2>{c: 4, d: 5}, c: 4, d: 5}}`,
-	}, {
-		desc: "different labels for templates",
-		in: `
-		a: [X=string]: { name: X }
-		a: [Name=string]: { name: Name }
-		a: foo: {}
-		`,
-		out: `<0>{a: <1>{[]: <2>(X: string)->(<3>{name: <2>.X} & <4>{name: <2>.X}), foo: <5>{name: "foo"}}}`,
-	}, {
-		// TODO: rename EE and FF to E and F to check correct ordering.
-
-		desc: "nested templates in one field",
-		in: `
-			a: [A=string]: b: [B=string]: {
-				name: A
-				kind: B
-			}
-			a: "A": b: "B": _
-			a: "C": b: "D": _
-			a: "EE": b: "FF": { c: "bar" }
-		`,
-		out: `<0>{a: <1>{[]: <2>(A: string)-><3>{b: <4>{[]: <5>(B: string)-><6>{name: <2>.A, kind: <5>.B}, }}, ` +
-			`A: <7>{b: <8>{[]: <9>(B: string)-><10>{name: <11>.A, kind: <9>.B}, ` +
-			`B: <12>{name: "A", kind: "B"}}}, ` +
-			`C: <13>{b: <14>{[]: <15>(B: string)-><16>{name: <17>.A, kind: <15>.B}, ` +
-			`D: <18>{name: "C", kind: "D"}}}, ` +
-			`EE: <19>{b: <20>{[]: <21>(B: string)-><22>{name: <23>.A, kind: <21>.B}, ` +
-			`FF: <24>{name: "EE", kind: "FF", c: "bar"}}}}}`,
-	}, {
-		desc: "template unification within one struct",
-		in: `
-			a: {
-				[A=string]: { name: A }
-				// TODO: allow duplicate alias here
-				[X=string]: { kind: X }
-			}
-			a: "A": _
-			a: "C": _
-			a: "E": { c: "bar" }
-		`,
-		out: `<0>{a: <1>{[]: <2>(A: string)->(<3>{name: <2>.A} & <4>{kind: <2>.A}), ` +
-			`E: <5>{name: "E", kind: "E", c: "bar"}, ` +
-			`A: <6>{name: "A", kind: "A"}, ` +
-			`C: <7>{name: "C", kind: "C"}}}`,
-	}, {
-		desc: "field comprehensions with multiple keys",
-		in: `
-			for x in [
-				{a: "A", b: "B" },
-				{a: "C", b: "D" },
-				{a: "E", b: "F" },
-			] {
-				a: "\(x.a)": b: "\(x.b)": x
-			}
-
-			for x in [
-				{a: "A", b: "B" },
-				{a: "C", b: "D" },
-				{a: "E", b: "F" },
-			] {
-				"\(x.a)": "\(x.b)": x
-			}
-			`,
-		out: `<0>{E: <1>{F: <2>{a: "E", b: "F"}}, ` +
-			`a: <3>{` +
-			`E: <4>{b: <5>{F: <6>{a: "E", b: "F"}}}, ` +
-			`A: <7>{b: <8>{B: <9>{a: "A", b: "B"}}}, ` +
-			`C: <10>{b: <11>{D: <12>{a: "C", b: "D"}}}}, ` +
-			`A: <13>{B: <14>{a: "A", b: "B"}}, ` +
-			`C: <15>{D: <16>{a: "C", b: "D"}}}`,
-		// TODO: this order would be desirable.
-		// out: `<0>{a: <1>{` +
-		// 	`A: <2>{b: <3>{B: <4>{a: "A", b: "B"}}}, ` +
-		// 	`C: <5>{b: <6>{D: <7>{a: "C", b: "D"}}}, ` +
-		// 	`E: <8>{b: <9>{F: <10>{a: "E", b: "F"}}}}, ` +
-		// 	`A: <11>{B: <12>{a: "A", b: "B"}}, ` +
-		// 	`C: <13>{D: <14>{a: "C", b: "D"}}, ` +
-		// 	`E: <15>{F: <16>{a: "E", b: "F"}}}`,
-	}, {
-		desc: "field comprehensions with templates",
-		in: `
-			num: 1
-			a: {
-				if num < 5 {
-					[A=string]: [B=string]: {
-						name: A
-						kind: B
-					}
-				}
-			}
-			a: b: c: d: "bar"
-			`,
-		out: `<0>{num: 1, a: <1>{[]: <2>(A: string)-><3>{[]: <4>(B: string)-><5>{name: <2>.A, kind: <4>.B}, }, ` +
-			`b: <6>{[]: <7>(B: string)-><8>{name: <9>.A, kind: <7>.B}, ` +
-			`c: <10>{name: "b", kind: "c", ` +
-			`d: "bar"}}}}`,
-	}, {
-		desc: "disjunctions of lists",
-		in: `
-			l: *[ int, int ] | [ string, string ]
-
-			l1: [ "a", "b" ]
-			l2: l & [ "c", "d" ]
-			`,
-		out: `<0>{l: [int,int], l1: ["a","b"], l2: ["c","d"]}`,
-	}, {
-		desc: "normalization",
-		in: `
-			a: string | string
-			b: *1 | *int
-			c: *1.0 | *float
-		`,
-		out: `<0>{a: string, b: int, c: float}`,
-	}, {
-		desc: "default disambiguation and elimination",
-		in: `
-		a: *1 | int
-		b: *3 | int
-		c: a & b
-		d: b & a
-
-		e: *1 | *1
-		`,
-		out: `<0>{a: 1, b: 3, c: int, d: int, e: 1}`,
-	}, {
-		desc: "list comprehension",
-		in: `
-			a: [ for k, v in b if k < "d" if v > b.a { k }]
-			b: {
-				a: 1
-				b: 2
-				c: 3
-				d: 4
-			}
-			c: [ for _, x in b for _, y in b  if x < y { x } ]
-			d: [ for x, _ in a { x } ]
-			`,
-		out: `<0>{a: ["b","c"], b: <1>{a: 1, b: 2, c: 3, d: 4}, c: [1,1,1,2,2,3], d: [0,1]}`,
-	}, {
-		desc: "struct comprehension with template",
-		in: `
-			result: [ for _, v in service { v } ]
-
-			service: [Name=string]: {
-				name: *Name | string
-				type: "service"
-				port: *7080 | int
-			}
-			service: foo: {}
-			service: bar: { port: 8000 }
-			service: baz: { name: "foobar" }
-			`,
-		out: `<0>{result: [` +
-			`<1>{name: "foo", type: "service", port: 7080},` +
-			`<2>{name: "bar", type: "service", port: 8000},` +
-			`<3>{name: "foobar", type: "service", port: 7080}], ` +
-
-			`service: <4>{` +
-			`[]: <5>(Name: string)-><6>{name: (*<5>.Name | string), type: "service", port: (*7080 | int)}, ` +
-			`foo: <7>{name: "foo", type: "service", port: 7080}, ` +
-			`bar: <8>{name: "bar", type: "service", port: 8000}, ` +
-			`baz: <9>{name: "foobar", type: "service", port: 7080}}}`,
-	}, {
-		desc: "resolutions in struct comprehension keys",
-		in: `
-			a: { for _, b in ["c"] { "\(b + ".")": "a" } }
-			`,
-		out: `<0>{a: <1>{"c.": "a"}}`,
-	}, {
-		desc: "recursive evaluation within list",
-		in: `
-			l: [a]
-			a: b & { c: "t" }
-			b: {
-				d: c
-				c: string
-			}
-			l1: [a1]
-			a1: b1 & { c: "t" }
-			b1: {
-				d: "s" + c
-				c:  string
-			}
-		`,
-		out: `<0>{` +
-			`l: [<1>{c: "t", d: "t"}], ` +
-			`a: <2>{c: "t", d: "t"}, ` +
-			`b: <3>{c: string, d: string}, ` +
-			`l1: [<4>{c: "t", d: "st"}], ` +
-			`a1: <5>{c: "t", d: "st"}, ` +
-			`b1: <6>{c: string, d: ("s" + <7>.c)}}`,
-	}, {
-		desc: "ips",
-		in: `
-		IP: 4*[ uint8 ]
-
-		Private:
-			*[ 192, 168, uint8, uint8 ] |
-			[ 10, uint8, uint8, uint8] |
-			[ 172, >=16 & <=32, uint8, uint8 ]
-
-		Inst: Private & [ _, 10, ... ]
-
-		MyIP: Inst & [_, _, 10, 10 ]
-		`,
-		out: `<0>{` +
-			`IP: [(int & >=0 & int & <=255),(int & >=0 & int & <=255),(int & >=0 & int & <=255),(int & >=0 & int & <=255)], ` +
-			`Private: [192,168,(int & >=0 & int & <=255),(int & >=0 & int & <=255)], ` +
-			`Inst: [10,10,(int & >=0 & int & <=255),(int & >=0 & int & <=255)], ` +
-			`MyIP: [10,10,10,10]` +
-			`}`,
-	}, {
-		desc: "complex interaction of groundness",
-		in: `
-			res: [ for x in a for y in x { y & { d: "b" } }]
-			res: [ a.b.c & { d: "b" } ]
-
-			a: b: [C=string]: { d: string, s: "a" + d }
-			a: b: c: d: string
-		`,
-		// TODO(perf): unification should catch shared node.
-		out: `<0>{res: [<1>{d: "b", s: "ab"}], ` +
-			`a: <2>{b: <3>{[]: <4>(C: string)-><5>{d: string, s: ("a" + <5>.d)}, c: <6>{d: string, s: ("a" + <7>.d)}}}}`,
-	}, {
-		desc: "complex groundness 2",
-		in: `
-			r1: f1 & { y: "c" }
-
-			f1: { y: string, res: a.b.c & { d: y } }
-
-			a: b: c: { d: string, s: "a" + d }
-			a: b: [C=string]: { d: string, s: "a" + d }
-			a: b: c: d: string
-		`,
-		out: `<0>{r1: <1>{y: "c", res: <2>{d: "c", s: "ac"}}, f1: <3>{y: string, res: <4>{d: string, s: (("a" + <5>.d) & ("a" + <5>.d))}}, a: <6>{b: <7>{[]: <8>(C: string)-><9>{d: string, s: ("a" + <9>.d)}, c: <10>{d: string, s: (("a" + <11>.d) & ("a" + <11>.d))}}}}`,
-	}, {
-		desc: "references from template to concrete",
-		in: `
-				res: [t]
-				t: [X=string]: {
-					a: c + b.str
-					b: str: string
-					c: "X"
-				}
-				t: x: { b: str: "DDDD" }
-				`,
-		out: `<0>{res: [<1>{[]: <2>(X: string)-><3>{a: (<3>.c + <3>.b.str), c: "X", b: <4>{str: string}}, x: <5>{a: "XDDDD", c: "X", b: <6>{str: "DDDD"}}}], ` +
-			`t: <7>{[]: <2>(X: string)-><3>{a: (<3>.c + <3>.b.str), c: "X", b: <4>{str: string}}, x: <8>{a: "XDDDD", c: "X", b: <9>{str: "DDDD"}}}}`,
-	}, {
-		// TODO: A nice property for CUE to have would be that evaluation time
-		// is proportional to the number of output nodes (note that this is
-		// not the same as saying that the running time is O(n)).
-		// We should probably disallow shenanigans like the one below. But until
-		// this is allowed, it should at least be correct. At least we are not
-		// making reentrant coding easy.
-		desc: "reentrance",
-		in: `
-		// This indirection is needed to avoid binding references to fib
-		// within fib to the instantiated version.
-		fibRec: {nn: int, out: (fib & {n: nn}).out}
-		fib: {
-			n: int
-
-			if n >= 2 {
-				out: (fibRec & {nn: n - 2}).out + (fibRec & {nn: n - 1}).out
-			}
-			if n < 2 {
-				out: n
-			}
-		}
-		fib2: (fib & {n: 2}).out
-		fib7: (fib & {n: 7}).out
-		fib12: (fib & {n: 12}).out
-		`,
-		out: `<0>{` +
-			`fibRec: <1>{` +
-			`nn: int, ` +
-			`out: (<2>.fib & <3>{n: <4>.nn}).out}, ` +
-			// NOTE: the node numbers are not correct here, but this is an artifact
-			// of the testing code.
-			`fib: <5>{n: int if (<6>.n >= 2) yield <7>{out: ((<2>.fibRec & <8>{nn: (<6>.n - 2)}).out + (<2>.fibRec & <9>{nn: (<6>.n - 1)}).out)},  if (<6>.n < 2) yield <10>{out: <6>.n}}, ` +
-			`fib2: 1, ` +
-			`fib7: 13, ` +
-			`fib12: 144}`,
-	}, {
-		desc: "Issue #23",
-		in: `
-			x: {a:1}|{a:2}
-			y: x & {a:3}
-		`,
-		out: `<0>{x: (<1>{a: 1} | <2>{a: 2}), y: _|_((1 & 3):empty disjunction: conflicting values 1 and 3;(2 & 3):empty disjunction: conflicting values 2 and 3)}`,
-	}, {
-		desc: "cannot resolve references that would be ambiguous",
-		in: `
-		a1: *0 | 1
-		a1: a3 - a2
-		a2: *0 | 1
-		a2: a3 - a1
-		a3: 1
-
-		b1: (*0 | 1) & b2
-		b2: (0 | *1) & b1
-
-		c1: (*{a:1} | {b:1}) & c2
-		c2: (*{a:2} | {b:2}) & c1
-		`,
-		out: `<0>{` +
-			`a1: ((*0 | 1) & (<1>.a3 - <1>.a2)), ` +
-			`a3: 1, ` +
-			`a2: ((*0 | 1) & (<1>.a3 - <1>.a1)), ` +
-			`b1: (0 | 1), ` +
-			`b2: (0 | 1), ` +
-			`c1: (<2>{a: 1, b: 2} | <3>{a: 2, b: 1}), ` +
-			`c2: (<4>{a: 2, b: 1} | <5>{a: 1, b: 2})}`,
-	}, {
-		desc: "dont convert incomplete errors to non-incomplete",
-		in: `
-		import "strings"
-
-		n1: {min: <max, max: >min}
-		n2: -num
-		n3: +num
-		n4: num + num
-		n5: num - num
-		n6: num * num
-		n7: num / num
-
-		b1: !is
-
-		s1: "\(str)"
-		s2: strings.ContainsAny("dd")
-		s3: strings.ContainsAny(str, "dd")
-
-		str: string
-		num: <4
-		is:  bool
-		`,
-		out: `<0>{` +
-			`n1: <1>{min: <<2>.max, max: ><2>.min}, ` +
-			`n2: -<3>.num, num: <4, ` +
-			`n3: +<3>.num, ` +
-			`n4: (<3>.num + <3>.num), ` +
-			`n5: (<3>.num - <3>.num), ` +
-			`n6: (<3>.num * <3>.num), ` +
-			`n7: (<3>.num / <3>.num), ` +
-			`b1: !<3>.is, ` +
-			`is: bool, ` +
-			`s1: ""+<3>.str+"", ` +
-			`str: string, ` +
-			`s2: strings.ContainsAny ("dd"), ` +
-			`s3: <4>.ContainsAny (<3>.str,"dd")}`,
-	}, {
-		desc: "len of incomplete types",
-		in: `
-		args: *[] | [...string]
-		v1: len(args)
-		v2: len([])
-		v3: len({})
-		v4: len({a: 3})
-		v5: len({a: 3} | {a: 4})
-		v6: len('sf' | 'dd')
-		v7: len([2] | *[1, 2])
-		v8: len([2] | [1, 2])
-		v9: len("😂")
-		v10: len("")
-		`,
-		out: `<0>{` +
-			`args: [], ` +
-			`v1: 0, ` +
-			`v2: 0, ` +
-			`v3: 0, ` +
-			`v4: 1, ` +
-			`v5: len ((<1>{a: 3} | <2>{a: 4})), ` +
-			`v6: len (('sf' | 'dd')), ` +
-			`v7: 2, ` +
-			`v8: len (([2] | [1,2])), ` +
-			`v9: 4, ` +
-			`v10: 0}`,
-	}, {
-		desc: "slice rewrite bug",
-		in: `
-		fn: {
-			arg: [...int] & [1]
-			out: arg[1:]
-		}
-		fn1: fn & {arg: [1]}
-		`,
-		out: `<0>{fn: <1>{arg: [1], out: []}, fn1: <2>{arg: [1], out: []}}`,
-	}, {
-		desc: "Issue #94",
-		in: `
-		foo: {
-			opt?: 1
-			"txt": 2
-			#def: 3
-			regular: 4
-			_hidden: 5
-		}
-		comp: { for k, v in foo { "\(k)": v } }
-		select: {
-			opt: foo.opt
-			"txt": foo.txt
-			#def: foo.#def
-			regular: foo.regular
-			_hidden: foo._hidden
-		}
-		index: {
-			opt: foo["opt"]
-			"txt": foo["txt"]
-			#def: foo["#def"]
-			regular: foo["regular"]
-			_hidden: foo["_hidden"]
-		}
-		`,
-		out: `<0>{` +
-			`foo: <1>{opt?: 1, txt: 2, #def: 3, regular: 4, _hidden: 5}, ` +
-			`comp: <2>{txt: 2, regular: 4}, ` +
-			`select: <3>{opt: <4>.foo.opt, txt: 2, #def: 3, regular: 4, _hidden: 5}, ` +
-			`index: <5>{opt: <4>.foo["opt"], txt: 2, #def: <4>.foo["#def"], regular: 4, _hidden: <4>.foo["_hidden"]}}`,
-	}, {
-		desc: "retain references with interleaved embedding",
-		in: `
-		a: d: {
-			#base
-			#info: {...}
-			Y: #info.X
-		}
-
-		#base: {
-			#info: {...}
-		}
-
-		a: [Name=string]: { #info: {
-			X: "foo"
-		}}
-		`,
-		out: `<0>{a: <1>{[]: <2>(Name: string)-><3>{#info: <4>C{X: "foo"}}, d: <5>C{#info: <6>C{X: "foo"}, Y: "foo"}}, #base: <7>C{#info: <8>{...}}}`,
-	}, {
-		desc: "comparison against bottom",
-		in: `
-		a: _|_ == _|_
-		b: err == 1&2 // not a literal error, so not allowed
-		c: err == _|_ // allowed
-		d: err != _|_ // allowed
-		e: err != 1&3
-		// z: err == err // TODO: should infer to be true?
-		f: ({a: 1} & {a: 2}) == _|_
-		g: ({a: 1} & {b: 2}) == _|_
-		h: _|_ == ({a: 1} & {a: 2})
-		i: _|_ == ({a: 1} & {b: 2})
-
-		err: 1 & 2
-		`,
-		out: `<0>{a: true, b: _|_((1 & 2):conflicting values 1 and 2), err: _|_((1 & 2):conflicting values 1 and 2), c: true, d: false, e: _|_((1 & 2):conflicting values 1 and 2), f: true, g: false, h: true, i: false}`,
-	}, {
-		desc: "or builtin should not fail on non-concrete empty list",
-		in: `
-		#Workflow: {
-			jobs: {
-				[jobID=string]: {
-				}
-			}
-			#JobID: or([ for k, _ in jobs { k } ])
-		}
-
-		foo: #Workflow & {
-			jobs: foo: {
-			}
-		}
-		`,
-		out: `<0>{#Workflow: <1>C{jobs: <2>{[]: <3>(jobID: string)-><4>C{}, }, #JobID: or ([ <5>for k, _ in <6>.jobs yield <5>.k ])}, foo: <7>C{jobs: <8>{[]: <9>(jobID: string)-><10>C{}, foo: <11>C{}}, #JobID: "foo"}}`,
-	}, {
-		desc: "Issue #153",
-		in: `
-		Foo: {
-			listOfCloseds: [...#Closed]
-		}
-
-		#Closed: {
-			a: int | *0
-		}
-
-		Junk: {
-			b: 2
-		}
-
-		Foo & {
-			listOfCloseds: [{
-				for k, v in Junk {
-					"\(k)": v
-				}
-			 }]
-		}
-		`,
-		out: `<0>{<1>{listOfCloseds: [_|_(<2>.v:field "b" not allowed in closed struct)]}, Foo: <3>{listOfCloseds: []}, #Closed: <4>C{a: 0}, Junk: <5>{b: 2}}`,
-	}, {
-		desc: "label and field aliases",
-		in: `
-		p: [ID=string]: { name: ID }
-		A="foo=bar": "str"
-		a: A
-		B=bb: 4
-		b1: B
-		b1: bb
-		C="\(a)": 5
-		c: C
-		`,
-		out: `<0>{` +
-			`p: <1>{[]: <2>(ID: string)-><3>{name: <2>.ID}, }, ` +
-			`"foo=bar": "str", ` +
-			`a: "str", ` +
-			`bb: 4, ` +
-			`b1: 4, ` +
-			`c: 5, ` +
-			`str: 5}`,
-	}, {
-		desc: "optionals with label filters",
-		in: `
-		#JobID: =~"^[a-zA-Z]*$"
-		#Job: {
-			name: string
-			cmd:  string
-		}
-		#Jobs: {
-			[#JobID]: #Job
-			[=~"Test$"]: name: =~"^test" // Must work without ...
-		}
-
-		jobs: foo: name: "allGood"
-		jobs: foo: name: "allGood"
-
-		jobs1: #Jobs
-		jobs1: foo1: {} // faulty
-
-		jobs2: #Jobs
-		jobs2: fooTest: name: "badName" // faulty
-
-		jobs3: #Jobs
-		jobs3: [string]: #Job
-		jobs3: fooTest1: name: "badName" // faulty
-		`,
-		out: `<0>{` +
-			`#JobID: =~"^[a-zA-Z]*$", ` +
-			`#Job: <1>C{name: string, cmd: string}, ` +
-			`#Jobs: <2>C{[=~"^[a-zA-Z]*$"]: <3>(_: string)-><4>.#Job, [=~"Test$"]: <5>(_: string)-><6>C{name: =~"^test"}, }, ` +
-			`jobs: <7>{foo: <8>{name: "allGood"}}, ` +
-			`jobs1: _|_(<9>{}:field "foo1" not allowed in closed struct), ` +
-			`jobs2: <10>C{[=~"^[a-zA-Z]*$"]: <11>(_: string)-><4>.#Job, [=~"Test$"]: <12>(_: string)-><13>C{name: =~"^test"}, fooTest: _|_(string:field "cmd" not allowed in closed struct)}, ` +
-			`jobs3: _|_(<14>{name: "badName"}:field "fooTest1" not allowed in closed struct)}`,
-	}, {
-		desc: "optionals in open structs",
-		in: `
-		A: {
-			[=~"^[a-s]*$"]: int
-		}
-		B: {
-			[=~"^[m-z]*$"]: int
-		}
-		#C: {A & B}
-		c: #C & { aaa: 3 }
-		`,
-		out: `<0>{A: <1>{[=~"^[a-s]*$"]: <2>(_: string)->int, }, B: <3>{[=~"^[m-z]*$"]: <4>(_: string)->int, }, #C: <5>C{[=~"^[a-s]*$"]: <6>(_: string)->int, [=~"^[m-z]*$"]: <7>(_: string)->int, }, c: <8>C{[=~"^[a-s]*$"]: <9>(_: string)->int, [=~"^[m-z]*$"]: <10>(_: string)->int, aaa: 3}}`,
-	}, {
-		desc: "conjunction of optional sets",
-		in: `
-		#A: {
-			[=~"^[a-s]*$"]: int
-		}
-		#B: {
-			[=~"^[m-z]*$"]: int
-		}
-
-		#C: #A & #B
-		c: #C & { aaa: 3 }
-
-		#D: {#A & #B}
-		d: #D & { aaa: 3 }
-		`,
-		out: `<0>{` +
-			`#A: <1>C{[=~"^[a-s]*$"]: <2>(_: string)->int, }, ` +
-			`#B: <3>C{[=~"^[m-z]*$"]: <4>(_: string)->int, }, ` +
-			`#C: <5>C{(C{[=~"^[a-s]*$"]: <6>(_: string)->int} & C{[=~"^[m-z]*$"]: <7>(_: string)->int}), }, ` +
-			`c: _|_(3:field "aaa" not allowed in closed struct), ` +
-			`#D: <8>C{(C{[=~"^[a-s]*$"]: <9>(_: string)->int} & C{[=~"^[m-z]*$"]: <10>(_: string)->int}), }, ` +
-			`d: _|_(3:field "aaa" not allowed in closed struct)` +
-			`}`,
-	}, {
-		desc: "continue recursive closing for optionals",
-		in: `
-		#S: {
-			[string]: { a: int }
-		}
-		a: #S & {
-			v: { b: int }
-		}
-		`,
-		out: `<0>{#S: <1>{[]: <2>(_: string)-><3>C{a: int}, }, a: <4>{[]: <5>(_: string)-><6>C{a: int}, v: _|_(int:field "b" not allowed in closed struct)}}`,
-	}, {
-		desc: "augment closed optionals",
-		in: `
-		#A: {
-			[=~"^[a-s]*$"]: int
-		}
-		#B: {
-			[=~"^[m-z]*?"]: int
-		}
-		#C: {
-			#A & #B
-			[=~"^Q*$"]: int
-		}
-		c: #C & { QQ: 3 }
-		#D: {
-			#A
-			#B
-		}
-		d: #D & { aaa: 4 }
-		`,
-		out: `<0>{` +
-			`#A: <1>C{[=~"^[a-s]*$"]: <2>(_: string)->int, }, ` +
-			`#B: <3>C{[=~"^[m-z]*?"]: <4>(_: string)->int, }, ` +
-			`#C: <5>C{C{[=~"^Q*$"]: <6>(_: string)->int}, C{(C{[=~"^[a-s]*$"]: <7>(_: string)->int} & C{[=~"^[m-z]*?"]: <8>(_: string)->int})}, }, ` +
-			`c: <9>C{C{[=~"^Q*$"]: <10>(_: string)->int}, C{(C{[=~"^[a-s]*$"]: <11>(_: string)->int} & C{[=~"^[m-z]*?"]: <12>(_: string)->int})}, QQ: 3}, ` +
-			`#D: <13>C{[=~"^[a-s]*$"]: <14>(_: string)->int, [=~"^[m-z]*?"]: <15>(_: string)->int, }, ` +
-			`d: <16>C{[=~"^[a-s]*$"]: <17>(_: string)->int, [=~"^[m-z]*?"]: <18>(_: string)->int, aaa: 4}}`,
-	}, {
-		in: `
-		#Task: {
-			{
-				op:          "pull"
-				tag:         *"latest" | string
-				refToTag:    tag
-				tagExpr: tag + "dd"
-				tagInString: "\(tag)"
-			} | {
-				op: "scratch"
-			}
-		}
-
-		foo: #Task & {"op": "pull"}
-		`,
-		out: `<0>{#Task: (<1>C{op: "pull", tag: (*"latest" | string), refToTag: <1>.tag, tagExpr: (<1>.tag + "dd"), tagInString: ""+<1>.tag+""} | <2>C{op: "scratch"}), foo: <3>C{op: "pull", tag: "latest", refToTag: "latest", tagExpr: "latestdd", tagInString: "latest"}}`,
-	}, {
-		in: `
-		t: {
-			#ok: *true | bool
-			if #ok {
-				x: int
-			}
-		}
-		s: t & {
-			#ok: false
-		}`,
-		out: `<0>{t: <1>{x: int, #ok: true}, s: <2>{#ok: false}}`,
-	}, {
-		desc: "cross-dependent comprehension",
-		// TODO(eval): fix: c should ultimately be allowed the struct. Current
-		// semantics require, however, that generated fields are not available
-		// for evaluation. This, however, does not have to hold, for closedness
-		// checks and allowing this would be more intuitive.
-		// Until that time, ensure that the behavior is at commutative.
-		in: `
-		#a: {
-			if b {
-				c: 4
-			}
-			b: bool
-		}
-		x: (#a & { b: true}) & {c: 4 }
-		y: x
-		`,
-		// c should not be allowed, as it would break commutativiy.
-		// See comments above.
-		out: `<0>{x: _|_(4:field "c" not allowed in closed struct), y: _|_(4:field "c" not allowed in closed struct), #a: <1>C{b: bool if <2>.b yield <3>C{c: 4}}}`,
-	}, {
-		desc: "optional expanded before lookup",
-		in: `
-		test: [ID=_]: {
-			name: ID
-		}
-
-		test: A: {
-			field1: "1"
-			field2: "2"
-		}
-
-		B: test.A & {}
-		`,
-		out: `<0>{test: <1>{[]: <2>(ID: string)-><3>{name: <2>.ID}, A: <4>{name: "A", field1: "1", field2: "2"}}, B: <5>{name: "A", field1: "1", field2: "2"}}`,
-	}, {
-		desc: "Issue #178",
-		in: `
-		import "encoding/csv"
-		import "encoding/hex"
-
-		foo: csv.Decode(data)
-		data: bytes
-
-		len: int
-		bar: hex.EncodedLen(len)
-		`,
-		out: `<0>{foo: <1>.Decode (<2>.data), data: bytes, len: int, bar: <3>.EncodedLen (<2>.len)}`,
-	}, {
-		// This resulted in an issue in an older version. Prevent regression.
-		desc: "comprehension and skipped field",
-		in: `
-		for key, value in {x: v: 1} {
-			"\(key)": {
-				v: *{for pod, _ in value.v {}} | {"\(value.v)": 2}
-				_p: 3
-			}
-		}
-		`,
-		out: `<0>{x: <1>{v: <2>{"1": 2}, _p: 3}}`,
-	}, {
-		desc: "non-structural direct cycles",
-		in: `
-		c1: {bar: baz: 2} & c1.bar
-		c2: {bar: 1} & c2.bar
-		`,
-		out: `<0>{` +
-			`c1: <1>{bar: <2>{baz: 2}, baz: 2}, ` +
-			`c2: _|_(conflicting values {bar: 1} and 1 (mismatched types struct and int))}`,
-	}, {
-		desc: "dont bind to string labels",
-		in: `
-			x: 1
-			y: {
-				"x": 2
-				z: x
-			}
-			`,
-		out: `<0>{x: 1, y: <1>{x: 2, z: 1}}`,
-	}, {
-		desc: "dont pass incomplete values to builtins",
-		in: `
-		import "encoding/json"
-
-		input: string
-		foo: json.Marshal(input)
-		`,
-		out: `<0>{input: string, foo: <1>.Marshal (<2>.input)}`,
-	}, {
-		desc: "alias reuse in nested scope",
-		in: `
-		#Foo: {
-			let X = or([ for k, _ in {} { k } ])
-			connection: [X]: X
-		}
-		#A: {
-			foo: "key"
-			let X = foo
-			a: foo: [X]: X
-		}
-		#B: {
-			foo: string
-			let X = foo
-			a: foo: [X]: X
-		}
-		b: #B & { foo: "key" }
-		`,
-		out: `<0>{` +
-			`#Foo: <1>C{connection: <2>C{[or ([ <3>for k, _ in <4>{} yield <3>.k ])]: <5>(_: string)->or ([ <3>for k, _ in <4>{} yield <3>.k ]), }}, ` +
-			`#A: <6>C{foo: "key", a: <7>C{foo: <8>C{["key"]: <9>(_: string)-><10>.foo, }}}, ` +
-			`#B: <11>C{foo: string, a: <12>C{foo: <13>C{[string]: <14>(_: string)-><15>.foo, }}}, ` +
-			`b: <16>C{foo: "key", a: <17>C{foo: <18>C{["key"]: <19>(_: string)-><20>.foo, }}}` +
-			`}`,
-	}, {
-		desc: "json Marshaling detects incomplete",
-		in: `
-		import "encoding/json"
-		a: json.Marshal({ a: string} )
-
-		foo: { a: 3, b: foo.c }
-		b: json.Marshal(foo)
-		`,
-		out: `<0>{` +
-			`a: <1>.Marshal (<2>{a: string}), ` +
-			`foo: <3>{a: 3, b: <4>.foo.c}, ` +
-			`b: <1>.Marshal (<4>.foo)}`,
-	}, {
-		desc: "detectIncompleteYAML",
-		in: `
-		package foobar
-
-		import yaml "encoding/yaml"
-
-		#Spec: {
-			_vars: {something: string}
-			data: {
-				#foo: {
-					use: _vars.something
-				}
-				baz:    yaml.Marshal(_vars.something)
-				foobar: yaml.Marshal(#foo)
-			}
-		}
-		Val: #Spec & {
-			_vars: something: "var-string"
-		}
-		`,
-		out: `<0>{#Spec: <1>C{_vars: <2>C{something: string}, data: <3>C{#foo: <4>C{use: string}, baz: <5>.Marshal (<6>._vars.something), foobar: <5>.Marshal (<7>.#foo)}}, Val: <8>C{_vars: <9>C{something: "var-string"}, data: <10>C{#foo: <11>C{use: "var-string"}, baz: "var-string\n", foobar: "use: var-string\n"}}}`,
-	}, {
-		desc: "detectIncompleteJSON",
-		in: `
-			package foobar
-	
-			import "encoding/json"
-		
-			#Spec: {
-				_vars: {something: string}
-				data: {
-					#foo: {
-						use: _vars.something
-					}
-					baz:    json.Marshal(_vars.something)
-					foobar: json.Marshal(#foo)
-				}
-			}
-			Val: #Spec & {
-				_vars: something: "var-string"
-			}
-			`,
-		out: `<0>{#Spec: <1>C{_vars: <2>C{something: string}, data: <3>C{#foo: <4>C{use: string}, baz: <5>.Marshal (<6>._vars.something), foobar: <5>.Marshal (<7>.#foo)}}, Val: <8>C{_vars: <9>C{something: "var-string"}, data: <10>C{#foo: <11>C{use: "var-string"}, baz: "\"var-string\"", foobar: "{\"use\":\"var-string\"}"}}}`,
-	}, {
-		desc: "issue312",
-		in: `
-		for x in [1] {
-			*close({}) | { [_]: null }
-		}
-		`,
-		out: `<0>{ <1>for _, x in [1] yield <2>{}, (*close (<3>{}) | <4>{[]: <5>(_: string)->null, })}`,
-	}, {
-		// TODO(eval): note that this behavior is incompatible with allowing
-		// non-struct as emit values. If we ever want to do this, we need to
-		// do it soon.
-		desc: "issue312",
-		in: `
-		y: *1 | {a: 2}
-		for x in [1] { y }
-		`,
-		out: `<0>{y: 1, a: 2}`,
-	}, {
-		desc: "issue318",
-		in: `
-		#T: {
-			arg: x: string
-			out1: "\(arg.x) \(arg.y)"
-			out2: "\(arg.y)"
-			vx: arg.x
-			vy: arg.y
-		}
-		`,
-		out: `<0>{` +
-			`#T: <1>C{` +
-			`arg: <2>C{x: string}, ` +
-			`out1: _|_(<3>.arg.y:undefined field "y"), ` +
-			`out2: _|_(<3>.arg.y:undefined field "y"), ` +
-			`vx: string, ` +
-			`vy: _|_(<3>.arg.y:undefined field "y")}}`,
-	}, {
-		desc: "issue314",
-		in: `
-		import (
-			"text/template"
-			"encoding/yaml"
-			"encoding/json"
-		)
-
-		x: {
-			s: "myname"
-			#T
-		}
-
-		#T: {
-			s: string
-			out: template.Execute("{{.s}}", {
-				"s": s
-			})
-		}
-
-		#V: {
-			s: string
-			out: json.Marshal({"s": s})
-		}
-
-		#U: {
-			s: string
-			out: yaml.Marshal({"s": s})
-		}`,
-		out: `<0>{` +
-			`x: <1>C{s: "myname", out: "myname"}, ` +
-			`#T: <2>C{s: string, out: <3>.Execute ("{{.s}}",<4>C{s: <5>.s})}, ` +
-			`#V: <6>C{s: string, out: <7>.Marshal (<8>C{s: <9>.s})}, ` +
-			`#U: <10>C{s: string, out: <11>.Marshal (<12>C{s: <13>.s})}}`,
-	}}
-	rewriteHelper(t, testCases, evalFull)
-}
-
 func TestX(t *testing.T) {
 	// Don't remove. For debugging.
 	in := `
@@ -3048,5 +29,34 @@
 	if strings.TrimSpace(in) == "" {
 		t.Skip()
 	}
-	rewriteHelper(t, []testCase{{in: in}}, evalFull)
+}
+
+// var traceOn = flag.Bool("debug", false, "enable tracing")
+
+// func compileFileWithErrors(t *testing.T, body string) (*context, *structLit, error) {
+// 	t.Helper()
+// 	ctx, inst, err := compileInstance(t, body)
+// 	return ctx, inst.root, err
+// }
+
+// func compileFile(t *testing.T, body string) (*context, *structLit) {
+// 	t.Helper()
+// 	ctx, inst, errs := compileInstance(t, body)
+// 	if errs != nil {
+// 		t.Fatal(errs)
+// 	}
+// 	return ctx, inst.root
+// }
+
+func compileInstance(t *testing.T, body string) (*context, *Instance, error) {
+	var r Runtime
+	inst, err := r.Compile("test", body)
+
+	if err != nil {
+		x := newInstance(newIndex(sharedIndex), nil, &adt.Vertex{})
+		ctx := x.newContext()
+		return ctx, x, err
+	}
+
+	return r.index().newContext(), inst, nil
 }
diff --git a/cue/rewrite.go b/cue/rewrite.go
deleted file mode 100644
index 7f7916f..0000000
--- a/cue/rewrite.go
+++ /dev/null
@@ -1,277 +0,0 @@
-// Copyright 2018 The 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
-
-// TODO: nodeRefs are currently not updated if the structs they point to are
-// updated. Handing this in uses of rewrite is tedious and hard to get correct.
-// Make this a general mechanism. This can be done using a Tomabechi-like
-// approach of associating copies with nodes in one pass, and then make a
-// complete copy in a second.
-
-type rewriteFunc func(ctx *context, v value) (value, bool)
-
-func rewrite(ctx *context, v value, fn rewriteFunc) value {
-	v, descend := fn(ctx, v)
-	if !descend {
-		return v
-	}
-	return v.rewrite(ctx, fn)
-}
-
-func (x *nodeRef) rewrite(ctx *context, fn rewriteFunc) value {
-	return x
-}
-
-func (x *closeIfStruct) rewrite(ctx *context, fn rewriteFunc) value {
-	v := rewrite(ctx, x.value, fn)
-	if v == x.value {
-		return x
-	}
-	return wrapFinalize(ctx, v)
-}
-
-func (x *structLit) rewrite(ctx *context, fn rewriteFunc) value {
-	emit := x.emit
-	if emit != nil {
-		emit = rewrite(ctx, x.emit, fn)
-	}
-	arcs := make(arcs, len(x.Arcs))
-	obj := &structLit{baseValue: x.baseValue, emit: emit, Arcs: arcs}
-	changed := emit == x.emit
-	for i, a := range x.Arcs {
-		a.setValue(rewrite(ctx, a.v, fn))
-		changed = changed || arcs[i].v != a.v
-		arcs[i] = a
-	}
-	if !changed {
-		return x
-	}
-	return obj
-}
-
-func (x *selectorExpr) rewrite(ctx *context, fn rewriteFunc) value {
-	v := rewrite(ctx, x.X, fn)
-	if v == x.X {
-		return x
-	}
-	return &selectorExpr{x.baseValue, v, x.Sel}
-}
-
-func (x *indexExpr) rewrite(ctx *context, fn rewriteFunc) value {
-	v := rewrite(ctx, x.X, fn)
-	index := rewrite(ctx, x.Index, fn)
-	if v == x.X && index == x.Index {
-		return x
-	}
-	return &indexExpr{x.baseValue, v, index}
-}
-
-// Even more boring stuff below.
-
-func (x *builtin) rewrite(ctx *context, fn rewriteFunc) value     { return x }
-func (x *top) rewrite(ctx *context, fn rewriteFunc) value         { return x }
-func (x *bottom) rewrite(ctx *context, fn rewriteFunc) value      { return x }
-func (x *basicType) rewrite(ctx *context, fn rewriteFunc) value   { return x }
-func (x *nullLit) rewrite(ctx *context, fn rewriteFunc) value     { return x }
-func (x *boolLit) rewrite(ctx *context, fn rewriteFunc) value     { return x }
-func (x *stringLit) rewrite(ctx *context, fn rewriteFunc) value   { return x }
-func (x *bytesLit) rewrite(ctx *context, fn rewriteFunc) value    { return x }
-func (x *numLit) rewrite(ctx *context, fn rewriteFunc) value      { return x }
-func (x *durationLit) rewrite(ctx *context, fn rewriteFunc) value { return x }
-
-func (x *customValidator) rewrite(ctx *context, fn rewriteFunc) value {
-	args := make([]evaluated, len(x.Args))
-	changed := false
-	for i, a := range x.Args {
-		v := rewrite(ctx, a, fn)
-		args[i] = v.(evaluated)
-		changed = changed || v != a
-	}
-	if !changed {
-		return x
-	}
-	return &customValidator{baseValue: x.baseValue, Args: args, Builtin: x.Builtin}
-}
-
-func (x *bound) rewrite(ctx *context, fn rewriteFunc) value {
-	v := rewrite(ctx, x.Expr, fn)
-	if v == x.Expr {
-		return x
-	}
-	return newBound(ctx, x.baseValue, x.Op, x.k, v)
-}
-
-func (x *interpolation) rewrite(ctx *context, fn rewriteFunc) value {
-	parts := make([]value, len(x.Parts))
-	changed := false
-	for i, p := range x.Parts {
-		parts[i] = rewrite(ctx, p, fn)
-		changed = changed || parts[i] != p
-	}
-	if !changed {
-		return x
-	}
-	return &interpolation{x.baseValue, x.K, parts}
-}
-
-func (x *list) rewrite(ctx *context, fn rewriteFunc) value {
-	elem := rewrite(ctx, x.elem, fn).(*structLit)
-	typ := rewrite(ctx, x.typ, fn)
-	len := rewrite(ctx, x.len, fn)
-	if elem == x.elem && typ == x.typ && len == x.len {
-		return x
-	}
-	return &list{x.baseValue, elem, typ, len}
-}
-
-func (x *sliceExpr) rewrite(ctx *context, fn rewriteFunc) value {
-	v := rewrite(ctx, x.X, fn)
-	var lo, hi value
-	if x.Lo != nil {
-		lo = rewrite(ctx, x.Lo, fn)
-	}
-	if x.Hi != nil {
-		hi = rewrite(ctx, x.Hi, fn)
-	}
-	if v == x.X && lo == x.Lo && hi == x.Hi {
-		return x
-	}
-	return &sliceExpr{x.baseValue, v, lo, hi}
-}
-
-func (x *callExpr) rewrite(ctx *context, fn rewriteFunc) value {
-	args := make([]value, len(x.Args))
-	changed := false
-	for i, a := range x.Args {
-		v := rewrite(ctx, a, fn)
-		args[i] = v
-		changed = changed || v != a
-	}
-	v := rewrite(ctx, x.Fun, fn)
-	if !changed && v == x.Fun {
-		return x
-	}
-	return &callExpr{baseValue: x.baseValue, Fun: v, Args: args}
-}
-
-func (x *lambdaExpr) rewrite(ctx *context, fn rewriteFunc) value {
-	arcs := make([]arc, len(x.arcs))
-	changed := false
-	for i, a := range x.arcs {
-		v := rewrite(ctx, a.v, fn)
-		arcs[i] = arc{Label: a.Label, v: v}
-		changed = changed || v != a.v
-	}
-	value := rewrite(ctx, x.value, fn)
-	if !changed && value == x.value {
-		return x
-	}
-	return &lambdaExpr{x.baseValue, &params{arcs}, value}
-}
-
-func (x *unaryExpr) rewrite(ctx *context, fn rewriteFunc) value {
-	v := rewrite(ctx, x.X, fn)
-	if v == x.X {
-		return x
-	}
-	return &unaryExpr{x.baseValue, x.Op, v}
-}
-
-func (x *binaryExpr) rewrite(ctx *context, fn rewriteFunc) value {
-	left := rewrite(ctx, x.X, fn)
-	right := rewrite(ctx, x.Y, fn)
-	if left == x.X && right == x.Y {
-		return x
-	}
-	return updateBin(ctx, &binaryExpr{x.baseValue, x.Op, left, right})
-}
-
-func (x *unification) rewrite(ctx *context, fn rewriteFunc) value {
-	values := make([]evaluated, len(x.Values))
-	changed := false
-	for i, v := range x.Values {
-		values[i] = rewrite(ctx, v, fn).(evaluated)
-		changed = changed || v != values[i]
-	}
-	if !changed {
-		return x
-	}
-	return &unification{x.baseValue, values}
-}
-
-func (x *disjunction) rewrite(ctx *context, fn rewriteFunc) value {
-	values := make([]dValue, len(x.Values))
-	changed := false
-	for i, d := range x.Values {
-		v := rewrite(ctx, d.Val, fn)
-		values[i] = dValue{v, d.Default}
-		changed = changed || v != d.Val
-	}
-	if !changed {
-		return x
-	}
-	return &disjunction{x.baseValue, values, x.errors, x.HasDefaults}
-}
-
-func (x *listComprehension) rewrite(ctx *context, fn rewriteFunc) value {
-	clauses := rewrite(ctx, x.clauses, fn).(yielder)
-	if clauses == x.clauses {
-		return x
-	}
-	return &listComprehension{x.baseValue, clauses}
-}
-
-func (x *structComprehension) rewrite(ctx *context, fn rewriteFunc) value {
-	clauses := rewrite(ctx, x.clauses, fn).(yielder)
-	if clauses == x.clauses {
-		return x
-	}
-	return &structComprehension{x.baseValue, clauses}
-}
-
-func (x *fieldComprehension) rewrite(ctx *context, fn rewriteFunc) value {
-	key := rewrite(ctx, x.key, fn)
-	val := rewrite(ctx, x.val, fn)
-	if key == x.key && val == x.val {
-		return x
-	}
-	return &fieldComprehension{x.baseValue, key, val, x.opt, x.def, x.doc, x.attrs}
-}
-
-func (x *yield) rewrite(ctx *context, fn rewriteFunc) value {
-	value := rewrite(ctx, x.value, fn)
-	if value == x.value {
-		return x
-	}
-	return &yield{x.baseValue, value}
-}
-
-func (x *guard) rewrite(ctx *context, fn rewriteFunc) value {
-	condition := rewrite(ctx, x.Condition, fn)
-	value := rewrite(ctx, x.Dst, fn).(yielder)
-	if condition == x.Condition && value == x.Dst {
-		return x
-	}
-	return &guard{x.baseValue, condition, value}
-}
-
-func (x *feed) rewrite(ctx *context, fn rewriteFunc) value {
-	source := rewrite(ctx, x.Src, fn)
-	lambda := rewrite(ctx, x.fn, fn).(*lambdaExpr)
-	if source == x.Src && lambda == x.fn {
-		return x
-	}
-	return &feed{x.baseValue, source, lambda}
-}
diff --git a/cue/rewrite_test.go b/cue/rewrite_test.go
deleted file mode 100644
index 4baa561..0000000
--- a/cue/rewrite_test.go
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright 2018 The 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
-
-type rewriteMode int
-
-const (
-	evalRaw rewriteMode = iota
-	evalSimplify
-	evalPartial // all but disjunctions
-	evalFull
-)
-
-// testResolve recursively
-func testResolve(ctx *context, v value, m rewriteMode) (result value) {
-	if m == evalRaw || v == nil {
-		return v
-	}
-	return rewriteRec(ctx, v, v.evalPartial(ctx), m)
-}
-
-func rewriteRec(ctx *context, raw value, eval evaluated, m rewriteMode) (result value) {
-	if m >= evalPartial {
-		if isIncomplete(eval) {
-			return raw
-		}
-		if m == evalFull {
-			eval = ctx.manifest(eval)
-			if isBottom(eval) {
-				return eval
-			}
-		}
-	}
-	switch x := eval.(type) {
-	case *structLit:
-		if m == evalFull {
-			e := ctx.manifest(x)
-			if isBottom(e) {
-				return e
-			}
-			x = e.(*structLit)
-		}
-		var err *bottom
-		x, err = x.expandFields(ctx)
-		if err != nil {
-			if isIncomplete(err) {
-				return raw
-			}
-			return err
-		}
-		arcs := make(arcs, len(x.Arcs))
-		for i, a := range x.Arcs {
-			v := x.at(ctx, i)
-			a.setValue(rewriteRec(ctx, a.v, v, m))
-			arcs[i] = a
-		}
-
-		t, e := x.optionals.rewrite(func(v value) value {
-			return rewriteRec(ctx, v, v.evalPartial(ctx), m)
-		})
-		if e != nil {
-			return err
-		}
-		emit := testResolve(ctx, x.emit, m)
-		obj := &structLit{x.baseValue, emit, t, x.closeStatus, x.comprehensions, arcs, nil}
-		return obj
-	case *list:
-		elm := rewriteRec(ctx, x.elem, x.elem, m).(*structLit)
-		len := rewriteRec(ctx, x.len, x.len.(evaluated), m)
-		typ := rewriteRec(ctx, x.typ, x.typ.evalPartial(ctx), m)
-		return &list{x.baseValue, elm, typ, len}
-	default:
-		return eval
-	}
-}
diff --git a/cue/strip.go b/cue/strip.go
deleted file mode 100644
index a806a3d..0000000
--- a/cue/strip.go
+++ /dev/null
@@ -1,129 +0,0 @@
-// Copyright 2018 The 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 (
-	"sort"
-)
-
-// A mergedValues type merges structs without unifying their templates.
-// It evaluates structs in parallel and then creates a new mergedValues
-// for each duplicate arc. The mergedValues do not reappear once there is
-// only a single value per arc.
-//
-// This is used to merge different instances which may have incompatible
-// specializations, but have disjuncts objects that may otherwise be shared
-// in the same namespace.
-type mergedValues struct {
-	baseValue
-	values []value
-}
-
-func (x *mergedValues) evalPartial(ctx *context) evaluated {
-	var structs []*structLit
-	for _, v := range x.values {
-		v = v.evalPartial(ctx)
-		o, ok := v.(*structLit)
-		if !ok {
-			v := x.values[0]
-			for _, w := range x.values[1:] {
-				v = mkBin(ctx, w.Pos(), opUnify, v, w)
-			}
-			return v.evalPartial(ctx)
-		}
-		o, err := o.expandFields(ctx)
-		if err != nil {
-			return err
-		}
-		structs = append(structs, o)
-	}
-
-	// Pre-expand the arcs so that we can discard the templates.
-	obj := &structLit{
-		baseValue: structs[0].baseValue,
-	}
-	var arcs arcs
-	for _, v := range structs {
-		for i := 0; i < len(v.Arcs); i++ {
-			w := v.iterAt(ctx, i)
-			arcs = append(arcs, w)
-		}
-	}
-	obj.Arcs = arcs
-	sort.Stable(obj)
-
-	values := []value{}
-	for _, v := range structs {
-		if v.emit != nil {
-			values = append(values, v.emit)
-		}
-	}
-	switch len(values) {
-	case 0:
-	case 1:
-		obj.emit = values[0]
-	default:
-		obj.emit = &mergedValues{values[0].base(), values}
-	}
-
-	// merge arcs
-	k := 0
-	for i := 0; i < len(arcs); k++ {
-		a := arcs[i]
-		// TODO: consider storing the evaluated value. This is a performance
-		// versus having more information tradeoff. It results in the same
-		// value.
-		values := []value{a.v}
-		for i++; i < len(arcs) && a.Label == arcs[i].Label; i++ {
-			values = append(values, arcs[i].v)
-			a.optional = a.optional && arcs[i].optional
-			var err evaluated
-			a.attrs, err = unifyAttrs(ctx, a.v, a.attrs, arcs[i].attrs)
-			if err != nil {
-				return err
-			}
-			a.docs = mergeDocs(a.docs, arcs[i].docs)
-		}
-		if len(values) == 1 {
-			arcs[k] = a
-			continue
-		}
-		a.Value = nil
-		a.v = &mergedValues{a.v.base(), values}
-		arcs[k] = a
-	}
-	obj.Arcs = arcs[:k]
-	return obj
-}
-
-func (x *mergedValues) Kind() kind {
-	k := x.values[0].Kind()
-	for _, v := range x.values {
-		k = unifyType(k, v.Kind())
-	}
-	return k
-}
-
-func (x *mergedValues) rewrite(ctx *context, fn rewriteFunc) value {
-	vs := make([]value, len(x.values))
-	for i, v := range x.values {
-		vs[i] = rewrite(ctx, v, fn)
-	}
-	return &mergedValues{x.baseValue, vs}
-}
-
-func (x *mergedValues) subsumesImpl(s *subsumer, v value) bool {
-	return false
-}
diff --git a/cue/subsume.go b/cue/subsume.go
deleted file mode 100644
index 6eca12d..0000000
--- a/cue/subsume.go
+++ /dev/null
@@ -1,662 +0,0 @@
-// Copyright 2018 The 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 (
-	"bytes"
-
-	"cuelang.org/go/cue/token"
-	"cuelang.org/go/internal"
-)
-
-// TODO: it probably makes sense to have only two modes left: subsuming a schema
-// and subsuming a final value.
-
-func subsumes(v, w Value, mode subsumeMode) error {
-	ctx := v.ctx()
-	gt := v.eval(ctx)
-	lt := w.eval(ctx)
-	s := subsumer{ctx: ctx, mode: mode}
-	if !s.subsumes(gt, lt) {
-		var b *bottom
-		src := binSrc(token.NoPos, opUnify, gt, lt)
-		if s.gt != nil && s.lt != nil {
-			src := binSrc(token.NoPos, opUnify, s.gt, s.lt)
-			var ok bool
-			if s.missing != 0 {
-				b = ctx.mkErr(src, "missing field %q", ctx.LabelStr(s.missing))
-			} else if b, ok = binOp(ctx, src, opUnify, s.gt, s.lt).(*bottom); !ok {
-				b = ctx.mkErr(src, "value not an instance")
-			}
-		}
-		if b == nil {
-			b = ctx.mkErr(src, "value not an instance")
-		} else {
-			b = ctx.mkErr(src, b, "%v", b)
-		}
-		err := w.toErr(b)
-		if s.inexact {
-			err = internal.DecorateError(internal.ErrInexact, err)
-		}
-		return err
-	}
-	return nil
-}
-
-type subsumer struct {
-	ctx  *context
-	mode subsumeMode
-
-	inexact bool // If true, the result could be a false negative.
-
-	// recorded values where an error occurred.
-	gt, lt  evaluated
-	missing label
-
-	// depth is used to work around undetected cycles.
-	// TODO(eval): remove once cycle detection is implemented.
-	depth int
-}
-
-type subsumeMode int
-
-const (
-	// subChoose ensures values are elected before doing a subsumption. This
-	// feature is on the conservative side and may result in false negatives.
-	subChoose subsumeMode = 1 << iota
-
-	// subNoOptional ignores optional fields for the purpose of subsumption.
-	// This option is predominantly intended for implementing equality checks.
-	// TODO: may be unnecessary now subFinal is available.
-	subNoOptional
-
-	// The subsumed value is final.
-	subFinal
-
-	// subSchema is used to compare schema. It should ignore closedness.
-	subSchema
-)
-
-// TODO: improve upon this highly inefficient implementation. There should
-// be a dedicated equal function once the dust settles.
-func equals(c *context, x, y value) bool {
-	s := subsumer{ctx: c, mode: subNoOptional}
-	return s.subsumes(x, y) && s.subsumes(y, x)
-}
-
-// subsumes checks gt subsumes lt. If any of the values contains references or
-// unevaluated expressions, structural subsumption is performed. This means
-// subsumption is conservative; it may return false when a guarantee for
-// subsumption could be proven. For concreted values it returns the exact
-// relation. It never returns a false positive.
-func (s *subsumer) subsumes(gt, lt value) (result bool) {
-	if s.depth > internal.MaxDepth {
-		return true
-	}
-	s.depth++
-	defer func() { s.depth-- }()
-
-	ctx := s.ctx
-	var v, w evaluated
-	if s.mode&subChoose == 0 {
-		v = gt.evalPartial(ctx)
-		w = lt.evalPartial(ctx)
-	} else {
-		v = ctx.manifest(gt)
-		w = ctx.manifest(lt)
-	}
-	if !isIncomplete(v) && !isIncomplete(w) {
-		gt = v
-		lt = w
-	}
-	a := gt.Kind()
-	b := lt.Kind()
-	switch {
-	case b == bottomKind:
-		return true
-	case b&^(a&b) != 0:
-		// a does not have strictly more bits. This implies any ground kind
-		// subsuming a non-ground type.
-		goto exit
-		// TODO: consider not supporting references.
-		// case (a|b)&(referenceKind) != 0:
-		// 	// no resolution if references are in play.
-		// 	return false, false
-	}
-	switch lt := lt.(type) {
-	case *unification:
-		if _, ok := gt.(*unification); !ok {
-			for _, x := range lt.Values {
-				if s.subsumes(gt, x) {
-					return true
-				}
-			}
-			goto exit
-		}
-
-	case *disjunction:
-		if _, ok := gt.(*disjunction); !ok {
-			for _, x := range lt.Values {
-				if !s.subsumes(gt, x.Val) {
-					return false
-				}
-			}
-			return true
-		}
-	}
-
-	result = gt.subsumesImpl(s, lt)
-exit:
-	if !result && s.gt == nil && s.lt == nil {
-		s.gt = v
-		s.lt = w
-	}
-	return result
-}
-
-func (x *structLit) subsumesImpl(s *subsumer, v value) bool {
-	ctx := s.ctx
-	ignoreOptional := s.mode&subNoOptional != 0
-	if o, ok := v.(*structLit); ok {
-		if x.optionals != nil && !ignoreOptional {
-			if s.mode&subFinal == 0 {
-				// TODO: also cross-validate optional fields in the schema case.
-				s.inexact = true
-				return false
-			}
-			for _, b := range o.Arcs {
-				if b.optional || b.definition {
-					continue
-				}
-				name := ctx.LabelStr(b.Label)
-				arg := &stringLit{x.baseValue, name, nil}
-				u, _ := x.optionals.constraint(ctx, arg)
-				if u != nil && !s.subsumes(u, b.v) {
-					return false
-				}
-			}
-		}
-		if len(x.comprehensions) > 0 {
-			s.inexact = true
-			return false
-		}
-		if x.emit != nil {
-			if o.emit == nil || !s.subsumes(x.emit, o.emit) {
-				return false
-			}
-		}
-
-		xClosed := x.closeStatus.shouldClose() && s.mode&subSchema == 0
-		oClosed := o.closeStatus.shouldClose() && s.mode&subSchema == 0
-
-		// all arcs in n must exist in v and its values must subsume.
-		for _, a := range x.Arcs {
-			if a.optional && ignoreOptional {
-				continue
-			}
-			b := o.Lookup(ctx, a.Label)
-			if !a.optional && b.optional {
-				return false
-			} else if b.val() == nil {
-				if a.definition && s.mode&subFinal != 0 {
-					continue
-				}
-				// if o is closed, the field is implicitly defined as _|_ and
-				// thus subsumed. Technically, this is even true if a is not
-				// optional, but in that case it means that o is invalid, so
-				// return false regardless
-				if a.optional && (oClosed || s.mode&subFinal != 0) {
-					continue
-				}
-				// If field a is optional and has value top, neither the
-				// omission of the field nor the field defined with any value
-				// may cause unification to fail.
-				if a.optional && isTop(a.v) {
-					continue
-				}
-				s.missing = a.Label
-				s.gt = a.val()
-				s.lt = o
-				return false
-			} else if a.definition != b.definition {
-				return false
-			} else if !s.subsumes(a.v, b.val()) {
-				return false
-			}
-		}
-		// For closed structs, all arcs in b must exist in a.
-		if xClosed {
-			if !ignoreOptional && !oClosed && s.mode&subFinal == 0 {
-				return false
-			}
-			ignoreOptional = ignoreOptional || s.mode&subFinal != 0
-			for _, b := range o.Arcs {
-				if ignoreOptional && b.optional {
-					continue
-				}
-				a := x.Lookup(ctx, b.Label)
-				if a.val() == nil {
-					name := ctx.LabelStr(b.Label)
-					arg := &stringLit{x.baseValue, name, nil}
-					u, _ := x.optionals.constraint(ctx, arg)
-					if u == nil { // subsumption already checked
-						s.lt = b.val()
-						return false
-					}
-				}
-			}
-		}
-	}
-	return !isBottom(v)
-}
-
-func (*top) subsumesImpl(s *subsumer, v value) bool {
-	return true
-}
-
-func (x *bottom) subsumesImpl(s *subsumer, v value) bool {
-	// never called.
-	return v.Kind() == bottomKind
-}
-
-func (x *basicType) subsumesImpl(s *subsumer, v value) bool {
-	return true
-}
-
-func (x *bound) subsumesImpl(s *subsumer, v value) bool {
-	ctx := s.ctx
-	if isBottom(v) {
-		return true
-	}
-	kx := x.Expr.Kind()
-	if !kx.isDone() || !kx.isGround() {
-		return false
-	}
-
-	switch y := v.(type) {
-	case *bound:
-		if ky := y.Expr.Kind(); ky.isDone() && ky.isGround() {
-			if (kx&ky)&^kx != 0 {
-				return false
-			}
-			// x subsumes y if
-			// x: >= a, y: >= b ==> a <= b
-			// x: >= a, y: >  b ==> a <= b
-			// x: >  a, y: >  b ==> a <= b
-			// x: >  a, y: >= b ==> a < b
-			//
-			// x: <= a, y: <= b ==> a >= b
-			//
-			// x: != a, y: != b ==> a != b
-			//
-			// false if types or op direction doesn't match
-
-			xv := x.Expr.(evaluated)
-			yv := y.Expr.(evaluated)
-			switch x.Op {
-			case opGtr:
-				if y.Op == opGeq {
-					return test(ctx, x, opLss, xv, yv)
-				}
-				fallthrough
-			case opGeq:
-				if y.Op == opGtr || y.Op == opGeq {
-					return test(ctx, x, opLeq, xv, yv)
-				}
-			case opLss:
-				if y.Op == opLeq {
-					return test(ctx, x, opGtr, xv, yv)
-				}
-				fallthrough
-			case opLeq:
-				if y.Op == opLss || y.Op == opLeq {
-					return test(ctx, x, opGeq, xv, yv)
-				}
-			case opNeq:
-				switch y.Op {
-				case opNeq:
-					return test(ctx, x, opEql, xv, yv)
-				case opGeq:
-					return test(ctx, x, opLss, xv, yv)
-				case opGtr:
-					return test(ctx, x, opLeq, xv, yv)
-				case opLss:
-					return test(ctx, x, opGeq, xv, yv)
-				case opLeq:
-					return test(ctx, x, opGtr, xv, yv)
-				}
-
-			case opMat, opNMat:
-				// these are just approximations
-				if y.Op == x.Op {
-					return test(ctx, x, opEql, xv, yv)
-				}
-
-			default:
-				// opNeq already handled above.
-				panic("cue: undefined bound mode")
-			}
-		}
-		// structural equivalence
-		return false
-
-	case *numLit, *stringLit, *durationLit, *boolLit:
-		return test(ctx, x, x.Op, y.(evaluated), x.Expr.(evaluated))
-	}
-	return false
-}
-
-func (x *nullLit) subsumesImpl(s *subsumer, v value) bool {
-	return true
-}
-
-func (x *boolLit) subsumesImpl(s *subsumer, v value) bool {
-	return x.B == v.(*boolLit).B
-}
-
-func (x *stringLit) subsumesImpl(s *subsumer, v value) bool {
-	return x.Str == v.(*stringLit).Str
-}
-
-func (x *bytesLit) subsumesImpl(s *subsumer, v value) bool {
-	return bytes.Equal(x.B, v.(*bytesLit).B)
-}
-
-func (x *numLit) subsumesImpl(s *subsumer, v value) bool {
-	b := v.(*numLit)
-	return x.X.Cmp(&b.X) == 0
-}
-
-func (x *durationLit) subsumesImpl(s *subsumer, v value) bool {
-	return x.d == v.(*durationLit).d
-}
-
-func (x *list) subsumesImpl(s *subsumer, v value) bool {
-	switch y := v.(type) {
-	case *list:
-		if !s.subsumes(x.len, y.len) {
-			return false
-		}
-		// TODO: need to handle case where len(x.elem) > len(y.elem) explicitly
-		// if we introduce cap().
-		if !s.subsumes(x.elem, y.elem) {
-			return false
-		}
-		// TODO: assuming continuous indices, use merge sort if we allow
-		// sparse arrays.
-		for _, a := range y.elem.Arcs[len(x.elem.Arcs):] {
-			if !s.subsumes(x.typ, a.v) {
-				return false
-			}
-		}
-		if y.isOpen() { // implies from first check that x.IsOpen.
-			return s.subsumes(x.typ, y.typ)
-		}
-		return true
-	}
-	return isBottom(v)
-}
-
-func (x *params) subsumes(s *subsumer, y *params) bool {
-	// structural equivalence
-	// TODO: make agnostic to argument names.
-	if len(y.arcs) != len(x.arcs) {
-		return false
-	}
-	for i, a := range x.arcs {
-		if !s.subsumes(a.v, y.arcs[i].v) {
-			return false
-		}
-	}
-	return true
-}
-
-func (x *lambdaExpr) subsumesImpl(s *subsumer, v value) bool {
-	// structural equivalence
-	if y, ok := v.(*lambdaExpr); ok {
-		return x.params.subsumes(s, y.params) &&
-			s.subsumes(x.value, y.value)
-	}
-	return isBottom(v)
-}
-
-func (x *unification) subsumesImpl(s *subsumer, v value) bool {
-	if y, ok := v.(*unification); ok {
-		// A unification subsumes another unification if for all values a in x
-		// there is a value b in y such that a subsumes b.
-		//
-		// This assumes overlapping ranges in disjunctions are merged.If this is
-		// not the case, subsumes will return a false negative, which is
-		// allowed.
-	outer:
-		for _, vx := range x.Values {
-			for _, vy := range y.Values {
-				if s.subsumes(vx, vy) {
-					continue outer
-				}
-			}
-			// TODO: should this be marked as inexact?
-			return false
-		}
-		return true
-	}
-	subsumed := true
-	for _, vx := range x.Values {
-		subsumed = subsumed && s.subsumes(vx, v)
-	}
-	return subsumed
-}
-
-// subsumes for disjunction is logically precise. However, just like with
-// structural subsumption, it should not have to be called after evaluation.
-func (x *disjunction) subsumesImpl(s *subsumer, v value) bool {
-	// A disjunction subsumes another disjunction if all values of v are
-	// subsumed by any of the values of x, and default values in v are subsumed
-	// by the default values of x.
-	//
-	// This assumes that overlapping ranges in x are merged. If this is not the
-	// case, subsumes will return a false negative, which is allowed.
-	if d, ok := v.(*disjunction); ok {
-		// at least one value in x should subsume each value in d.
-	outer:
-		for _, vd := range d.Values {
-			// v is subsumed if any value in x subsumes v.
-			for _, vx := range x.Values {
-				if (vx.Default || !vd.Default) && s.subsumes(vx.Val, vd.Val) {
-					continue outer
-				}
-			}
-			return false
-		}
-		return true
-	}
-	// v is subsumed if any value in x subsumes v.
-	for _, vx := range x.Values {
-		if s.subsumes(vx.Val, v) {
-			return true
-		}
-	}
-	// TODO: should this be marked as inexact?
-	return false
-}
-
-// Structural subsumption operations. Should never have to be called after
-// evaluation.
-
-// structural equivalence
-func (x *nodeRef) subsumesImpl(s *subsumer, v value) bool {
-	if r, ok := v.(*nodeRef); ok {
-		return x.node == r.node
-	}
-	return isBottom(v)
-}
-
-// structural equivalence
-func (x *selectorExpr) subsumesImpl(s *subsumer, v value) bool {
-	if r, ok := v.(*selectorExpr); ok {
-		return x.Sel == r.Sel && s.subsumes(x.X, r.X) // subChoose
-	}
-	return isBottom(v)
-}
-
-func (x *interpolation) subsumesImpl(s *subsumer, v value) bool {
-	switch v := v.(type) {
-	case *stringLit:
-		// Be conservative if not ground.
-		s.inexact = true
-		return false
-
-	case *interpolation:
-		// structural equivalence
-		if len(x.Parts) != len(v.Parts) {
-			return false
-		}
-		for i, p := range x.Parts {
-			if !s.subsumes(p, v.Parts[i]) {
-				return false
-			}
-		}
-		return true
-	}
-	return false
-}
-
-// structural equivalence
-func (x *indexExpr) subsumesImpl(s *subsumer, v value) bool {
-	// TODO: what does it mean to subsume if the index value is not known?
-	if r, ok := v.(*indexExpr); ok {
-		// TODO: could be narrowed down if we know the exact value of the index
-		// and referenced value.
-		return s.subsumes(x.X, r.X) && s.subsumes(x.Index, r.Index)
-	}
-	return isBottom(v)
-}
-
-// structural equivalence
-func (x *sliceExpr) subsumesImpl(s *subsumer, v value) bool {
-	// TODO: what does it mean to subsume if the index value is not known?
-	if r, ok := v.(*sliceExpr); ok {
-		// TODO: could be narrowed down if we know the exact value of the index
-		// and referenced value.
-		return s.subsumes(x.X, r.X) &&
-			s.subsumes(x.Lo, r.Lo) &&
-			s.subsumes(x.Hi, r.Hi)
-	}
-	return isBottom(v)
-}
-
-// structural equivalence
-func (x *customValidator) subsumesImpl(s *subsumer, v value) bool {
-	y, ok := v.(*customValidator)
-	if !ok {
-		return isBottom(v)
-	}
-	if x.Builtin != y.Builtin {
-		return false
-	}
-	for i, v := range x.Args {
-		if !s.subsumes(v, y.Args[i]) {
-			return false
-		}
-	}
-	return true
-}
-
-// structural equivalence
-func (x *callExpr) subsumesImpl(s *subsumer, v value) bool {
-	if c, ok := v.(*callExpr); ok {
-		if len(x.Args) != len(c.Args) {
-			return false
-		}
-		for i, a := range x.Args {
-			if !s.subsumes(a, c.Args[i]) {
-				return false
-			}
-		}
-		return s.subsumes(x.Fun, c.Fun)
-	}
-	return isBottom(v)
-}
-
-// structural equivalence
-func (x *unaryExpr) subsumesImpl(s *subsumer, v value) bool {
-	if b, ok := v.(*unaryExpr); ok {
-		return x.Op == b.Op && s.subsumes(x.X, b.X)
-	}
-	return isBottom(v)
-}
-
-// structural equivalence
-func (x *binaryExpr) subsumesImpl(s *subsumer, v value) bool {
-	if b, ok := v.(*binaryExpr); ok {
-		return x.Op == b.Op &&
-			s.subsumes(x.X, b.X) &&
-			s.subsumes(x.Y, b.Y)
-	}
-	return isBottom(v)
-}
-
-// structural equivalence
-func (x *listComprehension) subsumesImpl(s *subsumer, v value) bool {
-	if b, ok := v.(*listComprehension); ok {
-		return s.subsumes(x.clauses, b.clauses)
-	}
-	return isBottom(v)
-}
-
-// structural equivalence
-func (x *structComprehension) subsumesImpl(s *subsumer, v value) bool {
-	if b, ok := v.(*structComprehension); ok {
-		return s.subsumes(x.clauses, b.clauses)
-	}
-	return isBottom(v)
-}
-
-// structural equivalence
-func (x *fieldComprehension) subsumesImpl(s *subsumer, v value) bool {
-	if b, ok := v.(*fieldComprehension); ok {
-		return s.subsumes(x.key, b.key) &&
-			s.subsumes(x.val, b.val) &&
-			!x.opt && b.opt &&
-			x.def == b.def
-	}
-	return isBottom(v)
-}
-
-// structural equivalence
-func (x *yield) subsumesImpl(s *subsumer, v value) bool {
-	if b, ok := v.(*yield); ok {
-		return s.subsumes(x.value, b.value)
-	}
-	return isBottom(v)
-}
-
-// structural equivalence
-func (x *feed) subsumesImpl(s *subsumer, v value) bool {
-	if b, ok := v.(*feed); ok {
-		return s.subsumes(x.Src, b.Src) &&
-			s.subsumes(x.fn, b.fn)
-	}
-	return isBottom(v)
-}
-
-// structural equivalence
-func (x *guard) subsumesImpl(s *subsumer, v value) bool {
-	if b, ok := v.(*guard); ok {
-		return s.subsumes(x.Condition, b.Condition) &&
-			s.subsumes(x.Dst, b.Dst)
-	}
-	return isBottom(v)
-}
diff --git a/cue/subsume_test.go b/cue/subsume_test.go
deleted file mode 100644
index 0f6cd01..0000000
--- a/cue/subsume_test.go
+++ /dev/null
@@ -1,476 +0,0 @@
-// Copyright 2018 The 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 (
-	"regexp"
-	"strconv"
-	"strings"
-	"testing"
-)
-
-func TestSubsume(t *testing.T) {
-	// Do not inline: the named struct is used as a marker in
-	// testdata/gen.go.
-	type subsumeTest struct {
-		// the result of b ⊑ a, where a and b are defined in "in"
-		subsumes bool
-		in       string
-		mode     subsumeMode
-	}
-	testCases := []subsumeTest{
-		// Top subsumes everything
-		0: {subsumes: true, in: `a: _, b: _ `},
-		1: {subsumes: true, in: `a: _, b: null `},
-		2: {subsumes: true, in: `a: _, b: int `},
-		3: {subsumes: true, in: `a: _, b: 1 `},
-		4: {subsumes: true, in: `a: _, b: float `},
-		5: {subsumes: true, in: `a: _, b: "s" `},
-		6: {subsumes: true, in: `a: _, b: {} `},
-		7: {subsumes: true, in: `a: _, b: []`},
-		8: {subsumes: true, in: `a: _, b: _|_ `},
-
-		// Nothing besides top subsumed top
-		9:  {subsumes: false, in: `a: null,    b: _`},
-		10: {subsumes: false, in: `a: int, b: _`},
-		11: {subsumes: false, in: `a: 1,       b: _`},
-		12: {subsumes: false, in: `a: float, b: _`},
-		13: {subsumes: false, in: `a: "s",     b: _`},
-		14: {subsumes: false, in: `a: {},      b: _`},
-		15: {subsumes: false, in: `a: [],      b: _`},
-		16: {subsumes: false, in: `a: _|_ ,      b: _`},
-
-		// Bottom subsumes nothing except bottom itself.
-		17: {subsumes: false, in: `a: _|_, b: null `},
-		18: {subsumes: false, in: `a: _|_, b: int `},
-		19: {subsumes: false, in: `a: _|_, b: 1 `},
-		20: {subsumes: false, in: `a: _|_, b: float `},
-		21: {subsumes: false, in: `a: _|_, b: "s" `},
-		22: {subsumes: false, in: `a: _|_, b: {} `},
-		23: {subsumes: false, in: `a: _|_, b: [] `},
-		24: {subsumes: true, in: ` a: _|_, b: _|_ `},
-
-		// All values subsume bottom
-		25: {subsumes: true, in: `a: null,    b: _|_`},
-		26: {subsumes: true, in: `a: int, b: _|_`},
-		27: {subsumes: true, in: `a: 1,       b: _|_`},
-		28: {subsumes: true, in: `a: float, b: _|_`},
-		29: {subsumes: true, in: `a: "s",     b: _|_`},
-		30: {subsumes: true, in: `a: {},      b: _|_`},
-		31: {subsumes: true, in: `a: [],      b: _|_`},
-		32: {subsumes: true, in: `a: true,    b: _|_`},
-		33: {subsumes: true, in: `a: _|_,       b: _|_`},
-
-		// null subsumes only null
-		34: {subsumes: true, in: ` a: null, b: null `},
-		35: {subsumes: false, in: `a: null, b: 1 `},
-		36: {subsumes: false, in: `a: 1,    b: null `},
-
-		37: {subsumes: true, in: ` a: true, b: true `},
-		38: {subsumes: false, in: `a: true, b: false `},
-
-		39: {subsumes: true, in: ` a: "a",    b: "a" `},
-		40: {subsumes: false, in: `a: "a",    b: "b" `},
-		41: {subsumes: true, in: ` a: string, b: "a" `},
-		42: {subsumes: false, in: `a: "a",    b: string `},
-
-		// Number typing (TODO)
-		//
-		// In principle, an "int" cannot assume an untyped "1", as "1" may
-		// still by typed as a float. They are two different type aspects. When
-		// considering, keep in mind that:
-		//   Key requirement: if A subsumes B, it must not be possible to
-		//   specialize B further such that A does not subsume B. HOWEVER,
-		//   The type conversion rules for conversion are INDEPENDENT of the
-		//   rules for subsumption!
-		// Consider:
-		// - only having number, but allowing user-defined types.
-		//   Subsumption would still work the same, but it may be somewhat
-		//   less weird.
-		// - making 1 always an int and 1.0 always a float.
-		//   - the int type would subsume any derived type from int.
-		//   - arithmetic would allow implicit conversions, but maybe not for
-		//     types.
-		//
-		// TODO: irrational numbers: allow untyped, but require explicit
-		//       trunking when assigning to float.
-		//
-		// a: number; cue.IsInteger(a) && a > 0
-		// t: (x) -> number; cue.IsInteger(a) && a > 0
-		// type x number: cue.IsInteger(x) && x > 0
-		// x: typeOf(number); cue.IsInteger(x) && x > 0
-		43: {subsumes: true, in: `a: 1, b: 1 `},
-		44: {subsumes: true, in: `a: 1.0, b: 1.0 `},
-		45: {subsumes: true, in: `a: 3.0, b: 3.0 `},
-		46: {subsumes: false, in: `a: 1.0, b: 1 `},
-		47: {subsumes: false, in: `a: 1, b: 1.0 `},
-		48: {subsumes: false, in: `a: 3, b: 3.0`},
-		49: {subsumes: true, in: `a: int, b: 1`},
-		50: {subsumes: true, in: `a: int, b: int & 1`},
-		51: {subsumes: true, in: `a: float, b: 1.0`},
-		52: {subsumes: false, in: `a: float, b: 1`},
-		53: {subsumes: false, in: `a: int, b: 1.0`},
-		54: {subsumes: true, in: `a: int, b: int`},
-		55: {subsumes: true, in: `a: number, b: int`},
-
-		// Structs
-		64: {subsumes: true, in: `a: {}, b: {}`},
-		65: {subsumes: true, in: `a: {}, b: {a: 1}`},
-		66: {subsumes: true, in: `a: {a:1}, b: {a:1, b:1}`},
-		67: {subsumes: true, in: `a: {s: { a:1} }, b: { s: { a:1, b:2 }}`},
-		68: {subsumes: true, in: `a: {}, b: {}`},
-		// TODO: allow subsumption of unevaluated values?
-		// ref not yet evaluated and not structurally equivalent
-		69: {subsumes: true, in: `a: {}, b: {} & c, c: {}`},
-
-		70: {subsumes: false, in: `a: {a:1}, b: {}`},
-		71: {subsumes: false, in: `a: {a:1, b:1}, b: {a:1}`},
-		72: {subsumes: false, in: `a: {s: { a:1} }, b: { s: {}}`},
-
-		84: {subsumes: true, in: `a: 1 | 2, b: 2 | 1`},
-		85: {subsumes: true, in: `a: 1 | 2, b: 1 | 2`},
-
-		86: {subsumes: true, in: `a: number, b: 2 | 1`},
-		87: {subsumes: true, in: `a: number, b: 2 | 1`},
-		88: {subsumes: false, in: `a: int, b: 1 | 2 | 3.1`},
-
-		89: {subsumes: true, in: `a: float | number, b: 1 | 2 | 3.1`},
-
-		90: {subsumes: false, in: `a: int, b: 1 | 2 | 3.1`},
-		91: {subsumes: true, in: `a: 1 | 2, b: 1`},
-		92: {subsumes: true, in: `a: 1 | 2, b: 2`},
-		93: {subsumes: false, in: `a: 1 | 2, b: 3`},
-
-		// Structural
-		94: {subsumes: false, in: `a: int + int, b: int`},
-		95: {subsumes: true, in: `a: int + int, b: int + int`},
-		96: {subsumes: true, in: `a: int + number, b: int + int`},
-		97: {subsumes: true, in: `a: number + number, b: int + int`},
-		// TODO: allow subsumption of unevaluated values?
-		// TODO: may be false if we allow arithmetic on incomplete values.
-		98: {subsumes: false, in: `a: int + int, b: int * int`},
-
-		// TODO: allow subsumption of unevaluated values?
-		// true because both evaluate to bottom
-		99:  {subsumes: true, in: `a: !int, b: !int`},
-		100: {subsumes: true, in: `a: !number, b: !int`},
-		101: {subsumes: true, in: `a: !int, b: !number`},
-
-		// TODO: allow subsumption of unevaluated values?
-		102: {subsumes: false, in: `a: int + int, b: !number`},
-		// TODO: allow subsumption of unevaluated values?
-		103: {subsumes: false, in: `a: !bool, b: bool`},
-		104: {subsumes: true, in: `a: !bool, b: !bool`},
-
-		// Call
-		113: {subsumes: true, in: `
-			a: fn()
-			b: fn()
-			fn: _`,
-		},
-		114: {subsumes: false, in: `
-			a: fn(),
-			b: fn(1)
-			fn: _`,
-		},
-		115: {subsumes: true, in: `
-			a: fn(2)
-			b: fn(2)
-			fn: _`,
-		},
-		116: {subsumes: true, in: `
-			a: fn(number)
-			b: fn(2)
-			fn: _`,
-		},
-		117: {subsumes: false, in: `
-			a: fn(2)
-			b: fn(number)
-			fn: _`,
-		},
-
-		// TODO: allow subsumption of unevaluated values?
-		// TODO: okay, but why false?
-		121: {subsumes: false, in: `a: c + d, b: int, c: int, d: int`},
-		// TODO: allow subsumption of unevaluated values?
-		122: {subsumes: true, in: `a: {}, b: c & {}, c: {}`},
-
-		// references
-		123: {subsumes: true, in: `a: c, b: c, c: {}`},
-		// TODO: allow subsumption of unevaluated values?
-		124: {subsumes: true, in: `a: c, b: d, c: {}, d: {}`},
-		125: {subsumes: false, in: `a: c, b: d, c: {a:1}, d: {}`},
-		// TODO: allow subsumption of unevaluated values?
-		126: {subsumes: true, in: `a: c, b: d, c: {a:1}, d: c & {b:1}`},
-		127: {subsumes: false, in: `a: d, b: c, c: {a:1}, d: c & {b:1}`},
-		128: {subsumes: false, in: `a: c.c, b: c, c: { d: number}`},
-
-		// type unification catches a reference error.
-		129: {subsumes: false, in: `a: c, b: d, c: 1, d: 2`},
-
-		130: {subsumes: true, in: ` a: [1][1], b: [1][1]`},
-		131: {subsumes: true, in: ` a: [1][number], b: [1][1]`},
-		132: {subsumes: true, in: ` a: [number][1], b: [1][1]`},
-		133: {subsumes: true, in: ` a: [number][number], b: [1][1]`},
-		134: {subsumes: false, in: ` a: [1][0], b: [1][number]`},
-		135: {subsumes: false, in: ` a: [1][0], b: [number][0]`},
-		136: {subsumes: true, in: ` a: [number][number], b: [1][number]`},
-		137: {subsumes: true, in: ` a: [number][number], b: [number][1]`},
-		// purely structural:
-		138: {subsumes: false, in: ` a: [number][number], b: number`},
-
-		// interpolations
-		139: {subsumes: true, in: ` a: "\(d)", b: "\(d)", d: _`},
-		// TODO: allow subsumption of unevaluated values?
-		140: {subsumes: true, in: ` a: "\(d)", b: "\(e)", d: _, e: _`},
-
-		141: {subsumes: true, in: ` a: "\(string)", b: "\("foo")"`},
-		// TODO: allow subsumption of unevaluated values?
-		142: {subsumes: true, in: ` a: "\(string)", b: "\(d)", d: "foo"`},
-		143: {subsumes: true, in: ` a: "\("foo")", b: "\("foo")"`},
-		144: {subsumes: false, in: ` a: "\("foo")", b: "\(1) \(2)"`},
-
-		145: {subsumes: false, in: ` a: "s \(d) e", b: "s a e", d: _`},
-		146: {subsumes: false, in: ` a: "s \(d)m\(d) e", b: "s a e", d: _`},
-
-		147: {subsumes: true, in: ` a: 7080, b: *7080 | int`, mode: subChoose},
-
-		// Defaults
-		150: {subsumes: false, in: `a: number | *1, b: number | *2`},
-		151: {subsumes: true, in: `a: number | *2, b: number | *2`},
-		152: {subsumes: true, in: `a: int | *float, b: int | *2.0`},
-		153: {subsumes: false, in: `a: int | *2, b: int | *2.0`},
-		154: {subsumes: true, in: `a: number | *2 | *3, b: number | *2`},
-		155: {subsumes: true, in: `a: number, b: number | *2`},
-
-		// Bounds
-		170: {subsumes: true, in: `a: >=2, b: >=2`},
-		171: {subsumes: true, in: `a: >=1, b: >=2`},
-		172: {subsumes: true, in: `a: >0, b: >=2`},
-		173: {subsumes: true, in: `a: >1, b: >1`},
-		174: {subsumes: true, in: `a: >=1, b: >1`},
-		175: {subsumes: false, in: `a: >1, b: >=1`},
-		176: {subsumes: true, in: `a: >=1, b: >=1`},
-		177: {subsumes: true, in: `a: <1, b: <1`},
-		178: {subsumes: true, in: `a: <=1, b: <1`},
-		179: {subsumes: false, in: `a: <1, b: <=1`},
-		180: {subsumes: true, in: `a: <=1, b: <=1`},
-
-		181: {subsumes: true, in: `a: !=1, b: !=1`},
-		182: {subsumes: false, in: `a: !=1, b: !=2`},
-
-		183: {subsumes: false, in: `a: !=1, b: <=1`},
-		184: {subsumes: true, in: `a: !=1, b: <1`},
-		185: {subsumes: false, in: `a: !=1, b: >=1`},
-		186: {subsumes: true, in: `a: !=1, b: <1`},
-
-		187: {subsumes: true, in: `a: !=1, b: <=0`},
-		188: {subsumes: true, in: `a: !=1, b: >=2`},
-		189: {subsumes: true, in: `a: !=1, b: >1`},
-
-		195: {subsumes: false, in: `a: >=2, b: !=2`},
-		196: {subsumes: false, in: `a: >2, b: !=2`},
-		197: {subsumes: false, in: `a: <2, b: !=2`},
-		198: {subsumes: false, in: `a: <=2, b: !=2`},
-
-		200: {subsumes: true, in: `a: =~"foo", b: =~"foo"`},
-		201: {subsumes: false, in: `a: =~"foo", b: =~"bar"`},
-		202: {subsumes: false, in: `a: =~"foo1", b: =~"foo"`},
-
-		203: {subsumes: true, in: `a: !~"foo", b: !~"foo"`},
-		204: {subsumes: false, in: `a: !~"foo", b: !~"bar"`},
-		205: {subsumes: false, in: `a: !~"foo", b: !~"foo1"`},
-
-		// The following is could be true, but we will not go down the rabbit
-		// hold of trying to prove subsumption of regular expressions.
-		210: {subsumes: false, in: `a: =~"foo", b: =~"foo1"`},
-		211: {subsumes: false, in: `a: !~"foo1", b: !~"foo"`},
-
-		220: {subsumes: true, in: `a: <5, b: 4`},
-		221: {subsumes: false, in: `a: <5, b: 5`},
-		222: {subsumes: true, in: `a: <=5, b: 5`},
-		223: {subsumes: false, in: `a: <=5.0, b: 5.00000001`},
-		224: {subsumes: true, in: `a: >5, b: 6`},
-		225: {subsumes: false, in: `a: >5, b: 5`},
-		226: {subsumes: true, in: `a: >=5, b: 5`},
-		227: {subsumes: false, in: `a: >=5, b: 4`},
-		228: {subsumes: true, in: `a: !=5, b: 6`},
-		229: {subsumes: false, in: `a: !=5, b: 5`},
-		230: {subsumes: false, in: `a: !=5.0, b: 5.0`},
-		231: {subsumes: false, in: `a: !=5.0, b: 5`},
-
-		250: {subsumes: true, in: `a: =~ #"^\d{3}$"#, b: "123"`},
-		251: {subsumes: false, in: `a: =~ #"^\d{3}$"#, b: "1234"`},
-		252: {subsumes: true, in: `a: !~ #"^\d{3}$"#, b: "1234"`},
-		253: {subsumes: false, in: `a: !~ #"^\d{3}$"#, b: "123"`},
-
-		// Conjunctions
-		300: {subsumes: true, in: `a: >0, b: >=2 & <=100`},
-		301: {subsumes: false, in: `a: >0, b: >=0 & <=100`},
-
-		310: {subsumes: true, in: `a: >=0 & <=100, b: 10`},
-		311: {subsumes: true, in: `a: >=0 & <=100, b: >=0 & <=100`},
-		312: {subsumes: false, in: `a: !=2 & !=4, b: >3`},
-		313: {subsumes: true, in: `a: !=2 & !=4, b: >5`},
-
-		314: {subsumes: false, in: `a: >=0 & <=100, b: >=0 & <=150`},
-		315: {subsumes: true, in: `a: >=0 & <=150, b: >=0 & <=100`},
-
-		// Disjunctions
-		330: {subsumes: true, in: `a: >5, b: >10 | 8`},
-		331: {subsumes: false, in: `a: >8, b: >10 | 8`},
-
-		// Optional fields
-		// Optional fields defined constraints on fields that are not yet
-		// defined. So even if such a field is not part of the output, it
-		// influences the lattice structure.
-		// For a given A and B, where A and B unify and where A has an optional
-		// field that is not defined in B, the addition of an incompatible
-		// value of that field in B can cause A and B to no longer unify.
-		//
-		400: {subsumes: false, in: `a: {foo: 1}, b: {}`},
-		401: {subsumes: false, in: `a: {foo?: 1}, b: {}`},
-		402: {subsumes: true, in: `a: {}, b: {foo: 1}`},
-		403: {subsumes: true, in: `a: {}, b: {foo?: 1}`},
-
-		404: {subsumes: true, in: `a: {foo: 1}, b: {foo: 1}`},
-		405: {subsumes: true, in: `a: {foo?: 1}, b: {foo: 1}`},
-		406: {subsumes: true, in: `a: {foo?: 1}, b: {foo?: 1}`},
-		407: {subsumes: false, in: `a: {foo: 1}, b: {foo?: 1}`},
-
-		408: {subsumes: false, in: `a: {foo: 1}, b: {foo: 2}`},
-		409: {subsumes: false, in: `a: {foo?: 1}, b: {foo: 2}`},
-		410: {subsumes: false, in: `a: {foo?: 1}, b: {foo?: 2}`},
-		411: {subsumes: false, in: `a: {foo: 1}, b: {foo?: 2}`},
-
-		412: {subsumes: true, in: `a: {foo: number}, b: {foo: 2}`},
-		413: {subsumes: true, in: `a: {foo?: number}, b: {foo: 2}`},
-		414: {subsumes: true, in: `a: {foo?: number}, b: {foo?: 2}`},
-		415: {subsumes: false, in: `a: {foo: number}, b: {foo?: 2}`},
-
-		416: {subsumes: false, in: `a: {foo: 1}, b: {foo: number}`},
-		417: {subsumes: false, in: `a: {foo?: 1}, b: {foo: number}`},
-		418: {subsumes: false, in: `a: {foo?: 1}, b: {foo?: number}`},
-		419: {subsumes: false, in: `a: {foo: 1}, b: {foo?: number}`},
-
-		// The one exception of the rule: there is no value of foo that can be
-		// added to b which would cause the unification of a and b to fail.
-		// So an optional field with a value of top is equivalent to not
-		// defining one at all.
-		420: {subsumes: true, in: `a: {foo?: _}, b: {}`},
-
-		430: {subsumes: false, in: `a: {[_]: 4}, b: {[_]: int}`},
-		// TODO: handle optionals.
-		431: {subsumes: false, in: `a: {[_]: int}, b: {[_]: 2}`},
-
-		440: {subsumes: true, in: `a: {foo?: 1}, b: {}`, mode: subNoOptional},
-		441: {subsumes: true, in: `a: {}, b: {foo?: 1}`, mode: subNoOptional},
-		442: {subsumes: true, in: `a: {foo?: 1}, b: {foo: 1}`, mode: subNoOptional},
-		443: {subsumes: true, in: `a: {foo?: 1}, b: {foo?: 1}`, mode: subNoOptional},
-		444: {subsumes: false, in: `a: {foo: 1}, b: {foo?: 1}`, mode: subNoOptional},
-		445: {subsumes: true, in: `a: close({}), b: {foo?: 1}`, mode: subNoOptional},
-		446: {subsumes: true, in: `a: close({}), b: close({foo?: 1})`, mode: subNoOptional},
-		447: {subsumes: true, in: `a: {}, b: close({})`, mode: subNoOptional},
-		448: {subsumes: true, in: `a: {}, b: close({foo?: 1})`, mode: subNoOptional},
-
-		// Lists
-		506: {subsumes: true, in: `a: [], b: [] `},
-		507: {subsumes: true, in: `a: [1], b: [1] `},
-		508: {subsumes: false, in: `a: [1], b: [2] `},
-		509: {subsumes: false, in: `a: [1], b: [2, 3] `},
-		510: {subsumes: true, in: `a: [{b: string}], b: [{b: "foo"}] `},
-		511: {subsumes: true, in: `a: [...{b: string}], b: [{b: "foo"}] `},
-		512: {subsumes: false, in: `a: [{b: "foo"}], b: [{b: string}] `},
-		513: {subsumes: false, in: `a: [{b: string}], b: [{b: "foo"}, ...{b: "foo"}] `},
-		520: {subsumes: false, in: `a: [_, int, ...], b: [int, string, ...string] `},
-
-		// Closed structs.
-		600: {subsumes: false, in: `a: close({}), b: {a: 1}`},
-		601: {subsumes: false, in: `a: close({a: 1}), b: {a: 1}`},
-		602: {subsumes: false, in: `a: close({a: 1, b: 1}), b: {a: 1}`},
-		603: {subsumes: false, in: `a: {a: 1}, b: close({})`},
-		604: {subsumes: true, in: `a: {a: 1}, b: close({a: 1})`},
-		605: {subsumes: true, in: `a: {a: 1}, b: close({a: 1, b: 1})`},
-		606: {subsumes: true, in: `a: close({b?: 1}), b: close({b: 1})`},
-		607: {subsumes: false, in: `a: close({b: 1}), b: close({b?: 1})`},
-		608: {subsumes: true, in: `a: {}, b: close({})`},
-		609: {subsumes: true, in: `a: {}, b: close({foo?: 1})`},
-		610: {subsumes: true, in: `a: {foo?:1}, b: close({})`},
-
-		// Definitions are not regular fields.
-		630: {subsumes: false, in: `a: {#a: 1}, b: {a: 1}`},
-		631: {subsumes: false, in: `a: {a: 1}, b: {#a: 1}`},
-
-		// Subsuming final values.
-		700: {subsumes: true, in: `a: {[string]: 1}, b: {foo: 1}`, mode: subFinal},
-		701: {subsumes: true, in: `a: {[string]: int}, b: {foo: 1}`, mode: subFinal},
-		702: {subsumes: true, in: `a: {["foo"]: int}, b: {foo: 1}`, mode: subFinal},
-		703: {subsumes: false, in: `a: close({["foo"]: 1}), b: {bar: 1}`, mode: subFinal},
-		704: {subsumes: false, in: `a: {foo: 1}, b: {foo?: 1}`, mode: subFinal},
-		705: {subsumes: true, in: `a: close({}), b: {foo?: 1}`, mode: subFinal},
-		706: {subsumes: true, in: `a: close({}), b: close({foo?: 1})`, mode: subFinal},
-		707: {subsumes: true, in: `a: {}, b: close({})`, mode: subFinal},
-		708: {subsumes: false, in: `a: {[string]: 1}, b: {foo: 2}`, mode: subFinal},
-		709: {subsumes: true, in: `a: {}, b: close({foo?: 1})`, mode: subFinal},
-		710: {subsumes: false, in: `a: {foo: [...string]}, b: {}`, mode: subFinal},
-
-		// Schema values
-		800: {subsumes: true, in: `a: close({}), b: {foo: 1}`, mode: subSchema},
-		// TODO(eval): FIX
-		// 801: {subsumes: true, in: `a: {[string]: int}, b: {foo: 1}`, mode: subSchema},
-		804: {subsumes: false, in: `a: {foo: 1}, b: {foo?: 1}`, mode: subSchema},
-		805: {subsumes: true, in: `a: close({}), b: {foo?: 1}`, mode: subSchema},
-		806: {subsumes: true, in: `a: close({}), b: close({foo?: 1})`, mode: subSchema},
-		807: {subsumes: true, in: `a: {}, b: close({})`, mode: subSchema},
-		808: {subsumes: false, in: `a: {[string]: 1}, b: {foo: 2}`, mode: subSchema},
-		809: {subsumes: true, in: `a: {}, b: close({foo?: 1})`, mode: subSchema},
-	}
-
-	re := regexp.MustCompile(`a: (.*).*b: ([^\n]*)`)
-	for i, tc := range testCases {
-		if tc.in == "" {
-			continue
-		}
-		m := re.FindStringSubmatch(strings.Join(strings.Split(tc.in, "\n"), ""))
-		const cutset = "\n ,"
-		key := strings.Trim(m[1], cutset) + " ⊑ " + strings.Trim(m[2], cutset)
-
-		t.Run(strconv.Itoa(i)+"/"+key, func(t *testing.T) {
-			ctx, root := compileFile(t, tc.in)
-
-			// Use low-level lookup to avoid evaluation.
-			var a, b value
-			for _, arc := range root.Arcs {
-				switch arc.Label {
-				case ctx.StrLabel("a"):
-					a = arc.v
-				case ctx.StrLabel("b"):
-					b = arc.v
-				}
-			}
-			s := subsumer{ctx: ctx, mode: tc.mode}
-			got := s.subsumes(a, b)
-			if got != tc.subsumes {
-				t.Errorf("got %v; want %v (%v vs %v)", got, tc.subsumes, a.Kind(), b.Kind())
-			}
-		})
-	}
-}
-
-func TestTouchBottom(t *testing.T) {
-	// Just call this function to mark coverage. It is otherwise never called.
-	var x bottom
-	x.subsumesImpl(nil, &bottom{})
-}
diff --git a/cue/types.go b/cue/types.go
index a5deb07..3e5d0c2 100644
--- a/cue/types.go
+++ b/cue/types.go
@@ -27,10 +27,17 @@
 	"github.com/cockroachdb/apd/v2"
 
 	"cuelang.org/go/cue/ast"
+	"cuelang.org/go/cue/ast/astutil"
 	"cuelang.org/go/cue/errors"
+	"cuelang.org/go/cue/format"
 	"cuelang.org/go/cue/token"
 	"cuelang.org/go/internal"
 	"cuelang.org/go/internal/core/adt"
+	"cuelang.org/go/internal/core/convert"
+	"cuelang.org/go/internal/core/eval"
+	"cuelang.org/go/internal/core/export"
+	"cuelang.org/go/internal/core/subsume"
+	"cuelang.org/go/internal/core/validate"
 )
 
 // Kind determines the underlying type of a Value.
@@ -71,17 +78,17 @@
 	// NumberKind represents any kind of number.
 	NumberKind = IntKind | FloatKind
 
-	TopKind = Kind(adt.TopKind)
+	TopKind = adt.TopKind
 )
 
 // An structValue represents a JSON object.
 //
 // TODO: remove
 type structValue struct {
-	ctx  *context
-	path *valueData
-	obj  *structLit
-	Arcs arcs
+	ctx      *context
+	v        Value
+	obj      *adt.Vertex
+	features []adt.Feature
 }
 
 // Len reports the number of fields in this struct.
@@ -89,14 +96,28 @@
 	if o.obj == nil {
 		return 0
 	}
-	return len(o.Arcs)
+	return len(o.features)
 }
 
 // At reports the key and value of the ith field, i < o.Len().
 func (o *structValue) At(i int) (key string, v Value) {
-	a := o.Arcs[i]
-	v = newChildValue(o, i)
-	return o.ctx.LabelStr(a.Label), v
+	f := o.features[i]
+	return o.ctx.LabelStr(f), newChildValue(o, i)
+}
+
+func (o *structValue) at(i int) (v *adt.Vertex, isOpt bool) {
+	f := o.features[i]
+	arc := o.obj.Lookup(f)
+	if arc == nil {
+		arc = &adt.Vertex{
+			Parent: o.v.v,
+			Label:  f,
+		}
+		o.obj.MatchAndInsert(o.ctx.opCtx, arc)
+		arc.Finalize(o.ctx.opCtx)
+		isOpt = true
+	}
+	return arc, isOpt
 }
 
 // Lookup reports the field for the given key. The returned Value is invalid
@@ -106,7 +127,7 @@
 	i := 0
 	len := o.Len()
 	for ; i < len; i++ {
-		if o.Arcs[i].Label == f {
+		if o.features[i] == f {
 			break
 		}
 	}
@@ -114,8 +135,7 @@
 		// TODO: better message.
 		ctx := o.ctx
 		x := ctx.mkErr(o.obj, codeNotExist, "value %q not found", key)
-		v := x.evalPartial(ctx)
-		return Value{ctx.index, &valueData{o.path.parent, 0, arc{Label: o.path.Label, Value: v, v: x}}}
+		return newErrValue(o.v, x)
 	}
 	return newChildValue(o, i)
 }
@@ -190,25 +210,32 @@
 // An Iterator iterates over values.
 //
 type Iterator struct {
-	val  Value
-	ctx  *context
-	iter iterAtter
-	len  int
-	p    int
-	cur  Value
-	f    label
+	val   Value
+	ctx   *context
+	arcs  []field
+	p     int
+	cur   Value
+	f     label
+	isOpt bool
+}
+
+type field struct {
+	arc        *adt.Vertex
+	isOptional bool
 }
 
 // Next advances the iterator to the next value and reports whether there was
 // any. It must be called before the first call to Value or Key.
 func (i *Iterator) Next() bool {
-	if i.p >= i.len {
+	if i.p >= len(i.arcs) {
 		i.cur = Value{}
 		return false
 	}
-	arc := i.iter.iterAt(i.ctx, i.p)
-	i.cur = i.val.makeChild(i.ctx, uint32(i.p), arc)
-	i.f = arc.Label
+	f := i.arcs[i.p]
+	f.arc.Finalize(i.ctx.opCtx)
+	i.cur = makeValue(i.val.idx, f.arc)
+	i.f = f.arc.Label
+	i.isOpt = f.isOptional
 	i.p++
 	return true
 }
@@ -219,6 +246,10 @@
 	return i.cur
 }
 
+func (i *Iterator) Feature() adt.Feature {
+	return i.f
+}
+
 // Label reports the label of the value if i iterates over struct fields and
 // "" otherwise.
 func (i *Iterator) Label() string {
@@ -235,12 +266,12 @@
 
 // IsOptional reports if a field is optional.
 func (i *Iterator) IsOptional() bool {
-	return i.cur.v.arc.optional
+	return i.isOpt
 }
 
 // IsDefinition reports if a field is a definition.
 func (i *Iterator) IsDefinition() bool {
-	return i.cur.v.arc.definition
+	return i.f.IsDef()
 }
 
 // marshalJSON iterates over the list and generates JSON output. HasNext
@@ -266,10 +297,11 @@
 
 func (v Value) getNum(k kind) (*numLit, errors.Error) {
 	v, _ = v.Default()
-	if err := v.checkKind(v.ctx(), k); err != nil {
+	ctx := v.ctx()
+	if err := v.checkKind(ctx, k); err != nil {
 		return nil, v.toErr(err)
 	}
-	n, _ := v.v.Value.(*numLit)
+	n, _ := v.eval(ctx).(*numLit)
 	return n, nil
 }
 
@@ -491,183 +523,116 @@
 	return f, nil
 }
 
-type valueData struct {
-	parent *valueData
-	index  uint32
-	arc
-}
+func (v Value) appendPath(a []string) []string {
+	for _, f := range v.v.Path() {
+		switch f.Typ() {
+		case adt.IntLabel:
+			a = append(a, strconv.FormatInt(int64(f.Index()), 10))
 
-// path returns the path of the value.
-func (v *valueData) appendPath(a []string, idx *index) ([]string, kind) {
-	var k kind
-	if v.parent != nil {
-		a, k = v.parent.appendPath(a, idx)
-	}
-	switch k {
-	case listKind:
-		a = append(a, strconv.FormatInt(int64(v.index), 10))
-	case structKind:
-		label := idx.LabelStr(v.arc.Label)
-		if f := v.arc.Label; !f.IsDef() && !f.IsHidden() {
-			if !ast.IsValidIdent(label) {
-				label = strconv.Quote(label)
+		case adt.StringLabel:
+			label := v.idx.LabelStr(f)
+			if !f.IsDef() && !f.IsHidden() {
+				if !ast.IsValidIdent(label) {
+					label = strconv.Quote(label)
+				}
 			}
+			a = append(a, label)
+		default:
+			a = append(a, f.SelectorString(v.idx.Index))
 		}
-		a = append(a, label)
 	}
-	return a, v.arc.Value.Kind()
+	return a
 }
 
 // Value holds any value, which may be a Boolean, Error, List, Null, Number,
 // Struct, or String.
 type Value struct {
 	idx *index
-	v   *valueData
+	v   *adt.Vertex
 }
 
 func newErrValue(v Value, b *bottom) Value {
-	ctx := v.ctx()
-	p := v.v
-	if p == nil {
-		return newValueRoot(ctx, b)
+	node := &adt.Vertex{Value: b}
+	if v.v != nil {
+		node.Label = v.v.Label
+		node.Parent = v.v.Parent
 	}
-	return Value{
-		ctx.index,
-		&valueData{p.parent, p.index, arc{
-			Label: p.arc.Label,
-			Value: b,
-			v:     b,
-		}},
+	node.UpdateStatus(adt.Finalized)
+	node.AddConjunct(adt.MakeConjunct(nil, b))
+	return makeValue(v.idx, node)
+}
+
+func newVertexRoot(ctx *context, x *adt.Vertex) Value {
+	if ctx.opCtx != nil {
+		// This is indicative of an zero Value. In some cases this is called
+		// with an error value.
+		x.Finalize(ctx.opCtx)
+	} else {
+		x.UpdateStatus(adt.Finalized)
 	}
+	return makeValue(ctx.index, x)
 }
 
 func newValueRoot(ctx *context, x value) Value {
-	v := x.evalPartial(ctx)
-	return Value{ctx.index, &valueData{nil, 0, arc{Value: v, v: x}}}
+	if n, ok := x.(*adt.Vertex); ok {
+		return newVertexRoot(ctx, n)
+	}
+	node := &adt.Vertex{}
+	node.AddConjunct(adt.MakeConjunct(nil, x))
+	return newVertexRoot(ctx, node)
 }
 
-func newChildValue(obj *structValue, i int) Value {
-	a := obj.Arcs[i]
-	for j, b := range obj.obj.Arcs {
-		if b.Label == a.Label {
-			a = obj.obj.iterAt(obj.ctx, j)
-			// TODO: adding more technical debt here. The evaluator should be
-			// rewritten.
-			x := obj.obj
-			ctx := obj.ctx
-			if x.optionals != nil {
-				name := ctx.LabelStr(x.Arcs[i].Label)
-				arg := &stringLit{x.baseValue, name, nil}
-
-				val, _ := x.optionals.constraint(ctx, arg)
-				if val != nil {
-					a.v = mkBin(ctx, x.Pos(), opUnify, a.v, val)
-				}
-			}
-			break
-		}
-	}
-
-	return Value{obj.ctx.index, &valueData{obj.path, uint32(i), a}}
+func newChildValue(o *structValue, i int) Value {
+	arc, _ := o.at(i)
+	return makeValue(o.v.idx, arc)
 }
 
 // Dereference reports the value v refers to if v is a reference or v itself
 // otherwise.
 func Dereference(v Value) Value {
-	if v.v == nil {
+	n := v.v
+	if n == nil || len(n.Conjuncts) != 1 {
+		return v
+	}
+
+	c := n.Conjuncts[0]
+	r, _ := c.Expr().(adt.Resolver)
+	if r == nil {
 		return v
 	}
 
 	ctx := v.ctx()
-	a, n := appendPath(ctx, make([]label, 0, 3), v.v.v)
-
-	if n == nil {
-		return v
-
+	n, b := ctx.opCtx.Resolve(c.Env, r)
+	if b != nil {
+		return newErrValue(v, b)
 	}
-
-	p := locateNode(v.v, n)
-
-	if p == nil {
-
-		imp := ctx.getImportFromNode(n.node)
-		if imp == nil {
-			// TODO(eval): embedded structs are currently represented at the
-			// same level as the enclosing struct. This means that the parent
-			// of an embedded struct skips the struct in which it is embedded.
-			// Treat embedded structs as "anonymous" fields.
-			// See TestPathCorrection.
-			return v
-		}
-		p = &valueData{arc: arc{v: imp.rootValue, Value: imp.rootStruct}}
-	}
-
-	cached := p.Value
-	if cached == nil {
-		cached = p.v.evalPartial(ctx)
-	}
-	s := cached.(*structLit)
-	for _, f := range a {
-		a := s.Lookup(ctx, f)
-		if a.v == nil {
-			return Value{}
-		}
-		p = &valueData{parent: p, arc: a} // index
-		s, _ = a.Value.(*structLit)
-	}
-
-	v = Value{v.idx, p}
-	return v
+	return makeValue(v.idx, n)
 }
 
-func appendPath(ctx *context, a []label, v value) (path []label, n *nodeRef) {
-	switch x := v.(type) {
-	case *selectorExpr:
-		a, n = appendPath(ctx, a, x.X)
-		if n == nil {
-			return nil, nil
-		}
-
-		a = append(a, x.Sel)
-
-	case *indexExpr:
-		e := x.Index.evalPartial(ctx)
-		s, ok := e.(*stringLit)
-		if !ok {
-			return nil, nil
-		}
-
-		a, n = appendPath(ctx, a, x.X)
-		if n == nil {
-			return nil, nil
-		}
-
-		a = append(a, ctx.Label(s.Str, false))
-
-	case *nodeRef:
-		n = x
+func makeValue(idx *index, v *adt.Vertex) Value {
+	if v.Status() == 0 || v.Value == nil {
+		panic(fmt.Sprintf("not properly initialized (state: %v, value: %T)",
+			v.Status(), v.Value))
 	}
-	return a, n
+	return Value{idx, v}
 }
 
-func remakeValue(base Value, v value) Value {
-	p := base.v
-	if n, ok := v.(*nodeRef); ok {
-		if q := locateNode(p, n); q != nil {
-			p = q
-		}
+func remakeValue(base Value, env *adt.Environment, v value) Value {
+	// TODO: right now this is necessary because disjunctions do not have
+	// populated conjuncts.
+	if v, ok := v.(*adt.Vertex); ok && v.Status() >= adt.Partial {
+		return Value{base.idx, v}
 	}
-	path := *p
-	path.v = v
-	path.Value = v.evalPartial(base.ctx())
-	return Value{base.idx, &path}
+	n := &adt.Vertex{Parent: base.v.Parent, Label: base.v.Label}
+	n.AddConjunct(adt.MakeConjunct(env, v))
+	n = base.ctx().manifest(n)
+	return makeValue(base.idx, n)
 }
 
-func locateNode(p *valueData, n *nodeRef) *valueData {
-	// the parent must exist.
-	for ; p != nil && p.Value != n.node.(value); p = p.parent {
-	}
-	return p
+func remakeFinal(base Value, env *adt.Environment, v adt.Value) Value {
+	n := &adt.Vertex{Parent: base.v.Parent, Label: base.v.Label, Value: v}
+	n.UpdateStatus(adt.Finalized)
+	return makeValue(base.idx, n)
 }
 
 func (v Value) ctx() *context {
@@ -675,41 +640,8 @@
 }
 
 func (v Value) makeChild(ctx *context, i uint32, a arc) Value {
-	return Value{v.idx, &valueData{v.v, i, a}}
-}
-
-func (v Value) makeElem(x value) Value {
-	v, e := v.evalFull(x)
-	return Value{v.idx, &valueData{v.v, 0, arc{
-		optional: true,
-		v:        x,
-		Value:    e,
-	}}}
-}
-
-func (v Value) eval(ctx *context) evaluated {
-	if v.v == nil || v.v.Value == nil {
-		panic("undefined value")
-	}
-	return ctx.manifest(v.v.Value)
-}
-
-func (v Value) evalFull(u value) (Value, evaluated) {
-	ctx := v.ctx()
-	x := u.evalPartial(ctx)
-	if st, ok := x.(*structLit); ok {
-		var err *bottom
-		x, err = st.expandFields(ctx)
-		if err != nil {
-			x = err
-		}
-		if x != st {
-			p := *v.v
-			p.Value = x
-			v.v = &p
-		}
-	}
-	return v, x
+	a.Parent = v.v
+	return makeValue(v.idx, a)
 }
 
 // Eval resolves the references of a value and returns the result.
@@ -718,7 +650,12 @@
 	if v.v == nil {
 		return v
 	}
-	return remakeValue(v.evalFull(v.v.v))
+	x := v.v
+	// x = eval.FinalizeValue(v.idx.Runtime, v.v)
+	// x.Finalize(v.ctx().opCtx)
+	x = x.ToDataSingle()
+	return makeValue(v.idx, x)
+	// return remakeValue(v, nil, ctx.value(x))
 }
 
 // Default reports the default value and whether it existed. It returns the
@@ -727,12 +664,139 @@
 	if v.v == nil {
 		return v, false
 	}
-	v, u := v.evalFull(v.v.v)
-	x := v.ctx().manifest(u)
-	if x != u {
-		return remakeValue(v, x), true
+
+	d := v.v.Default()
+	if d == v.v {
+		return v, false
 	}
-	return v, false
+	return makeValue(v.idx, d), true
+
+	// d, ok := v.v.Value.(*adt.Disjunction)
+	// if !ok {
+	// 	return v, false
+	// }
+
+	// var w *adt.Vertex
+
+	// switch d.NumDefaults {
+	// case 0:
+	// 	return v, false
+
+	// case 1:
+	// 	w = d.Values[0]
+
+	// default:
+	// 	x := *v.v
+	// 	x.Value = &adt.Disjunction{
+	// 		Src:         d.Src,
+	// 		Values:      d.Values[:d.NumDefaults],
+	// 		NumDefaults: 0,
+	// 	}
+	// 	w = &x
+	// }
+
+	// w.Conjuncts = nil
+	// for _, c := range v.v.Conjuncts {
+	// 	// TODO: preserve field information.
+	// 	expr, _ := stripNonDefaults(c.Expr())
+	// 	w.AddConjunct(adt.MakeConjunct(c.Env, expr))
+	// }
+
+	// return makeValue(v.idx, w), true
+
+	// if !stripped {
+	// 	return v, false
+	// }
+
+	// n := *v.v
+	// n.Conjuncts = conjuncts
+	// return Value{v.idx, &n}, true
+
+	// isDefault := false
+	// for _, c := range v.v.Conjuncts {
+	// 	if hasDisjunction(c.Expr()) {
+	// 		isDefault = true
+	// 		break
+	// 	}
+	// }
+
+	// if !isDefault {
+	// 	return v, false
+	// }
+
+	// TODO: record expanded disjunctions in output.
+	// - Rename Disjunction to DisjunctionExpr
+	// - Introduce Disjuncts with Values.
+	// - In Expr introduce Star
+	// - Don't pick default by default?
+
+	// Evaluate the value.
+	// 	x := eval.FinalizeValue(v.idx.Runtime, v.v)
+	// 	if b, _ := x.Value.(*adt.Bottom); b != nil { // && b.IsIncomplete() {
+	// 		return v, false
+	// 	}
+	// 	// Finalize and return here.
+	// 	return Value{v.idx, x}, isDefault
+}
+
+// TODO: this should go: record preexpanded disjunctions in Vertex.
+func hasDisjunction(expr adt.Expr) bool {
+	switch x := expr.(type) {
+	case *adt.DisjunctionExpr:
+		return true
+	case *adt.Conjunction:
+		for _, v := range x.Values {
+			if hasDisjunction(v) {
+				return true
+			}
+		}
+	case *adt.BinaryExpr:
+		switch x.Op {
+		case adt.OrOp:
+			return true
+		case adt.AndOp:
+			return hasDisjunction(x.X) || hasDisjunction(x.Y)
+		}
+	}
+	return false
+}
+
+// TODO: this should go: record preexpanded disjunctions in Vertex.
+func stripNonDefaults(expr adt.Expr) (r adt.Expr, stripped bool) {
+	switch x := expr.(type) {
+	case *adt.DisjunctionExpr:
+		if !x.HasDefaults {
+			return x, false
+		}
+		d := *x
+		d.Values = []adt.Disjunct{}
+		for _, v := range x.Values {
+			if v.Default {
+				d.Values = append(d.Values, v)
+			}
+		}
+		if len(d.Values) == 1 {
+			return d.Values[0].Val, true
+		}
+		return &d, true
+
+	case *adt.BinaryExpr:
+		if x.Op != adt.AndOp {
+			return x, false
+		}
+		a, sa := stripNonDefaults(x.X)
+		b, sb := stripNonDefaults(x.Y)
+		if sa || sb {
+			bin := *x
+			bin.X = a
+			bin.Y = b
+			return &bin, true
+		}
+		return x, false
+
+	default:
+		return x, false
+	}
 }
 
 // Label reports he label used to obtain this value from the enclosing struct.
@@ -740,7 +804,7 @@
 // TODO: get rid of this somehow. Probably by including a FieldInfo struct
 // or the like.
 func (v Value) Label() (string, bool) {
-	if v.v.Label == 0 {
+	if v.v == nil || v.v.Label == 0 {
 		return "", false
 	}
 	return v.idx.LabelStr(v.v.Label), true
@@ -754,33 +818,13 @@
 		return BottomKind
 	}
 	c := v.v.Value
-	if c == nil {
-		c = v.v.v.evalPartial(v.ctx())
+	if !adt.IsConcrete(c) {
+		return BottomKind
 	}
-	k := c.Kind()
-	if k.isGround() {
-		switch {
-		case k.isAnyOf(nullKind):
-			return NullKind
-		case k.isAnyOf(boolKind):
-			return BoolKind
-		case k&numKind == (intKind):
-			return IntKind
-		case k&numKind == (floatKind):
-			return FloatKind
-		case k.isAnyOf(numKind):
-			return NumberKind
-		case k.isAnyOf(bytesKind):
-			return BytesKind
-		case k.isAnyOf(stringKind):
-			return StringKind
-		case k.isAnyOf(structKind):
-			return StructKind
-		case k.isAnyOf(listKind):
-			return ListKind
-		}
+	if v.IncompleteKind() == adt.ListKind && !v.IsClosed() {
+		return BottomKind
 	}
-	return BottomKind
+	return c.Kind()
 }
 
 // IncompleteKind returns a mask of all kinds that this value may be.
@@ -788,40 +832,7 @@
 	if v.v == nil {
 		return BottomKind
 	}
-	var k kind
-	x := v.v.v.evalPartial(v.ctx())
-	switch x := convertBuiltin(x).(type) {
-	case *builtin:
-		k = x.representedKind()
-	case *customValidator:
-		k = x.Builtin.Params[0]
-	default:
-		k = x.Kind()
-	}
-	vk := BottomKind // Everything is a bottom kind.
-	for i := kind(1); i < nonGround; i <<= 1 {
-		if k&i != 0 {
-			switch i {
-			case nullKind:
-				vk |= NullKind
-			case boolKind:
-				vk |= BoolKind
-			case intKind:
-				vk |= IntKind
-			case floatKind:
-				vk |= FloatKind
-			case stringKind:
-				vk |= StringKind
-			case bytesKind:
-				vk |= BytesKind
-			case structKind:
-				vk |= StructKind
-			case listKind:
-				vk |= ListKind
-			}
-		}
-	}
-	return vk
+	return v.v.Kind()
 }
 
 // MarshalJSON marshalls this value into valid JSON.
@@ -840,6 +851,14 @@
 	}
 	ctx := v.idx.newContext()
 	x := v.eval(ctx)
+
+	if _, ok := x.(adt.Resolver); ok {
+		return nil, marshalErrf(v, x, codeIncomplete, "value %q contains unresolved references", ctx.str(x))
+	}
+	if !adt.IsConcrete(x) {
+		return nil, marshalErrf(v, x, codeIncomplete, "cannot convert incomplete value %q to JSON", ctx.str(x))
+	}
+
 	// TODO: implement marshalles in value.
 	switch k := x.Kind(); k {
 	case nullKind:
@@ -847,7 +866,9 @@
 	case boolKind:
 		return json.Marshal(x.(*boolLit).B)
 	case intKind, floatKind, numKind:
-		return x.(*numLit).X.MarshalText()
+		b, err := x.(*numLit).X.MarshalText()
+		b = bytes.TrimLeft(b, "+")
+		return b, err
 	case stringKind:
 		return json.Marshal(x.(*stringLit).Str)
 	case bytesKind:
@@ -857,15 +878,6 @@
 		return marshalList(&i)
 	case structKind:
 		obj, err := v.structValData(ctx)
-		st := obj.obj
-		if len(st.comprehensions) > 0 {
-			// This should always evaluate to incomplete. However, fall back
-			// to a bad error message, rather than crashing, in case it doesn't.
-			if err, ok := st.comprehensions[0].comp.evalPartial(ctx).(*bottom); ok {
-				return nil, toMarshalErr(v, err)
-			}
-		}
-
 		if err != nil {
 			return nil, toMarshalErr(v, err)
 		}
@@ -873,12 +885,6 @@
 	case bottomKind:
 		return nil, toMarshalErr(v, x.(*bottom))
 	default:
-		if k.hasReferences() {
-			return nil, marshalErrf(v, x, codeIncomplete, "value %q contains unresolved references", ctx.str(x))
-		}
-		if !k.isGround() {
-			return nil, marshalErrf(v, x, codeIncomplete, "cannot convert incomplete value %q to JSON", ctx.str(x))
-		}
 		return nil, marshalErrf(v, x, 0, "cannot convert value %q of type %T to JSON", ctx.str(x), x)
 	}
 }
@@ -889,21 +895,57 @@
 	// TODO: the default should ideally be simplified representation that
 	// exactly represents the value. The latter can currently only be
 	// ensured with Raw().
-	if v.v == nil || v.v.Value == nil {
+	if v.v == nil {
 		return nil
 	}
-	ctx := v.ctx()
-	o := getOptions(opts)
-	var inst *Instance
-	if !o.final && !o.concrete {
-		inst = v.instance()
+	var o options = getOptions(opts)
+	// var inst *Instance
+
+	p := export.Profile{
+		Simplify:        !o.raw,
+		ShowOptional:    !o.omitOptional && !o.concrete,
+		ShowDefinitions: !o.omitDefinitions && !o.concrete,
+		ShowHidden:      !o.omitHidden && !o.concrete,
+		ShowAttributes:  !o.omitAttrs,
+		ShowDocs:        o.docs,
 	}
-	if o.raw {
-		n, _ := export(ctx, inst, v.v.v, o)
-		return n
+
+	// var expr ast.Expr
+	var err error
+	var f *ast.File
+	if o.concrete || o.final {
+		// inst = v.instance()
+		var expr ast.Expr
+		expr, err = p.Value(v.idx.Runtime, v.v)
+		if err != nil {
+			return nil
+		}
+
+		// This introduces gratuitous unshadowing!
+		f, err = astutil.ToFile(expr)
+		if err != nil {
+			return nil
+		}
+		// return expr
+	} else {
+		f, err = p.Def(v.idx.Runtime, v.v)
+		if err != nil {
+			panic(err)
+		}
 	}
-	n, _ := export(ctx, inst, v.v.Value, o)
-	return n
+
+	if d := internal.Imports(f); len(d) == 0 {
+		if len(f.Decls) == 1 {
+			if e, ok := f.Decls[0].(*ast.EmbedDecl); ok {
+				return e.Expr
+			}
+		}
+		return &ast.StructLit{
+			Elts: f.Decls,
+		}
+	}
+
+	return f
 }
 
 // Decode initializes x with Value v. If x is a struct, it will validate the
@@ -928,7 +970,7 @@
 	if v.v == nil {
 		return nil
 	}
-	return v.v.docs.appendDocs(nil)
+	return export.ExtractDoc(v.v)
 }
 
 // Split returns a list of values from which v originated such that
@@ -942,27 +984,9 @@
 	if v.v == nil {
 		return nil
 	}
-	ctx := v.ctx()
 	a := []Value{}
-	for _, x := range separate(v.v.v) {
-		path := *v.v
-		path.Value = x.evalPartial(ctx)
-		path.v = x
-		a = append(a, Value{v.idx, &path})
-	}
-	return a
-}
-
-func separate(v value) (a []value) {
-	c := v.computed()
-	if c == nil || (c.op != opUnify && c.op != opUnifyUnchecked) {
-		return []value{v}
-	}
-	if c.x != nil {
-		a = append(a, separate(c.x)...)
-	}
-	if c.y != nil {
-		a = append(a, separate(c.y)...)
+	for _, x := range v.v.Conjuncts {
+		a = append(a, remakeValue(v, x.Env, x.Expr()))
 	}
 	return a
 }
@@ -975,7 +999,10 @@
 	if v.v == nil {
 		return nil
 	}
-	return v.v.v.Source()
+	if len(v.v.Conjuncts) == 1 {
+		return v.v.Conjuncts[0].Source()
+	}
+	return v.v.Value.Source()
 }
 
 // Err returns the error represented by v or nil v is not an error.
@@ -1000,19 +1027,10 @@
 // IsClosed reports whether a list of struct is closed. It reports false when
 // when the value is not a list or struct.
 func (v Value) IsClosed() bool {
-	switch v.Kind() {
-	case StructKind:
-		if st, ok := v.v.val().(*structLit); ok {
-			return st.closeStatus.shouldClose()
-		}
-	case ListKind:
-		if l, ok := v.v.val().(*list); ok {
-			if n, ok := l.len.(*numLit); ok {
-				return n.intValue(v.ctx()) == len(l.elem.Arcs)
-			}
-		}
+	if v.v == nil {
+		return false
 	}
-	return false
+	return v.v.IsClosed(v.ctx().opCtx)
 }
 
 // IsConcrete reports whether the current value is a concrete scalar value
@@ -1023,35 +1041,32 @@
 	if v.v == nil {
 		return false // any is neither concrete, not a list or struct.
 	}
-	x := v.v.v.evalPartial(v.ctx())
-
-	// Errors marked as incomplete are treated as not complete.
-	if isIncomplete(x) {
+	if b, ok := v.v.Value.(*adt.Bottom); ok {
+		return !b.IsIncomplete()
+	}
+	if !adt.IsConcrete(v.v) {
 		return false
 	}
-	// Other errors are considered ground.
-	return x.Kind().isConcrete()
+	if v.IncompleteKind() == adt.ListKind && !v.IsClosed() {
+		return false
+	}
+	return true
 }
 
-// Deprecated: IsIncomplete
-//
-// It indicates that the value cannot be fully evaluated due to
-// insufficient information.
-func (v Value) IsIncomplete() bool {
-	// TODO: remove
-	x := v.eval(v.ctx())
-	if !x.Kind().isConcrete() {
-		return true
-	}
-	return isIncomplete(x)
-}
+// // Deprecated: IsIncomplete
+// //
+// // It indicates that the value cannot be fully evaluated due to
+// // insufficient information.
+// func (v Value) IsIncomplete() bool {
+// 	panic("deprecated")
+// }
 
 // Exists reports whether this value existed in the configuration.
 func (v Value) Exists() bool {
 	if v.v == nil {
 		return false
 	}
-	return exists(v.eval(v.ctx()))
+	return exists(v.v.Value)
 }
 
 func (v Value) checkKind(ctx *context, want kind) *bottom {
@@ -1063,22 +1078,23 @@
 	if b, ok := x.(*bottom); ok {
 		return b
 	}
-	got := x.Kind()
+	k := x.Kind()
 	if want != bottomKind {
-		if got&want&concreteKind == bottomKind {
+		if k&want == bottomKind {
 			return ctx.mkErr(x, "cannot use value %v (type %s) as %s",
-				v.ctx().str(x), got, want)
+				ctx.opCtx.Str(x), k, want)
 		}
-		if !got.isGround() {
-			return ctx.mkErr(x, codeIncomplete,
-				"non-concrete value %v", got)
+		if !adt.IsConcrete(x) {
+			return ctx.mkErr(x, codeIncomplete, "non-concrete value %v", k)
 		}
 	}
 	return nil
 }
 
 func makeInt(v Value, x int64) Value {
-	return remakeValue(v, newInt(v.v.v.base(), base10).setInt64(x))
+	n := &adt.Num{K: intKind}
+	n.X.SetInt64(int64(x))
+	return remakeFinal(v, nil, n)
 }
 
 // Len returns the number of items of the underlying value.
@@ -1086,17 +1102,35 @@
 // number of fields, for bytes the number of bytes.
 func (v Value) Len() Value {
 	if v.v != nil {
-		switch x := v.v.v.evalPartial(v.ctx()).(type) {
-		case *list:
-			return remakeValue(v, x.len.evalPartial(v.ctx()))
+		switch x := v.eval(v.ctx()).(type) {
+		case *adt.Vertex:
+			if x.IsList() {
+				ctx := v.ctx()
+				n := &adt.Num{K: intKind}
+				n.X.SetInt64(int64(len(x.Elems())))
+				if x.IsClosed(ctx.opCtx) {
+					return remakeFinal(v, nil, n)
+				}
+				// Note: this HAS to be a Conjunction value and cannot be
+				// an adt.BinaryExpr, as the expressions would be considered
+				// to be self-contained and unresolvable when evaluated
+				// (can never become concrete).
+				c := &adt.Conjunction{Values: []adt.Value{
+					&adt.BasicType{K: adt.IntKind},
+					&adt.BoundValue{Op: adt.GreaterEqualOp, Value: n},
+				}}
+				return remakeFinal(v, nil, c)
+
+			}
 		case *bytesLit:
-			return makeInt(v, int64(x.len()))
+			return makeInt(v, int64(len(x.B)))
 		case *stringLit:
-			return makeInt(v, int64(x.len()))
+			return makeInt(v, int64(len([]rune(x.Str))))
 		}
 	}
 	const msg = "len not supported for type %v"
-	return remakeValue(v, v.ctx().mkErr(v.v.v, msg, v.Kind()))
+	return remakeValue(v, nil, v.ctx().mkErr(v.v, msg, v.Kind()))
+
 }
 
 // Elem returns the value of undefined element types of lists and structs.
@@ -1104,51 +1138,51 @@
 	if v.v == nil {
 		return Value{}, false
 	}
-	ctx := v.ctx()
-	switch x := v.v.Value.(type) {
-	case *structLit:
-		t, _ := x.optionals.constraint(ctx, nil)
-		if t == nil {
-			break
-		}
-		return v.makeElem(t), true
-	case *list:
-		return v.makeElem(x.typ), true
+	ctx := v.ctx().opCtx
+	x := &adt.Vertex{
+		Parent: v.v,
+		Label:  0,
 	}
-	return Value{}, false
+	v.v.Finalize(ctx)
+	v.v.MatchAndInsert(ctx, x)
+	if len(x.Conjuncts) == 0 {
+		return Value{}, false
+	}
+	x.Finalize(ctx)
+	return makeValue(v.idx, x), true
 }
 
-// BulkOptionals returns all bulk optional fields as key-value pairs.
-// See also Elem and Template.
-func (v Value) BulkOptionals() [][2]Value {
-	x, ok := v.v.Value.(*structLit)
-	if !ok {
-		return nil
-	}
-	return v.appendBulk(nil, x.optionals)
-}
+// // BulkOptionals returns all bulk optional fields as key-value pairs.
+// // See also Elem and Template.
+// func (v Value) BulkOptionals() [][2]Value {
+// 	x, ok := v.path.cache.(*structLit)
+// 	if !ok {
+// 		return nil
+// 	}
+// 	return v.appendBulk(nil, x.optionals)
+// }
 
-func (v Value) appendBulk(a [][2]Value, x *optionals) [][2]Value {
-	if x == nil {
-		return a
-	}
-	a = v.appendBulk(a, x.left)
-	a = v.appendBulk(a, x.right)
-	for _, set := range x.fields {
-		if set.key != nil {
-			ctx := v.ctx()
-			fn, ok := ctx.manifest(set.value).(*lambdaExpr)
-			if !ok {
-				// create error
-				continue
-			}
-			x := fn.call(ctx, set.value, &basicType{K: stringKind})
+// func (v Value) appendBulk(a [][2]Value, x *optionals) [][2]Value {
+// 	if x == nil {
+// 		return a
+// 	}
+// 	a = v.appendBulk(a, x.left)
+// 	a = v.appendBulk(a, x.right)
+// 	for _, set := range x.fields {
+// 		if set.key != nil {
+// 			ctx := v.ctx()
+// 			fn, ok := ctx.manifest(set.value).(*lambdaExpr)
+// 			if !ok {
+// 				// create error
+// 				continue
+// 			}
+// 			x := fn.call(ctx, set.value, &basicType{K: stringKind})
 
-			a = append(a, [2]Value{v.makeElem(set.key), v.makeElem(x)})
-		}
-	}
-	return a
-}
+// 			a = append(a, [2]Value{v.makeElem(set.key), v.makeElem(x)})
+// 		}
+// 	}
+// 	return a
+// }
 
 // List creates an iterator over the values of a list or reports an error if
 // v is not a list.
@@ -1158,8 +1192,13 @@
 	if err := v.checkKind(ctx, listKind); err != nil {
 		return Iterator{ctx: ctx}, v.toErr(err)
 	}
-	l := v.eval(ctx).(*list)
-	return Iterator{ctx: ctx, val: v, iter: l, len: len(l.elem.Arcs)}, nil
+	arcs := []field{}
+	for _, a := range v.v.Elems() {
+		if a.Label.IsInt() {
+			arcs = append(arcs, field{arc: a})
+		}
+	}
+	return Iterator{ctx: ctx, val: v, arcs: arcs}, nil
 }
 
 // Null reports an error if v is not null.
@@ -1243,97 +1282,76 @@
 
 // structVal returns an structVal or an error if v is not a struct.
 func (v Value) structValOpts(ctx *context, o options) (structValue, *bottom) {
-	v, _ = v.Default() // TODO: remove?
+	v, _ = v.Default()
 
-	obj, path, err := v.getStruct()
+	obj, err := v.getStruct()
 	if err != nil {
 		return structValue{}, err
 	}
 
-	// check if any fields can be omitted
-	needFilter := false
-	if o.omitHidden || o.omitOptional || o.omitDefinitions {
-		f := label(0)
-		for _, a := range obj.Arcs {
-			f |= a.Label
-			if a.optional && o.omitOptional {
-				needFilter = true
-				break
-			}
-			if a.definition && (o.omitDefinitions || o.concrete) {
-				needFilter = true
-				break
-			}
-		}
-		needFilter = needFilter || f.IsHidden()
-	}
+	features := export.VertexFeatures(obj)
 
-	if needFilter {
-		arcs := make([]arc, len(obj.Arcs))
-		k := 0
-		for _, a := range obj.Arcs {
-			if a.definition && (o.omitDefinitions || o.concrete) {
-				continue
-			}
-			if a.Label.IsHidden() && o.omitHidden {
-				continue
-			}
-			if o.omitOptional && a.optional {
-				continue
-			}
-			arcs[k] = a
-			k++
+	k := 0
+	for _, f := range features {
+		if f.IsDef() && (o.omitDefinitions || o.concrete) {
+			continue
 		}
-		arcs = arcs[:k]
-		return structValue{ctx, path, obj, arcs}, nil
+		if f.IsHidden() && o.omitHidden {
+			continue
+		}
+		if arc := obj.Lookup(f); arc == nil {
+			if o.omitOptional {
+				continue
+			}
+			// ensure it really exists.
+			v := adt.Vertex{
+				Parent: obj,
+				Label:  f,
+			}
+			obj.MatchAndInsert(ctx.opCtx, &v)
+			if len(v.Conjuncts) == 0 {
+				continue
+			}
+		}
+		features[k] = f
+		k++
 	}
-	return structValue{ctx, path, obj, obj.Arcs}, nil
+	features = features[:k]
+	return structValue{ctx, v, obj, features}, nil
 }
 
 // Struct returns the underlying struct of a value or an error if the value
 // is not a struct.
 func (v Value) Struct() (*Struct, error) {
-	obj, path, err := v.getStruct()
+	ctx := v.ctx()
+	obj, err := v.structValOpts(ctx, options{})
 	if err != nil {
 		return nil, v.toErr(err)
 	}
-	return &Struct{Value{v.idx, path}, obj}, nil
+	return &Struct{obj}, nil
 }
 
-func (v Value) getStruct() (*structLit, *valueData, *bottom) {
+func (v Value) getStruct() (*structLit, *bottom) {
 	ctx := v.ctx()
 	if err := v.checkKind(ctx, structKind); err != nil {
-		return nil, nil, err
+		if !err.ChildError {
+			return nil, err
+		}
 	}
-	orig := v.eval(ctx).(*structLit)
-
-	// TODO: This is expansion appropriate?
-	obj, err := orig.expandFields(ctx)
-	if err != nil {
-		return nil, nil, err
-	}
-
-	path := v.v
-	if obj != orig {
-		p := *path
-		p.arc.Value = obj
-		path = &p
-	}
-
-	return obj, path, nil
+	return v.v, nil
 }
 
 // Struct represents a CUE struct value.
 type Struct struct {
-	v Value
-	s *structLit
+	structValue
 }
 
 // FieldInfo contains information about a struct field.
 type FieldInfo struct {
-	Name  string
-	Pos   int
-	Value Value
+	Selector string
+	Name     string // Deprecated: use Selector
+	Pos      int
+	Value    Value
 
 	IsDefinition bool
 	IsOptional   bool
@@ -1341,31 +1359,18 @@
 }
 
 func (s *Struct) Len() int {
-	return len(s.s.Arcs)
+	return s.structValue.Len()
 }
 
 // field reports information about the ith field, i < o.Len().
 func (s *Struct) Field(i int) FieldInfo {
+	a, opt := s.at(i)
 	ctx := s.v.ctx()
-	a := s.s.Arcs[i]
-	a.Value = s.s.at(ctx, i)
 
-	// TODO: adding more technical debt here. The evaluator should be
-	// rewritten.
-	x := s.s
-	if x.optionals != nil {
-		name := ctx.LabelStr(x.Arcs[i].Label)
-		arg := &stringLit{x.baseValue, name, nil}
-
-		val, _ := x.optionals.constraint(ctx, arg)
-		if val != nil {
-			a.v = mkBin(ctx, x.Pos(), opUnify, a.v, val)
-		}
-	}
-
-	v := Value{ctx.index, &valueData{s.v.v, uint32(i), a}}
-	str := ctx.LabelStr(a.Label)
-	return FieldInfo{str, i, v, a.definition, a.optional, a.Label.IsHidden()}
+	v := makeValue(s.v.idx, a)
+	name := ctx.LabelStr(a.Label)
+	str := a.Label.SelectorString(ctx.opCtx)
+	return FieldInfo{str, name, i, v, a.Label.IsDef(), opt, a.Label.IsHidden()}
 }
 
 // FieldByName looks up a field for the given name. If isIdent is true, it will
@@ -1373,8 +1378,8 @@
 // it interprets name as an arbitrary string for a regular field.
 func (s *Struct) FieldByName(name string, isIdent bool) (FieldInfo, error) {
 	f := s.v.ctx().Label(name, isIdent)
-	for i, a := range s.s.Arcs {
-		if a.Label == f {
+	for i, a := range s.features {
+		if a == f {
 			return s.Field(i), nil
 		}
 	}
@@ -1397,16 +1402,13 @@
 	if err != nil {
 		return &Iterator{ctx: ctx}, v.toErr(err)
 	}
-	n := &structLit{
-		obj.obj.baseValue,   // baseValue
-		obj.obj.emit,        // emit
-		obj.obj.optionals,   // template
-		obj.obj.closeStatus, // closeStatus
-		nil,                 // comprehensions
-		obj.Arcs,            // arcs
-		nil,                 // attributes
+
+	arcs := []field{}
+	for i := range obj.features {
+		arc, isOpt := obj.at(i)
+		arcs = append(arcs, field{arc: arc, isOptional: isOpt})
 	}
-	return &Iterator{ctx: ctx, val: v, iter: n, len: len(n.Arcs)}, nil
+	return &Iterator{ctx: ctx, val: v, arcs: arcs}, nil
 }
 
 // Lookup reports the value at a path starting from v. The empty path returns v
@@ -1440,9 +1442,9 @@
 	}
 
 	f := v.ctx().Label(name, true)
-	for i, a := range o.Arcs {
-		if a.Label == f {
-			if f.IsHidden() || !a.definition || a.optional {
+	for i, a := range o.features {
+		if a == f {
+			if f.IsHidden() || !f.IsDef() { // optional not possible for now
 				break
 			}
 			return newChildValue(&o, i)
@@ -1455,8 +1457,7 @@
 			return alt
 		}
 	}
-	return newErrValue(v, ctx.mkErr(v.v.v,
-		"definition %q not found", name))
+	return newErrValue(v, ctx.mkErr(v.v, "definition %q not found", name))
 }
 
 var errNotFound = errors.Newf(token.NoPos, "field not found")
@@ -1516,16 +1517,15 @@
 		return v
 	}
 	ctx := v.ctx()
-	root := v.v.val()
 	for i := len(path) - 1; i >= 0; i-- {
 		x = map[string]interface{}{path[i]: x}
 	}
-	value := convertVal(ctx, root, true, x)
-	a := v.v.arc
-	a.v = mkBin(ctx, v.Pos(), opUnify, root, value)
-	a.Value = a.v.evalPartial(ctx)
-	// TODO: validate recursively?
-	return Value{v.idx, &valueData{v.v.parent, v.v.index, a}}
+	var value = convert.GoValueToExpr(ctx.opCtx, true, x)
+	n := &adt.Vertex{Parent: v.v.Parent}
+	n.AddConjunct(adt.MakeConjunct(nil, value))
+	n.Finalize(ctx.opCtx)
+	w := makeValue(v.idx, n)
+	return v.Unify(w)
 }
 
 // Template returns a function that represents the template definition for a
@@ -1540,19 +1540,22 @@
 		return nil
 	}
 
-	ctx := v.ctx()
-	x, ok := v.v.Value.(*structLit)
-	if !ok || x.optionals.isEmpty() {
+	types := v.v.OptionalTypes()
+	if types&(adt.HasAdditional|adt.HasPattern) == 0 {
 		return nil
 	}
 
+	parent := v.v
+	ctx := v.ctx().opCtx
 	return func(label string) Value {
-		arg := &stringLit{x.baseValue, label, nil}
-
-		if val, _ := x.optionals.constraint(ctx, arg); val != nil {
-			return remakeValue(v, val)
+		f := ctx.StringLabel(label)
+		arc := &adt.Vertex{Parent: parent, Label: f}
+		v.v.MatchAndInsert(ctx, arc)
+		if len(arc.Conjuncts) == 0 {
+			return Value{}
 		}
-		return Value{}
+		arc.Finalize(ctx)
+		return makeValue(v.idx, arc)
 	}
 }
 
@@ -1570,15 +1573,19 @@
 // Value v and w must be obtained from the same build.
 // TODO: remove this requirement.
 func (v Value) Subsume(w Value, opts ...Option) error {
-	var mode subsumeMode
 	o := getOptions(opts)
-	if o.final {
-		mode |= subFinal | subChoose
+	p := subsume.CUE
+	switch {
+	case o.final && o.ignoreClosedness:
+		p = subsume.FinalOpen
+	case o.final:
+		p = subsume.Final
+	case o.ignoreClosedness:
+		p = subsume.API
 	}
-	if o.ignoreClosedness {
-		mode |= subSchema
-	}
-	return subsumes(v, w, mode)
+	p.Defaults = true
+	ctx := v.ctx().opCtx
+	return p.Value(ctx, v.v, w.v)
 }
 
 // Deprecated: use Subsume.
@@ -1588,11 +1595,12 @@
 // Without options, Subsumes checks whether v is a backwards compatbile schema
 // of w.
 //
-// By default, Subsumes tests whether two values are compatib
+// By default, Subsumes tests whether two values are compatible
 // Value v and w must be obtained from the same build.
 // TODO: remove this requirement.
 func (v Value) Subsumes(w Value) bool {
-	return subsumes(v, w, subChoose) == nil
+	p := subsume.Profile{Defaults: true}
+	return p.Check(v.ctx().opCtx, v.v, w.v)
 }
 
 // Unify reports the greatest lower bound of v and w.
@@ -1600,29 +1608,47 @@
 // Value v and w must be obtained from the same build.
 // TODO: remove this requirement.
 func (v Value) Unify(w Value) Value {
-	ctx := v.ctx()
+	// ctx := v.ctx()
 	if v.v == nil {
 		return w
 	}
 	if w.v == nil {
 		return v
 	}
-	if v.Err() != nil {
-		// TODO: perhaps keep both errors.
-		return v
-	}
-	if w.Err() != nil {
+	n := &adt.Vertex{Parent: v.v.Parent, Label: v.v.Label}
+	n.AddConjunct(adt.MakeConjunct(nil, v.v))
+	n.AddConjunct(adt.MakeConjunct(nil, w.v))
+
+	ctx := v.idx.newContext()
+	n.Finalize(ctx.opCtx)
+	return makeValue(v.idx, n)
+}
+
+// UnifyAccept is as v.Unify(w), but will disregard any field that is allowed
+// in the Value accept.
+func (v Value) UnifyAccept(w Value, accept Value) Value {
+	if v.v == nil {
 		return w
 	}
-	a := v.v.v
-	b := w.v.v
-	src := binSrc(token.NoPos, opUnify, a, b)
-	val := mkBin(ctx, src.Pos(), opUnify, a, b)
-	u := remakeValue(v, val)
-	if err := u.Validate(); err != nil {
-		u = newValueRoot(ctx, ctx.mkErr(src, err))
+	if w.v == nil {
+		return v
 	}
-	return u
+	if accept.v == nil {
+		panic("accept must exist")
+	}
+
+	n := &adt.Vertex{Parent: v.v.Parent, Label: v.v.Label}
+	n.AddConjunct(adt.MakeConjunct(nil, v.v))
+	n.AddConjunct(adt.MakeConjunct(nil, w.v))
+
+	e := eval.New(v.idx.Runtime)
+	ctx := e.NewContext(n)
+	e.UnifyAccept(ctx, n, adt.Finalized, accept.v.Closed)
+
+	// ctx := v.idx.newContext()
+	n.Closed = accept.v.Closed
+	n.Finalize(ctx)
+	return makeValue(v.idx, n)
 }
 
 // Equals reports whether two values are equal, ignoring optional fields.
@@ -1631,9 +1657,8 @@
 	if v.v == nil || other.v == nil {
 		return false
 	}
-	x := v.v.val()
-	y := other.v.val()
-	return equals(v.ctx(), x, y)
+	return eval.Equal(v.ctx().opCtx, v.v, other.v)
+
 }
 
 // Format prints a debug version of a value.
@@ -1645,11 +1670,13 @@
 	}
 	switch {
 	case state.Flag('#'):
-		_, _ = io.WriteString(state, ctx.str(v.v.v))
+		_, _ = io.WriteString(state, ctx.str(v.v))
 	case state.Flag('+'):
-		_, _ = io.WriteString(state, debugStr(ctx, v.v.v))
+		_, _ = io.WriteString(state, debugStr(ctx, v.v))
 	default:
-		_, _ = io.WriteString(state, ctx.str(v.v.Value))
+		n, _ := export.Raw.Expr(v.idx.Runtime, v.v)
+		b, _ := format.Node(n)
+		_, _ = state.Write(b)
 	}
 }
 
@@ -1657,7 +1684,7 @@
 	if v.v == nil {
 		return nil
 	}
-	return v.ctx().getImportFromNode(v.v.v)
+	return v.ctx().getImportFromNode(v.v)
 }
 
 // Reference returns the instance and path referred to by this value such that
@@ -1666,154 +1693,72 @@
 // only return a reference if the index resolves to a concrete value.
 func (v Value) Reference() (inst *Instance, path []string) {
 	// TODO: don't include references to hidden fields.
-	if v.v == nil {
+	if v.v == nil || len(v.v.Conjuncts) != 1 {
 		return nil, nil
 	}
 	ctx := v.ctx()
-	var x value
-	var feature string
-	switch sel := v.v.v.(type) {
-	case *selectorExpr:
-		x = sel.X
-		feature = ctx.LabelStr(sel.Sel)
+	c := v.v.Conjuncts[0]
 
-	case *indexExpr:
-		e := sel.Index.evalPartial(ctx)
-		s, ok := e.(*stringLit)
-		if !ok {
-			return nil, nil
-		}
-		x = sel.X
-		feature = s.Str
+	return reference(ctx, c.Env, c.Expr())
+}
 
-	default:
+func reference(c *context, env *adt.Environment, r adt.Expr) (inst *Instance, path []string) {
+	ctx := c.opCtx
+	defer ctx.PopState(ctx.PushState(env, r.Source()))
+
+	switch x := r.(type) {
+	case *adt.FieldReference:
+		env := ctx.Env(x.UpCount)
+		inst, path = mkPath(c, nil, env.Vertex)
+		path = append(path, x.Label.SelectorString(c.Index))
+
+	case *adt.LabelReference:
+		env := ctx.Env(x.UpCount)
+		return mkPath(c, nil, env.Vertex)
+
+	case *adt.DynamicReference:
+		env := ctx.Env(x.UpCount)
+		inst, path = mkPath(c, nil, env.Vertex)
+		v, _ := ctx.Evaluate(env, x.Label)
+		str := ctx.StringValue(v)
+		path = append(path, str)
+
+	case *adt.ImportReference:
+		imp := x.ImportPath.StringValue(ctx)
+		inst = c.index.getImportFromPath(imp)
+
+	case *adt.SelectorExpr:
+		inst, path = reference(c, env, x.X)
+		path = append(path, x.Sel.SelectorString(ctx))
+
+	case *adt.IndexExpr:
+		inst, path = reference(c, env, x.X)
+		v, _ := ctx.Evaluate(env, x.Index)
+		str := ctx.StringValue(v)
+		path = append(path, str)
+	}
+	if inst == nil {
 		return nil, nil
 	}
-	imp, a := mkPath(ctx, v.v, x, feature, 0)
-	return imp, a
+	return inst, path
 }
 
-func mkPath(c *context, up *valueData, x value, feature string, d int) (imp *Instance, a []string) {
-	switch x := x.(type) {
-	case *selectorExpr:
-		imp, a = mkPath(c, up, x.X, c.LabelStr(x.Sel), d+1)
-		if imp == nil {
-			return nil, nil
-		}
-
-	case *indexExpr:
-		e := x.Index.evalPartial(c)
-		s, ok := e.(*stringLit)
-		if !ok {
-			return nil, nil
-		}
-		imp, a = mkPath(c, up, x.X, s.Str, d+1)
-		if imp == nil {
-			return nil, nil
-		}
-
-	case *nodeRef:
-		// the parent must exist.
-		var v value
-		if p := locateNode(up, x); p != nil {
-			v, a = mkFromRoot(c, p, d+2)
-		} else {
-			// Either this references another parent, or it is an embedding.
-			imp = c.getImportFromNode(x.node)
-			if imp != nil {
-				break
-			}
-			// This must be an embedding, go one up.
-			v, a = mkFromRoot(c, up.parent, d+2)
-		}
-		if v == nil {
-			v = x.node
-		}
-		imp = c.getImportFromNode(v)
-	default:
-		return nil, nil
+func mkPath(ctx *context, a []string, v *adt.Vertex) (inst *Instance, path []string) {
+	if v.Parent == nil {
+		return ctx.index.getImportFromNode(v), a
 	}
-	return imp, append(a, feature)
+	inst, path = mkPath(ctx, a, v.Parent)
+	path = append(path, v.Label.SelectorString(ctx.opCtx))
+	return inst, path
 }
 
-func mkFromRoot(c *context, up *valueData, d int) (root value, a []string) {
-	if up == nil {
-		return nil, make([]string, 0, d)
-	}
-	root, a = mkFromRoot(c, up.parent, d+1)
-	if up.parent != nil {
-		a = append(a, c.LabelStr(up.Label))
-	} else {
-		root = up.v
-	}
-	return root, a
-}
-
-// References reports all references used to evaluate this value. It does not
-// report references for sub fields if v is a struct.
-//
-// Deprecated: can be implemented in terms of Reference and Expr.
-func (v Value) References() [][]string {
-	// TODO: the pathFinder algorithm is quite broken. Using Reference and Expr
-	// will cast a much more accurate net on referenced values.
-	ctx := v.ctx()
-	pf := pathFinder{up: v.v}
-	raw := v.v.v
-	if raw == nil {
-		return nil
-	}
-	rewrite(ctx, raw, pf.find)
-	return pf.paths
-}
-
-type pathFinder struct {
-	paths [][]string
-	stack []label
-	up    *valueData
-}
-
-func (p *pathFinder) find(ctx *context, v value) (value, bool) {
-	switch x := v.(type) {
-	case *selectorExpr:
-		i := len(p.stack)
-		p.stack = append(p.stack, x.Sel)
-		rewrite(ctx, x.X, p.find)
-		p.stack = p.stack[:i]
-		return v, false
-
-	case *nodeRef:
-		i := len(p.stack)
-		up := p.up
-		for ; up != nil && up.Value != x.node.(value); up = up.parent {
-		}
-		for ; up != nil && up.Label > 0; up = up.parent {
-			p.stack = append(p.stack, up.Label)
-		}
-		path := make([]string, len(p.stack))
-		for i, v := range p.stack {
-			path[len(path)-1-i] = ctx.LabelStr(v)
-		}
-		p.paths = append(p.paths, path)
-		p.stack = p.stack[:i]
-		return v, false
-
-	case *structLit:
-		// If the stack is empty, we do not descend, as we are not evaluating
-		// sub fields.
-		if len(p.stack) == 0 {
-			return v, false
-		}
-
-		stack := p.stack
-		p.stack = nil
-		for _, a := range x.Arcs {
-			rewrite(ctx, a.v, p.find)
-		}
-		p.stack = stack
-		return v, false
-	}
-	return v, true
-}
+// // References reports all references used to evaluate this value. It does not
+// // report references for sub fields if v is a struct.
+// //
+// // Deprecated: can be implemented in terms of Reference and Expr.
+// func (v Value) References() [][]string {
+// 	panic("deprecated")
+// }
 
 type options struct {
 	concrete          bool // enforce that values are concrete
@@ -1950,108 +1895,18 @@
 // more than one error, retrievable with errors.Errors, if more than one
 // exists.
 func (v Value) Validate(opts ...Option) error {
-	x := validator{}
 	o := options{}
 	o.updateOptions(opts)
-	// Logically, errors are always permitted in logical fields, so we
-	// force-disable them.
-	// TODO: consider whether we should honor the option to allow checking
-	// optional fields.
-	o.omitOptional = true
-	x.walk(v, o)
-	return errors.Sanitize(x.errs)
-}
 
-type validator struct {
-	errs  errors.Error
-	depth int
-}
-
-func (x *validator) before(v Value, o options) bool {
-	if err := v.checkKind(v.ctx(), bottomKind); err != nil {
-		if !o.concrete && isIncomplete(err) {
-			if o.disallowCycles && err.Code == codeCycle {
-				x.errs = errors.Append(x.errs, v.toErr(err))
-			}
-			return false
-		}
-		x.errs = errors.Append(x.errs, v.toErr(err))
-		if len(errors.Errors(x.errs)) > 50 {
-			return false // mostly to avoid some hypothetical cycle issue
-		}
+	cfg := &validate.Config{
+		Concrete:       o.concrete,
+		DisallowCycles: o.disallowCycles,
+		AllErrors:      true,
 	}
-	if o.concrete {
-		ctx := v.ctx()
-		if err := isGroundRecursive(ctx, v.eval(ctx)); err != nil {
-			x.errs = errors.Append(x.errs, v.toErr(err))
-		}
-	}
-	return true
-}
 
-func (x *validator) walk(v Value, opts options) {
-	// TODO(#42): we can get rid of the arbitrary evaluation depth once CUE has
-	// proper structural cycle detection. See Issue #42. Currently errors
-	// occurring at a depth > internal.MaxDepth will not be detected.
-	if x.depth > internal.MaxDepth {
-		return
-	}
-	ctx := v.ctx()
-	switch v.Kind() {
-	case StructKind:
-		if !x.before(v, opts) {
-			return
-		}
-		x.depth++
-		obj, err := v.structValOpts(ctx, opts)
-		if err != nil {
-			if !isIncomplete(err) && opts.concrete {
-				x.errs = errors.Append(x.errs, v.toErr(err))
-			}
-		}
-		for i := 0; i < obj.Len(); i++ {
-			_, v := obj.At(i)
-			opts := opts
-			if obj.Arcs[i].definition {
-				opts.concrete = false
-			}
-			x.walk(v, opts)
-		}
-		x.depth--
-
-	case ListKind:
-		if !x.before(v, opts) {
-			return
-		}
-		x.depth++
-		list, _ := v.List()
-		for list.Next() {
-			x.walk(list.Value(), opts)
-		}
-		x.depth--
-
-	default:
-		x.before(v, opts)
-	}
-}
-
-func isGroundRecursive(ctx *context, v value) *bottom {
-	switch x := v.(type) {
-	case *bottom:
-		if isIncomplete(x) {
-			return x
-		}
-	case *list:
-		for i := 0; i < len(x.elem.Arcs); i++ {
-			v := ctx.manifest(x.at(ctx, i))
-			if err := isGroundRecursive(ctx, v); err != nil {
-				return err
-			}
-		}
-	default:
-		if !x.Kind().isGround() {
-			return ctx.mkErr(v, "incomplete value (%v)", ctx.str(v))
-		}
+	b := validate.Validate(v.ctx().opCtx, v.v, cfg)
+	if b != nil {
+		return b.Err
 	}
 	return nil
 }
@@ -2094,15 +1949,18 @@
 // is no attribute for the requested key.
 func (v Value) Attribute(key string) Attribute {
 	// look up the attributes
-	if v.v == nil || v.v.attrs == nil {
+	if v.v == nil {
 		return Attribute{internal.NewNonExisting(key)}
 	}
-	for _, a := range v.v.attrs.attr {
-		if a.key() != key {
+	// look up the attributes
+	for _, a := range export.ExtractFieldAttrs(v.v.Conjuncts) {
+		k, body := a.Split()
+		if key != k {
 			continue
 		}
-		return Attribute{internal.ParseAttrBody(token.NoPos, a.body())}
+		return Attribute{internal.ParseAttrBody(token.NoPos, body)}
 	}
+
 	return Attribute{internal.NewNonExisting(key)}
 }
 
@@ -2167,79 +2025,219 @@
 	if v.v == nil {
 		return NoOp, nil
 	}
+
+	var expr adt.Expr
+	var env *adt.Environment
+
+	if v.v.IsData() {
+		switch x := v.v.Value.(type) {
+		case *adt.ListMarker, *adt.StructMarker:
+			expr = v.v
+		default:
+			expr = x
+		}
+
+	} else {
+		switch len(v.v.Conjuncts) {
+		case 0:
+			if v.v.Value == nil {
+				return NoOp, []Value{makeValue(v.idx, v.v)}
+			}
+			switch x := v.v.Value.(type) {
+			case *adt.ListMarker, *adt.StructMarker:
+				expr = v.v
+			default:
+				expr = x
+			}
+
+		case 1:
+			// the default case, processed below.
+			c := v.v.Conjuncts[0]
+			env = c.Env
+			expr = c.Expr()
+			if w, ok := expr.(*adt.Vertex); ok {
+				return Value{v.idx, w}.Expr()
+			}
+
+		default:
+			a := []Value{}
+			ctx := v.ctx().opCtx
+			for _, c := range v.v.Conjuncts {
+				n := &adt.Vertex{
+					Parent: v.v.Parent,
+					Label:  v.v.Label,
+				}
+				n.AddConjunct(c)
+				n.Finalize(ctx)
+				a = append(a, makeValue(v.idx, n))
+			}
+			return adt.AndOp, a
+		}
+	}
+
 	// TODO: replace appends with []Value{}. For not leave.
 	a := []Value{}
 	op := NoOp
-	switch x := v.v.v.(type) {
+	switch x := expr.(type) {
 	case *binaryExpr:
-		a = append(a, remakeValue(v, x.X))
-		a = append(a, remakeValue(v, x.Y))
-		op = opToOp[x.Op]
+		a = append(a, remakeValue(v, env, x.X))
+		a = append(a, remakeValue(v, env, x.Y))
+		op = x.Op
 	case *unaryExpr:
-		a = append(a, remakeValue(v, x.X))
-		op = opToOp[x.Op]
-	case *bound:
-		a = append(a, remakeValue(v, x.Expr))
-		op = opToOp[x.Op]
-	case *unification:
+		a = append(a, remakeValue(v, env, x.X))
+		op = x.Op
+	case *boundExpr:
+		a = append(a, remakeValue(v, env, x.Expr))
+		op = x.Op
+	case *boundValue:
+		a = append(a, remakeValue(v, env, x.Value))
+		op = x.Op
+	case *adt.Conjunction:
 		// pre-expanded unification
 		for _, conjunct := range x.Values {
-			a = append(a, remakeValue(v, conjunct))
+			a = append(a, remakeValue(v, env, conjunct))
 		}
 		op = AndOp
-	case *disjunction:
-		// Filter defaults that are subsumed by another value.
+	case *adt.Disjunction:
 		count := 0
 	outer:
-		for _, disjunct := range x.Values {
-			if disjunct.Default {
-				for _, n := range x.Values {
-					s := subsumer{ctx: v.ctx()}
-					if !n.Default && s.subsumes(n.Val, disjunct.Val) {
+		for i, disjunct := range x.Values {
+			if i < x.NumDefaults {
+				for _, n := range x.Values[x.NumDefaults:] {
+					if subsume.Value(v.ctx().opCtx, n, disjunct) == nil {
 						continue outer
 					}
 				}
 			}
 			count++
-			a = append(a, remakeValue(v, disjunct.Val))
+			a = append(a, remakeValue(v, env, disjunct))
 		}
 		if count > 1 {
 			op = OrOp
 		}
+
+	case *adt.DisjunctionExpr:
+		// Filter defaults that are subsumed by another value.
+		count := 0
+	outerExpr:
+		for _, disjunct := range x.Values {
+			if disjunct.Default {
+				for _, n := range x.Values {
+					a := adt.Vertex{
+						Parent: v.v.Parent,
+						Label:  v.v.Label,
+						Closed: v.v.Closed,
+					}
+					b := a
+					a.AddConjunct(adt.MakeConjunct(env, n.Val))
+					b.AddConjunct(adt.MakeConjunct(env, disjunct.Val))
+
+					e := eval.New(v.idx.Runtime)
+					ctx := e.NewContext(nil)
+					e.UnifyAccept(ctx, &a, adt.Finalized, v.v.Closed)
+					e.UnifyAccept(ctx, &b, adt.Finalized, v.v.Closed)
+					if !n.Default && subsume.Value(ctx, &a, &b) == nil {
+						continue outerExpr
+					}
+				}
+			}
+			count++
+			a = append(a, remakeValue(v, env, disjunct.Val))
+		}
+		if count > 1 {
+			op = adt.OrOp
+		}
+
 	case *interpolation:
 		for _, p := range x.Parts {
-			a = append(a, remakeValue(v, p))
+			a = append(a, remakeValue(v, env, p))
 		}
 		op = InterpolationOp
+
+	case *adt.FieldReference:
+		// TODO: allow hard link
+		ctx := v.ctx().opCtx
+		f := ctx.PushState(env, x.Src)
+		env := ctx.Env(x.UpCount)
+		a = append(a, remakeValue(v, nil, &adt.NodeLink{Node: env.Vertex}))
+		a = append(a, remakeValue(v, nil, ctx.NewString(x.Label.SelectorString(ctx))))
+		_ = ctx.PopState(f)
+		op = SelectorOp
+
 	case *selectorExpr:
-		a = append(a, remakeValue(v, x.X))
-		a = append(a, remakeValue(v, &stringLit{
-			x.baseValue,
-			v.ctx().LabelStr(x.Sel),
-			nil,
+		a = append(a, remakeValue(v, env, x.X))
+		// A string selector is quoted.
+		a = append(a, remakeValue(v, env, &adt.String{
+			Str: x.Sel.SelectorString(v.idx.Index),
 		}))
 		op = SelectorOp
+
 	case *indexExpr:
-		a = append(a, remakeValue(v, x.X))
-		a = append(a, remakeValue(v, x.Index))
+		a = append(a, remakeValue(v, env, x.X))
+		a = append(a, remakeValue(v, env, x.Index))
 		op = IndexOp
 	case *sliceExpr:
-		a = append(a, remakeValue(v, x.X))
-		a = append(a, remakeValue(v, x.Lo))
-		a = append(a, remakeValue(v, x.Hi))
+		a = append(a, remakeValue(v, env, x.X))
+		a = append(a, remakeValue(v, env, x.Lo))
+		a = append(a, remakeValue(v, env, x.Hi))
 		op = SliceOp
 	case *callExpr:
-		a = append(a, remakeValue(v, x.Fun))
+		a = append(a, remakeValue(v, env, x.Fun))
 		for _, arg := range x.Args {
-			a = append(a, remakeValue(v, arg))
+			a = append(a, remakeValue(v, env, arg))
 		}
 		op = CallOp
 	case *customValidator:
-		a = append(a, remakeValue(v, x.Builtin))
+		a = append(a, remakeValue(v, env, x.Builtin))
 		for _, arg := range x.Args {
-			a = append(a, remakeValue(v, arg))
+			a = append(a, remakeValue(v, env, arg))
 		}
 		op = CallOp
+
+	case *adt.StructLit:
+		// Simulate old embeddings.
+		envEmbed := &adt.Environment{
+			Up:     env,
+			Vertex: v.v,
+		}
+		fields := []adt.Decl{}
+		ctx := v.ctx().opCtx
+		for _, d := range x.Decls {
+			switch x := d.(type) {
+			case adt.Expr:
+				// embedding
+				n := &adt.Vertex{
+					Parent: v.v.Parent,
+					Label:  v.v.Label}
+				c := adt.MakeConjunct(envEmbed, x)
+				n.AddConjunct(c)
+				n.Finalize(ctx)
+				a = append(a, makeValue(v.idx, n))
+
+			default:
+				fields = append(fields, d)
+			}
+		}
+		if len(a) == 0 {
+			a = append(a, v)
+			break
+		}
+
+		if len(fields) > 0 {
+			n := &adt.Vertex{
+				Parent: v.v.Parent,
+				Label:  v.v.Label,
+			}
+			c := adt.MakeConjunct(env, &adt.StructLit{
+				Decls: fields,
+			})
+			n.AddConjunct(c)
+			n.Finalize(ctx)
+			a = append(a, makeValue(v.idx, n))
+		}
+
+		op = adt.AndOp
+
 	default:
 		a = append(a, v)
 	}
diff --git a/cue/types_test.go b/cue/types_test.go
index cea8a14..b36c6c5 100644
--- a/cue/types_test.go
+++ b/cue/types_test.go
@@ -30,6 +30,8 @@
 	"cuelang.org/go/cue/ast"
 	"cuelang.org/go/cue/errors"
 	"cuelang.org/go/internal"
+	"cuelang.org/go/internal/core/adt"
+	"cuelang.org/go/internal/core/debug"
 )
 
 func getInstance(t *testing.T, body ...string) *Instance {
@@ -175,6 +177,12 @@
 		concrete: false,
 	}, {
 		value: `import "time"
+		v: time.Time`,
+		kind:           BottomKind,
+		incompleteKind: StringKind,
+		concrete:       false,
+	}, {
+		value: `import "time"
 		v: {a: time.Time}.a`,
 		kind:           BottomKind,
 		incompleteKind: StringKind,
@@ -567,7 +575,7 @@
 		res:   "[1,2,3,]",
 	}, {
 		value: `>=5*[1,2,3, ...int]`,
-		err:   "incomplete",
+		err:   "non-concrete value >=5 in operand to *",
 	}, {
 		value: `[for x in #y if x > 1 { x }]
 		#y: [1,2,3]`,
@@ -602,6 +610,9 @@
 		res   string
 		err   string
 	}{{
+		value: `{ #def: 1, _hidden: 2, opt?: 3, reg: 4 }`,
+		res:   "{reg:4,}",
+	}, {
 		value: `_|_`,
 		err:   "from source",
 	}, {
@@ -680,6 +691,9 @@
 	}, {
 		value: `{_a:"a"}`,
 		res:   `{_a:"a",}`,
+	}, {
+		value: `{_a:"a", b?: "b", #c: 3}`,
+		res:   `{_a:"a",b?:"b",#c:3,}`,
 	}}
 	for _, tc := range testCases {
 		t.Run(tc.value, func(t *testing.T) {
@@ -692,6 +706,9 @@
 			buf := []byte{'{'}
 			for iter.Next() {
 				buf = append(buf, iter.Label()...)
+				if iter.IsOptional() {
+					buf = append(buf, '?')
+				}
 				buf = append(buf, ':')
 				b, err := iter.Value().MarshalJSON()
 				checkFatal(t, err, tc.err, "Obj.At")
@@ -731,7 +748,7 @@
 		eval string
 	}{{
 		ref:  []string{"v", "x"},
-		raw:  "(int & <=9223372036854775807 & int & >=-9223372036854775808)",
+		raw:  ">=-9223372036854775808 & <=9223372036854775807 & int",
 		eval: "int64",
 	}}
 	for _, tc := range testCases {
@@ -788,6 +805,7 @@
 	return x
 }
 
+// TODO: Exporting of Vertex as Conjunct
 func TestFill(t *testing.T) {
 	r := &Runtime{}
 
@@ -838,10 +856,13 @@
 			path = strings.Split(tc.path, ",")
 		}
 
-		v := compileT(t, r, tc.in).Value().Fill(tc.x, path...)
+		v := compileT(t, r, tc.in).Value()
+		v = v.Fill(tc.x, path...)
+
 		w := compileT(t, r, tc.out).Value()
 
-		if !reflect.DeepEqual(goValue(v), goValue(w)) {
+		if !cmp.Equal(goValue(v), goValue(w)) {
+			t.Error(cmp.Diff(goValue(v), goValue(w)))
 			t.Errorf("\ngot:  %s\nwant: %s", v, w)
 		}
 	}
@@ -854,6 +875,8 @@
 	#Provider: {
 		ID: string
 		notConcrete: bool
+		a: int
+		b: int
 	}
 	`)
 
@@ -869,9 +892,24 @@
 	}
 
 	got := fmt.Sprint(root.Value())
-
-	if got != `{#Provider: C{ID: string, notConcrete: bool}, providers: {myprovider: C{ID: (string & "12345"), notConcrete: bool}}}` {
-		t.Error(got)
+	want := `{
+	#Provider: {
+		ID:          string
+		notConcrete: bool
+		a:           int
+		b:           int
+	}
+	providers: {
+		myprovider: {
+			ID:          "12345"
+			notConcrete: bool
+			a:           int
+			b:           int
+		}
+	}
+}`
+	if got != want {
+		t.Errorf("got:  %s\nwant: %s", got, want)
 	}
 }
 
@@ -890,11 +928,11 @@
 	}, {
 		in:  `_foo: 3`,
 		def: "_foo",
-		out: `_|_(definition "_foo" not found)`,
+		out: `_|_ // definition "_foo" not found`,
 	}, {
 		in:  `_#foo: 3`,
 		def: "_#foo",
-		out: `_|_(definition "_#foo" not found)`,
+		out: `_|_ // definition "_#foo" not found`,
 	}}
 
 	for _, tc := range testCases {
@@ -910,6 +948,7 @@
 	}
 }
 
+// TODO: trim down to individual defaults?
 func TestDefaults(t *testing.T) {
 	testCases := []struct {
 		value string
@@ -928,12 +967,12 @@
 		ok:    true,
 	}, {
 		value: `*{a:1,b:2}|{a:1}|{b:2}`,
-		def:   "{a: 1, b: 2}",
+		def:   "{a:1,b:2}",
 		val:   "{a: 1}|{b: 2}",
 		ok:    true,
 	}, {
 		value: `{a:1}&{b:2}`,
-		def:   `{a: 1, b: 2}`,
+		def:   `({a:1} & {b:2})`,
 		val:   ``,
 		ok:    false,
 	}}
@@ -946,11 +985,11 @@
 				t.Errorf("hasDefault: got %v; want %v", ok, tc.ok)
 			}
 
-			if got := fmt.Sprint(d); got != tc.def {
+			if got := compactRawStr(d); got != tc.def {
 				t.Errorf("default: got %v; want %v", got, tc.def)
 			}
 
-			op, val := v.Expr()
+			op, val := d.Expr()
 			if op != OrOp {
 				return
 			}
@@ -987,7 +1026,7 @@
 		// 	length: "2",
 	}, {
 		input:  "3",
-		length: "_|_(len not supported for type int)",
+		length: "_|_ // len not supported for type int",
 	}}
 	for _, tc := range testCases {
 		t.Run(tc.input, func(t *testing.T) {
@@ -1036,7 +1075,7 @@
 		a: foo: b: [Bar=string]: { d: Bar }
 		`,
 		path: []string{"a", "foo", "b", ""},
-		want: `{"c":"foolabel","d":"label"}`,
+		want: `{"d":"label","c":"foolabel"}`,
 	}}
 	for _, tc := range testCases {
 		t.Run("", func(t *testing.T) {
@@ -1059,6 +1098,67 @@
 	}
 }
 
+func TestElem(t *testing.T) {
+	testCases := []struct {
+		value string
+		path  []string
+		want  string
+	}{{
+		value: `
+		a: [...int]
+		`,
+		path: []string{"a", ""},
+		want: `int`,
+	}, {
+		value: `
+		[Name=string]: { a: Name }
+		`,
+		path: []string{"", "a"},
+		want: `string`,
+	}, {
+		value: `
+		[Name=string]: { a: Name }
+		`,
+		path: []string{""},
+		want: "{\n\ta: string\n}",
+	}, {
+		value: `
+		a: [Foo=string]: [Bar=string]: { b: Foo+Bar }
+		`,
+		path: []string{"a", "", ""},
+		want: "{\n\tb: string + string\n}",
+	}, {
+		value: `
+		a: [Foo=string]: b: [Bar=string]: { c: Foo+Bar }
+		a: foo: b: [Bar=string]: { d: Bar }
+		`,
+		path: []string{"a", "foo", "b", ""},
+		want: "{\n\td: string\n\tc: string + string\n}",
+	}}
+	for _, tc := range testCases {
+		t.Run("", func(t *testing.T) {
+			v := getInstance(t, tc.value).Value()
+			v.v.Finalize(v.ctx().opCtx) // TODO: do in instance.
+			for _, p := range tc.path {
+				if p == "" {
+					var ok bool
+					v, ok = v.Elem()
+					if !ok {
+						t.Fatal("expected element")
+					}
+				} else {
+					v = v.Lookup(p)
+				}
+			}
+			got := fmt.Sprint(v)
+			// got := debug.NodeString(v.ctx().opCtx, v.v, &debug.Config{Compact: true})
+			if got != tc.want {
+				t.Errorf("\n got: %q\nwant: %q", got, tc.want)
+			}
+		})
+	}
+}
+
 func TestSubsumes(t *testing.T) {
 	a := []string{"a"}
 	b := []string{"b"}
@@ -1281,6 +1381,7 @@
 	}
 }
 
+// TODO: options: disallow cycles.
 func TestValidate(t *testing.T) {
 	testCases := []struct {
 		desc string
@@ -1475,7 +1576,7 @@
 					v = v.Lookup(e)
 				}
 			}
-			got, _ := v.v.appendPath(nil, v.idx)
+			got := v.appendPath(nil)
 			if !reflect.DeepEqual(got, tc) {
 				t.Errorf("got %v; want %v", got, tc)
 			}
@@ -1514,7 +1615,7 @@
 	}, {
 		config: config,
 		path:   strList(),
-		str:    "{a: {a: 0, b: 1, c: 2}, b: {d: a.a, e: int}",
+		str:    "{a:{a:0,b:1,c:2},b:{d:0,e:int}",
 	}, {
 		config: config,
 		path:   strList("a", "a"),
@@ -1522,7 +1623,7 @@
 	}, {
 		config: config,
 		path:   strList("a"),
-		str:    "{a: 0, b: 1, c: 2}",
+		str:    "{a:0,b:1,c:2}",
 	}, {
 		config: config,
 		path:   strList("b", "d"),
@@ -1544,7 +1645,7 @@
 				t.Errorf("exists: got %v; want %v", got, tc.notExists)
 			}
 
-			got := fmt.Sprint(v)
+			got := v.ctx().opCtx.Str(v.v)
 			if tc.str == "" {
 				t.Fatalf("str empty, got %q", got)
 			}
@@ -1843,6 +1944,7 @@
 	}
 }
 
+// TODO: duplicate docs.
 func TestValueDoc(t *testing.T) {
 	const config = `
 	// foobar defines at least foo.
@@ -1923,21 +2025,19 @@
 	}, {
 		val:  v1,
 		path: "foos MyFoo field1",
-		doc: `field1 is an int.
+		doc: `local field comment.
 
-local field comment.
+field1 is an int.
 `,
 	}, {
 		val:  v1,
 		path: "foos MyFoo field2",
 		doc:  "other field comment.\n",
 	}, {
+		// Duplicates are now removed.
 		val:  v1,
 		path: "foos MyFoo dup3",
-		doc: `duplicate field comment
-
-duplicate field comment
-`,
+		doc:  "duplicate field comment\n",
 	}, {
 		val:  v1,
 		path: "bar field1",
@@ -1945,9 +2045,9 @@
 	}, {
 		val:  v1,
 		path: "baz field1",
-		doc: `comment from baz on field 1
+		doc: `comment from bar on field 1
 
-comment from bar on field 1
+comment from baz on field 1
 `,
 	}, {
 		val:  v1,
@@ -1961,9 +2061,9 @@
 	}, {
 		val:  both,
 		path: "Foo",
-		doc: `Another Foo.
+		doc: `A Foo fooses stuff.
 
-A Foo fooses stuff.
+Another Foo.
 `,
 	}}
 	for _, tc := range testCases {
@@ -1992,6 +2092,8 @@
 	return doc
 }
 
+// TODO: unwrap marshal error
+// TODO: improve error messages
 func TestMarshalJSON(t *testing.T) {
 	testCases := []struct {
 		value string
@@ -2048,7 +2150,7 @@
 		err:   `0: cannot convert incomplete value`,
 	}, {
 		value: `(>=3 * [1, 2])`,
-		err:   "incomplete error", // TODO: improve error
+		err:   "cue: marshal error: non-concrete value >=3 in operand to *",
 	}, {
 		value: `{}`,
 		json:  `{}`,
@@ -2117,11 +2219,11 @@
 	}, {
 		// Issue #326
 		value: `x: "\(string)": "v"`,
-		err:   `x: incomplete value 'string' in interpolation`,
+		err:   `x: invalid interpolation`,
 	}, {
 		// Issue #326
 		value: `x: "\(bool)": "v"`,
-		err:   `x: expression in interpolation must evaluate to a number kind or string (found bool)`,
+		err:   `invalid interpolation`,
 	}, {
 		// Issue #326
 		value: `
@@ -2173,8 +2275,8 @@
 		out:   "_|_(from source)",
 	}, {
 		value: `(a.b)
-		a: {}`,
-		out: `_|_(undefined field "b")`,
+			a: {}`,
+		out: `_|_(undefined field b)`,
 	}, {
 		value: `true`,
 		out:   `true`,
@@ -2190,15 +2292,18 @@
 	}, {
 		value: `12_000`,
 		out:   `12000`,
+		// out:   `12_000`,
 	}, {
 		value: `12.000`,
 		out:   `12.000`,
 	}, {
 		value: `12M`,
 		out:   `12000000`,
+		// out:   `12M`,
 	}, {
 		value: `3.0e100`,
 		out:   `3.0e+100`,
+		// out:   `3.0e100`,
 	}, {
 		value: `[]`,
 		out:   `[]`,
@@ -2228,8 +2333,11 @@
 				}
 			}
 			inst.Value().Walk(func(v Value) bool {
-				if k, ok := v.Label(); ok {
-					buf = append(buf, k+":"...)
+				v = v.Eval()
+				if !v.v.Label.IsInt() {
+					if k, ok := v.Label(); ok {
+						buf = append(buf, k+":"...)
+					}
 				}
 				switch v.Kind() {
 				case StructKind:
@@ -2237,6 +2345,11 @@
 				case ListKind:
 					buf = append(buf, '[')
 				default:
+					if b, _ := v.v.Value.(*adt.Bottom); b != nil {
+						s := debugStr(v.ctx(), b)
+						buf = append(buf, fmt.Sprint(s, ",")...)
+						return true
+					}
 					buf = append(buf, fmt.Sprint(v, ",")...)
 				}
 				return true
@@ -2283,6 +2396,7 @@
 	testCases := []struct {
 		input string
 		want  string
+		alt   string
 	}{{
 		input: "v: w: x: _|_",
 		want:  "",
@@ -2327,6 +2441,14 @@
 		a: 1
 		`,
 		want: "a",
+	}, {
+		input: `
+		import "math"
+
+		v: w: x: math.Pi
+		`,
+		want: "Pi",
+		alt:  "3.14159265358979323846264338327950288419716939937510582097494459",
 	}}
 	for _, tc := range testCases {
 		t.Run("", func(t *testing.T) {
@@ -2339,15 +2461,20 @@
 			}
 
 			if tc.want != "" {
-				v := inst.Lookup(a...)
-				if x, _ := v.Int64(); x != 1 {
-					t.Errorf("path resolved to %s; want 1", v)
+				want := "1"
+				if tc.alt != "" {
+					want = tc.alt
+				}
+				v := fmt.Sprint(inst.Lookup(a...))
+				if v != want {
+					t.Errorf("path resolved to %s; want %s", v, want)
 				}
 			}
 		})
 	}
 }
 
+// TODO: stack overflow
 func TestPathCorrection(t *testing.T) {
 	testCases := []struct {
 		input  string
@@ -2355,34 +2482,39 @@
 		want   string
 		skip   bool
 	}{{
+		// // TODO: structural cycle.
+		// input: `
+		// a: b: {
+		// 	c: d: b
+		// }
+		// `,
+		// lookup: func(i *Instance) Value {
+		// 	_, a := i.Lookup("a", "b", "c", "d").Expr()
+		// 	return a[0].Lookup("b", "c", "d")
+		// },
+		// want: "a.b",
+		// }, {
+
+		// TODO: embedding: have field operators.
+		// input: `
+		// 	a: {
+		// 		c: 3
+		// 		{x: c}
+		// 	}
+		// 	`,
+		// lookup: func(i *Instance) Value {
+		// 	_, a := i.Lookup("a").Expr()
+		// 	return a[1].Lookup("x")
+		// },
+		// want: "a.c",
+		// }, {
+
+		// TODO: implement proper Elem()
 		input: `
-		a: b: {
-			c: d: b
-		}
-		`,
-		lookup: func(i *Instance) Value {
-			_, a := i.Lookup("a", "b", "c", "d").Expr()
-			return a[0].Lookup("b", "c", "d")
-		},
-		want: "a.b",
-	}, {
-		input: `
-		a: {
-			c: 3
-			{x: c}
-		}
-		`,
-		lookup: func(i *Instance) Value {
-			_, a := i.Lookup("a").Expr()
-			return a[1].Lookup("x")
-		},
-		want: "a.c",
-	}, {
-		input: `
-		a: b: [...T]
-		a: b: [...T]
-		T: 1
-		`,
+			a: b: [...T]
+			a: b: [...T]
+			T: int
+			`,
 		lookup: func(i *Instance) Value {
 			v, _ := i.Lookup("a", "b").Elem()
 			_, a := v.Expr()
@@ -2391,12 +2523,12 @@
 		want: "T",
 	}, {
 		input: `
-			#S: {
-				b?: [...#T]
-				b?: [...#T]
-			}
-			#T: int
-			`,
+				#S: {
+					b?: [...#T]
+					b?: [...#T]
+				}
+				#T: int
+				`,
 		lookup: func(i *Instance) Value {
 			v := i.LookupDef("#S")
 			f, _ := v.LookupField("b")
@@ -2407,43 +2539,65 @@
 		want: "#T",
 	}, {
 		input: `
-			#a: {
-				#T: {b: 3}
-				close({}) | close({c: #T}) | close({d: string})
-			}
-			`,
+		#S: {
+			a?: [...#T]
+			b?: [...#T]
+		}
+		#T: int
+		`,
 		lookup: func(i *Instance) Value {
-			f, _ := i.LookupField("#a")
-			_, a := f.Value.Expr() // &
-			_, a = a[1].Expr()     // |
-			return a[1].Lookup("c")
+			v := i.LookupDef("#S")
+			f, _ := v.LookupField("a")
+			x := f.Value
+			f, _ = v.LookupField("b")
+			y := f.Value
+			u := x.Unify(y)
+			v, _ = u.Elem()
+			_, a := v.Expr()
+			return a[0]
 		},
-		want: "#a.#T",
+		want: "#T",
+		// }, {
+		// 	input: `
+		// 		#a: {
+		// 			#T: {b: 3}
+		// 			close({}) | close({c: #T}) | close({d: string})
+		// 		}
+		// 		`,
+		// 	lookup: func(i *Instance) Value {
+		// 		f, _ := i.LookupField("#a")
+		// 		_, a := f.Value.Expr() // &
+		// 		_, a = a[1].Expr()     // |
+		// 		return a[1].Lookup("c")
+		// 	},
+		// 	want: "#a.#T",
 	}, {
-		input: `
-		package foo
+		// TODO: iterate over Definitions
+		// input: `
+		// 	package foo
 
-		#Struct: {
-			#T: int
+		// 	#Struct: {
+		// 		#T: int
 
-			{b?: #T}
-		}`,
-		want: "#Struct.#T",
-		lookup: func(inst *Instance) Value {
-			// Locate Struct
-			i, _ := inst.Value().Fields(Definitions(true))
-			if !i.Next() {
-				t.Fatal("no fields")
-			}
-			// Locate b
-			i, _ = i.Value().Fields(Definitions(true), Optional(true))
-			if !(i.Next() && i.Next()) {
-				t.Fatal("no fields")
-			}
-			v := i.Value()
-			return v
-		},
-	}, {
+		// 		{b?: #T}
+		// 	}`,
+		// want: "#Struct.#T",
+		// lookup: func(inst *Instance) Value {
+		// 	// Locate Struct
+		// 	i, _ := inst.Value().Fields(Definitions(true))
+		// 	if !i.Next() {
+		// 		t.Fatal("no fields")
+		// 	}
+		// 	// Locate b
+		// 	i, _ = i.Value().Fields(Definitions(true), Optional(true))
+		// 	if !(i.Next() && i.Next()) {
+		// 		t.Fatal("no fields")
+		// 	}
+		// 	v := i.Value()
+		// 	return v
+		// },
+		// }, {
+
 		input: `
 		package foo
 
@@ -2463,75 +2617,80 @@
 			v = v.Lookup("a")
 			return v
 		},
-	}, {
-		input: `
-		package foo
+		// }, {
 
-		#A: #B: #T
+		// TODO: record additionalItems in list
+		// input: `
+		// 	package foo
 
-		#T: {
-			a: [...#S]
-			#S: {}
-		}
-		`,
-		want: "#T.#S",
-		lookup: func(inst *Instance) Value {
-			f, _ := inst.Value().LookupField("#A")
-			f, _ = f.Value.LookupField("#B")
-			v := f.Value
-			v = Dereference(v)
-			v, _ = v.Lookup("a").Elem()
-			return v
-		},
-	}, {
-		input: `
-		#A: {
-			b: #T
-		}
+		// 	#A: #B: #T
 
-		#T: {
-			a: #S
-			#S: {}
-		}
-		`,
-		want: "#T.#S",
-		lookup: func(inst *Instance) Value {
-			f, _ := inst.Value().LookupField("#A")
-			v := f.Value.Lookup("b")
-			v = Dereference(v)
-			v = v.Lookup("a")
-			return v
-		},
-	}, {
-		// TODO(eval): embedded structs are currently represented at the same
-		// level as the enclosing struct. This means that the parent of an
-		// embedded struct skips the struct in which it is embedded. Treat
-		// embedded structs as "anonymous" fields.
-		// This could perhaps be made fixed with dereferencing as well.
-		skip: true,
-		input: `
-		#Tracing: {
-			#T: { address?: string }
-			#S: { ip?: string }
+		// 	#T: {
+		// 		a: [...#S]
+		// 		#S: {}
+		// 	}
+		// 	`,
+		// want: "#T.#S",
+		// lookup: func(inst *Instance) Value {
+		// 	f, _ := inst.Value().LookupField("#A")
+		// 	f, _ = f.Value.LookupField("#B")
+		// 	v := f.Value
+		// 	v = Dereference(v)
+		// 	v, _ = v.Lookup("a").Elem()
+		// 	return v
+		// },
+		// }, {
 
-			close({}) | close({
-				t: #T
-			}) | close({
-				s: S
-			})
-		}
-		#X: {}
-		#X // Disconnect top-level struct from the one visible by close.
-		`,
-		want: "",
-		lookup: func(inst *Instance) Value {
-			f, _ := inst.Value().LookupField("#Tracing")
-			v := f.Value.Eval()
-			_, args := v.Expr()
-			v = args[1].Lookup("t")
-			v = Dereference(v)
-			return v
-		},
+		// YAY: works.
+		// input: `
+		// 	#A: {
+		// 		b: #T
+		// 	}
+
+		// 	#T: {
+		// 		a: #S
+		// 		#S: {}
+		// 	}
+		// 	`,
+		// want: "#T.#S",
+		// lookup: func(inst *Instance) Value {
+		// 	f, _ := inst.Value().LookupField("#A")
+		// 	v := f.Value.Lookup("b")
+		// 	v = Dereference(v)
+		// 	v = v.Lookup("a")
+		// 	return v
+		// },
+		// }, {
+
+		// 	// TODO(eval): embedded structs are currently represented at the same
+		// 	// level as the enclosing struct. This means that the parent of an
+		// 	// embedded struct skips the struct in which it is embedded. Treat
+		// 	// embedded structs as "anonymous" fields.
+		// 	// This could perhaps be made fixed with dereferencing as well.
+		// 	skip: true,
+		// input: `
+		// 	#Tracing: {
+		// 		#T: { address?: string }
+		// 		#S: { ip?: string }
+
+		// 		close({}) | close({
+		// 			t: #T
+		// 		}) | close({
+		// 			s: #S
+		// 		})
+		// 	}
+		// 	#X: {}
+		// 	#X // Disconnect top-level struct from the one visible by close.
+		// 	`,
+		// want: "",
+		// lookup: func(inst *Instance) Value {
+		// 	f, _ := inst.Value().LookupField("#Tracing")
+		// 	v := f.Value.Eval()
+		// 	_, args := v.Expr()
+		// 	v = args[1].Lookup("t")
+		// 	v = Dereference(v)
+		// 	return v
+		// },
 	}}
 	for _, tc := range testCases {
 		if tc.skip {
@@ -2556,64 +2715,64 @@
 	}
 }
 
-func TestReferences(t *testing.T) {
-	config1 := `
-	a: {
-		b: 3
-	}
-	c: {
-		d: a.b
-		e: c.d
-		f: a
-	}
-	`
-	config2 := `
-	a: { c: 3 }
-	b: { c: int, d: 4 }
-	r: (a & b).c
-	c: {args: s1 + s2}.args
-	s1: string
-	s2: string
-	d: ({arg: b}).arg.c
-	e: f.arg.c
-	f: {arg: b}
-	`
-	testCases := []struct {
-		config string
-		in     string
-		out    string
-	}{
-		{config1, "c.d", "a.b"},
-		{config1, "c.e", "c.d"},
-		{config1, "c.f", "a"},
+// func TestReferences(t *testing.T) {
+// 	config1 := `
+// 	a: {
+// 		b: 3
+// 	}
+// 	c: {
+// 		d: a.b
+// 		e: c.d
+// 		f: a
+// 	}
+// 	`
+// 	config2 := `
+// 	a: { c: 3 }
+// 	b: { c: int, d: 4 }
+// 	r: (a & b).c
+// 	c: {args: s1 + s2}.args
+// 	s1: string
+// 	s2: string
+// 	d: ({arg: b}).arg.c
+// 	e: f.arg.c
+// 	f: {arg: b}
+// 	`
+// 	testCases := []struct {
+// 		config string
+// 		in     string
+// 		out    string
+// 	}{
+// 		{config1, "c.d", "a.b"},
+// 		{config1, "c.e", "c.d"},
+// 		{config1, "c.f", "a"},
 
-		{config2, "r", "a.c b.c"},
-		{config2, "c", "s1 s2"},
-		// {config2, "d", "b.c"}, // TODO: make this work as well.
-		{config2, "e", "f.arg.c"}, // TODO: should also report b.c.
-	}
-	for _, tc := range testCases {
-		t.Run(tc.in, func(t *testing.T) {
-			ctx, st := compileFile(t, tc.config)
-			v := newValueRoot(ctx, st)
-			for _, k := range strings.Split(tc.in, ".") {
-				obj, err := v.structValFull(ctx)
-				if err != nil {
-					t.Fatal(err)
-				}
-				v = obj.Lookup(k)
-			}
-			got := []string{}
-			for _, r := range v.References() {
-				got = append(got, strings.Join(r, "."))
-			}
-			want := strings.Split(tc.out, " ")
-			if !reflect.DeepEqual(got, want) {
-				t.Errorf("got %v; want %v", got, want)
-			}
-		})
-	}
-}
+// 		{config2, "r", "a.c b.c"},
+// 		{config2, "c", "s1 s2"},
+// 		// {config2, "d", "b.c"}, // TODO: make this work as well.
+// 		{config2, "e", "f.arg.c"}, // TODO: should also report b.c.
+// 	}
+// 	for _, tc := range testCases {
+// 		t.Run(tc.in, func(t *testing.T) {
+// 			ctx, st := compileFile(t, tc.config)
+// 			v := newValueRoot(ctx, st)
+// 			for _, k := range strings.Split(tc.in, ".") {
+// 				obj, err := v.structValFull(ctx)
+// 				if err != nil {
+// 					t.Fatal(err)
+// 				}
+// 				v = obj.Lookup(k)
+// 			}
+// 			got := []string{}
+// 			for _, r := range v.References() {
+// 				got = append(got, strings.Join(r, "."))
+// 			}
+// 			want := strings.Split(tc.out, " ")
+// 			if !reflect.DeepEqual(got, want) {
+// 				t.Errorf("got %v; want %v", got, want)
+// 			}
+// 		})
+// 	}
+// }
 
 func checkErr(t *testing.T, err error, str, name string) bool {
 	t.Helper()
@@ -2659,13 +2818,16 @@
 		input: "v: 3 + 4",
 		want:  "+(3 4)",
 	}, {
-		input: "v: !a, a: 3",
-		want:  `!(.(<0> "a"))`,
+		input: "v: !a, a: bool",
+		want:  `!(.(〈〉 "a"))`,
+	}, {
+		input: "v: !a, a: 3", // TODO: Should still look up.
+		want:  `!(.(〈〉 "a"))`,
 	}, {
 		input: "v: 1 | 2 | 3 | *4",
 		want:  "|(1 2 3 4)",
 	}, {
-		input: "v: 2 & 5",
+		input: "v: 2 & 5", // Allow even with error.
 		want:  "&(2 5)",
 	}, {
 		input: "v: 2 | 5",
@@ -2681,7 +2843,7 @@
 		want:  "==(2 5)",
 	}, {
 		input: "v: !b, b: true",
-		want:  `!(.(<0> "b"))`,
+		want:  `!(.(〈〉 "b"))`,
 	}, {
 		input: "v: 2 != 5",
 		want:  "!=(2 5)",
@@ -2729,31 +2891,31 @@
 		want:  "mod(2 5)",
 	}, {
 		input: "v: a.b, a: b: 4",
-		want:  `.(.(<0> "a") "b")`,
+		want:  `.(.(〈〉 "a") "b")`,
 	}, {
 		input: `v: a["b"], a: b: 3 `,
-		want:  `[](.(<0> "a") "b")`,
+		want:  `[](.(〈〉 "a") "b")`,
 	}, {
 		input: "v: a[2:5], a: [1, 2, 3, 4, 5]",
-		want:  `[:](.(<0> "a") 2 5)`,
+		want:  `[:](.(〈〉 "a") 2 5)`,
 	}, {
 		input: "v: len([])",
 		want:  "()(len [])",
 	}, {
 		input: "v: a.b, a: { b: string }",
-		want:  `.(.(<0> "a") "b")`,
+		want:  `.(.(〈〉 "a") "b")`,
 	}, {
 		input: `v: "Hello, \(x)! Welcome to \(place)", place: string, x: string`,
-		want:  `\()("Hello, " .(<0> "x") "! Welcome to " .(<0> "place") "")`,
+		want:  `\()("Hello, " .(〈〉 "x") "! Welcome to " .(〈〉 "place") "")`,
 	}, {
 		input: `v: { a, b: 1 }, a: 2`,
-		want:  `&(<0>{b: 1} .(<0> "a"))`,
+		want:  `&(.(〈〉 "a") {b:1})`,
 	}, {
 		input: `v: { {c: a}, b: a }, a: int`,
-		want:  `&(<0>{b: <1>.a} <0>{c: <1>.a})`,
+		want:  `&({c:a} {b:a})`,
 	}, {
 		input: `v: [...number] | *[1, 2, 3]`,
-		want:  `([, ...number] | *[1,2,3])`,
+		want:  `([...number]|*[1,2,3])`,
 	}}
 	for _, tc := range testCases {
 		t.Run(tc.input, func(t *testing.T) {
@@ -2765,10 +2927,11 @@
 		})
 	}
 }
+
 func exprStr(v Value) string {
 	op, operands := v.Expr()
 	if op == NoOp {
-		return debugStr(v.ctx(), v.v.v)
+		return compactRawStr(v)
 	}
 	s := op.String()
 	s += "("
@@ -2781,3 +2944,15 @@
 	s += ")"
 	return s
 }
+
+func compactRawStr(v Value) string {
+	ctx := v.ctx()
+	cfg := &debug.Config{Compact: true, Raw: true}
+	return debug.NodeString(ctx.opCtx, v.v, cfg)
+}
+
+func compactValueStr(v Value) string {
+	ctx := v.ctx()
+	cfg := &debug.Config{Compact: true}
+	return debug.NodeString(ctx.opCtx, v.v, cfg)
+}
diff --git a/cue/validate.go b/cue/validate.go
deleted file mode 100644
index f6890d4..0000000
--- a/cue/validate.go
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2018 The 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"
-
-// validate returns whether there is any error, recursively.
-func validate(ctx *context, v value) (err *bottom) {
-	eval := v.evalPartial(ctx)
-	if err, ok := eval.(*bottom); ok && err.Code != codeIncomplete && err.Code != codeCycle {
-		return eval.(*bottom)
-	}
-	switch x := eval.(type) {
-	case *structLit:
-		x, err = x.expandFields(ctx)
-		if err != nil {
-			return err
-		}
-		if ctx.maxDepth++; ctx.maxDepth > internal.MaxDepth {
-			return nil
-		}
-		for i, a := range x.Arcs {
-			if a.optional {
-				continue
-			}
-			if err := validate(ctx, x.at(ctx, i)); err != nil {
-				ctx.maxDepth--
-				return err
-			}
-		}
-		ctx.maxDepth--
-	case *list:
-		// TODO: also validate types for open lists?
-		return validate(ctx, x.elem)
-	}
-	return nil
-}
diff --git a/cue/value.go b/cue/value.go
deleted file mode 100644
index 29e81ff..0000000
--- a/cue/value.go
+++ /dev/null
@@ -1,1948 +0,0 @@
-// Copyright 2018 The 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 (
-	"math/big"
-	"regexp"
-	"sort"
-	"strconv"
-	"time"
-
-	"github.com/cockroachdb/apd/v2"
-
-	"cuelang.org/go/cue/ast"
-	"cuelang.org/go/cue/literal"
-	"cuelang.org/go/cue/token"
-	"cuelang.org/go/internal/core/adt"
-)
-
-type value interface {
-	source
-
-	rewrite(*context, rewriteFunc) value
-
-	// evalPartial evaluates a value without choosing default values.
-	evalPartial(*context) evaluated
-
-	Kind() kind
-
-	// subsumesImpl is only defined for non-reference types.
-	// It should only be called by the subsumes function.
-	subsumesImpl(*subsumer, value) bool
-}
-
-type evaluated interface {
-	value
-	binOp(*context, source, op, evaluated) evaluated
-	strValue() string
-}
-
-type scope interface {
-	value
-	Lookup(*context, label) arc
-}
-
-type atter interface {
-	// at returns the evaluated and its original value at the given position.
-	// If the original could not be found, it returns an error and nil.
-	at(*context, int) evaluated
-}
-
-type iterAtter interface {
-	// at returns the evaluated and its original value at the given position.
-	// If the original could not be found, it returns an error and nil.
-	iterAt(*context, int) arc
-}
-
-// caller must be implemented by any concrete lambdaKind
-type caller interface {
-	call(ctx *context, src source, args ...evaluated) value
-	returnKind() kind
-}
-
-func checkKind(ctx *context, x value, want kind) *bottom {
-	if b, ok := x.(*bottom); ok {
-		return b
-	}
-	got := x.Kind()
-	if got&want&concreteKind == bottomKind && want != bottomKind {
-		return ctx.mkErr(x, "cannot use value %v (type %s) as %s", ctx.str(x), got, want)
-	}
-	if !got.isGround() {
-		return ctx.mkErr(x, codeIncomplete,
-			"non-concrete value %v", got)
-	}
-	return nil
-}
-
-func newDecl(n ast.Decl) baseValue {
-	if n == nil {
-		panic("empty node")
-	}
-	return baseValue{n}
-}
-
-func newExpr(n ast.Expr) baseValue {
-	if n == nil {
-		panic("empty node")
-	}
-	return baseValue{n}
-}
-
-func newNode(n ast.Node) baseValue {
-	if n == nil {
-		panic("empty node")
-	}
-	return baseValue{n}
-}
-
-type source interface {
-	// syntax returns the parsed file of the underlying node or a computed
-	// node indicating that it is a computed binary expression.
-	Source() ast.Node
-	computed() *computedSource
-	Pos() token.Pos
-	base() baseValue
-}
-
-type computedSource struct {
-	pos token.Pos
-	op  op
-	x   value
-	y   value
-}
-
-func (s *computedSource) Pos() token.Pos {
-	return s.pos
-}
-
-type posser interface {
-	Pos() token.Pos
-}
-
-type baseValue struct {
-	pos posser
-}
-
-func (b baseValue) Pos() token.Pos {
-	if b.pos == nil {
-		return token.NoPos
-	}
-	return b.pos.Pos()
-}
-
-func (b baseValue) computed() *computedSource {
-	switch x := b.pos.(type) {
-	case *computedSource:
-		return x
-	}
-	return nil
-}
-
-func (b baseValue) Source() ast.Node {
-	switch x := b.pos.(type) {
-	case ast.Node:
-		return x
-	}
-	return nil
-}
-
-func (b baseValue) base() baseValue {
-	return b
-}
-
-func (b baseValue) strValue() string { panic("unimplemented") }
-func (b baseValue) returnKind() kind { panic("unimplemented") }
-
-// top is the top of the value lattice. It subsumes all possible values.
-type top struct{ baseValue }
-
-func (x *top) Kind() kind { return topKind }
-
-// basicType represents the root class of any specific type.
-type basicType struct {
-	baseValue
-	K kind
-}
-
-func (x *basicType) Kind() kind { return x.K | nonGround }
-
-// Literals
-
-type nullLit struct{ baseValue }
-
-func (x *nullLit) Kind() kind { return nullKind }
-
-type boolLit struct {
-	baseValue
-	B bool
-}
-
-func (x *boolLit) Kind() kind { return boolKind }
-
-func boolTonode(src source, b bool) evaluated {
-	return &boolLit{src.base(), b}
-}
-
-type bytesLit struct {
-	baseValue
-	B []byte
-	// Also support https://github.com/dlclark/regexp2 to
-	// accommodate JSON Schema?
-	RE *regexp.Regexp // only set if needed
-}
-
-func (x *bytesLit) Kind() kind       { return bytesKind }
-func (x *bytesLit) strValue() string { return string(x.B) }
-
-func (x *bytesLit) iterAt(ctx *context, i int) arc {
-	if i >= len(x.B) {
-		return arc{}
-	}
-	v := x.at(ctx, i)
-	return arc{v: v, Value: v}
-}
-
-func (x *bytesLit) at(ctx *context, i int) evaluated {
-	if i < 0 || i >= len(x.B) {
-		return ctx.mkErr(x, "index %d out of bounds", i)
-	}
-	// TODO: this is incorrect.
-	return newInt(x, 0).setUInt64(uint64(x.B[i]))
-}
-
-func (x *bytesLit) len() int { return len(x.B) }
-
-func (x *bytesLit) slice(ctx *context, lo, hi *numLit) evaluated {
-	lox := 0
-	hix := len(x.B)
-	if lo != nil {
-		lox = lo.intValue(ctx)
-	}
-	if hi != nil {
-		hix = hi.intValue(ctx)
-	}
-	if lox < 0 {
-		return ctx.mkErr(x, "invalid slice index %d (must be non-negative)", lox)
-	}
-	if hix < 0 {
-		return ctx.mkErr(x, "invalid slice index %d (must be non-negative)", hix)
-	}
-	if hix < lox {
-		return ctx.mkErr(x, "invalid slice index: %d > %d", lox, hix)
-	}
-	if len(x.B) < hix {
-		return ctx.mkErr(hi, "slice bounds out of range")
-	}
-	return &bytesLit{x.baseValue, x.B[lox:hix], nil}
-}
-
-type stringLit struct {
-	baseValue
-	Str string
-	RE  *regexp.Regexp // only set if needed
-
-	// TODO: maintain extended grapheme index cache.
-}
-
-func (x *stringLit) Kind() kind       { return stringKind }
-func (x *stringLit) strValue() string { return x.Str }
-
-func (x *stringLit) iterAt(ctx *context, i int) arc {
-	runes := []rune(x.Str)
-	if i >= len(runes) {
-		return arc{}
-	}
-	v := x.at(ctx, i)
-	return arc{v: v, Value: v}
-}
-
-func (x *stringLit) at(ctx *context, i int) evaluated {
-	runes := []rune(x.Str)
-	if i < 0 || i >= len(runes) {
-		return ctx.mkErr(x, "index %d out of bounds", i)
-	}
-	// TODO: this is incorrect.
-	return &stringLit{x.baseValue, string(runes[i : i+1]), nil}
-}
-func (x *stringLit) len() int { return len([]rune(x.Str)) }
-
-func (x *stringLit) slice(ctx *context, lo, hi *numLit) evaluated {
-	runes := []rune(x.Str)
-	lox := 0
-	hix := len(runes)
-	if lo != nil {
-		lox = lo.intValue(ctx)
-	}
-	if hi != nil {
-		hix = hi.intValue(ctx)
-	}
-	if lox < 0 {
-		return ctx.mkErr(x, "invalid slice index %d (must be non-negative)", lox)
-	}
-	if hix < 0 {
-		return ctx.mkErr(x, "invalid slice index %d (must be non-negative)", hix)
-	}
-	if hix < lox {
-		return ctx.mkErr(x, "invalid slice index: %d > %d", lox, hix)
-	}
-	if len(runes) < hix {
-		return ctx.mkErr(hi, "slice bounds out of range")
-	}
-	return &stringLit{x.baseValue, string(runes[lox:hix]), nil}
-}
-
-type numLit struct {
-	baseValue
-	rep literal.Multiplier
-	K   kind
-	X   apd.Decimal
-}
-
-func newNum(src source, k kind, rep literal.Multiplier) *numLit {
-	if k&numKind == 0 {
-		panic("not a number")
-	}
-	return &numLit{baseValue: src.base(), rep: rep, K: k}
-}
-
-func newInt(src source, rep literal.Multiplier) *numLit {
-	return newNum(src, intKind, rep)
-}
-
-func newFloat(src source, rep literal.Multiplier) *numLit {
-	return newNum(src, floatKind, rep)
-}
-
-func (n numLit) specialize(k kind) *numLit {
-	n.K = k
-	return &n
-}
-
-func (n *numLit) set(d *apd.Decimal) *numLit {
-	n.X.Set(d)
-	return n
-}
-
-func (n *numLit) setInt(x int) *numLit {
-	n.X.SetInt64(int64(x))
-	return n
-}
-
-func (n *numLit) setInt64(x int64) *numLit {
-	n.X.SetInt64(x)
-	return n
-}
-
-func (n *numLit) setUInt64(x uint64) *numLit {
-	n.X.Coeff.SetUint64(x)
-	return n
-}
-
-func (n *numLit) setString(s string) *numLit {
-	_, _, _ = n.X.SetString(s)
-	return n
-}
-
-func (n *numLit) String() string {
-	if n.K&intKind != 0 {
-		return n.X.Text('f') // also render info
-	}
-	s := n.X.Text('g')
-	if len(s) == 1 {
-		s += "."
-	}
-	return s // also render info
-}
-
-func parseInt(k kind, s string) *numLit {
-	num := newInt(newExpr(ast.NewLit(token.INT, s)), 0)
-	_, _, err := num.X.SetString(s)
-	if err != nil {
-		panic(err)
-	}
-	return num
-}
-
-func parseFloat(s string) *numLit {
-	num := newFloat(newExpr(ast.NewLit(token.FLOAT, s)), 0)
-	_, _, err := num.X.SetString(s)
-	if err != nil {
-		panic(err)
-	}
-	return num
-}
-
-var ten = big.NewInt(10)
-
-var one = parseInt(intKind, "1")
-
-func (x *numLit) Kind() kind       { return x.K }
-func (x *numLit) strValue() string { return x.X.String() }
-
-func (x *numLit) isInt(ctx *context) bool {
-	return x.Kind()&intKind != 0
-}
-
-func (x *numLit) intValue(ctx *context) int {
-	v, err := x.X.Int64()
-	if err != nil {
-		return 0
-	}
-	return int(v)
-}
-
-type durationLit struct {
-	baseValue
-	d time.Duration
-}
-
-func (x *durationLit) Kind() kind       { return durationKind }
-func (x *durationLit) strValue() string { return x.d.String() }
-
-type bound struct {
-	baseValue
-	Op   op   // opNeq, opLss, opLeq, opGeq, or opGtr
-	k    kind // mostly used for number kind
-	Expr value
-}
-
-func newBound(ctx *context, base baseValue, op op, k kind, v value) evaluated {
-	kv := v.Kind()
-	if kv.isAnyOf(numKind) {
-		kv |= numKind
-	} else if op == opNeq && kv&atomKind == nullKind {
-		kv = typeKinds &^ nullKind
-	}
-	if op == opMat || op == opNMat {
-		v = compileRegexp(ctx, v)
-		if isBottom(v) {
-			return v.(*bottom)
-		}
-	}
-	return &bound{base, op, unifyType(k&topKind, kv) | nonGround, v}
-}
-
-func (x *bound) Kind() kind {
-	return x.k
-}
-
-func mkIntRange(a, b string) evaluated {
-	from := newBound(nil, baseValue{}, opGeq, intKind, parseInt(intKind, a))
-	to := newBound(nil, baseValue{}, opLeq, intKind, parseInt(intKind, b))
-	e := &unification{
-		binSrc(token.NoPos, opUnify, from, to),
-		[]evaluated{from, to},
-	}
-	// TODO: make this an integer
-	// int := &basicType{k: intKind}
-	// e = &unification{
-	// 	binSrc(token.NoPos, opUnify, int, e),
-	// 	[]evaluated{int, e},
-	// }
-	return e
-}
-
-func mkFloatRange(a, b string) evaluated {
-	from := newBound(nil, baseValue{}, opGeq, numKind, parseFloat(a))
-	to := newBound(nil, baseValue{}, opLeq, numKind, parseFloat(b))
-	e := &unification{
-		binSrc(token.NoPos, opUnify, from, to),
-		[]evaluated{from, to},
-	}
-	// TODO: make this an integer
-	// int := &basicType{k: intKind}
-	// e = &unification{
-	// 	binSrc(token.NoPos, opUnify, int, e),
-	// 	[]evaluated{int, e},
-	// }
-	return e
-}
-
-var predefinedRanges = map[string]evaluated{
-	"rune":  mkIntRange("0", strconv.Itoa(0x10FFFF)),
-	"int8":  mkIntRange("-128", "127"),
-	"int16": mkIntRange("-32768", "32767"),
-	"int32": mkIntRange("-2147483648", "2147483647"),
-	"int64": mkIntRange("-9223372036854775808", "9223372036854775807"),
-	"int128": mkIntRange(
-		"-170141183460469231731687303715884105728",
-		"170141183460469231731687303715884105727"),
-
-	// Do not include an alias for "byte", as it would be too easily confused
-	// with the builtin "bytes".
-	"uint":    newBound(nil, baseValue{}, opGeq, intKind, parseInt(intKind, "0")),
-	"uint8":   mkIntRange("0", "255"),
-	"uint16":  mkIntRange("0", "65535"),
-	"uint32":  mkIntRange("0", "4294967295"),
-	"uint64":  mkIntRange("0", "18446744073709551615"),
-	"uint128": mkIntRange("0", "340282366920938463463374607431768211455"),
-
-	// 2**127 * (2**24 - 1) / 2**23
-	"float32": mkFloatRange(
-		"-3.40282346638528859811704183484516925440e+38",
-		"+3.40282346638528859811704183484516925440e+38",
-	),
-	// 2**1023 * (2**53 - 1) / 2**52
-	"float64": mkFloatRange(
-		"-1.797693134862315708145274237317043567981e+308",
-		"+1.797693134862315708145274237317043567981e+308",
-	),
-}
-
-type interpolation struct {
-	baseValue
-	K     kind    // string or bytes
-	Parts []value // odd: strings, even expressions
-}
-
-func (x *interpolation) Kind() kind { return x.K | nonGround }
-
-type list struct {
-	baseValue
-	elem *structLit
-
-	typ value
-
-	// TODO: consider removing len. Currently can only be len(a) or >= len(a)
-	// and could be replaced with a bool.
-	len value
-}
-
-// initLit initializes a literal list.
-func (x *list) initLit() {
-	x.len = newInt(x, 0).setInt(len(x.elem.Arcs))
-	x.typ = &top{x.baseValue}
-}
-
-func (x *list) manifest(ctx *context) evaluated {
-	if x.Kind().isGround() {
-		return x
-	}
-	// A list is ground if its length is ground, or if the current length
-	// meets matches the cap.
-	n := newInt(x, 0).setInt(len(x.elem.Arcs))
-	if n := binOp(ctx, x, opUnify, n, x.len.evalPartial(ctx)); !isBottom(n) {
-		return &list{
-			baseValue: x.baseValue,
-			elem:      x.elem,
-			len:       n,
-			typ:       &top{x.baseValue},
-		}
-	}
-	return x
-}
-
-func (x *list) Kind() kind {
-	k := listKind
-	if _, ok := x.len.(*numLit); ok {
-		return k
-	}
-	return k | nonGround
-}
-
-// at returns the evaluated and original value of position i. List x must
-// already have been evaluated. It returns an error and nil if there was an
-// issue evaluating the list itself.
-func (x *list) at(ctx *context, i int) evaluated {
-	arc := x.iterAt(ctx, i)
-	if arc.Value == nil {
-		return ctx.mkErr(x, "index %d out of bounds", i)
-	}
-	return arc.Value
-}
-
-// iterAt returns the evaluated and original value of position i. List x must
-// already have been evaluated. It returns an error and nil if there was an
-// issue evaluating the list itself.
-func (x *list) iterAt(ctx *context, i int) arc {
-	if i < 0 {
-		v := ctx.mkErr(x, "index %d out of bounds", i)
-		return arc{Value: v}
-	}
-	if i < len(x.elem.Arcs) {
-		a := x.elem.iterAt(ctx, i)
-		a.Label = 0
-		return a
-	}
-	max := maxNum(x.len.(evaluated))
-	if max.Kind().isGround() {
-		if max.Kind()&intKind == bottomKind {
-			v := ctx.mkErr(max, "length indicator of list not of type int")
-			return arc{Value: v}
-		}
-		n := max.(*numLit).intValue(ctx)
-		if i >= n {
-			return arc{}
-		}
-	}
-	return arc{Value: x.typ.evalPartial(ctx), v: x.typ}
-}
-
-func (x *list) isOpen() bool {
-	return !x.len.Kind().isGround()
-}
-
-// lo and hi must be nil or a ground integer.
-func (x *list) slice(ctx *context, lo, hi *numLit) evaluated {
-	a := x.elem.Arcs
-	max := maxNum(x.len).evalPartial(ctx)
-	if hi != nil {
-		n := hi.intValue(ctx)
-		if n < 0 {
-			return ctx.mkErr(x, "negative slice index")
-		}
-		if max.Kind().isGround() && !leq(ctx, hi, hi, max) {
-			return ctx.mkErr(hi, "slice bounds out of range")
-		}
-		max = hi
-		if n < len(a) {
-			a = a[:n]
-		}
-	}
-
-	if lo != nil {
-		n := lo.intValue(ctx)
-		if n < 0 {
-			return ctx.mkErr(x, "negative slice index")
-		}
-		if n > 0 && max.Kind().isGround() {
-			if !leq(ctx, lo, lo, max) {
-				max := max.(*numLit).intValue(ctx)
-				return ctx.mkErr(x, "invalid slice index: %v > %v", n, max)
-			}
-			max = binOp(ctx, lo, opSub, max, lo)
-		}
-		if n < len(a) {
-			a = a[n:]
-		} else {
-			a = []arc{}
-		}
-	}
-	arcs := make([]arc, len(a))
-	for i, a := range a {
-		arcs[i] = arc{Label: label(i), v: a.v, docs: a.docs}
-	}
-	s := &structLit{baseValue: x.baseValue, Arcs: arcs}
-	return &list{baseValue: x.baseValue, elem: s, typ: x.typ, len: max}
-}
-
-// An structLit is a single structLit in the configuration tree.
-//
-// An structLit may have multiple arcs. There may be only one arc per label. Use
-// insertRaw to insert arcs to ensure this invariant holds.
-type structLit struct {
-	baseValue
-
-	// TODO(perf): separate out these infrequent values to save space.
-	emit value // currently only supported at top level.
-	// TODO: make this a list of templates and don't unify until templates are
-	// applied. This allows generalization of having different constraints
-	// for different field sets. This could also be used to mark closedness:
-	// use [string]: _ for fully open. This could be a sentinel value.
-	// For now we use a boolean for closedness.
-
-	// NOTE: must be conjunction of lists.
-	// For lists originating from closed structs,
-	// there must be at least one match.
-	// templates [][]value
-	// catch_all: value
-
-	// optionals holds pattern-constraint pairs that
-	// are applied to all concrete values in this struct.
-	optionals   *optionals
-	closeStatus closeMode
-
-	comprehensions []compValue
-
-	// TODO: consider hoisting the template arc to its own value.
-	Arcs     []arc
-	expanded evaluated
-}
-
-// compValue is a temporary stop-gap until the correct unification algorithm is
-// implemented. This implementation is more strict than should be. When two
-// structs, of which at least one is closed, are unified, the fields resolving
-// later from unresolved comprehensions should match the closedness constraints.
-// To relax this constraint, unification could follow the lines of
-// traditional unification with bookkeeping of which fields are
-// allowed, to be applied as constraints after full unification.
-
-type compValue struct {
-	checked bool
-	comp    value
-}
-
-// optionals holds a set of key pattern-constraint pairs, where constraints are
-// to be applied to concrete fields of which the label matches the key pattern.
-//
-// optionals will either hold concrete fields or a couple of nested optional
-// structs combined based on the op type, but not both.
-type optionals struct {
-	closed closeMode
-	op     op
-	left   *optionals // nil means empty closed struct
-	right  *optionals // nil means empty closed struct
-	fields []optionalSet
-}
-
-type optionalSet struct {
-	// A key filter may be nil, in which case it means all strings, or _.
-	key value
-
-	// constraint must evaluate to a lambda and is applied to any concrete
-	// value for which the key matches key.
-	value value
-}
-
-func newOptional(key, value value) *optionals {
-	return &optionals{
-		fields: []optionalSet{{key, value}},
-	}
-}
-
-// isClosed mirrors the closed status of the struct to which
-// this optionals belongs.
-func (o *optionals) isClosed() bool {
-	if o == nil {
-		return true
-	}
-	return o.closed.isClosed()
-}
-
-func (o *optionals) close() *optionals {
-	if o == nil {
-		return nil
-	}
-	o.closed |= isClosed
-	return o
-}
-
-// isEmpty reports whether this optionals may report true for match. Even if an
-// optionals is empty, it may still hold constraints to be applied to already
-// existing concrete fields.
-func (o *optionals) isEmpty() bool {
-	if o == nil {
-		return true
-	}
-	le := o.left.isEmpty()
-	re := o.right.isEmpty()
-
-	if o.op == opUnify {
-		if le && o.left.isClosed() {
-			return true
-		}
-		if re && o.right.isClosed() {
-			return true
-		}
-	}
-	return le && re && len(o.fields) == 0
-}
-
-// isFull reports whether match reports true for all fields.
-func (o *optionals) isFull() bool {
-	found, _ := o.match(nil, nil)
-	return found
-}
-
-// match reports whether a field with the given name may be added in the
-// associated struct as a new field. ok is false if there was any closed
-// struct that failed to match. Even if match returns false, there may still be
-// constraints represented by optionals that are to be applied to existing
-// concrete fields.
-func (o *optionals) match(ctx *context, str *stringLit) (found, ok bool) {
-	if o == nil {
-		return false, true
-	}
-
-	found1, ok := o.left.match(ctx, str)
-	if !ok && o.op == opUnify {
-		return false, false
-	}
-
-	found2, ok := o.right.match(ctx, str)
-	if !ok && o.op == opUnify {
-		return false, false
-	}
-
-	if found1 || found2 {
-		return true, true
-	}
-
-	for _, f := range o.fields {
-		if f.key == nil {
-			return true, true
-		}
-		if str != nil {
-			v := binOp(ctx, f.value, opUnify, f.key.evalPartial(ctx), str)
-			if !isBottom(v) {
-				return true, true
-			}
-		}
-	}
-
-	return false, !o.closed.isClosed()
-}
-
-func (o *optionals) allows(ctx *context, f label) bool {
-	if o == nil {
-		return false
-	}
-	if f.IsDef() || f.IsHidden() {
-		return false
-	}
-
-	str := ctx.LabelStr(f)
-	arg := &stringLit{Str: str}
-
-	found, ok := o.match(ctx, arg)
-	return found && ok
-}
-
-func (o *optionals) add(ctx *context, key, value value) {
-	for i, b := range o.fields {
-		if b.key == key {
-			o.fields[i].value = mkBin(ctx, token.NoPos, opUnify, b.value, value)
-			return
-		}
-	}
-	o.fields = append(o.fields, optionalSet{key, value})
-}
-
-// isDotDotDot reports whether optionals only contains fully-qualified
-// constraints. This is useful for some optimizations.
-func (o *optionals) isDotDotDot() bool {
-	if o == nil {
-		return false
-	}
-	if len(o.fields) > 1 {
-		return false
-	}
-	if len(o.fields) == 1 {
-		f := o.fields[0]
-		if f.key != nil {
-			return false
-		}
-		lambda, ok := f.value.(*lambdaExpr)
-		if ok {
-			if _, ok = lambda.value.(*top); ok {
-				return true
-			}
-		}
-		return false
-	}
-	if o.left == nil {
-		return o.right.isDotDotDot()
-	}
-	if o.right == nil {
-		return o.left.isDotDotDot()
-	}
-	return o.left.isDotDotDot() && o.right.isDotDotDot()
-}
-
-// constraint returns the unification of all constraints for which arg matches
-// the key filter. doc contains the documentation of all applicable fields.
-func (o *optionals) constraint(ctx *context, label evaluated) (u value, doc *docNode) {
-	if o == nil {
-		return nil, nil
-	}
-	add := func(v value) {
-		if v != nil {
-			if u == nil {
-				u = v
-			} else {
-				u = mkBin(ctx, token.NoPos, opUnify, u, v)
-			}
-		}
-	}
-	v, doc1 := o.left.constraint(ctx, label)
-	add(v)
-	v, doc2 := o.right.constraint(ctx, label)
-	add(v)
-
-	if doc1 != nil || doc2 != nil {
-		doc = &docNode{left: doc1, right: doc2}
-	}
-
-	arg := label
-	if arg == nil {
-		arg = &basicType{K: stringKind}
-	}
-
-	for _, s := range o.fields {
-		if s.key != nil {
-			if label == nil {
-				continue
-			}
-			key := s.key.evalPartial(ctx)
-			if v := binOp(ctx, label, opUnify, key, label); isBottom(v) {
-				continue
-			}
-		}
-		fn, ok := ctx.manifest(s.value).(*lambdaExpr)
-		if !ok {
-			// create error
-			continue
-		}
-		add(fn.call(ctx, s.value, arg))
-		if f, _ := s.value.base().Source().(*ast.Field); f != nil {
-			doc = &docNode{n: f, left: doc}
-		}
-	}
-	return u, doc
-}
-
-func (o *optionals) rewrite(fn func(value) value) (c *optionals, err evaluated) {
-	if o == nil {
-		return nil, nil
-	}
-
-	left, err := o.left.rewrite(fn)
-	if err != nil {
-		return nil, err
-	}
-	right, err := o.right.rewrite(fn)
-	if err != nil {
-		return nil, err
-	}
-
-	fields := make([]optionalSet, len(o.fields))
-	for i, s := range o.fields {
-		if s.key != nil {
-			s.key = fn(s.key)
-			if b, ok := s.key.(*bottom); ok {
-				return nil, b
-			}
-		}
-		s.value = fn(s.value)
-		if b, ok := s.value.(*bottom); ok {
-			return nil, b
-		}
-		fields[i] = s
-	}
-
-	return &optionals{o.closed, o.op, left, right, fields}, nil
-}
-
-type closeMode byte
-
-const (
-	shouldFinalize closeMode = 1 << iota
-	toClose
-	isClosed
-)
-
-func (m closeMode) shouldFinalize() bool {
-	return m&shouldFinalize != 0
-}
-
-func (m *closeMode) unclose() {
-	*m &^= (toClose | isClosed)
-}
-
-func (m closeMode) isClosed() bool {
-	return m&isClosed != 0
-}
-
-func (m closeMode) shouldClose() bool {
-	return m >= toClose
-}
-
-func (x *structLit) isClosed() bool {
-	return x.closeStatus.isClosed()
-}
-
-func (x *structLit) addTemplate(ctx *context, pos token.Pos, key, value value) {
-	if x.optionals == nil {
-		x.optionals = &optionals{}
-	}
-	x.optionals.add(ctx, key, value)
-}
-
-func (x *structLit) allows(ctx *context, f label) bool {
-	return !x.closeStatus.isClosed() ||
-		f.IsHidden() ||
-		x.optionals.allows(ctx, f)
-}
-
-func newStruct(src source) *structLit {
-	return &structLit{baseValue: src.base()}
-}
-
-func (x *structLit) Kind() kind { return structKind }
-
-type arcs []arc
-
-func (x *structLit) Len() int           { return len(x.Arcs) }
-func (x *structLit) Less(i, j int) bool { return x.Arcs[i].Label < x.Arcs[j].Label }
-func (x *structLit) Swap(i, j int)      { x.Arcs[i], x.Arcs[j] = x.Arcs[j], x.Arcs[i] }
-
-func (x *structLit) close() *structLit {
-	if x.optionals.isFull() {
-		return x
-	}
-
-	newS := *x
-	newS.closeStatus = isClosed
-	return &newS
-}
-
-// lookup returns the node for the given label f, if present, or nil otherwise.
-func (x *structLit) Lookup(ctx *context, f label) arc {
-	x, err := x.expandFields(ctx)
-	if err != nil {
-		return arc{}
-	}
-	// Lookup is done by selector or index references. Either this is done on
-	// literal nodes or nodes obtained from references. In the later case,
-	// noderef will have ensured that the ancestors were evaluated.
-	for i, a := range x.Arcs {
-		if a.Label == f {
-			a := x.iterAt(ctx, i)
-			// TODO: adding more technical debt here. The evaluator should be
-			// rewritten.
-			if x.optionals != nil {
-				name := ctx.LabelStr(x.Arcs[i].Label)
-				arg := &stringLit{x.baseValue, name, nil}
-
-				val, _ := x.optionals.constraint(ctx, arg)
-				if val != nil {
-					a.v = mkBin(ctx, x.Pos(), opUnify, a.v, val)
-				}
-			}
-			return a
-		}
-	}
-	return arc{}
-}
-
-func (x *structLit) iterAt(ctx *context, i int) arc {
-	x, err := x.expandFields(ctx)
-	if err != nil || i >= len(x.Arcs) {
-		return arc{}
-	}
-	a := x.Arcs[i]
-	a.Value = x.at(ctx, i) // TODO: return template & v for original?
-	return a
-}
-
-func (x *structLit) at(ctx *context, i int) evaluated {
-	// TODO: limit visibility of definitions:
-	// Approach:
-	// - add package identifier to arc (label)
-	// - assume ctx is unique for a package
-	// - record package identifier in context
-	// - if arc is a definition, check IsExported and verify the package if not.
-	//
-	// The same approach could be valid for looking up package-level identifiers.
-	// - detect somehow aht root nodes are.
-	//
-	// Allow import of CUE files. These cannot have a package clause.
-
-	var err *bottom
-
-	// Lookup is done by selector or index references. Either this is done on
-	// literal nodes or nodes obtained from references. In the later case,
-	// noderef will have ensured that the ancestors were evaluated.
-	if v := x.Arcs[i].Value; v == nil {
-
-		// cycle detection
-
-		popped := ctx.evalStack
-		ctx.evalStack = append(ctx.evalStack, bottom{
-			baseValue: x.base(),
-			index:     ctx.index,
-			Code:      codeCycle,
-			value:     x.Arcs[i].v,
-			format:    "cycle detected",
-		})
-		x.Arcs[i].Value = &(ctx.evalStack[len(ctx.evalStack)-1])
-
-		v := x.Arcs[i].v.evalPartial(ctx)
-		ctx.evalStack = popped
-
-		var doc *docNode
-		v, doc = x.applyTemplate(ctx, i, v)
-		// only place to apply template?
-
-		if (len(ctx.evalStack) > 0 && ctx.cycleErr) || cycleError(v) != nil {
-			// Don't cache while we're in a evaluation cycle as it will cache
-			// partial results. Each field involved in the cycle will have to
-			// reevaluated the values from scratch. As the result will be
-			// cached after one cycle, it will evaluate the cycle at most twice.
-			x.Arcs[i].Value = nil
-			return v
-		}
-
-		// If there as a cycle error, we have by now evaluated a full cycle and
-		// it is safe to cache the result.
-		ctx.cycleErr = false
-
-		v = updateCloseStatus(ctx, v)
-		if st, ok := v.(*structLit); ok {
-			v, err = st.expandFields(ctx)
-			if err != nil {
-				v = err
-			}
-		}
-		x.Arcs[i].Value = v
-		if doc != nil {
-			x.Arcs[i].docs = &docNode{left: doc, right: x.Arcs[i].docs}
-		}
-		if len(ctx.evalStack) == 0 {
-			if err := ctx.processDelayedConstraints(); err != nil {
-				x.Arcs[i].Value = err
-			}
-		}
-	} else if b := cycleError(v); b != nil {
-		copy := *b
-		return &copy
-	}
-	return x.Arcs[i].Value
-}
-
-// expandFields merges in embedded and interpolated fields.
-// Such fields are semantically equivalent to child values, and thus
-// should not be evaluated until the other fields of a struct are
-// fully evaluated.
-func (x *structLit) expandFields(ctx *context) (st *structLit, err *bottom) {
-	switch v := x.expanded.(type) {
-	case nil:
-	case *structLit:
-		return v, nil
-	default:
-		return nil, x.expanded.(*bottom)
-	}
-	if len(x.comprehensions) == 0 {
-		x.expanded = x
-		return x, nil
-	}
-
-	x.expanded = x
-
-	comprehensions := x.comprehensions
-
-	var incomplete []compValue
-
-	var n evaluated = &top{x.baseValue}
-	if x.emit != nil {
-		n = x.emit.evalPartial(ctx)
-	}
-
-	var checked evaluated = &top{x.baseValue}
-
-	for _, x := range comprehensions {
-		v := x.comp.evalPartial(ctx)
-		if v, ok := v.(*bottom); ok {
-			if isIncomplete(v) {
-				incomplete = append(incomplete, x)
-				continue
-			}
-
-			return nil, v
-		}
-		src := binSrc(x.comp.Pos(), opUnify, x.comp, v)
-		_ = checked
-		if x.checked {
-			checked = binOp(ctx, src, opUnifyUnchecked, checked, v)
-		} else {
-			n = binOp(ctx, src, opUnifyUnchecked, n, v)
-		}
-	}
-	if len(comprehensions) == len(incomplete) {
-		return x, nil
-	}
-
-	switch n.(type) {
-	case *bottom, *top:
-	default:
-		orig := x.comprehensions
-		x.comprehensions = incomplete
-		src := binSrc(x.Pos(), opUnify, x, n)
-		n = binOp(ctx, src, opUnifyUnchecked, x, n)
-		x.comprehensions = orig
-	}
-
-	switch checked.(type) {
-	case *bottom, *top:
-	default:
-		orig := x.comprehensions
-		x.comprehensions = incomplete
-		src := binSrc(x.Pos(), opUnify, n, checked)
-		n = binOp(ctx, src, opUnify, x, checked)
-		x.comprehensions = orig
-	}
-
-	switch v := n.(type) {
-	case *bottom:
-		x.expanded = n
-		return nil, v
-	case *structLit:
-		x.expanded = n
-		return v, nil
-
-	default:
-		x.expanded = x
-		return x, nil
-	}
-}
-
-func (x *structLit) applyTemplate(ctx *context, i int, v evaluated) (e evaluated, doc *docNode) {
-	if x.optionals == nil {
-		return v, nil
-	}
-
-	if f := x.Arcs[i].Label; !f.IsHidden() && !f.IsDef() {
-		name := ctx.LabelStr(x.Arcs[i].Label)
-		arg := &stringLit{x.baseValue, name, nil}
-
-		var val value
-		val, doc = x.optionals.constraint(ctx, arg)
-		if val != nil {
-			v = binOp(ctx, x, opUnify, v, val.evalPartial(ctx))
-		}
-	}
-
-	if x.closeStatus != 0 {
-		v = updateCloseStatus(ctx, v)
-	}
-	return v, doc
-}
-
-// A label is a canonicalized feature name.
-type label = adt.Feature
-
-// An arc holds the label-value pair.
-//
-// A fully evaluated arc has either a node or a value. An unevaluated arc,
-// however, may have both. In this case, the value must ultimately evaluate
-// to a node, which will then be merged with the existing one.
-type arc struct {
-	Label      label
-	optional   bool
-	definition bool // field is a definition
-
-	// TODO: add index to preserve approximate order within a struct and use
-	// topological sort to compute new struct order when unifying. This could
-	// also be achieved by not sorting labels on features and doing
-	// a linear search in fields.
-
-	v     value
-	Value evaluated // also used as newValue during unification.
-	attrs *attributes
-	docs  *docNode
-}
-
-type docNode struct {
-	n     *ast.Field
-	left  *docNode
-	right *docNode
-}
-
-func (d *docNode) appendDocs(docs []*ast.CommentGroup) []*ast.CommentGroup {
-	if d == nil {
-		return docs
-	}
-	docs = d.left.appendDocs(docs)
-	if d.n != nil {
-		docs = appendDocComments(docs, d.n)
-		docs = appendDocComments(docs, d.n.Label)
-	}
-	docs = d.right.appendDocs(docs)
-	return docs
-}
-
-func appendDocComments(docs []*ast.CommentGroup, n ast.Node) []*ast.CommentGroup {
-	for _, c := range n.Comments() {
-		if c.Doc {
-			docs = append(docs, c)
-		}
-	}
-	return docs
-}
-
-func mergeDocs(a, b *docNode) *docNode {
-	if a == b || a == nil {
-		return b
-	}
-	if b == nil {
-		return a
-	}
-	// TODO: filter out duplicates?
-	return &docNode{nil, a, b}
-}
-
-func (a *arc) val() evaluated {
-	return a.Value
-}
-
-func (a *arc) setValue(v value) {
-	a.v = v
-	a.Value = nil
-}
-
-type closeIfStruct struct {
-	value
-}
-
-func wrapFinalize(ctx *context, v value) value {
-	if v.Kind().isAnyOf(structKind | listKind) {
-		switch x := v.(type) {
-		case *top:
-			return v
-		case *structLit:
-			v = updateCloseStatus(ctx, x)
-		case *list:
-			v = updateCloseStatus(ctx, x)
-		case *disjunction:
-			v = updateCloseStatus(ctx, x)
-		case *closeIfStruct:
-			return x
-		}
-		return &closeIfStruct{v}
-	}
-	return v
-}
-
-func updateCloseStatus(ctx *context, v evaluated) evaluated {
-	switch x := v.(type) {
-	case *structLit:
-		if x.closeStatus.shouldClose() {
-			x.closeStatus = isClosed
-			x.optionals = x.optionals.close()
-		}
-		x.closeStatus |= shouldFinalize
-		return x
-
-	case *disjunction:
-		for _, d := range x.Values {
-			d.Val = wrapFinalize(ctx, d.Val)
-		}
-
-	case *list:
-		wrapFinalize(ctx, x.elem)
-		if x.typ != nil {
-			wrapFinalize(ctx, x.typ)
-		}
-	}
-	return v
-}
-
-// insertValue is used during initialization but never during evaluation.
-func (x *structLit) insertValue(ctx *context, f label, optional, isDef bool, value value, a *attributes, docs *docNode) {
-	for i, p := range x.Arcs {
-		if f != p.Label {
-			continue
-		}
-		x.Arcs[i].optional = x.Arcs[i].optional && optional
-		x.Arcs[i].docs = mergeDocs(x.Arcs[i].docs, docs)
-		x.Arcs[i].v = mkBin(ctx, token.NoPos, opUnify, p.v, value)
-		if isDef != p.definition {
-			src := binSrc(token.NoPos, opUnify, p.v, value)
-			x.Arcs[i].v = ctx.mkErr(src,
-				"field %q declared as definition and regular field",
-				ctx.LabelStr(f))
-			isDef = false
-		}
-		x.Arcs[i].definition = isDef
-		attrs, err := unifyAttrs(ctx, x, x.Arcs[i].attrs, a)
-		if err != nil {
-			x.Arcs[i].v = err
-		}
-		x.Arcs[i].attrs = attrs
-		// TODO: should we warn if there is a mixed mode of optional and non
-		// optional fields at this point?
-		return
-	}
-	x.Arcs = append(x.Arcs, arc{f, optional, isDef, value, nil, a, docs})
-	sort.Stable(x)
-}
-
-// A nodeRef is a reference to a node.
-type nodeRef struct {
-	baseValue
-	node  scope
-	label label // for direct ancestor nodes
-}
-
-func (x *nodeRef) Kind() kind {
-	// TODO(REWORK): no context available
-	// n := x.node.deref(nil)
-	n := x.node
-	return n.Kind() | nonGround | referenceKind
-}
-
-type selectorExpr struct {
-	baseValue
-	X   value
-	Sel label
-}
-
-// TODO: could this be narrowed down?
-func (x *selectorExpr) Kind() kind {
-	isRef := x.X.Kind() & referenceKind
-	return topKind | isRef
-}
-
-type indexExpr struct {
-	baseValue
-	X     value
-	Index value
-}
-
-// TODO: narrow this down when we have list types.
-func (x *indexExpr) Kind() kind { return topKind | referenceKind }
-
-type sliceExpr struct {
-	baseValue
-	X  value
-	Lo value
-	Hi value
-}
-
-// TODO: narrow this down when we have list types.
-func (x *sliceExpr) Kind() kind { return topKind | referenceKind }
-
-type callExpr struct {
-	baseValue
-	Fun  value
-	Args []value
-}
-
-func (x *callExpr) Kind() kind {
-	// TODO: could this be narrowed down?
-	switch c := x.Fun.(type) {
-	case *lambdaExpr:
-		return c.returnKind() | nonGround
-	case *builtin:
-		switch len(x.Args) {
-		case len(c.Params):
-			return c.Result
-		case len(c.Params) - 1:
-			if len(c.Params) == 0 || c.Result&boolKind == 0 {
-				return bottomKind
-			}
-			return c.Params[0]
-		}
-	}
-	return topKind | referenceKind
-}
-
-type customValidator struct {
-	baseValue
-
-	Builtin *builtin    // function must return a bool
-	Args    []evaluated // any but the first value
-}
-
-func (x *customValidator) Kind() kind {
-	if len(x.Builtin.Params) == 0 {
-		return bottomKind
-	}
-	return x.Builtin.Params[0] | nonGround
-}
-
-type params struct {
-	arcs []arc
-}
-
-func (x *params) add(f label, v value) {
-	if v == nil {
-		panic("nil node")
-	}
-	x.arcs = append(x.arcs, arc{Label: f, v: v})
-}
-
-func (x *params) iterAt(ctx *context, i int) (evaluated, value) {
-	if i >= len(x.arcs) {
-		return nil, nil
-	}
-	return x.at(ctx, i), x.arcs[i].v
-}
-
-// lookup returns the node for the given label f, if present, or nil otherwise.
-func (x *params) at(ctx *context, i int) evaluated {
-	// Lookup is done by selector or index references. Either this is done on
-	// literal nodes or nodes obtained from references. In the later case,
-	// noderef will have ensured that the ancestors were evaluated.
-	if x.arcs[i].Value == nil {
-		x.arcs[i].Value = x.arcs[i].v.evalPartial(ctx)
-	}
-	return x.arcs[i].Value
-}
-
-// lookup returns the node for the given label f, if present, or nil otherwise.
-func (x *params) Lookup(ctx *context, f label) arc {
-	if f == 0 && len(x.arcs) == 1 {
-		// A template binding.
-		a := x.arcs[0]
-		a.Value = x.at(ctx, 0)
-		return a
-	}
-	// Lookup is done by selector or index references. Either this is done on
-	// literal nodes or nodes obtained from references. In the later case,
-	// noderef will have ensured that the ancestors were evaluated.
-	for i, a := range x.arcs {
-		if a.Label == f {
-			a.Value = x.at(ctx, i)
-			return a
-		}
-	}
-	return arc{}
-}
-
-type lambdaExpr struct {
-	baseValue
-	*params
-	value value
-}
-
-// TODO: could this be narrowed down?
-func (x *lambdaExpr) Kind() kind       { return lambdaKind }
-func (x *lambdaExpr) returnKind() kind { return x.value.Kind() }
-
-// call calls and evaluates a  lambda expression. It is assumed that x may be
-// destroyed, either because it is copied as a result of a reference or because
-// it is invoked as a literal.
-func (x *lambdaExpr) call(ctx *context, p source, args ...evaluated) value {
-	// fully evaluated.
-	if len(x.params.arcs) != len(args) {
-		return ctx.mkErr(p, x, "number of arguments does not match (%d vs %d)",
-			len(x.params.arcs), len(args))
-	}
-
-	// force parameter substitution. It is important that the result stands on
-	// its own and does not depend on its input parameters.
-	arcs := make(arcs, len(x.arcs))
-	for i, a := range x.arcs {
-		v := binOp(ctx, p, opUnify, a.v.evalPartial(ctx), args[i])
-		if isBottom(v) {
-			return v
-		}
-		arcs[i] = arc{Label: a.Label, v: v, Value: v}
-	}
-	lambda := &lambdaExpr{x.baseValue, &params{arcs}, nil}
-	defer ctx.pushForwards(x, lambda).popForwards()
-	obj := ctx.copy(x.value)
-	return obj
-}
-
-// Operations
-
-type unaryExpr struct {
-	baseValue
-	Op op
-	X  value
-}
-
-func (x *unaryExpr) Kind() kind { return x.X.Kind() }
-
-func compileRegexp(ctx *context, v value) value {
-	var err error
-	switch x := v.(type) {
-	case *stringLit:
-		if x.RE == nil {
-			x.RE, err = regexp.Compile(x.Str)
-			if err != nil {
-				return ctx.mkErr(v, "could not compile regular expression %q: %v", x.Str, err)
-			}
-		}
-	case *bytesLit:
-		if x.RE == nil {
-			x.RE, err = regexp.Compile(string(x.B))
-			if err != nil {
-				return ctx.mkErr(v, "could not compile regular expression %q: %v", x.B, err)
-			}
-		}
-	}
-	return v
-}
-
-type binaryExpr struct {
-	baseValue
-	Op op
-	X  value
-	Y  value
-}
-
-func mkBin(ctx *context, pos token.Pos, op op, left, right value) value {
-	if left == nil || right == nil {
-		panic("operands may not be nil")
-	}
-	if op == opUnify {
-		if left == right {
-			return left
-		}
-		if _, ok := left.(*top); ok {
-			return right
-		}
-		if _, ok := right.(*top); ok {
-			return left
-		}
-		// TODO(perf): consider adding a subsumption filter.
-		// if subsumes(ctx, left, right) {
-		// 	return right
-		// }
-		// if subsumes(ctx, right, left) {
-		// 	return left
-		// }
-	}
-	bin := &binaryExpr{binSrc(pos, op, left, right), op, left, right}
-	return updateBin(ctx, bin)
-}
-
-func updateBin(ctx *context, bin *binaryExpr) value {
-	switch bin.Op {
-	case opMat, opNMat:
-		bin.Y = compileRegexp(ctx, bin.Y)
-		if isBottom(bin.Y) {
-			return bin.Y
-		}
-	}
-	return bin
-}
-
-func (x *binaryExpr) Kind() kind {
-	// TODO: cache results
-	kind, _, _ := matchBinOpKind(x.Op, x.X.Kind(), x.Y.Kind())
-	return kind | nonGround
-}
-
-// unification collects evaluated values that are not mutually exclusive
-// but cannot be represented as a single value. It allows doing the bookkeeping
-// on accumulating conjunctions, simplifying them along the way, until they do
-// resolve into a single value.
-type unification struct {
-	baseValue
-	Values []evaluated
-}
-
-func (x *unification) Kind() kind {
-	k := topKind
-	for _, v := range x.Values {
-		k &= v.Kind()
-	}
-	return k | nonGround
-}
-
-type disjunction struct {
-	baseValue
-
-	Values []dValue
-
-	// errors is used to keep track of all errors that occurred in
-	// a disjunction for better error reporting down the road.
-	// TODO: consider storing the errors in values.
-	errors []*bottom
-
-	HasDefaults bool // also true if it had elminated defaults.
-
-	// bind is the node that a successful disjunction will bind to. This
-	// allows other arcs to point to this node before the disjunction is
-	// completed. For early failure, this node can be set to the glb of all
-	// disjunctions. Otherwise top will suffice.
-	// bind node
-}
-
-type dValue struct {
-	Val     value
-	Default bool
-}
-
-func (x *disjunction) Kind() kind {
-	k := kind(0)
-	for _, v := range x.Values {
-		k |= v.Val.Kind()
-	}
-	if k != bottomKind {
-		k |= nonGround
-	}
-	return k
-}
-
-func (x *disjunction) Pos() token.Pos { return x.Values[0].Val.Pos() }
-
-// add add a value to the disjunction. It is assumed not to be a disjunction.
-func (x *disjunction) add(ctx *context, v value, marked bool) {
-	x.Values = append(x.Values, dValue{v, marked})
-	if b, ok := v.(*bottom); ok {
-		x.errors = append(x.errors, b)
-	}
-}
-
-// normalize removes redundant element from unification.
-// x must already have been evaluated.
-func (x *disjunction) normalize(ctx *context, src source) mVal {
-	leq := func(ctx *context, lt, gt dValue) bool {
-		if isBottom(lt.Val) {
-			return true
-		}
-		s := subsumer{ctx: ctx}
-		return (!lt.Default || gt.Default) && s.subsumes(gt.Val, lt.Val)
-	}
-	k := 0
-
-	hasMarked := false
-	var markedErr *bottom
-outer:
-	for i, v := range x.Values {
-		// TODO: this is pre-evaluation is quite aggressive. Verify whether
-		// this does not trigger structural cycles (it does). If so, this can check for
-		// bottom and the validation can be delayed to as late as picking
-		// defaults. The drawback of this approach is that printed intermediate
-		// results will not look great.
-		if err := validate(ctx, v.Val); err != nil {
-			x.errors = append(x.errors, err)
-			if v.Default {
-				markedErr = err
-			}
-			continue
-		}
-		if v.Default {
-			hasMarked = true
-		}
-		for j, w := range x.Values {
-			if i == j {
-				continue
-			}
-			if leq(ctx, v, w) && (!leq(ctx, w, v) || j < i) {
-				// strictly subsumed, or equal and and the equal element was
-				// processed earlier.
-				continue outer
-			}
-		}
-		// If there was a three-way equality, an element w, where w == v could
-		// already have been added.
-		for j := 0; j < k; j++ {
-			if leq(ctx, v, x.Values[j]) {
-				continue outer
-			}
-		}
-		// TODO: do not modify value, but create a new disjunction.
-		x.Values[k] = v
-		k++
-	}
-	if !hasMarked && markedErr != nil && (k > 1 || !x.Values[0].Val.Kind().isGround()) {
-		x.Values[k] = dValue{&bottom{}, true}
-		k++
-	}
-
-	switch k {
-	case 0:
-		// Empty disjunction. All elements must be errors.
-		// Take the first error as an example.
-		err := x.Values[0].Val
-		if !isBottom(err) {
-			// TODO: use format instead of debugStr.
-			err = ctx.mkErr(src, ctx.str(err))
-		}
-		return mVal{x.computeError(ctx, src), false}
-	case 1:
-		v := x.Values[0]
-		return mVal{v.Val.(evaluated), v.Default}
-	}
-	// TODO: do not modify value, but create a new disjunction.
-	x.Values = x.Values[:k]
-	return mVal{x, false}
-}
-
-func (x *disjunction) computeError(ctx *context, src source) evaluated {
-	var errors []*bottom
-
-	// Ensure every position is visited at least once.
-	// This prevents discriminators fields from showing up too much. A special
-	// "all errors" flag could be used to expand all errors.
-	visited := map[token.Pos]bool{}
-
-	for _, b := range x.errors {
-		positions := b.Positions(ctx)
-		if len(positions) == 0 {
-			positions = append(positions, token.NoPos)
-		}
-		// Include the error if at least one of its positions wasn't covered
-		// before.
-		done := true
-		for _, p := range positions {
-			if !visited[p] {
-				done = false
-			}
-			visited[p] = true
-		}
-		if !done {
-			b := *b
-			b.format = "empty disjunction: " + b.format
-			errors = append(errors, &b)
-		}
-	}
-	switch len(errors) {
-	case 0:
-		// Should never happen.
-		return ctx.mkErr(src, errors, "empty disjunction")
-	case 1:
-		return ctx.mkErr(src, errors, "empty disjunction: %v", errors[0])
-	default:
-		return ctx.mkErr(src, errors, "empty disjunction: %v (and %d other errors)", errors[0], len(errors)-1)
-	}
-}
-
-type listComprehension struct {
-	baseValue
-	clauses yielder
-}
-
-func (x *listComprehension) Kind() kind {
-	return listKind | nonGround | referenceKind
-}
-
-type structComprehension struct {
-	baseValue
-	clauses yielder
-}
-
-func (x *structComprehension) Kind() kind {
-	return structKind | nonGround | referenceKind
-}
-
-// TODO: rename to something better. No longer a comprehension.
-// Generated field, perhaps.
-type fieldComprehension struct {
-	baseValue
-	key   value
-	val   value
-	opt   bool
-	def   bool
-	doc   *docNode
-	attrs *attributes
-}
-
-func (x *fieldComprehension) Kind() kind {
-	return structKind | nonGround
-}
-
-type yieldFunc func(v evaluated) *bottom
-
-type yielder interface {
-	value
-	yield(*context, yieldFunc) *bottom
-}
-
-type yield struct {
-	baseValue
-	value value
-}
-
-func (x *yield) Kind() kind { return topKind | referenceKind }
-
-func (x *yield) yield(ctx *context, fn yieldFunc) *bottom {
-	v := x.value.evalPartial(ctx)
-	if err, ok := v.(*bottom); ok {
-		return err
-	}
-	if err := fn(v); err != nil {
-		return err
-	}
-	return nil
-}
-
-type guard struct { // rename to guard
-	baseValue
-	Condition value
-	Dst       yielder
-}
-
-func (x *guard) Kind() kind { return topKind | referenceKind }
-
-func (x *guard) yield(ctx *context, fn yieldFunc) *bottom {
-	filter := ctx.manifest(x.Condition)
-	if err, ok := filter.(*bottom); ok {
-		return err
-	}
-	if err := checkKind(ctx, filter, boolKind); err != nil {
-		return err
-	}
-	if filter.(*boolLit).B {
-		if err := x.Dst.yield(ctx, fn); err != nil {
-			return err
-		}
-	}
-	return nil
-}
-
-type feed struct {
-	baseValue
-	Src value
-	fn  *lambdaExpr
-}
-
-func (x *feed) Kind() kind { return topKind | referenceKind }
-
-func (x *feed) yield(ctx *context, yfn yieldFunc) (result *bottom) {
-	if ctx.trace {
-		defer uni(indent(ctx, "feed", x))
-	}
-	source := ctx.manifest(x.Src)
-	fn := x.fn // no need to evaluate eval
-
-	switch src := source.(type) {
-	case *structLit:
-		var err *bottom
-		src, err = src.expandFields(ctx)
-		if err != nil {
-			return err
-		}
-		for i, a := range src.Arcs {
-			key := &stringLit{
-				x.baseValue,
-				ctx.LabelStr(a.Label),
-				nil,
-			}
-			if a.definition || a.optional || a.Label.IsHidden() {
-				continue
-			}
-			val := src.at(ctx, i)
-			v := fn.call(ctx, x, key, val)
-			if err, ok := v.(*bottom); ok {
-				return err
-			}
-			if err := v.(yielder).yield(ctx, yfn); err != nil {
-				return err
-			}
-		}
-		return nil
-
-	case *list:
-		for i := range src.elem.Arcs {
-			idx := newInt(x, 0).setInt(i)
-			v := fn.call(ctx, x, idx, src.at(ctx, i))
-			if err, ok := v.(*bottom); ok {
-				return err
-			}
-			if err := v.(yielder).yield(ctx, yfn); err != nil {
-				return err
-			}
-		}
-		return nil
-
-	default:
-		if err, ok := source.(*bottom); ok {
-			return err
-		}
-		if k := source.Kind(); k&(structKind|listKind) == bottomKind {
-			return ctx.mkErr(x, x.Src, "feed source must be list or struct, found %s", k)
-		}
-		return ctx.mkErr(x, x.Src, codeIncomplete, "incomplete feed source")
-	}
-}
diff --git a/cuego/cuego.go b/cuego/cuego.go
index d666fe7..f2460a3 100644
--- a/cuego/cuego.go
+++ b/cuego/cuego.go
@@ -19,9 +19,9 @@
 	"reflect"
 	"sync"
 
+	"cuelang.org/go/cue"
 	"cuelang.org/go/cue/parser"
 	"cuelang.org/go/internal"
-	"cuelang.org/go/internal/legacy/cue"
 )
 
 // DefaultContext is the shared context used with top-level functions.
diff --git a/encoding/gocode/generator.go b/encoding/gocode/generator.go
index eef0216..451fa8f 100644
--- a/encoding/gocode/generator.go
+++ b/encoding/gocode/generator.go
@@ -24,9 +24,9 @@
 
 	"golang.org/x/tools/go/packages"
 
+	"cuelang.org/go/cue"
 	"cuelang.org/go/cue/errors"
 	"cuelang.org/go/internal"
-	"cuelang.org/go/internal/legacy/cue"
 )
 
 // Config defines options for generation Go code.
diff --git a/encoding/gocode/generator_test.go b/encoding/gocode/generator_test.go
index e639db0..85780cc 100644
--- a/encoding/gocode/generator_test.go
+++ b/encoding/gocode/generator_test.go
@@ -25,9 +25,9 @@
 
 	"github.com/kylelemons/godebug/diff"
 
+	"cuelang.org/go/cue"
 	"cuelang.org/go/cue/errors"
 	"cuelang.org/go/cue/load"
-	"cuelang.org/go/internal/legacy/cue"
 )
 
 var update = flag.Bool("update", false, "update test files")
diff --git a/encoding/gocode/gocodec/codec.go b/encoding/gocode/gocodec/codec.go
index 268b509..6631683 100644
--- a/encoding/gocode/gocodec/codec.go
+++ b/encoding/gocode/gocodec/codec.go
@@ -23,8 +23,8 @@
 import (
 	"sync"
 
+	"cuelang.org/go/cue"
 	"cuelang.org/go/internal"
-	"cuelang.org/go/internal/legacy/cue"
 )
 
 // Config has no options yet, but is defined for future extensibility.
diff --git a/encoding/gocode/gocodec/codec_test.go b/encoding/gocode/gocodec/codec_test.go
index 9b81384..9114f92 100644
--- a/encoding/gocode/gocodec/codec_test.go
+++ b/encoding/gocode/gocodec/codec_test.go
@@ -22,7 +22,7 @@
 	"github.com/google/go-cmp/cmp"
 	"github.com/kr/pretty"
 
-	"cuelang.org/go/internal/legacy/cue"
+	"cuelang.org/go/cue"
 )
 
 type Sum struct {
diff --git a/encoding/gocode/templates.go b/encoding/gocode/templates.go
index 7a766c8..22fb940 100644
--- a/encoding/gocode/templates.go
+++ b/encoding/gocode/templates.go
@@ -26,7 +26,7 @@
 import (
 	"fmt"
 
-	"cuelang.org/go/internal/legacy/cue"
+	"cuelang.org/go/cue"
 	"cuelang.org/go/encoding/gocode/gocodec"
 )
 
diff --git a/encoding/gocode/testdata/pkg1/cue_gen.go b/encoding/gocode/testdata/pkg1/cue_gen.go
index b585545..c16cab9 100644
--- a/encoding/gocode/testdata/pkg1/cue_gen.go
+++ b/encoding/gocode/testdata/pkg1/cue_gen.go
@@ -5,8 +5,8 @@
 import (
 	"fmt"
 
+	"cuelang.org/go/cue"
 	"cuelang.org/go/encoding/gocode/gocodec"
-	"cuelang.org/go/internal/legacy/cue"
 )
 
 var cuegenvalMyStruct = cuegenMake("MyStruct", &MyStruct{})
diff --git a/encoding/gocode/testdata/pkg2/cue_gen.go b/encoding/gocode/testdata/pkg2/cue_gen.go
index 6cd4325..927bf6e 100644
--- a/encoding/gocode/testdata/pkg2/cue_gen.go
+++ b/encoding/gocode/testdata/pkg2/cue_gen.go
@@ -5,8 +5,8 @@
 import (
 	"fmt"
 
+	"cuelang.org/go/cue"
 	"cuelang.org/go/encoding/gocode/gocodec"
-	"cuelang.org/go/internal/legacy/cue"
 )
 
 var cuegenvalImportMe = cuegenMake("ImportMe", &ImportMe{})
diff --git a/encoding/json/json.go b/encoding/json/json.go
index f795802..50b9726 100644
--- a/encoding/json/json.go
+++ b/encoding/json/json.go
@@ -21,13 +21,13 @@
 	"strconv"
 	"strings"
 
+	"cuelang.org/go/cue"
 	"cuelang.org/go/cue/ast"
 	"cuelang.org/go/cue/ast/astutil"
 	"cuelang.org/go/cue/errors"
 	"cuelang.org/go/cue/literal"
 	"cuelang.org/go/cue/parser"
 	"cuelang.org/go/cue/token"
-	"cuelang.org/go/internal/legacy/cue"
 	"cuelang.org/go/pkg/encoding/json"
 )
 
diff --git a/encoding/jsonschema/constraints.go b/encoding/jsonschema/constraints.go
index 7eeaf63..ef941e2 100644
--- a/encoding/jsonschema/constraints.go
+++ b/encoding/jsonschema/constraints.go
@@ -20,11 +20,11 @@
 	"path"
 	"regexp"
 
+	"cuelang.org/go/cue"
 	"cuelang.org/go/cue/ast"
 	"cuelang.org/go/cue/errors"
 	"cuelang.org/go/cue/token"
 	"cuelang.org/go/internal"
-	"cuelang.org/go/internal/legacy/cue"
 )
 
 // TODO: skip invalid regexps containing ?! and foes.
diff --git a/encoding/jsonschema/decode.go b/encoding/jsonschema/decode.go
index a1d1144..54f8fd6 100644
--- a/encoding/jsonschema/decode.go
+++ b/encoding/jsonschema/decode.go
@@ -24,12 +24,12 @@
 	"sort"
 	"strings"
 
+	"cuelang.org/go/cue"
 	"cuelang.org/go/cue/ast"
 	"cuelang.org/go/cue/ast/astutil"
 	"cuelang.org/go/cue/errors"
 	"cuelang.org/go/cue/token"
 	"cuelang.org/go/internal"
-	"cuelang.org/go/internal/legacy/cue"
 )
 
 // rootDefs defines the top-level name of the map of definitions that do not
diff --git a/encoding/jsonschema/decode_test.go b/encoding/jsonschema/decode_test.go
index 08ed07f..adc5bd6 100644
--- a/encoding/jsonschema/decode_test.go
+++ b/encoding/jsonschema/decode_test.go
@@ -24,13 +24,13 @@
 	"strings"
 	"testing"
 
+	"cuelang.org/go/cue"
 	"cuelang.org/go/cue/ast"
 	"cuelang.org/go/cue/errors"
 	"cuelang.org/go/cue/format"
 	"cuelang.org/go/cue/token"
 	"cuelang.org/go/encoding/json"
 	"cuelang.org/go/encoding/yaml"
-	"cuelang.org/go/internal/legacy/cue"
 	"github.com/google/go-cmp/cmp"
 	"github.com/stretchr/testify/assert"
 	"golang.org/x/tools/txtar"
diff --git a/encoding/jsonschema/jsonschema.go b/encoding/jsonschema/jsonschema.go
index 6451157..9e81b73 100644
--- a/encoding/jsonschema/jsonschema.go
+++ b/encoding/jsonschema/jsonschema.go
@@ -31,9 +31,9 @@
 package jsonschema
 
 import (
+	"cuelang.org/go/cue"
 	"cuelang.org/go/cue/ast"
 	"cuelang.org/go/cue/token"
-	"cuelang.org/go/internal/legacy/cue"
 )
 
 // Extract converts JSON Schema data into an equivalent CUE representation.
diff --git a/encoding/jsonschema/ref.go b/encoding/jsonschema/ref.go
index c57253c..26443fe 100644
--- a/encoding/jsonschema/ref.go
+++ b/encoding/jsonschema/ref.go
@@ -20,11 +20,11 @@
 	"strconv"
 	"strings"
 
+	"cuelang.org/go/cue"
 	"cuelang.org/go/cue/ast"
 	"cuelang.org/go/cue/errors"
 	"cuelang.org/go/cue/token"
 	"cuelang.org/go/internal"
-	"cuelang.org/go/internal/legacy/cue"
 )
 
 func (d *decoder) parseRef(p token.Pos, str string) []string {
diff --git a/encoding/openapi/build.go b/encoding/openapi/build.go
index 5bcd485..a6d8a21 100644
--- a/encoding/openapi/build.go
+++ b/encoding/openapi/build.go
@@ -23,11 +23,11 @@
 	"strconv"
 	"strings"
 
+	"cuelang.org/go/cue"
 	"cuelang.org/go/cue/ast"
 	"cuelang.org/go/cue/errors"
 	"cuelang.org/go/cue/token"
 	"cuelang.org/go/internal"
-	"cuelang.org/go/internal/legacy/cue"
 	"golang.org/x/xerrors"
 )
 
diff --git a/encoding/openapi/crd.go b/encoding/openapi/crd.go
index 7e691fa..7251b43 100644
--- a/encoding/openapi/crd.go
+++ b/encoding/openapi/crd.go
@@ -44,8 +44,8 @@
 //
 
 import (
+	"cuelang.org/go/cue"
 	"cuelang.org/go/cue/ast"
-	"cuelang.org/go/internal/legacy/cue"
 )
 
 // newCoreBuilder returns a builder that represents a structural schema.
diff --git a/encoding/openapi/decode.go b/encoding/openapi/decode.go
index b45100a..a8a61b8 100644
--- a/encoding/openapi/decode.go
+++ b/encoding/openapi/decode.go
@@ -17,12 +17,12 @@
 import (
 	"strings"
 
+	"cuelang.org/go/cue"
 	"cuelang.org/go/cue/ast"
 	"cuelang.org/go/cue/errors"
 	"cuelang.org/go/cue/token"
 	"cuelang.org/go/encoding/jsonschema"
 	"cuelang.org/go/internal"
-	"cuelang.org/go/internal/legacy/cue"
 )
 
 // Extract converts OpenAPI definitions to an equivalent CUE representation.
diff --git a/encoding/openapi/decode_test.go b/encoding/openapi/decode_test.go
index b3d417d..8a6d8a8 100644
--- a/encoding/openapi/decode_test.go
+++ b/encoding/openapi/decode_test.go
@@ -27,12 +27,12 @@
 	"github.com/stretchr/testify/assert"
 	"golang.org/x/tools/txtar"
 
+	"cuelang.org/go/cue"
 	"cuelang.org/go/cue/errors"
 	"cuelang.org/go/cue/format"
 	"cuelang.org/go/encoding/json"
 	"cuelang.org/go/encoding/openapi"
 	"cuelang.org/go/encoding/yaml"
-	"cuelang.org/go/internal/legacy/cue"
 )
 
 // TestDecode reads the testdata/*.txtar files, converts the contained
diff --git a/encoding/openapi/openapi.go b/encoding/openapi/openapi.go
index 463d758..f26cff6 100644
--- a/encoding/openapi/openapi.go
+++ b/encoding/openapi/openapi.go
@@ -19,11 +19,11 @@
 	"fmt"
 	"strings"
 
+	"cuelang.org/go/cue"
 	"cuelang.org/go/cue/ast"
 	"cuelang.org/go/cue/errors"
 	"cuelang.org/go/cue/token"
 	cuejson "cuelang.org/go/encoding/json"
-	"cuelang.org/go/internal/legacy/cue"
 )
 
 // A Config defines options for converting CUE to and from OpenAPI.
diff --git a/encoding/openapi/openapi_test.go b/encoding/openapi/openapi_test.go
index c8134f2..e8c3705 100644
--- a/encoding/openapi/openapi_test.go
+++ b/encoding/openapi/openapi_test.go
@@ -25,11 +25,11 @@
 
 	"github.com/kylelemons/godebug/diff"
 
+	"cuelang.org/go/cue"
 	"cuelang.org/go/cue/ast"
 	"cuelang.org/go/cue/errors"
 	"cuelang.org/go/cue/load"
 	"cuelang.org/go/encoding/openapi"
-	"cuelang.org/go/internal/legacy/cue"
 )
 
 var update *bool = flag.Bool("update", false, "update the test output")
diff --git a/encoding/openapi/types.go b/encoding/openapi/types.go
index a216a08..ccc237a 100644
--- a/encoding/openapi/types.go
+++ b/encoding/openapi/types.go
@@ -20,10 +20,10 @@
 
 	"github.com/cockroachdb/apd/v2"
 
+	"cuelang.org/go/cue"
 	"cuelang.org/go/cue/ast"
 	"cuelang.org/go/cue/literal"
 	"cuelang.org/go/cue/token"
-	"cuelang.org/go/internal/legacy/cue"
 )
 
 // See https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#data-types
diff --git a/encoding/yaml/yaml.go b/encoding/yaml/yaml.go
index e038776..0787077 100644
--- a/encoding/yaml/yaml.go
+++ b/encoding/yaml/yaml.go
@@ -20,9 +20,9 @@
 	"bytes"
 	"io"
 
+	"cuelang.org/go/cue"
 	"cuelang.org/go/cue/ast"
 	cueyaml "cuelang.org/go/internal/encoding/yaml"
-	"cuelang.org/go/internal/legacy/cue"
 	"cuelang.org/go/internal/third_party/yaml"
 	pkgyaml "cuelang.org/go/pkg/encoding/yaml"
 )
diff --git a/encoding/yaml/yaml_test.go b/encoding/yaml/yaml_test.go
index b9e4e38..304b488 100644
--- a/encoding/yaml/yaml_test.go
+++ b/encoding/yaml/yaml_test.go
@@ -18,9 +18,9 @@
 	"strings"
 	"testing"
 
+	"cuelang.org/go/cue"
 	"cuelang.org/go/cue/ast"
 	"cuelang.org/go/cue/format"
-	"cuelang.org/go/internal/legacy/cue"
 )
 
 func TestYAML(t *testing.T) {
diff --git a/internal/cli/cli.go b/internal/cli/cli.go
index 404b43d..f6ffd25 100644
--- a/internal/cli/cli.go
+++ b/internal/cli/cli.go
@@ -17,11 +17,11 @@
 import (
 	"strings"
 
+	"cuelang.org/go/cue"
 	"cuelang.org/go/cue/ast"
 	"cuelang.org/go/cue/errors"
 	"cuelang.org/go/cue/parser"
 	"cuelang.org/go/cue/token"
-	"cuelang.org/go/internal/legacy/cue"
 )
 
 func ParseValue(pos token.Pos, name, str string, k cue.Kind) (x ast.Expr, errs errors.Error) {
diff --git a/internal/core/convert/go_test.go b/internal/core/convert/go_test.go
index 88db590..4a2c93e 100644
--- a/internal/core/convert/go_test.go
+++ b/internal/core/convert/go_test.go
@@ -23,13 +23,13 @@
 	"github.com/cockroachdb/apd/v2"
 	"github.com/google/go-cmp/cmp"
 
+	_ "cuelang.org/go/cue" // set internal.CoreValue
 	"cuelang.org/go/cue/errors"
 	"cuelang.org/go/internal/core/adt"
 	"cuelang.org/go/internal/core/convert"
 	"cuelang.org/go/internal/core/debug"
 	"cuelang.org/go/internal/core/eval"
 	"cuelang.org/go/internal/core/runtime"
-	_ "cuelang.org/go/internal/legacy/cue" // set internal.CoreValue
 )
 
 func mkBigInt(a int64) (v apd.Decimal) { v.SetInt64(a); return }
diff --git a/internal/core/eval/eval_test.go b/internal/core/eval/eval_test.go
index 68eb20f..af4e8c9 100644
--- a/internal/core/eval/eval_test.go
+++ b/internal/core/eval/eval_test.go
@@ -20,11 +20,11 @@
 	"strings"
 	"testing"
 
+	"cuelang.org/go/cue"
 	"cuelang.org/go/internal/core/debug"
 	"cuelang.org/go/internal/core/eval"
 	"cuelang.org/go/internal/core/validate"
 	"cuelang.org/go/internal/cuetxtar"
-	"cuelang.org/go/internal/legacy/cue"
 	"github.com/rogpeppe/go-internal/txtar"
 )
 
diff --git a/internal/core/export/export_test.go b/internal/core/export/export_test.go
index 804122e..1b415d2 100644
--- a/internal/core/export/export_test.go
+++ b/internal/core/export/export_test.go
@@ -18,6 +18,7 @@
 	"flag"
 	"testing"
 
+	"cuelang.org/go/cue"
 	"cuelang.org/go/cue/ast"
 	"cuelang.org/go/cue/errors"
 	"cuelang.org/go/cue/format"
@@ -26,7 +27,6 @@
 	"cuelang.org/go/internal/core/export"
 	"cuelang.org/go/internal/core/runtime"
 	"cuelang.org/go/internal/cuetxtar"
-	"cuelang.org/go/internal/legacy/cue"
 	"github.com/rogpeppe/go-internal/txtar"
 )
 
diff --git a/internal/core/export/extract_test.go b/internal/core/export/extract_test.go
index 2d5153d..02a098c 100644
--- a/internal/core/export/extract_test.go
+++ b/internal/core/export/extract_test.go
@@ -18,12 +18,12 @@
 	"fmt"
 	"testing"
 
+	"cuelang.org/go/cue"
 	"cuelang.org/go/internal/core/adt"
 	"cuelang.org/go/internal/core/compile"
 	"cuelang.org/go/internal/core/eval"
 	"cuelang.org/go/internal/core/export"
 	"cuelang.org/go/internal/cuetxtar"
-	"cuelang.org/go/internal/legacy/cue"
 )
 
 func TestExtract(t *testing.T) {
diff --git a/internal/core/export/value_test.go b/internal/core/export/value_test.go
index ac506cd..193555c 100644
--- a/internal/core/export/value_test.go
+++ b/internal/core/export/value_test.go
@@ -18,6 +18,7 @@
 	"fmt"
 	"testing"
 
+	"cuelang.org/go/cue"
 	"cuelang.org/go/cue/ast"
 	"cuelang.org/go/cue/errors"
 	"cuelang.org/go/internal/core/adt"
@@ -26,7 +27,6 @@
 	"cuelang.org/go/internal/core/export"
 	"cuelang.org/go/internal/core/runtime"
 	"cuelang.org/go/internal/cuetxtar"
-	"cuelang.org/go/internal/legacy/cue"
 	"github.com/rogpeppe/go-internal/txtar"
 )
 
diff --git a/internal/diff/diff.go b/internal/diff/diff.go
index 538d662..d9c29ed 100644
--- a/internal/diff/diff.go
+++ b/internal/diff/diff.go
@@ -15,8 +15,8 @@
 package diff
 
 import (
+	"cuelang.org/go/cue"
 	"cuelang.org/go/cue/errors"
-	"cuelang.org/go/internal/legacy/cue"
 )
 
 // Profile configures a diff operation.
diff --git a/internal/diff/diff_test.go b/internal/diff/diff_test.go
index 02c3acd..83aa395 100644
--- a/internal/diff/diff_test.go
+++ b/internal/diff/diff_test.go
@@ -18,7 +18,7 @@
 	"bytes"
 	"testing"
 
-	"cuelang.org/go/internal/legacy/cue"
+	"cuelang.org/go/cue"
 )
 
 func TestDiff(t *testing.T) {
diff --git a/internal/diff/print.go b/internal/diff/print.go
index 51f45bc..a87832e 100644
--- a/internal/diff/print.go
+++ b/internal/diff/print.go
@@ -18,8 +18,8 @@
 	"fmt"
 	"io"
 
+	"cuelang.org/go/cue"
 	"cuelang.org/go/cue/errors"
-	"cuelang.org/go/internal/legacy/cue"
 )
 
 // Print the differences between two structs represented by an edit script.
diff --git a/internal/encoding/detect.go b/internal/encoding/detect.go
index 25537db..b125a3f 100644
--- a/internal/encoding/detect.go
+++ b/internal/encoding/detect.go
@@ -19,8 +19,8 @@
 	"path"
 	"strings"
 
+	"cuelang.org/go/cue"
 	"cuelang.org/go/cue/build"
-	"cuelang.org/go/internal/legacy/cue"
 )
 
 // Detect detects the interpretation.
diff --git a/internal/encoding/detect_test.go b/internal/encoding/detect_test.go
index 5850761..bdb1b9b 100644
--- a/internal/encoding/detect_test.go
+++ b/internal/encoding/detect_test.go
@@ -17,8 +17,8 @@
 import (
 	"testing"
 
+	"cuelang.org/go/cue"
 	"cuelang.org/go/cue/build"
-	"cuelang.org/go/internal/legacy/cue"
 )
 
 func TestDetect(t *testing.T) {
diff --git a/internal/encoding/encoder.go b/internal/encoding/encoder.go
index 31f0b0b..fbb019f 100644
--- a/internal/encoding/encoder.go
+++ b/internal/encoding/encoder.go
@@ -21,6 +21,7 @@
 	"os"
 	"path/filepath"
 
+	"cuelang.org/go/cue"
 	"cuelang.org/go/cue/ast"
 	"cuelang.org/go/cue/build"
 	"cuelang.org/go/cue/errors"
@@ -29,7 +30,6 @@
 	"cuelang.org/go/encoding/openapi"
 	"cuelang.org/go/internal"
 	"cuelang.org/go/internal/filetypes"
-	"cuelang.org/go/internal/legacy/cue"
 	"cuelang.org/go/pkg/encoding/yaml"
 )
 
diff --git a/internal/encoding/encoding.go b/internal/encoding/encoding.go
index 875ac21..8606bcb 100644
--- a/internal/encoding/encoding.go
+++ b/internal/encoding/encoding.go
@@ -26,6 +26,7 @@
 	"os"
 	"strings"
 
+	"cuelang.org/go/cue"
 	"cuelang.org/go/cue/ast"
 	"cuelang.org/go/cue/build"
 	"cuelang.org/go/cue/errors"
@@ -38,7 +39,6 @@
 	"cuelang.org/go/encoding/protobuf"
 	"cuelang.org/go/internal"
 	"cuelang.org/go/internal/filetypes"
-	"cuelang.org/go/internal/legacy/cue"
 	"cuelang.org/go/internal/third_party/yaml"
 	"golang.org/x/text/encoding/unicode"
 	"golang.org/x/text/transform"
diff --git a/internal/filetypes/filetypes.go b/internal/filetypes/filetypes.go
index c03c1a8..4e291af 100644
--- a/internal/filetypes/filetypes.go
+++ b/internal/filetypes/filetypes.go
@@ -20,10 +20,10 @@
 	"path/filepath"
 	"strings"
 
+	"cuelang.org/go/cue"
 	"cuelang.org/go/cue/build"
 	"cuelang.org/go/cue/errors"
 	"cuelang.org/go/cue/token"
-	"cuelang.org/go/internal/legacy/cue"
 )
 
 // Mode indicate the base mode of operation and indicates a different set of
diff --git a/internal/filetypes/gen.go b/internal/filetypes/gen.go
index 6430ff9..f0b9f03 100644
--- a/internal/filetypes/gen.go
+++ b/internal/filetypes/gen.go
@@ -21,9 +21,9 @@
 	"log"
 	"os"
 
+	"cuelang.org/go/cue"
 	"cuelang.org/go/cue/load"
 	"cuelang.org/go/encoding/gocode"
-	"cuelang.org/go/internal/legacy/cue"
 )
 
 func main() {
diff --git a/internal/filetypes/types.go b/internal/filetypes/types.go
index ba3c586..4c47c9b 100644
--- a/internal/filetypes/types.go
+++ b/internal/filetypes/types.go
@@ -5,8 +5,8 @@
 import (
 	"fmt"
 
+	"cuelang.org/go/cue"
 	"cuelang.org/go/encoding/gocode/gocodec"
-	"cuelang.org/go/internal/legacy/cue"
 )
 
 var cuegenCodec, cuegenInstance = func() (*gocodec.Codec, *cue.Instance) {
diff --git a/internal/legacy/cue/build.go b/internal/legacy/cue/build.go
deleted file mode 100644
index 65f0932..0000000
--- a/internal/legacy/cue/build.go
+++ /dev/null
@@ -1,341 +0,0 @@
-// Copyright 2018 The 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 (
-	"strings"
-	"sync"
-
-	"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/compile"
-	"cuelang.org/go/internal/core/runtime"
-)
-
-// A Runtime is used for creating CUE interpretations.
-//
-// 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 {
-	ctx *build.Context // TODO: remove
-	idx *index
-}
-
-func init() {
-	internal.GetRuntimeNew = 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.CheckAndForkRuntimeNew = func(runtime, value interface{}) interface{} {
-		r := runtime.(*Runtime)
-		idx := value.(Value).ctx().index
-		if idx != r.idx {
-			panic("value not from same runtime")
-		}
-		return &Runtime{idx: newIndex(idx)}
-	}
-
-	internal.CoreValue = func(value interface{}) (runtime, vertex interface{}) {
-		if v, ok := value.(Value); ok && v.v != nil {
-			return v.idx.Index, v.v
-		}
-		return nil, nil
-	}
-}
-
-func dummyLoad(token.Pos, string) *build.Instance { return nil }
-
-func (r *Runtime) index() *index {
-	if r.idx == nil {
-		r.idx = newIndex(sharedIndex)
-	}
-	return r.idx
-}
-
-func (r *Runtime) buildContext() *build.Context {
-	ctx := r.ctx
-	if r.ctx == nil {
-		ctx = build.NewContext()
-	}
-	return ctx
-}
-
-func (r *Runtime) complete(p *build.Instance) (*Instance, error) {
-	idx := r.index()
-	if err := p.Complete(); err != nil {
-		return nil, err
-	}
-	inst := idx.loadInstance(p)
-	inst.ImportPath = p.ImportPath
-	if inst.Err != nil {
-		return nil, inst.Err
-	}
-	return inst, nil
-}
-
-// Compile compiles the given source into an Instance. The source code may be
-// 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.
-func (r *Runtime) Compile(filename string, source interface{}) (*Instance, error) {
-	ctx := r.buildContext()
-	p := ctx.NewInstance(filename, dummyLoad)
-	if err := p.AddFile(filename, source); err != nil {
-		return nil, p.Err
-	}
-	return r.complete(p)
-}
-
-// CompileFile compiles the given source file into an Instance. The source may
-// import builtin packages. Use Build to allow importing non-builtin packages.
-func (r *Runtime) CompileFile(file *ast.File) (*Instance, error) {
-	ctx := r.buildContext()
-	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)
-}
-
-// CompileExpr compiles the given source expression into an Instance. The source
-// may import builtin packages. Use Build to allow importing non-builtin
-// packages.
-func (r *Runtime) CompileExpr(expr ast.Expr) (*Instance, error) {
-	f, err := astutil.ToFile(expr)
-	if err != nil {
-		return nil, err
-	}
-	return r.CompileFile(f)
-}
-
-// 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
-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)
-}
-
-// 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))
-//
-func Build(instances []*build.Instance) []*Instance {
-	if len(instances) == 0 {
-		panic("cue: list of instances must not be empty")
-	}
-	var r Runtime
-	a, _ := r.build(instances)
-	return a
-}
-
-func (r *Runtime) build(instances []*build.Instance) ([]*Instance, error) {
-	index := r.index()
-
-	loaded := []*Instance{}
-
-	var errs errors.Error
-
-	for _, p := range instances {
-		_ = p.Complete()
-		errs = errors.Append(errs, p.Err)
-
-		i := index.loadInstance(p)
-		errs = errors.Append(errs, i.Err)
-		loaded = append(loaded, i)
-	}
-
-	// TODO: insert imports
-	return loaded, errs
-}
-
-// FromExpr creates an instance from an expression.
-// Any references must be resolved beforehand.
-//
-// Deprecated: use CompileExpr
-func (r *Runtime) FromExpr(expr ast.Expr) (*Instance, error) {
-	return r.CompileFile(&ast.File{
-		Decls: []ast.Decl{&ast.EmbedDecl{Expr: expr}},
-	})
-}
-
-// index maps conversions from label names to internal codes.
-//
-// All instances belonging to the same package should share this index.
-type index struct {
-	adt.Runtime
-	*runtime.Index
-
-	loaded map[*build.Instance]*Instance
-	mutex  sync.Mutex
-}
-
-// sharedIndex is used for indexing builtins and any other labels common to
-// all instances.
-var sharedIndex = &index{
-	Runtime: runtime.SharedRuntimeNew,
-	Index:   runtime.SharedIndexNew,
-	loaded:  map[*build.Instance]*Instance{},
-}
-
-// NewRuntime creates a *runtime.Runtime with builtins preloaded.
-func NewRuntime() *runtime.Runtime {
-	idx := runtime.NewIndex(sharedIndex.Index)
-	r := runtime.NewWithIndex(idx)
-	i := &index{
-		Runtime: r,
-		Index:   idx,
-		loaded:  map[*build.Instance]*Instance{},
-	}
-	r.Data = i
-	return r
-}
-
-// newIndex creates a new index.
-func newIndex(parent *index) *index {
-	idx := runtime.NewIndex(parent.Index)
-	r := runtime.NewWithIndex(idx)
-	i := &index{
-		Runtime: r,
-		Index:   idx,
-		loaded:  map[*build.Instance]*Instance{},
-	}
-	r.Data = i
-	return i
-}
-
-func isBuiltin(s string) bool {
-	_, ok := builtins[s]
-	return ok
-}
-
-func (idx *index) loadInstance(p *build.Instance) *Instance {
-	_ = visitInstances(p, func(p *build.Instance, errs errors.Error) errors.Error {
-		if inst := idx.loaded[p]; inst != nil {
-			if !inst.complete {
-				// cycles should be detected by the builder and it should not be
-				// possible to construct a build.Instance that has them.
-				panic("cue: cycle")
-			}
-			return inst.Err
-		}
-
-		err := runtime.ResolveFiles(idx.Index, p, isBuiltin)
-		errs = errors.Append(errs, err)
-
-		v, err := compile.Files(nil, idx.Runtime, p.Files...)
-		errs = errors.Append(errs, err)
-
-		inst := newInstance(idx, p, v)
-		idx.loaded[p] = inst
-		inst.Err = errs
-
-		inst.ImportPath = p.ImportPath
-		inst.complete = true
-
-		return inst.Err
-	})
-
-	return idx.loaded[p]
-}
-
-// TODO: runtime.Runtime has a similar, much simpler, implementation. This
-// code should go.
-
-type visitFunc func(b *build.Instance, err errors.Error) (errs errors.Error)
-
-// visitInstances calls f for each transitive dependency.
-//
-// It passes any errors that occur in transitive dependencies to the visitFunc.
-// visitFunc must return the errors it is passed or return nil to ignore it.
-func visitInstances(b *build.Instance, f visitFunc) (errs errors.Error) {
-	v := visitor{b: b, f: f, errs: b.Err}
-	for _, file := range b.Files {
-		v.file(file)
-	}
-	return v.f(b, v.errs)
-}
-
-type visitor struct {
-	b    *build.Instance
-	f    visitFunc
-	errs errors.Error
-}
-
-func (v *visitor) addErr(e errors.Error) {
-	v.errs = errors.Append(v.errs, e)
-}
-
-func (v *visitor) file(file *ast.File) {
-	for _, d := range file.Decls {
-		switch x := d.(type) {
-		case *ast.Package:
-		case *ast.ImportDecl:
-			for _, s := range x.Specs {
-				v.spec(s)
-			}
-		case *ast.CommentGroup:
-		default:
-			return
-		}
-	}
-}
-
-func (v *visitor) spec(spec *ast.ImportSpec) {
-	info, err := astutil.ParseImportSpec(spec)
-	if err != nil {
-		v.addErr(errors.Promote(err, "invalid import path"))
-		return
-	}
-
-	pkg := v.b.LookupImport(info.ID)
-	if pkg == nil {
-		if strings.Contains(info.ID, ".") {
-			v.addErr(errors.Newf(spec.Pos(),
-				"package %q imported but not defined in %s",
-				info.ID, v.b.ImportPath))
-		}
-		return
-	}
-
-	v.addErr(visitInstances(pkg, v.f))
-}
diff --git a/internal/legacy/cue/build_test.go b/internal/legacy/cue/build_test.go
deleted file mode 100644
index 4cf0ccb..0000000
--- a/internal/legacy/cue/build_test.go
+++ /dev/null
@@ -1,259 +0,0 @@
-// Copyright 2018 The 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 (
-	"fmt"
-	"testing"
-
-	"cuelang.org/go/cue/ast"
-	"cuelang.org/go/cue/build"
-	"cuelang.org/go/cue/token"
-	"cuelang.org/go/internal/core/debug"
-)
-
-func TestFromExpr(t *testing.T) {
-	testCases := []struct {
-		expr ast.Expr
-		out  string
-	}{{
-		expr: ast.NewString("Hello"),
-		out:  `"Hello"`,
-	}, {
-		expr: ast.NewList(
-			ast.NewString("Hello"),
-			ast.NewString("World"),
-		),
-		out: `["Hello", "World"]`,
-	}}
-	for _, tc := range testCases {
-		t.Run("", func(t *testing.T) {
-			r := &Runtime{}
-			inst, err := r.CompileExpr(tc.expr)
-			if err != nil {
-				t.Fatal(err)
-			}
-			if got := fmt.Sprint(inst.Value()); got != tc.out {
-				t.Errorf("\n got: %v; want %v", got, tc.out)
-			}
-		})
-	}
-}
-
-func TestBuild(t *testing.T) {
-	files := func(s ...string) []string { return s }
-	insts := func(i ...*bimport) []*bimport { return i }
-	pkg1 := &bimport{
-		"pkg1",
-		files(`
-		package pkg1
-
-		Object: "World"
-		`),
-	}
-	pkg2 := &bimport{
-		"example.com/foo/pkg2:pkg",
-		files(`
-		package pkg
-
-		Number: 12
-		`),
-	}
-	pkg3 := &bimport{
-		"example.com/foo/v1:pkg3",
-		files(`
-		package pkg3
-
-		List: [1,2,3]
-		`),
-	}
-
-	testCases := []struct {
-		instances []*bimport
-		emit      string
-	}{{
-		insts(&bimport{"", files(`test: "ok"`)}),
-		`{test:"ok"}`,
-	}, {
-		insts(&bimport{"",
-			files(
-				`package test
-
-				import "math"
-
-				"Pi: \(math.Pi)!"`)}),
-		`"Pi: 3.14159265358979323846264338327950288419716939937510582097494459!"`,
-	}, {
-		insts(&bimport{"",
-			files(
-				`package test
-
-				import math2 "math"
-
-				"Pi: \(math2.Pi)!"`)}),
-		`"Pi: 3.14159265358979323846264338327950288419716939937510582097494459!"`,
-	}, {
-		insts(pkg1, &bimport{"",
-			files(
-				`package test
-
-				import "pkg1"
-
-				"Hello \(pkg1.Object)!"`),
-		}),
-		`"Hello World!"`,
-	}, {
-		insts(pkg1, &bimport{"",
-			files(
-				`package test
-
-				import "pkg1"
-
-				"Hello \(pkg1.Object)!"`),
-		}),
-		`"Hello World!"`,
-	}, {
-		insts(pkg1, &bimport{"",
-			files(
-				`package test
-
-				import pkg2 "pkg1"
-				#pkg1: pkg2.Object
-
-				"Hello \(#pkg1)!"`),
-		}),
-		`"Hello World!"`,
-	}, {
-		insts(pkg1, pkg2, &bimport{"",
-			files(
-				`package test
-
-				import bar "pkg1"
-				import baz "example.com/foo/pkg2:pkg"
-
-				pkg1: Object: 3
-				"Hello \(pkg1.Object)!"`),
-		}),
-		`imported and not used: "pkg1" as bar (and 1 more errors)`,
-	}, {
-		insts(pkg2, &bimport{"",
-			files(
-				`package test
-
-				import "example.com/foo/pkg2:pkg"
-
-				"Hello \(pkg2.Number)!"`),
-		}),
-		`imported and not used: "example.com/foo/pkg2:pkg" (and 1 more errors)`,
-		// `file0.cue:5:14: unresolved reference pkg2`,
-	}, {
-		insts(pkg2, &bimport{"",
-			files(
-				`package test
-
-				import "example.com/foo/pkg2:pkg"
-
-				"Hello \(pkg.Number)!"`),
-		}),
-		`"Hello 12!"`,
-	}, {
-		insts(pkg3, &bimport{"",
-			files(
-				`package test
-
-				import "example.com/foo/v1:pkg3"
-
-				"Hello \(pkg3.List[1])!"`),
-		}),
-		`"Hello 2!"`,
-	}, {
-		insts(pkg3, &bimport{"",
-			files(
-				`package test
-
-				import "example.com/foo/v1:pkg3"
-
-				pkg3: 3
-
-				"Hello \(pkg3.List[1])!"`),
-		}),
-		`pkg3 redeclared as imported package name
-	previous declaration at file0.cue:5:5`,
-	}}
-	for _, tc := range testCases {
-		t.Run("", func(t *testing.T) {
-			insts := Build(makeInstances(tc.instances))
-			var got string
-			if err := insts[0].Err; err != nil {
-				got = err.Error()
-			} else {
-				cfg := &debug.Config{Compact: true}
-				got = debug.NodeString(insts[0].Index, insts[0].Value().v, cfg)
-			}
-			if got != tc.emit {
-				t.Errorf("\n got: %s\nwant: %s", got, tc.emit)
-			}
-		})
-	}
-}
-
-type builder struct {
-	ctxt    *build.Context
-	imports map[string]*bimport
-}
-
-func (b *builder) load(pos token.Pos, path string) *build.Instance {
-	bi := b.imports[path]
-	if bi == nil {
-		return nil
-	}
-	return b.build(bi)
-}
-
-type bimport struct {
-	path  string // "" means top-level
-	files []string
-}
-
-func makeInstances(insts []*bimport) (instances []*build.Instance) {
-	b := builder{
-		ctxt:    build.NewContext(),
-		imports: map[string]*bimport{},
-	}
-	for _, bi := range insts {
-		if bi.path != "" {
-			b.imports[bi.path] = bi
-		}
-	}
-	for _, bi := range insts {
-		if bi.path == "" {
-			instances = append(instances, b.build(bi))
-		}
-	}
-	return
-}
-
-func (b *builder) build(bi *bimport) *build.Instance {
-	path := bi.path
-	if path == "" {
-		path = "dir"
-	}
-	p := b.ctxt.NewInstance(path, b.load)
-	for i, f := range bi.files {
-		_ = p.AddFile(fmt.Sprintf("file%d.cue", i), f)
-	}
-	_ = p.Complete()
-	return p
-}
diff --git a/internal/legacy/cue/builtin.go b/internal/legacy/cue/builtin.go
deleted file mode 100644
index 9fa9fa1..0000000
--- a/internal/legacy/cue/builtin.go
+++ /dev/null
@@ -1,740 +0,0 @@
-// Copyright 2018 The 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.
-
-//go:generate go run golang.org/x/tools/cmd/goimports -w -local cuelang.org/go builtins.go
-//go:generate gofmt -s -w builtins.go
-
-package cue
-
-import (
-	"encoding/json"
-	"fmt"
-	"io"
-	"math/big"
-	"path"
-	"sort"
-	"strings"
-
-	"github.com/cockroachdb/apd/v2"
-
-	"cuelang.org/go/cue/errors"
-	"cuelang.org/go/cue/parser"
-	"cuelang.org/go/cue/token"
-	"cuelang.org/go/internal"
-	"cuelang.org/go/internal/core/adt"
-	"cuelang.org/go/internal/core/compile"
-	"cuelang.org/go/internal/core/convert"
-	"cuelang.org/go/internal/core/runtime"
-)
-
-// A builtin is a builtin function or constant.
-//
-// A function may return and a constant may be any of the following types:
-//
-//   error (translates to bottom)
-//   nil   (translates to null)
-//   bool
-//   int*
-//   uint*
-//   float64
-//   string
-//   *big.Float
-//   *big.Int
-//
-//   For any of the above, including interface{} and these types recursively:
-//   []T
-//   map[string]T
-//
-type builtin struct {
-	Name   string
-	pkg    label
-	Params []kind
-	Result kind
-	Func   func(c *callCtxt)
-	// Const  interface{}
-	Const string
-}
-
-type builtinPkg struct {
-	native []*builtin
-	cue    string
-}
-
-func mustCompileBuiltins(ctx *context, p *builtinPkg, pkgName string) *adt.Vertex {
-	obj := &adt.Vertex{}
-	pkgLabel := ctx.Label(pkgName, false)
-	st := &adt.StructLit{}
-	if len(p.native) > 0 {
-		obj.AddConjunct(adt.MakeConjunct(nil, st))
-	}
-	for _, b := range p.native {
-		b.pkg = pkgLabel
-
-		f := ctx.Label(b.Name, false) // never starts with _
-		// n := &node{baseValue: newBase(imp.Path)}
-		var v adt.Expr = toBuiltin(ctx, b)
-		if b.Const != "" {
-			v = mustParseConstBuiltin(ctx, b.Name, b.Const)
-		}
-		st.Decls = append(st.Decls, &adt.Field{
-			Label: f,
-			Value: v,
-		})
-	}
-
-	// Parse builtin CUE
-	if p.cue != "" {
-		expr, err := parser.ParseExpr(pkgName, p.cue)
-		if err != nil {
-			panic(fmt.Errorf("could not parse %v: %v", p.cue, err))
-		}
-		c, err := compile.Expr(nil, ctx.opCtx.Runtime, expr)
-		if err != nil {
-			panic(fmt.Errorf("could compile parse %v: %v", p.cue, err))
-		}
-		obj.AddConjunct(c)
-	}
-
-	// We could compile lazily, but this is easier for debugging.
-	obj.Finalize(ctx.opCtx)
-	if err := obj.Err(ctx.opCtx, adt.Finalized); err != nil {
-		panic(err.Err)
-	}
-
-	return obj
-}
-
-func toBuiltin(ctx *context, b *builtin) *adt.Builtin {
-	x := &adt.Builtin{
-		Params:  b.Params,
-		Result:  b.Result,
-		Package: b.pkg,
-		Name:    b.Name,
-	}
-	x.Func = func(ctx *adt.OpContext, args []adt.Value) (ret adt.Expr) {
-		runtime := ctx.Impl().(*runtime.Runtime)
-		index := runtime.Data.(*index)
-
-		// call, _ := ctx.Source().(*ast.CallExpr)
-		c := &callCtxt{
-			idx: index,
-			// src:  call,
-			ctx:     index.newContext(),
-			args:    args,
-			builtin: b,
-		}
-		defer func() {
-			var errVal interface{} = c.err
-			if err := recover(); err != nil {
-				errVal = err
-			}
-			ret = processErr(c, errVal, ret)
-		}()
-		b.Func(c)
-		switch v := c.ret.(type) {
-		case adt.Value:
-			return v
-		case *valueError:
-			return v.err
-		}
-		if c.err != nil {
-			return nil
-		}
-		return convert.GoValueToValue(ctx, c.ret, true)
-	}
-	return x
-}
-
-// newConstBuiltin parses and creates any CUE expression that does not have
-// fields.
-func mustParseConstBuiltin(ctx *context, name, val string) adt.Expr {
-	expr, err := parser.ParseExpr("<builtin:"+name+">", val)
-	if err != nil {
-		panic(err)
-	}
-	c, err := compile.Expr(nil, ctx.Runtime, expr)
-	if err != nil {
-		panic(err)
-	}
-	return c.Expr()
-
-}
-
-var lenBuiltin = &builtin{
-	Name:   "len",
-	Params: []kind{stringKind | bytesKind | listKind | structKind},
-	Result: intKind,
-	Func: func(c *callCtxt) {
-		v := c.value(0)
-		switch k := v.IncompleteKind(); k {
-		case StructKind:
-			s, err := v.structValData(c.ctx)
-			if err != nil {
-				c.ret = err
-				break
-			}
-			c.ret = s.Len()
-		case ListKind:
-			i := 0
-			iter, err := v.List()
-			if err != nil {
-				c.ret = err
-				break
-			}
-			for ; iter.Next(); i++ {
-			}
-			c.ret = i
-		case BytesKind:
-			b, err := v.Bytes()
-			if err != nil {
-				c.ret = err
-				break
-			}
-			c.ret = len(b)
-		case StringKind:
-			s, err := v.String()
-			if err != nil {
-				c.ret = err
-				break
-			}
-			c.ret = len(s)
-		default:
-			c.ret = c.ctx.opCtx.Newf("invalid argument type %v", k)
-		}
-	},
-}
-
-func pos(n adt.Node) (p token.Pos) {
-	if n == nil {
-		return
-	}
-	src := n.Source()
-	if src == nil {
-		return
-	}
-	return src.Pos()
-}
-
-var closeBuiltin = &builtin{
-	Name:   "close",
-	Params: []kind{structKind},
-	Result: structKind,
-	Func: func(c *callCtxt) {
-		s, ok := c.args[0].(*adt.Vertex)
-		if !ok {
-			c.ret = errors.Newf(pos(c.args[0]), "struct argument must be concrete")
-			return
-		}
-		if s.IsClosed(c.ctx.opCtx) {
-			c.ret = s
-		} else {
-			v := *s
-			v.Closed = nil // TODO: set dedicated Closer.
-			c.ret = &v
-		}
-	},
-}
-
-var andBuiltin = &builtin{
-	Name:   "and",
-	Params: []kind{listKind},
-	Result: intKind,
-	Func: func(c *callCtxt) {
-		iter := c.iter(0)
-		if !iter.Next() {
-			c.ret = &top{}
-			return
-		}
-		var u adt.Expr = iter.Value().v
-		for iter.Next() {
-			u = &adt.BinaryExpr{Op: adt.AndOp, X: u, Y: iter.Value().v}
-		}
-		c.ret = u
-	},
-}
-
-var orBuiltin = &builtin{
-	Name:   "or",
-	Params: []kind{listKind},
-	Result: intKind,
-	Func: func(c *callCtxt) {
-		iter := c.iter(0)
-		d := []adt.Disjunct{}
-		for iter.Next() {
-			d = append(d, adt.Disjunct{iter.Value().v, false})
-		}
-		c.ret = &adt.DisjunctionExpr{nil, d, false}
-		if len(d) == 0 {
-			// TODO(manifest): This should not be unconditionally incomplete,
-			// but it requires results from comprehensions and all to have
-			// some special status. Maybe this can be solved by having results
-			// of list comprehensions be open if they result from iterating over
-			// an open list or struct. This would actually be exactly what
-			// that means. The error here could then only add an incomplete
-			// status if the source is open.
-			c.ret = &adt.Bottom{
-				Code: adt.IncompleteError,
-				Err:  errors.Newf(c.Pos(), "empty list in call to or"),
-			}
-		}
-	},
-}
-
-func (x *builtin) name(ctx *context) string {
-	if x.pkg == 0 {
-		return x.Name
-	}
-	return fmt.Sprintf("%s.%s", ctx.LabelStr(x.pkg), x.Name)
-}
-
-func (x *builtin) isValidator() bool {
-	return len(x.Params) == 1 && x.Result == boolKind
-}
-
-func processErr(call *callCtxt, errVal interface{}, ret adt.Expr) adt.Expr {
-	ctx := call.ctx
-	src := call.src
-	switch err := errVal.(type) {
-	case nil:
-	case *callError:
-		ret = err.b
-	case *json.MarshalerError:
-		if err, ok := err.Err.(*marshalError); ok && err.b != nil {
-			ret = err.b
-		}
-	case *marshalError:
-		ret = wrapCallErr(call, err.b)
-	case *valueError:
-		ret = wrapCallErr(call, err.err)
-	case errors.Error:
-		ret = wrapCallErr(call, &adt.Bottom{Err: err})
-	case error:
-		if call.err == internal.ErrIncomplete {
-			ret = ctx.mkErr(src, codeIncomplete, "incomplete value")
-		} else {
-			// TODO: store the underlying error explicitly
-			ret = wrapCallErr(call, &adt.Bottom{Err: errors.Promote(err, "")})
-		}
-	default:
-		// Likely a string passed to panic.
-		ret = wrapCallErr(call, &adt.Bottom{
-			Err: errors.Newf(call.Pos(), "%s", err),
-		})
-	}
-	return ret
-}
-
-func wrapCallErr(c *callCtxt, b *adt.Bottom) *adt.Bottom {
-	pos := token.NoPos
-	if c.src != nil {
-		if src := c.src.Source(); src != nil {
-			pos = src.Pos()
-		}
-	}
-	const msg = "error in call to %s"
-	return &adt.Bottom{
-		Code: b.Code,
-		Err:  errors.Wrapf(b.Err, pos, msg, c.builtin.name(c.ctx)),
-	}
-}
-
-func (c *callCtxt) convertError(x interface{}, name string) *adt.Bottom {
-	var err errors.Error
-	switch v := x.(type) {
-	case nil:
-		return nil
-
-	case *adt.Bottom:
-		return v
-
-	case *json.MarshalerError:
-		err = errors.Promote(v, "marshal error")
-
-	case errors.Error:
-		err = v
-
-	case error:
-		if name != "" {
-			err = errors.Newf(c.Pos(), "%s: %v", name, v)
-		} else {
-			err = errors.Newf(c.Pos(), "error in call to %s: %v", c.name(), v)
-		}
-
-	default:
-		err = errors.Newf(token.NoPos, "%s", name)
-	}
-	if err != internal.ErrIncomplete {
-		return &adt.Bottom{
-			// Wrap to preserve position information.
-			Err: errors.Wrapf(err, c.Pos(), "error in call to %s", c.name()),
-		}
-	}
-	return &adt.Bottom{
-		Code: adt.IncompleteError,
-		Err:  errors.Newf(c.Pos(), "incomplete values in call to %s", c.name()),
-	}
-}
-
-// callCtxt is passed to builtin implementations.
-type callCtxt struct {
-	idx     *index
-	src     adt.Expr // *adt.CallExpr
-	ctx     *context
-	builtin *builtin
-	err     interface{}
-	ret     interface{}
-
-	args []adt.Value
-}
-
-func (c *callCtxt) Pos() token.Pos {
-	return c.ctx.opCtx.Pos()
-}
-
-func (c *callCtxt) name() string {
-	return c.builtin.name(c.ctx)
-}
-
-var builtins = map[string]*Instance{}
-
-func initBuiltins(pkgs map[string]*builtinPkg) {
-	ctx := sharedIndex.newContext()
-	keys := []string{}
-	for k := range pkgs {
-		keys = append(keys, k)
-	}
-	sort.Strings(keys)
-	for _, k := range keys {
-		b := pkgs[k]
-		e := mustCompileBuiltins(ctx, b, k)
-
-		i := sharedIndex.addInst(&Instance{
-			ImportPath: k,
-			PkgName:    path.Base(k),
-			root:       e,
-		})
-
-		builtins[k] = i
-		builtins["-/"+path.Base(k)] = i
-	}
-}
-
-func getBuiltinShorthandPkg(ctx *context, shorthand string) *structLit {
-	return getBuiltinPkg(ctx, "-/"+shorthand)
-}
-
-func getBuiltinPkg(ctx *context, path string) *structLit {
-	p, ok := builtins[path]
-	if !ok {
-		return nil
-	}
-	return p.root
-}
-
-func init() {
-	internal.UnifyBuiltin = func(val interface{}, kind string) interface{} {
-		v := val.(Value)
-		ctx := v.ctx()
-
-		p := strings.Split(kind, ".")
-		pkg, name := p[0], p[1]
-		s := getBuiltinPkg(ctx, pkg)
-		if s == nil {
-			return v
-		}
-		a := s.Lookup(ctx.Label(name, false))
-		if a == nil {
-			return v
-		}
-
-		return v.Unify(makeValue(v.idx, a))
-	}
-}
-
-// do returns whether the call should be done.
-func (c *callCtxt) do() bool {
-	return c.err == nil
-}
-
-type callError struct {
-	b *bottom
-}
-
-func (e *callError) Error() string {
-	return fmt.Sprint(e.b)
-}
-
-func (c *callCtxt) errf(src source, underlying error, format string, args ...interface{}) {
-	a := make([]interface{}, 0, 2+len(args))
-	if err, ok := underlying.(*valueError); ok {
-		a = append(a, err.err)
-	}
-	a = append(a, format)
-	a = append(a, args...)
-	err := c.ctx.mkErr(src, a...)
-	c.err = &callError{err}
-}
-
-func (c *callCtxt) errcf(src source, code adt.ErrorCode, format string, args ...interface{}) {
-	a := make([]interface{}, 0, 2+len(args))
-	a = append(a, code)
-	a = append(a, format)
-	a = append(a, args...)
-	err := c.ctx.mkErr(src, a...)
-	c.err = &callError{err}
-}
-
-func (c *callCtxt) value(i int) Value {
-	v := newValueRoot(c.ctx, c.args[i])
-	// TODO: remove default
-	// v, _ = v.Default()
-	if !v.IsConcrete() {
-		c.errcf(c.src, adt.IncompleteError, "non-concrete argument %d", i)
-	}
-	return v
-}
-
-func (c *callCtxt) structVal(i int) *Struct {
-	v := newValueRoot(c.ctx, c.args[i])
-	s, err := v.Struct()
-	if err != nil {
-		c.invalidArgType(c.args[i], i, "struct", err)
-		return nil
-	}
-	return s
-}
-
-func (c *callCtxt) invalidArgType(arg value, i int, typ string, err error) {
-	if ve, ok := err.(*valueError); ok && ve.err.IsIncomplete() {
-		c.err = ve
-		return
-	}
-	v, ok := arg.(adt.Value)
-	// TODO: make these permanent errors if the value did not originate from
-	// a reference.
-	if !ok {
-		c.errf(c.src, nil,
-			"cannot use incomplete value %s as %s in argument %d to %s: %v",
-			c.ctx.str(arg), typ, i, c.name(), err)
-	}
-	if err != nil {
-		c.errf(c.src, err,
-			"cannot use %s (type %s) as %s in argument %d to %s: %v",
-			c.ctx.str(arg), v.Kind(), typ, i, c.name(), err)
-	} else {
-		c.errf(c.src, err,
-			"cannot use %s (type %s) as %s in argument %d to %s",
-			c.ctx.str(arg), v.Kind(), typ, i, c.name())
-	}
-}
-
-func (c *callCtxt) int(i int) int     { return int(c.intValue(i, 64, "int64")) }
-func (c *callCtxt) int8(i int) int8   { return int8(c.intValue(i, 8, "int8")) }
-func (c *callCtxt) int16(i int) int16 { return int16(c.intValue(i, 16, "int16")) }
-func (c *callCtxt) int32(i int) int32 { return int32(c.intValue(i, 32, "int32")) }
-func (c *callCtxt) rune(i int) rune   { return rune(c.intValue(i, 32, "rune")) }
-func (c *callCtxt) int64(i int) int64 { return int64(c.intValue(i, 64, "int64")) }
-
-func (c *callCtxt) intValue(i, bits int, typ string) int64 {
-	arg := c.args[i]
-	x := newValueRoot(c.ctx, arg)
-	n, err := x.Int(nil)
-	if err != nil {
-		c.invalidArgType(arg, i, typ, err)
-		return 0
-	}
-	if n.BitLen() > bits {
-		c.errf(c.src, err, "int %s overflows %s in argument %d in call to %s",
-			n, typ, i, c.name())
-	}
-	res, _ := x.Int64()
-	return res
-}
-
-func (c *callCtxt) uint(i int) uint     { return uint(c.uintValue(i, 64, "uint64")) }
-func (c *callCtxt) uint8(i int) uint8   { return uint8(c.uintValue(i, 8, "uint8")) }
-func (c *callCtxt) byte(i int) uint8    { return byte(c.uintValue(i, 8, "byte")) }
-func (c *callCtxt) uint16(i int) uint16 { return uint16(c.uintValue(i, 16, "uint16")) }
-func (c *callCtxt) uint32(i int) uint32 { return uint32(c.uintValue(i, 32, "uint32")) }
-func (c *callCtxt) uint64(i int) uint64 { return uint64(c.uintValue(i, 64, "uint64")) }
-
-func (c *callCtxt) uintValue(i, bits int, typ string) uint64 {
-	x := newValueRoot(c.ctx, c.args[i])
-	n, err := x.Int(nil)
-	if err != nil || n.Sign() < 0 {
-		c.invalidArgType(c.args[i], i, typ, err)
-		return 0
-	}
-	if n.BitLen() > bits {
-		c.errf(c.src, err, "int %s overflows %s in argument %d in call to %s",
-			n, typ, i, c.name())
-	}
-	res, _ := x.Uint64()
-	return res
-}
-
-func (c *callCtxt) decimal(i int) *apd.Decimal {
-	x := newValueRoot(c.ctx, c.args[i])
-	if _, err := x.MantExp(nil); err != nil {
-		c.invalidArgType(c.args[i], i, "Decimal", err)
-		return nil
-	}
-	return &c.args[i].(*numLit).X
-}
-
-func (c *callCtxt) float64(i int) float64 {
-	x := newValueRoot(c.ctx, c.args[i])
-	res, err := x.Float64()
-	if err != nil {
-		c.invalidArgType(c.args[i], i, "float64", err)
-		return 0
-	}
-	return res
-}
-
-func (c *callCtxt) bigInt(i int) *big.Int {
-	x := newValueRoot(c.ctx, c.args[i])
-	n, err := x.Int(nil)
-	if err != nil {
-		c.invalidArgType(c.args[i], i, "int", err)
-		return nil
-	}
-	return n
-}
-
-var ten = big.NewInt(10)
-
-func (c *callCtxt) bigFloat(i int) *big.Float {
-	x := newValueRoot(c.ctx, c.args[i])
-	var mant big.Int
-	exp, err := x.MantExp(&mant)
-	if err != nil {
-		c.invalidArgType(c.args[i], i, "float", err)
-		return nil
-	}
-	f := &big.Float{}
-	f.SetInt(&mant)
-	if exp != 0 {
-		var g big.Float
-		e := big.NewInt(int64(exp))
-		f.Mul(f, g.SetInt(e.Exp(ten, e, nil)))
-	}
-	return f
-}
-
-func (c *callCtxt) string(i int) string {
-	x := newValueRoot(c.ctx, c.args[i])
-	v, err := x.String()
-	if err != nil {
-		c.invalidArgType(c.args[i], i, "string", err)
-		return ""
-	}
-	return v
-}
-
-func (c *callCtxt) bytes(i int) []byte {
-	x := newValueRoot(c.ctx, c.args[i])
-	v, err := x.Bytes()
-	if err != nil {
-		c.invalidArgType(c.args[i], i, "bytes", err)
-		return nil
-	}
-	return v
-}
-
-func (c *callCtxt) reader(i int) io.Reader {
-	x := newValueRoot(c.ctx, c.args[i])
-	// TODO: optimize for string and bytes cases
-	r, err := x.Reader()
-	if err != nil {
-		c.invalidArgType(c.args[i], i, "bytes|string", err)
-		return nil
-	}
-	return r
-}
-
-func (c *callCtxt) bool(i int) bool {
-	x := newValueRoot(c.ctx, c.args[i])
-	b, err := x.Bool()
-	if err != nil {
-		c.invalidArgType(c.args[i], i, "bool", err)
-		return false
-	}
-	return b
-}
-
-func (c *callCtxt) list(i int) (a []Value) {
-	arg := c.args[i]
-	x := newValueRoot(c.ctx, arg)
-	v, err := x.List()
-	if err != nil {
-		c.invalidArgType(c.args[i], i, "list", err)
-		return a
-	}
-	for v.Next() {
-		a = append(a, v.Value())
-	}
-	return a
-}
-
-func (c *callCtxt) iter(i int) (a Iterator) {
-	arg := c.args[i]
-	x := newValueRoot(c.ctx, arg)
-	v, err := x.List()
-	if err != nil {
-		c.invalidArgType(c.args[i], i, "list", err)
-		return Iterator{ctx: c.ctx}
-	}
-	return v
-}
-
-func (c *callCtxt) decimalList(i int) (a []*apd.Decimal) {
-	arg := c.args[i]
-	x := newValueRoot(c.ctx, arg)
-	v, err := x.List()
-	if err != nil {
-		c.invalidArgType(c.args[i], i, "list", err)
-		return nil
-	}
-	for j := 0; v.Next(); j++ {
-		num, err := v.Value().getNum(numKind)
-		if err != nil {
-			c.errf(c.src, err, "invalid list element %d in argument %d to %s: %v",
-				j, i, c.name(), err)
-			break
-		}
-		a = append(a, &num.X)
-	}
-	return a
-}
-
-func (c *callCtxt) strList(i int) (a []string) {
-	arg := c.args[i]
-	x := newValueRoot(c.ctx, arg)
-	v, err := x.List()
-	if err != nil {
-		c.invalidArgType(c.args[i], i, "list", err)
-		return nil
-	}
-	for j := 0; v.Next(); j++ {
-		str, err := v.Value().String()
-		if err != nil {
-			c.err = errors.Wrapf(err, c.Pos(),
-				"element %d of list argument %d", j, i)
-			break
-		}
-		a = append(a, str)
-	}
-	return a
-}
diff --git a/internal/legacy/cue/builtin_test.go b/internal/legacy/cue/builtin_test.go
deleted file mode 100644
index 617235e..0000000
--- a/internal/legacy/cue/builtin_test.go
+++ /dev/null
@@ -1,714 +0,0 @@
-// Copyright 2018 The 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 (
-	"fmt"
-	"math/big"
-	"strconv"
-	"strings"
-	"testing"
-)
-
-func TestBuiltins(t *testing.T) {
-	test := func(pkg, expr string) []*bimport {
-		return []*bimport{{"",
-			[]string{fmt.Sprintf("import %q\n(%s)", pkg, expr)},
-		}}
-	}
-	testExpr := func(expr string) []*bimport {
-		return []*bimport{{"",
-			[]string{fmt.Sprintf("(%s)", expr)},
-		}}
-	}
-	hexToDec := func(s string) string {
-		var x big.Int
-		x.SetString(s, 16)
-		return x.String()
-	}
-	testCases := []struct {
-		instances []*bimport
-		emit      string
-	}{{
-		test("math", "math.Pi"),
-		`3.14159265358979323846264338327950288419716939937510582097494459`,
-	}, {
-		test("math", "math.Floor(math.Pi)"),
-		`3`,
-	}, {
-		test("math", "math.Pi(3)"),
-		`_|_(cannot call non-function math.Pi (type float))`,
-	}, {
-		test("math", "math.Floor(3, 5)"),
-		`_|_(too many arguments in call to math.Floor (have 2, want 1))`,
-	}, {
-		test("math", `math.Floor("foo")`),
-		`_|_(cannot use "foo" (type string) as number in argument 1 to math.Floor)`,
-	}, {
-		test("crypto/sha256", `sha256.Sum256("hash me")`),
-		`'\xeb \x1a\xf5\xaa\xf0\xd6\x06)\xd3Ҧ\x1eFl\xfc\x0f\xed\xb5\x17\xad\xd81\xec\xacR5\xe1کc\xd6'`,
-	}, {
-		test("crypto/md5", `len(md5.Sum("hash me"))`),
-		`16`,
-	}, {
-		test("crypto/sha1", `len(sha1.Sum("hash me"))`),
-		`20`,
-	}, {
-		test("crypto/sha256", `len(sha256.Sum256("hash me"))`),
-		`32`,
-	}, {
-		test("crypto/sha256", `len(sha256.Sum224("hash me"))`),
-		`28`,
-	}, {
-		test("crypto/sha512", `len(sha512.Sum512("hash me"))`),
-		`64`,
-	}, {
-		test("crypto/sha512", `len(sha512.Sum384("hash me"))`),
-		`48`,
-	}, {
-		test("crypto/sha512", `len(sha512.Sum512_224("hash me"))`),
-		`28`,
-	}, {
-		test("crypto/sha512", `len(sha512.Sum512_256("hash me"))`),
-		`32`,
-	}, {
-		test("encoding/base64", `base64.Encode(null, "foo")`),
-		`"Zm9v"`,
-	}, {
-		test("encoding/base64", `base64.Decode(null, base64.Encode(null, "foo"))`),
-		`'foo'`,
-	}, {
-		test("encoding/base64", `base64.Decode(null, "foo")`),
-		`_|_(error in call to encoding/base64.Decode: illegal base64 data at input byte 0 (and 1 more errors))`,
-	}, {
-		test("encoding/base64", `base64.Decode({}, "foo")`),
-		`_|_(error in call to encoding/base64.Decode: base64: unsupported encoding: cannot use value {} (type struct) as null (and 1 more errors))`,
-	}, {
-		test("encoding/hex", `hex.Encode("foo")`),
-		`"666f6f"`,
-	}, {
-		test("encoding/hex", `hex.Decode(hex.Encode("foo"))`),
-		`'foo'`,
-	}, {
-		test("encoding/hex", `hex.Decode("foo")`),
-		`_|_(error in call to encoding/hex.Decode: encoding/hex: invalid byte: U+006F 'o' (and 1 more errors))`,
-	}, {
-		test("encoding/hex", `hex.Dump('foo')`),
-		`"00000000  66 6f 6f                                          |foo|\n"`,
-	}, {
-		test("encoding/json", `json.Validate("{\"a\":10}", {b:string})`),
-		`true`,
-	}, {
-		test("encoding/json", `json.Validate("{\"a\":10}", {a:<3})`),
-		`_|_(error in call to encoding/json.Validate: a: invalid value 10 (out of bound <3) (and 1 more errors))`,
-	}, {
-		test("encoding/yaml", `yaml.Validate("a: 2\n---\na: 4", {a:<3})`),
-		`_|_(error in call to encoding/yaml.Validate: a: invalid value 4 (out of bound <3) (and 1 more errors))`,
-	}, {
-		test("encoding/yaml", `yaml.Validate("a: 2\n---\na: 4", {a:<5})`),
-		`true`,
-	}, {
-		test("encoding/yaml", `yaml.Validate("a: 2\n", {a:<5, b:int})`),
-		`_|_(error in call to encoding/yaml.Validate: b: incomplete value int (and 1 more errors))`,
-	}, {
-		test("encoding/yaml", `yaml.ValidatePartial("a: 2\n---\na: 4", {a:<3})`),
-		`_|_(error in call to encoding/yaml.ValidatePartial: a: invalid value 4 (out of bound <3) (and 1 more errors))`,
-	}, {
-		test("encoding/yaml", `yaml.ValidatePartial("a: 2\n---\na: 4", {a:<5})`),
-		`true`,
-	}, {
-		test("encoding/yaml", `yaml.ValidatePartial("a: 2\n", {a:<5, b:int})`),
-		`true`,
-	}, {
-		test("strconv", `strconv.FormatUint(64, 16)`),
-		`"40"`,
-	}, {
-		// Find a better alternative, as this call should go.
-		test("strconv", `strconv.FormatFloat(3.02, 300, 4, 64)`),
-		`_|_(int 300 overflows byte in argument 1 in call to strconv.FormatFloat (and 1 more errors))`,
-	}, {
-		// Find a better alternative, as this call should go.
-		test("strconv", `strconv.FormatFloat(3.02, -1, 4, 64)`),
-		`_|_(cannot use -1 (type int) as byte in argument 1 to strconv.FormatFloat (and 1 more errors))`,
-	}, {
-		// Find a better alternative, as this call should go.
-		test("strconv", `strconv.FormatFloat(3.02, 1.0, 4, 64)`),
-		`_|_(cannot use 1.0 (type float) as int in argument 2 to strconv.FormatFloat)`,
-	}, {
-		test("list", `list.Avg([1, 2, 3, 4])`),
-		`2.5`,
-	}, {
-		test("list", `list.Avg([])`),
-		`_|_(error in call to list.Avg: empty list (and 1 more errors))`,
-	}, {
-		test("list", `list.Avg("foo")`),
-		`_|_(cannot use "foo" (type string) as list in argument 1 to list.Avg)`,
-	}, {
-		test("list", `list.Drop([1, 2, 3, 4], 0)`),
-		`[1,2,3,4]`,
-	}, {
-		test("list", `list.Drop([1, 2, 3, 4], 2)`),
-		`[3,4]`,
-	}, {
-		test("list", `list.Drop([1, 2, 3, 4], 10)`),
-		`[]`,
-	}, {
-		test("list", `list.Drop([1, 2, 3, 4], -1)`),
-		`_|_(error in call to list.Drop: negative index (and 1 more errors))`,
-	}, {
-		test("list", `list.FlattenN([1, [[2, 3], []], [4]], -1)`),
-		`[1,2,3,4]`,
-	}, {
-		test("list", `list.FlattenN([1, [[2, 3], []], [4]], 0)`),
-		`[1,[[2,3],[]],[4]]`,
-	}, {
-		test("list", `list.FlattenN([1, [[2, 3], []], [4]], 1)`),
-		`[1,[2,3],[],4]`,
-	}, {
-		test("list", `list.FlattenN([1, [[2, 3], []], [4]], 2)`),
-		`[1,2,3,4]`,
-	}, {
-		test("list", `list.FlattenN([[1, 2] | *[]], -1)`),
-		`[]`,
-	}, {
-		test("list", `list.FlattenN("foo", 1)`),
-		`_|_(error in call to list.FlattenN: cannot use value "foo" (type string) as list (and 1 more errors))`,
-	}, {
-		test("list", `list.FlattenN([], "foo")`),
-		`_|_(cannot use "foo" (type string) as int in argument 2 to list.FlattenN)`,
-	}, {
-		test("list", `list.Max([1, 2, 3, 4])`),
-		`4`,
-	}, {
-		test("list", `list.Max([])`),
-		`_|_(error in call to list.Max: empty list (and 1 more errors))`,
-	}, {
-		test("list", `list.Max("foo")`),
-		`_|_(cannot use "foo" (type string) as list in argument 1 to list.Max)`,
-	}, {
-		test("list", `list.Min([1, 2, 3, 4])`),
-		`1`,
-	}, {
-		test("list", `list.Min([])`),
-		`_|_(error in call to list.Min: empty list (and 1 more errors))`,
-	}, {
-		test("list", `list.Min("foo")`),
-		`_|_(cannot use "foo" (type string) as list in argument 1 to list.Min)`,
-	}, {
-		test("list", `list.Product([1, 2, 3, 4])`),
-		`24`,
-	}, {
-		test("list", `list.Product([])`),
-		`1`,
-	}, {
-		test("list", `list.Product("foo")`),
-		`_|_(cannot use "foo" (type string) as list in argument 1 to list.Product)`,
-	}, {
-		test("list", `list.Range(0, 5, 0)`),
-		`_|_(error in call to list.Range: step must be non zero (and 1 more errors))`,
-	}, {
-		test("list", `list.Range(5, 0, 1)`),
-		`_|_(error in call to list.Range: end must be greater than start when step is positive (and 1 more errors))`,
-	}, {
-		test("list", `list.Range(0, 5, -1)`),
-		`_|_(error in call to list.Range: end must be less than start when step is negative (and 1 more errors))`,
-	}, {
-		test("list", `list.Range(0, 5, 1)`),
-		`[0,1,2,3,4]`,
-	}, {
-		test("list", `list.Range(0, 1, 1)`),
-		`[0]`,
-	}, {
-		test("list", `list.Range(0, 5, 2)`),
-		`[0,2,4]`,
-	}, {
-		test("list", `list.Range(5, 0, -1)`),
-		`[5,4,3,2,1]`,
-	}, {
-		test("list", `list.Range(0, 5, 0.5)`),
-		`[0,0.5,1.0,1.5,2.0,2.5,3.0,3.5,4.0,4.5]`,
-	}, {
-		test("list", `list.Slice([1, 2, 3, 4], 1, 3)`),
-		`[2,3]`,
-	}, {
-		test("list", `list.Slice([1, 2, 3, 4], -1, 3)`),
-		`_|_(error in call to list.Slice: negative index (and 1 more errors))`,
-	}, {
-		test("list", `list.Slice([1, 2, 3, 4], 3, 1)`),
-		`_|_(error in call to list.Slice: invalid index: 3 > 1 (and 1 more errors))`,
-	}, {
-		test("list", `list.Slice([1, 2, 3, 4], 5, 5)`),
-		`_|_(error in call to list.Slice: slice bounds out of range (and 1 more errors))`,
-	}, {
-		test("list", `list.Slice([1, 2, 3, 4], 1, 5)`),
-		`_|_(error in call to list.Slice: slice bounds out of range (and 1 more errors))`,
-	}, {
-		test("list", `list.Sort([], list.Ascending)`),
-		`[]`,
-	}, {
-		test("list", `list.Sort([2, 3, 1, 4], {x:_, y:_, less: x<y})`),
-		`[1,2,3,4]`,
-	}, {
-		test("list", `list.SortStable([{a:2,v:1}, {a:1,v:2}, {a:1,v:3}], {
-			x:_,
-			y:_,
-			less: (x.a < y.a)
-		})`),
-		`[{a:1,v:2},{a:1,v:3},{a:2,v:1}]`,
-	}, {
-		test("list", `list.Sort([{a:1}, {b:2}], list.Ascending)`),
-		`_|_(error in call to list.Sort: x: conflicting values string and {b:2} (mismatched types string and struct) (and 1 more errors) (and 1 more errors))`,
-	}, {
-		test("list", `list.SortStrings(["b", "a"])`),
-		`["a","b"]`,
-	}, {
-		// TODO: path error. This should be done as part of builtin refactoring.
-		test("list", `list.SortStrings([1, 2])`),
-		`_|_(error in call to list.SortStrings: element 0 of list argument 0: 0: cannot use value 1 (type int) as string (and 1 more errors))`,
-	}, {
-		test("list", `list.Sum([1, 2, 3, 4])`),
-		`10`,
-	}, {
-		test("list", `list.Sum([])`),
-		`0`,
-	}, {
-		test("list", `list.Sum("foo")`),
-		`_|_(cannot use "foo" (type string) as list in argument 1 to list.Sum)`,
-	}, {
-		test("list", `list.Take([1, 2, 3, 4], 0)`),
-		`[]`,
-	}, {
-		test("list", `list.Take([1, 2, 3, 4], 2)`),
-		`[1,2]`,
-	}, {
-		test("list", `list.Take([1, 2, 3, 4], 10)`),
-		`[1,2,3,4]`,
-	}, {
-		test("list", `list.Take([1, 2, 3, 4], -1)`),
-		`_|_(error in call to list.Take: negative index (and 1 more errors))`,
-	}, {
-		test("list", `list.MinItems([1, 2, 3, 4], 2)`),
-		`true`,
-	}, {
-		test("list", `list.MinItems([1, 2, 3, 4], 5)`),
-		`false`,
-	}, {
-		test("list", `list.MaxItems([1, 2, 3, 4], 5)`),
-		`true`,
-	}, {
-		test("list", `list.MaxItems([1, 2, 3, 4], 2)`),
-		`false`,
-	}, {
-		// Panics
-		test("math", `math.Jacobi(1000, 2000)`),
-		`_|_(error in call to math.Jacobi: big: invalid 2nd argument to Int.Jacobi: need odd integer but got 2000 (and 1 more errors))`,
-	}, {
-		test("math", `math.Jacobi(1000, 201)`),
-		`1`,
-	}, {
-		test("math", `math.Asin(2.0e400)`),
-		`_|_(cannot use 2.0E+400 (type float) as float64 in argument 0 to math.Asin: value was rounded up (and 1 more errors))`,
-	}, {
-		test("math", `math.MultipleOf(4, 2)`), `true`,
-	}, {
-		test("math", `math.MultipleOf(5, 2)`), `false`,
-	}, {
-		test("math", `math.MultipleOf(5, 0)`),
-		`_|_(error in call to math.MultipleOf: division by zero (and 1 more errors))`,
-	}, {
-		test("math", `math.MultipleOf(100, 1.00001)`), `false`,
-	}, {
-		test("math", `math.MultipleOf(1, 1)`), `true`,
-	}, {
-		test("math", `math.MultipleOf(5, 2.5)`), `true`,
-	}, {
-		test("math", `math.MultipleOf(100e100, 10)`), `true`,
-	}, {
-		test("encoding/csv", `csv.Decode("1,2,3\n4,5,6")`),
-		`[["1","2","3"],["4","5","6"]]`,
-	}, {
-		test("regexp", `regexp.Find(#"f\w\w"#, "afoot")`),
-		`"foo"`,
-	}, {
-		test("regexp", `regexp.Find(#"f\w\w"#, "bar")`),
-		`_|_(error in call to regexp.Find: no match (and 1 more errors))`,
-	}, {
-		test("regexp", `regexp.FindAll(#"f\w\w"#, "afoot afloat from", 2)`),
-		`["foo","flo"]`,
-	}, {
-		test("regexp", `regexp.FindAll(#"f\w\w"#, "afoot afloat from", 2)`),
-		`["foo","flo"]`,
-	}, {
-		test("regexp", `regexp.FindAll(#"f\w\w"#, "bla bla", -1)`),
-		`_|_(error in call to regexp.FindAll: no match (and 1 more errors))`,
-	}, {
-		test("regexp", `regexp.FindSubmatch(#"f(\w)(\w)"#, "afloat afoot from")`),
-		`["flo","l","o"]`,
-	}, {
-		test("regexp", `regexp.FindAllSubmatch(#"f(\w)(\w)"#, "afloat afoot from", -1)`),
-		`[["flo","l","o"],["foo","o","o"],["fro","r","o"]]`,
-	}, {
-		test("regexp", `regexp.FindAllSubmatch(#"f(\w)(\w)"#, "aglom", -1)`),
-		`_|_(error in call to regexp.FindAllSubmatch: no match (and 1 more errors))`,
-	}, {
-		test("regexp", `regexp.FindNamedSubmatch(#"f(?P<A>\w)(?P<B>\w)"#, "afloat afoot from")`),
-		`{A:"l",B:"o"}`,
-	}, {
-		test("regexp", `regexp.FindAllNamedSubmatch(#"f(?P<A>\w)(?P<B>\w)"#, "afloat afoot from", -1)`),
-		`[{A:"l",B:"o"},{A:"o",B:"o"},{A:"r",B:"o"}]`,
-	}, {
-		test("regexp", `regexp.FindAllNamedSubmatch(#"f(?P<A>optional)?"#, "fbla", -1)`),
-		`[{A:""}]`,
-	}, {
-		test("regexp", `regexp.FindAllNamedSubmatch(#"f(?P<A>\w)(?P<B>\w)"#, "aglom", -1)`),
-		`_|_(error in call to regexp.FindAllNamedSubmatch: no match (and 1 more errors))`,
-	}, {
-		test("regexp", `regexp.Valid & "valid"`),
-		`"valid"`,
-	}, {
-		test("regexp", `regexp.Valid & "invalid)"`),
-		"_|_(error in call to regexp.Valid: error parsing regexp: unexpected ): `invalid)`)",
-	}, {
-		test("strconv", `strconv.FormatBool(true)`),
-		`"true"`,
-	}, {
-		test("strings", `strings.Join(["Hello", "World!"], " ")`),
-		`"Hello World!"`,
-	}, {
-		test("strings", `strings.Join([1, 2], " ")`),
-		`_|_(error in call to strings.Join: element 0 of list argument 0: 0: cannot use value 1 (type int) as string (and 1 more errors))`,
-	}, {
-		test("strings", `strings.ByteAt("a", 0)`),
-		strconv.Itoa('a'),
-	}, {
-		test("strings", `strings.ByteSlice("Hello", 2, 5)`),
-		`'llo'`,
-	}, {
-		test("strings", `strings.SliceRunes("✓ Hello", 0, 3)`),
-		`"✓ H"`,
-	}, {
-		test("strings", `strings.Runes("Café")`),
-		strings.Replace(fmt.Sprint([]rune{'C', 'a', 'f', 'é'}), " ", ",", -1),
-	}, {
-		test("math/bits", `bits.Or(0x8, 0x1)`),
-		`9`,
-	}, {
-		testExpr(`len({})`),
-		`0`,
-	}, {
-		testExpr(`len({a: 1, b: 2, {[foo=_]: int}, _c: 3})`),
-		`2`,
-	}, {
-		testExpr(`len([1, 2, 3])`),
-		`3`,
-	}, {
-		testExpr(`len("foo")`),
-		`3`,
-	}, {
-		testExpr(`len('f\x20\x20')`),
-		`3`,
-	}, {
-		testExpr(`and([string, "foo"])`),
-		`"foo"`,
-	}, {
-		testExpr(`and([string, =~"fo"]) & "foo"`),
-		`"foo"`,
-	}, {
-		testExpr(`and([])`),
-		`{}`, // _ & top scope
-	}, {
-		testExpr(`or([1, 2, 3]) & 2`),
-		`2`,
-	}, {
-		testExpr(`or([])`),
-		`_|_(empty list in call to or (and 1 more errors))`,
-	}, {
-		test("encoding/csv", `csv.Encode([[1,2,3],[4,5],[7,8,9]])`),
-		`"1,2,3\n4,5\n7,8,9\n"`,
-	}, {
-		test("encoding/csv", `csv.Encode([["a", "b"], ["c"]])`),
-		`"a,b\nc\n"`,
-	}, {
-		test("encoding/json", `json.Valid("1")`),
-		`true`,
-	}, {
-		test("encoding/json", `json.Compact("[1, 2]")`),
-		`"[1,2]"`,
-	}, {
-		test("encoding/json", `json.Indent(#"{"a": 1, "b": 2}"#, "", "  ")`),
-		`"{\n  \"a\": 1,\n  \"b\": 2\n}"`,
-	}, {
-		test("encoding/json", `json.Unmarshal("1")`),
-		`1`,
-	}, {
-		test("encoding/json", `json.MarshalStream([{a: 1}, {b: 2}])`),
-		`"{\"a\":1}\n{\"b\":2}\n"`,
-	}, {
-		test("encoding/json", `{
-			x: int
-			y: json.Marshal({a: x})
-		}`),
-		`{x:int,y:_|_(cannot convert incomplete value "int" to JSON (and 1 more errors))}`,
-	}, {
-		test("encoding/yaml", `yaml.MarshalStream([{a: 1}, {b: 2}])`),
-		`"a: 1\n---\nb: 2\n"`,
-	}, {
-		test("net", `net.FQDN & "foo.bar."`),
-		`"foo.bar."`,
-	}, {
-		test("net", `net.FQDN("foo.bararararararararararararararararararararararararararararararararara")`),
-		`false`,
-	}, {
-		test("net", `net.SplitHostPort("[::%lo0]:80")`),
-		`["::%lo0","80"]`,
-	}, {
-		test("net", `net.JoinHostPort("example.com", "80")`),
-		`"example.com:80"`,
-	}, {
-		test("net", `net.JoinHostPort("2001:db8::1", 80)`),
-		`"[2001:db8::1]:80"`,
-	}, {
-		test("net", `net.JoinHostPort([192,30,4,2], 80)`),
-		`"192.30.4.2:80"`,
-	}, {
-		// TODO: why is this not printing compactly?
-		test("net", `net.JoinHostPort([192, 30, 4], 80)`),
-		`_|_(error in call to net.JoinHostPort: invalid host [192, 30, 4] (and 1 more errors))`,
-	}, {
-		test("net", `net.IP("23.23.23.23")`),
-		`true`,
-	}, {
-		test("net", `net.IPv4 & "23.23.23.2333"`),
-		`_|_(invalid value "23.23.23.2333" (does not satisfy net.IPv4))`,
-	}, {
-		test("net", `net.IP("23.23.23.23")`),
-		`true`,
-	}, {
-		test("net", `net.IP("2001:db8::1")`),
-		`true`,
-	}, {
-		test("net", `net.IPv4("2001:db8::1")`),
-		`false`,
-	}, {
-		test("net", `net.IPv4() & "ff02::1:3"`),
-		`_|_(invalid value "ff02::1:3" (does not satisfy net.IPv4))`,
-	}, {
-		test("net", `net.LoopbackIP([127, 0, 0, 1])`),
-		`true`,
-	}, {
-		test("net", `net.LoopbackIP("127.0.0.1")`),
-		`true`,
-	}, {
-		test("net", `net.ToIP4("127.0.0.1")`),
-		`[127,0,0,1]`,
-	}, {
-		test("net", `net.ToIP16("127.0.0.1")`),
-		`[0,0,0,0,0,0,0,0,0,0,255,255,127,0,0,1]`,
-	}, {
-		test("strings", `strings.ToCamel("AlphaBeta")`),
-		`"alphaBeta"`,
-	}, {
-		test("strings", `strings.ToTitle("alpha")`),
-		`"Alpha"`,
-	}, {
-		test("strings", `strings.MaxRunes(3) & "foo"`),
-		`"foo"`,
-	}, {
-		test("strings", `strings.MaxRunes(3) & "quux"`),
-		`_|_(invalid value "quux" (does not satisfy strings.MaxRunes(3)))`,
-	}, {
-		test("strings", `strings.MinRunes(1) & "e"`),
-		`"e"`,
-	}, {
-		test("strings", `strings.MaxRunes(0) & "e"`),
-		`_|_(invalid value "e" (does not satisfy strings.MaxRunes(0)))`,
-	}, {
-		test("strings", `strings.MaxRunes(0) & ""`),
-		`""`,
-	}, {
-		test("strings", `strings.MinRunes(3) & "hello"`),
-		`"hello"`,
-	}, {
-		test("strings", `strings.MaxRunes(10) & "hello"`),
-		`"hello"`,
-	}, {
-		test("strings", `strings.MaxRunes(3) & "hello"`),
-		`_|_(invalid value "hello" (does not satisfy strings.MaxRunes(3)))`,
-	}, {
-		test("strings", `strings.MinRunes(10) & "hello"`),
-		`_|_(invalid value "hello" (does not satisfy strings.MinRunes(10)))`,
-	}, {
-		test("struct", `struct.MinFields(0) & ""`),
-		`_|_(conflicting values struct.MinFields(0) and "" (mismatched types struct and string))`,
-	}, {
-		test("struct", `struct.MinFields(0) & {a: 1}`),
-		`{a:1}`,
-	}, {
-		test("struct", `struct.MinFields(2) & {a: 1}`),
-		`_|_(invalid value {a:1} (does not satisfy struct.MinFields(2)))`,
-	}, {
-		test("struct", `struct.MaxFields(0) & {a: 1}`),
-		`_|_(invalid value {a:1} (does not satisfy struct.MaxFields(0)))`,
-	}, {
-		test("struct", `struct.MaxFields(2) & {a: 1}`),
-		`{a:1}`,
-	}, {
-		test("math", `math.Pow(8, 4)`), `4096`,
-	}, {
-		test("math", `math.Pow10(4)`), `1E+4`,
-	}, {
-		test("math", `math.Signbit(-4)`), `true`,
-	}, {
-		test("math", `math.Round(2.5)`), `3`,
-	}, {
-		test("math", `math.Round(-2.5)`), `-3`,
-	}, {
-		test("math", `math.RoundToEven(2.5)`), `2`,
-	}, {
-		test("math", `math.RoundToEven(-2.5)`), `-2`,
-	}, {
-		test("math", `math.Abs(2.5)`), `2.5`,
-	}, {
-		test("math", `math.Abs(-2.2)`), `2.2`,
-	}, {
-		test("math", `math.Cbrt(2)`), `1.25992104989487316476721`,
-	}, {
-		test("math", `math.Copysign(5, -2.2)`), `-5`,
-	}, {
-		test("math", `math.Exp(3)`), `20.0855369231876677409285`,
-	}, {
-		test("math", `math.Exp2(3.5)`), `11.3137084989847603904135`,
-	}, {
-		test("math", `math.Log(4)`), `1.38629436111989061883446`,
-	}, {
-		test("math", `math.Log10(4)`), `0.602059991327962390427478`,
-	}, {
-		test("math", `math.Log2(5)`),
-		`2.32192809488736234787032`,
-	}, {
-		test("math", `math.Dim(3, 2.5)`), `0.5`,
-	}, {
-		test("math", `math.Dim(5, 7.2)`), `0`,
-	}, {
-		test("math", `math.Ceil(2.5)`), `3`,
-	}, {
-		test("math", `math.Ceil(-2.2)`), `-2`,
-	}, {
-		test("math", `math.Floor(2.9)`), `2`,
-	}, {
-		test("math", `math.Floor(-2.2)`), `-3`,
-	}, {
-		test("math", `math.Trunc(2.5)`), `2`,
-	}, {
-		test("math", `math.Trunc(-2.9)`), `-2`,
-	}, {
-		test("math/bits", `bits.Lsh(0x8, 4)`), `128`,
-	}, {
-		test("math/bits", `bits.Rsh(0x100, 4)`), `16`,
-	}, {
-		test("math/bits", `bits.At(0x100, 8)`), `1`,
-	}, {
-		test("math/bits", `bits.At(0x100, 9)`), `0`,
-	}, {
-		test("math/bits", `bits.Set(0x100, 7, 1)`), `384`,
-	}, {
-		test("math/bits", `bits.Set(0x100, 8, 0)`), `0`,
-	}, {
-		test("math/bits", `bits.And(0x10000000000000F0E, 0xF0F7)`), `6`,
-	}, {
-		test("math/bits", `bits.Or(0x100000000000000F0, 0x0F)`),
-		hexToDec("100000000000000FF"),
-	}, {
-		test("math/bits", `bits.Xor(0x10000000000000F0F, 0xFF0)`),
-		hexToDec("100000000000000FF"),
-	}, {
-		test("math/bits", `bits.Xor(0xFF0, 0x10000000000000F0F)`),
-		hexToDec("100000000000000FF"),
-	}, {
-		test("math/bits", `bits.Clear(0xF, 0x100000000000008)`), `7`,
-	}, {
-		test("math/bits", `bits.Clear(0x1000000000000000008, 0xF)`),
-		hexToDec("1000000000000000000"),
-	}, {
-		test("text/tabwriter", `tabwriter.Write("""
-			a\tb\tc
-			aaa\tbb\tvv
-			""")`),
-		`"a   b  c\naaa bb vv"`,
-	}, {
-		test("text/tabwriter", `tabwriter.Write([
-				"a\tb\tc",
-				"aaa\tbb\tvv"])`),
-		`"a   b  c\naaa bb vv\n"`,
-	}, {
-		test("text/template", `template.Execute("{{.}}-{{.}}", "foo")`),
-		`"foo-foo"`,
-	}, {
-		test("time", `time.Time & "1937-01-01T12:00:27.87+00:20"`),
-		`"1937-01-01T12:00:27.87+00:20"`,
-	}, {
-		test("time", `time.Time & "no time"`),
-		`_|_(error in call to time.Time: invalid time "no time")`,
-	}, {
-		test("time", `time.Unix(1500000000, 123456)`),
-		`"2017-07-14T02:40:00.000123456Z"`,
-	}}
-	for i, tc := range testCases {
-		t.Run(fmt.Sprint(i), func(t *testing.T) {
-			insts := Build(makeInstances(tc.instances))
-			if err := insts[0].Err; err != nil {
-				t.Fatal(err)
-			}
-			v := insts[0].Value()
-			ctx := v.ctx()
-			got := ctx.opCtx.Str(v.v)
-			if got != tc.emit {
-				t.Errorf("\n got: %s\nwant: %s", got, tc.emit)
-			}
-		})
-	}
-}
-
-// For debugging purposes. Do not remove.
-func TestSingleBuiltin(t *testing.T) {
-	t.Skip("error message")
-
-	test := func(pkg, expr string) []*bimport {
-		return []*bimport{{"",
-			[]string{fmt.Sprintf("import %q\n(%s)", pkg, expr)},
-		}}
-	}
-	testCases := []struct {
-		instances []*bimport
-		emit      string
-	}{{
-		test("list", `list.Sort([{a:1}, {b:2}], list.Ascending)`),
-		`_|_(error in call to list.Sort: less: invalid operands {b:2} and {a:1} to '<' (type struct and struct) (and 1 more errors))`,
-	}}
-	for i, tc := range testCases {
-		t.Run(fmt.Sprint(i), func(t *testing.T) {
-			insts := Build(makeInstances(tc.instances))
-			if err := insts[0].Err; err != nil {
-				t.Fatal(err)
-			}
-			v := insts[0].Value()
-			ctx := v.ctx()
-			got := ctx.opCtx.Str(v.v)
-			if got != tc.emit {
-				t.Errorf("\n got: %s\nwant: %s", got, tc.emit)
-			}
-		})
-	}
-}
diff --git a/internal/legacy/cue/builtins.go b/internal/legacy/cue/builtins.go
deleted file mode 100644
index 87ad902..0000000
--- a/internal/legacy/cue/builtins.go
+++ /dev/null
@@ -1,3784 +0,0 @@
-// Code generated by go generate. DO NOT EDIT.
-
-package cue
-
-import (
-	"bytes"
-	"crypto/md5"
-	"crypto/sha1"
-	"crypto/sha256"
-	"crypto/sha512"
-	"encoding/base64"
-	"encoding/csv"
-	"encoding/hex"
-	"encoding/json"
-	"fmt"
-	"html"
-	"io"
-	"math"
-	"math/big"
-	"math/bits"
-	"net"
-	"path"
-	"regexp"
-	"sort"
-	"strconv"
-	"strings"
-	"text/tabwriter"
-	"text/template"
-	"time"
-	"unicode"
-	"unicode/utf8"
-
-	"github.com/cockroachdb/apd/v2"
-	"golang.org/x/net/idna"
-
-	"cuelang.org/go/cue/errors"
-	"cuelang.org/go/cue/literal"
-	"cuelang.org/go/cue/parser"
-	"cuelang.org/go/internal"
-	cueyaml "cuelang.org/go/internal/encoding/yaml"
-	"cuelang.org/go/internal/third_party/yaml"
-)
-
-func init() {
-	initBuiltins(builtinPackages)
-}
-
-var _ io.Reader
-
-var roundTruncContext = apd.Context{Rounding: apd.RoundDown}
-
-var roundUpContext = apd.Context{Rounding: apd.RoundHalfUp}
-
-var roundEvenContext = apd.Context{Rounding: apd.RoundHalfEven}
-
-var mulContext = apd.BaseContext.WithPrecision(1)
-
-var apdContext = apd.BaseContext.WithPrecision(24)
-
-var zero = apd.New(0, 0)
-
-var two = apd.New(2, 0)
-
-var idnaProfile = idna.New(
-	idna.ValidateLabels(true),
-	idna.VerifyDNSLength(true),
-	idna.StrictDomainName(true),
-)
-
-func netGetIP(ip Value) (goip net.IP) {
-	switch ip.Kind() {
-	case StringKind:
-		s, err := ip.String()
-		if err != nil {
-			return nil
-		}
-		goip := net.ParseIP(s)
-		if goip == nil {
-			return nil
-		}
-		return goip
-
-	case BytesKind:
-		b, err := ip.Bytes()
-		if err != nil {
-			return nil
-		}
-		goip := net.ParseIP(string(b))
-		if goip == nil {
-			return nil
-		}
-		return goip
-
-	case ListKind:
-		iter, err := ip.List()
-		if err != nil {
-			return nil
-		}
-		for iter.Next() {
-			v, err := iter.Value().Int64()
-			if err != nil {
-				return nil
-			}
-			if v < 0 || 255 < v {
-				return nil
-			}
-			goip = append(goip, byte(v))
-		}
-		return goip
-
-	default:
-
-		return nil
-	}
-}
-
-func netToList(ip net.IP) []uint {
-	a := make([]uint, len(ip))
-	for i, p := range ip {
-		a[i] = uint(p)
-	}
-	return a
-}
-
-var split = path.Split
-
-var pathClean = path.Clean
-
-var pathExt = path.Ext
-
-var pathBase = path.Base
-
-var pathIsAbs = path.IsAbs
-
-var pathDir = path.Dir
-
-var errNoMatch = errors.New("no match")
-
-var errNoNamedGroup = errors.New("no named groups")
-
-func timeFormat(value, layout string) (bool, error) {
-	_, err := time.Parse(layout, value)
-	if err != nil {
-
-		return false, fmt.Errorf("invalid time %q", value)
-	}
-	return true, nil
-}
-
-var builtinPackages = map[string]*builtinPkg{
-	// "": {
-	// 	native: []*builtin{},
-	// },
-	"crypto/md5": {
-		native: []*builtin{{
-			Name:  "Size",
-			Const: "16",
-		}, {
-			Name:  "BlockSize",
-			Const: "64",
-		}, {
-			Name:   "Sum",
-			Params: []kind{bytesKind | stringKind},
-			Result: bytesKind | stringKind,
-			Func: func(c *callCtxt) {
-				data := c.bytes(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						a := md5.Sum(data)
-						return a[:]
-					}()
-				}
-			},
-		}},
-	},
-	"crypto/sha1": {
-		native: []*builtin{{
-			Name:  "Size",
-			Const: "20",
-		}, {
-			Name:  "BlockSize",
-			Const: "64",
-		}, {
-			Name:   "Sum",
-			Params: []kind{bytesKind | stringKind},
-			Result: bytesKind | stringKind,
-			Func: func(c *callCtxt) {
-				data := c.bytes(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						a := sha1.Sum(data)
-						return a[:]
-					}()
-				}
-			},
-		}},
-	},
-	"crypto/sha256": {
-		native: []*builtin{{
-			Name:  "Size",
-			Const: "32",
-		}, {
-			Name:  "Size224",
-			Const: "28",
-		}, {
-			Name:  "BlockSize",
-			Const: "64",
-		}, {
-			Name:   "Sum256",
-			Params: []kind{bytesKind | stringKind},
-			Result: bytesKind | stringKind,
-			Func: func(c *callCtxt) {
-				data := c.bytes(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						a := sha256.Sum256(data)
-						return a[:]
-					}()
-				}
-			},
-		}, {
-			Name:   "Sum224",
-			Params: []kind{bytesKind | stringKind},
-			Result: bytesKind | stringKind,
-			Func: func(c *callCtxt) {
-				data := c.bytes(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						a := sha256.Sum224(data)
-						return a[:]
-					}()
-				}
-			},
-		}},
-	},
-	"crypto/sha512": {
-		native: []*builtin{{
-			Name:  "Size",
-			Const: "64",
-		}, {
-			Name:  "Size224",
-			Const: "28",
-		}, {
-			Name:  "Size256",
-			Const: "32",
-		}, {
-			Name:  "Size384",
-			Const: "48",
-		}, {
-			Name:  "BlockSize",
-			Const: "128",
-		}, {
-			Name:   "Sum512",
-			Params: []kind{bytesKind | stringKind},
-			Result: bytesKind | stringKind,
-			Func: func(c *callCtxt) {
-				data := c.bytes(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						a := sha512.Sum512(data)
-						return a[:]
-					}()
-				}
-			},
-		}, {
-			Name:   "Sum384",
-			Params: []kind{bytesKind | stringKind},
-			Result: bytesKind | stringKind,
-			Func: func(c *callCtxt) {
-				data := c.bytes(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						a := sha512.Sum384(data)
-						return a[:]
-					}()
-				}
-			},
-		}, {
-			Name:   "Sum512_224",
-			Params: []kind{bytesKind | stringKind},
-			Result: bytesKind | stringKind,
-			Func: func(c *callCtxt) {
-				data := c.bytes(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						a := sha512.Sum512_224(data)
-						return a[:]
-					}()
-				}
-			},
-		}, {
-			Name:   "Sum512_256",
-			Params: []kind{bytesKind | stringKind},
-			Result: bytesKind | stringKind,
-			Func: func(c *callCtxt) {
-				data := c.bytes(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						a := sha512.Sum512_256(data)
-						return a[:]
-					}()
-				}
-			},
-		}},
-	},
-	"encoding/base64": {
-		native: []*builtin{{
-			Name:   "EncodedLen",
-			Params: []kind{topKind, intKind},
-			Result: intKind,
-			Func: func(c *callCtxt) {
-				encoding, n := c.value(0), c.int(1)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						if err := encoding.Null(); err != nil {
-							return 0, fmt.Errorf("base64: unsupported encoding: %v", err)
-						}
-						return base64.StdEncoding.EncodedLen(n), nil
-					}()
-				}
-			},
-		}, {
-			Name:   "DecodedLen",
-			Params: []kind{topKind, intKind},
-			Result: intKind,
-			Func: func(c *callCtxt) {
-				encoding, x := c.value(0), c.int(1)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						if err := encoding.Null(); err != nil {
-							return 0, fmt.Errorf("base64: unsupported encoding: %v", err)
-						}
-						return base64.StdEncoding.DecodedLen(x), nil
-					}()
-				}
-			},
-		}, {
-			Name:   "Encode",
-			Params: []kind{topKind, bytesKind | stringKind},
-			Result: stringKind,
-			Func: func(c *callCtxt) {
-				encoding, src := c.value(0), c.bytes(1)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						if err := encoding.Null(); err != nil {
-							return "", fmt.Errorf("base64: unsupported encoding: %v", err)
-						}
-						return base64.StdEncoding.EncodeToString(src), nil
-					}()
-				}
-			},
-		}, {
-			Name:   "Decode",
-			Params: []kind{topKind, stringKind},
-			Result: bytesKind | stringKind,
-			Func: func(c *callCtxt) {
-				encoding, s := c.value(0), c.string(1)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						if err := encoding.Null(); err != nil {
-							return nil, fmt.Errorf("base64: unsupported encoding: %v", err)
-						}
-						return base64.StdEncoding.DecodeString(s)
-					}()
-				}
-			},
-		}},
-	},
-	"encoding/csv": {
-		native: []*builtin{{
-			Name:   "Encode",
-			Params: []kind{topKind},
-			Result: stringKind,
-			Func: func(c *callCtxt) {
-				x := c.value(0)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						buf := &bytes.Buffer{}
-						w := csv.NewWriter(buf)
-						iter, err := x.List()
-						if err != nil {
-							return "", err
-						}
-						for iter.Next() {
-							row, err := iter.Value().List()
-							if err != nil {
-								return "", err
-							}
-							a := []string{}
-							for row.Next() {
-								col := row.Value()
-								if str, err := col.String(); err == nil {
-									a = append(a, str)
-								} else {
-									b, err := col.MarshalJSON()
-									if err != nil {
-										return "", err
-									}
-									a = append(a, string(b))
-								}
-							}
-							_ = w.Write(a)
-						}
-						w.Flush()
-						return buf.String(), nil
-					}()
-				}
-			},
-		}, {
-			Name:   "Decode",
-			Params: []kind{bytesKind | stringKind},
-			Result: listKind,
-			Func: func(c *callCtxt) {
-				r := c.reader(0)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						return csv.NewReader(r).ReadAll()
-					}()
-				}
-			},
-		}},
-	},
-	"encoding/hex": {
-		native: []*builtin{{
-			Name:   "EncodedLen",
-			Params: []kind{intKind},
-			Result: intKind,
-			Func: func(c *callCtxt) {
-				n := c.int(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return hex.EncodedLen(n)
-					}()
-				}
-			},
-		}, {
-			Name:   "DecodedLen",
-			Params: []kind{intKind},
-			Result: intKind,
-			Func: func(c *callCtxt) {
-				x := c.int(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return hex.DecodedLen(x)
-					}()
-				}
-			},
-		}, {
-			Name:   "Decode",
-			Params: []kind{stringKind},
-			Result: bytesKind | stringKind,
-			Func: func(c *callCtxt) {
-				s := c.string(0)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						return hex.DecodeString(s)
-					}()
-				}
-			},
-		}, {
-			Name:   "Dump",
-			Params: []kind{bytesKind | stringKind},
-			Result: stringKind,
-			Func: func(c *callCtxt) {
-				data := c.bytes(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return hex.Dump(data)
-					}()
-				}
-			},
-		}, {
-			Name:   "Encode",
-			Params: []kind{bytesKind | stringKind},
-			Result: stringKind,
-			Func: func(c *callCtxt) {
-				src := c.bytes(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return hex.EncodeToString(src)
-					}()
-				}
-			},
-		}},
-	},
-	"encoding/json": {
-		native: []*builtin{{
-			Name:   "Valid",
-			Params: []kind{bytesKind | stringKind},
-			Result: boolKind,
-			Func: func(c *callCtxt) {
-				data := c.bytes(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return json.Valid(data)
-					}()
-				}
-			},
-		}, {
-			Name:   "Compact",
-			Params: []kind{bytesKind | stringKind},
-			Result: stringKind,
-			Func: func(c *callCtxt) {
-				src := c.bytes(0)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						dst := bytes.Buffer{}
-						if err := json.Compact(&dst, src); err != nil {
-							return "", err
-						}
-						return dst.String(), nil
-					}()
-				}
-			},
-		}, {
-			Name:   "Indent",
-			Params: []kind{bytesKind | stringKind, stringKind, stringKind},
-			Result: stringKind,
-			Func: func(c *callCtxt) {
-				src, prefix, indent := c.bytes(0), c.string(1), c.string(2)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						dst := bytes.Buffer{}
-						if err := json.Indent(&dst, src, prefix, indent); err != nil {
-							return "", err
-						}
-						return dst.String(), nil
-					}()
-				}
-			},
-		}, {
-			Name:   "HTMLEscape",
-			Params: []kind{bytesKind | stringKind},
-			Result: stringKind,
-			Func: func(c *callCtxt) {
-				src := c.bytes(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						dst := &bytes.Buffer{}
-						json.HTMLEscape(dst, src)
-						return dst.String()
-					}()
-				}
-			},
-		}, {
-			Name:   "Marshal",
-			Params: []kind{topKind},
-			Result: stringKind,
-			Func: func(c *callCtxt) {
-				v := c.value(0)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						b, err := json.Marshal(v)
-						return string(b), err
-					}()
-				}
-			},
-		}, {
-			Name:   "MarshalStream",
-			Params: []kind{topKind},
-			Result: stringKind,
-			Func: func(c *callCtxt) {
-				v := c.value(0)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-
-						iter, err := v.List()
-						if err != nil {
-							return "", err
-						}
-						buf := &bytes.Buffer{}
-						for iter.Next() {
-							b, err := json.Marshal(iter.Value())
-							if err != nil {
-								return "", err
-							}
-							buf.Write(b)
-							buf.WriteByte('\n')
-						}
-						return buf.String(), nil
-					}()
-				}
-			},
-		}, {
-			Name:   "Unmarshal",
-			Params: []kind{bytesKind | stringKind},
-			Result: topKind,
-			Func: func(c *callCtxt) {
-				b := c.bytes(0)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						if !json.Valid(b) {
-							return nil, fmt.Errorf("json: invalid JSON")
-						}
-						expr, err := parser.ParseExpr("json", b)
-						if err != nil {
-
-							return nil, fmt.Errorf("json: could not parse JSON: %v", err)
-						}
-						return expr, nil
-					}()
-				}
-			},
-		}, {
-			Name:   "Validate",
-			Params: []kind{bytesKind | stringKind, topKind},
-			Result: boolKind,
-			Func: func(c *callCtxt) {
-				b, v := c.bytes(0), c.value(1)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						if !json.Valid(b) {
-							return false, fmt.Errorf("json: invalid JSON")
-						}
-						r := internal.GetRuntimeNew(v).(*Runtime)
-						inst, err := r.Compile("json.Validate", b)
-						if err != nil {
-							return false, err
-						}
-
-						t := inst.Value()
-
-						v = v.Unify(t)
-						if v.Err() != nil {
-							return false, v.Err()
-						}
-						return true, nil
-					}()
-				}
-			},
-		}},
-	},
-	"encoding/yaml": {
-		native: []*builtin{{
-			Name:   "Marshal",
-			Params: []kind{topKind},
-			Result: stringKind,
-			Func: func(c *callCtxt) {
-				v := c.value(0)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						if err := v.Validate(Concrete(true)); err != nil {
-							if err := v.Validate(); err != nil {
-								return "", err
-							}
-							return "", internal.ErrIncomplete
-						}
-						n := v.Syntax(Final(), Concrete(true))
-						b, err := cueyaml.Encode(n)
-						return string(b), err
-					}()
-				}
-			},
-		}, {
-			Name:   "MarshalStream",
-			Params: []kind{topKind},
-			Result: stringKind,
-			Func: func(c *callCtxt) {
-				v := c.value(0)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-
-						iter, err := v.List()
-						if err != nil {
-							return "", err
-						}
-						buf := &bytes.Buffer{}
-						for i := 0; iter.Next(); i++ {
-							if i > 0 {
-								buf.WriteString("---\n")
-							}
-							v := iter.Value()
-							if err := v.Validate(Concrete(true)); err != nil {
-								if err := v.Validate(); err != nil {
-									return "", err
-								}
-								return "", internal.ErrIncomplete
-							}
-							n := v.Syntax(Final(), Concrete(true))
-							b, err := cueyaml.Encode(n)
-							if err != nil {
-								return "", err
-							}
-							buf.Write(b)
-						}
-						return buf.String(), nil
-					}()
-				}
-			},
-		}, {
-			Name:   "Unmarshal",
-			Params: []kind{bytesKind | stringKind},
-			Result: topKind,
-			Func: func(c *callCtxt) {
-				data := c.bytes(0)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						return yaml.Unmarshal("", data)
-					}()
-				}
-			},
-		}, {
-			Name:   "Validate",
-			Params: []kind{bytesKind | stringKind, topKind},
-			Result: boolKind,
-			Func: func(c *callCtxt) {
-				b, v := c.bytes(0), c.value(1)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						d, err := yaml.NewDecoder("yaml.Validate", b)
-						if err != nil {
-							return false, err
-						}
-						r := internal.GetRuntimeNew(v).(*Runtime)
-						for {
-							expr, err := d.Decode()
-							if err != nil {
-								if err == io.EOF {
-									return true, nil
-								}
-								return false, err
-							}
-
-							inst, err := r.CompileExpr(expr)
-							if err != nil {
-								return false, err
-							}
-
-							x := v.Unify(inst.Value())
-							if err := x.Err(); err != nil {
-								return false, err
-							}
-							if err := x.Validate(Concrete(true)); err != nil {
-								return false, err
-							}
-
-						}
-					}()
-				}
-			},
-		}, {
-			Name:   "ValidatePartial",
-			Params: []kind{bytesKind | stringKind, topKind},
-			Result: boolKind,
-			Func: func(c *callCtxt) {
-				b, v := c.bytes(0), c.value(1)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						d, err := yaml.NewDecoder("yaml.ValidatePartial", b)
-						if err != nil {
-							return false, err
-						}
-						r := internal.GetRuntimeNew(v).(*Runtime)
-						for {
-							expr, err := d.Decode()
-							if err != nil {
-								if err == io.EOF {
-									return true, nil
-								}
-								return false, err
-							}
-
-							inst, err := r.CompileExpr(expr)
-							if err != nil {
-								return false, err
-							}
-
-							if x := v.Unify(inst.Value()); x.Err() != nil {
-								return false, x.Err()
-							}
-						}
-					}()
-				}
-			},
-		}},
-	},
-	"html": {
-		native: []*builtin{{
-			Name:   "Escape",
-			Params: []kind{stringKind},
-			Result: stringKind,
-			Func: func(c *callCtxt) {
-				s := c.string(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return html.EscapeString(s)
-					}()
-				}
-			},
-		}, {
-			Name:   "Unescape",
-			Params: []kind{stringKind},
-			Result: stringKind,
-			Func: func(c *callCtxt) {
-				s := c.string(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return html.UnescapeString(s)
-					}()
-				}
-			},
-		}},
-	},
-	"list": {
-		native: []*builtin{{
-			Name:   "Drop",
-			Params: []kind{listKind, intKind},
-			Result: listKind,
-			Func: func(c *callCtxt) {
-				x, n := c.list(0), c.int(1)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						if n < 0 {
-							return nil, fmt.Errorf("negative index")
-						}
-
-						if n > len(x) {
-							return []Value{}, nil
-						}
-
-						return x[n:], nil
-					}()
-				}
-			},
-		}, {
-			Name:   "FlattenN",
-			Params: []kind{topKind, intKind},
-			Result: listKind,
-			Func: func(c *callCtxt) {
-				xs, depth := c.value(0), c.int(1)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						var flattenN func(Value, int) ([]Value, error)
-						flattenN = func(xs Value, depth int) ([]Value, error) {
-							var res []Value
-							iter, err := xs.List()
-							if err != nil {
-								return nil, err
-							}
-							for iter.Next() {
-								val, _ := iter.Value().Default()
-								if val.Kind() == ListKind && depth != 0 {
-									d := depth - 1
-									values, err := flattenN(val, d)
-									if err != nil {
-										return nil, err
-									}
-									res = append(res, values...)
-								} else {
-									res = append(res, val)
-								}
-							}
-							return res, nil
-						}
-						return flattenN(xs, depth)
-					}()
-				}
-			},
-		}, {
-			Name:   "Take",
-			Params: []kind{listKind, intKind},
-			Result: listKind,
-			Func: func(c *callCtxt) {
-				x, n := c.list(0), c.int(1)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						if n < 0 {
-							return nil, fmt.Errorf("negative index")
-						}
-
-						if n > len(x) {
-							return x, nil
-						}
-
-						return x[:n], nil
-					}()
-				}
-			},
-		}, {
-			Name:   "Slice",
-			Params: []kind{listKind, intKind, intKind},
-			Result: listKind,
-			Func: func(c *callCtxt) {
-				x, i, j := c.list(0), c.int(1), c.int(2)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						if i < 0 {
-							return nil, fmt.Errorf("negative index")
-						}
-
-						if i > j {
-							return nil, fmt.Errorf("invalid index: %v > %v", i, j)
-						}
-
-						if i > len(x) {
-							return nil, fmt.Errorf("slice bounds out of range")
-						}
-
-						if j > len(x) {
-							return nil, fmt.Errorf("slice bounds out of range")
-						}
-
-						return x[i:j], nil
-					}()
-				}
-			},
-		}, {
-			Name:   "MinItems",
-			Params: []kind{listKind, intKind},
-			Result: boolKind,
-			Func: func(c *callCtxt) {
-				a, n := c.list(0), c.int(1)
-				if c.do() {
-					c.ret = func() interface{} {
-						return len(a) >= n
-					}()
-				}
-			},
-		}, {
-			Name:   "MaxItems",
-			Params: []kind{listKind, intKind},
-			Result: boolKind,
-			Func: func(c *callCtxt) {
-				a, n := c.list(0), c.int(1)
-				if c.do() {
-					c.ret = func() interface{} {
-						return len(a) <= n
-					}()
-				}
-			},
-		}, {
-			Name:   "UniqueItems",
-			Params: []kind{listKind},
-			Result: boolKind,
-			Func: func(c *callCtxt) {
-				a := c.list(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						b := []string{}
-						for _, v := range a {
-							b = append(b, fmt.Sprint(v))
-						}
-						sort.Strings(b)
-						for i := 1; i < len(b); i++ {
-							if b[i-1] == b[i] {
-								return false
-							}
-						}
-						return true
-					}()
-				}
-			},
-		}, {
-			Name:   "Contains",
-			Params: []kind{listKind, topKind},
-			Result: boolKind,
-			Func: func(c *callCtxt) {
-				a, v := c.list(0), c.value(1)
-				if c.do() {
-					c.ret = func() interface{} {
-						for _, w := range a {
-							if v.Equals(w) {
-								return true
-							}
-						}
-						return false
-					}()
-				}
-			},
-		}, {
-			Name:   "Avg",
-			Params: []kind{listKind},
-			Result: numKind,
-			Func: func(c *callCtxt) {
-				xs := c.decimalList(0)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						if 0 == len(xs) {
-							return nil, fmt.Errorf("empty list")
-						}
-
-						s := apd.New(0, 0)
-						for _, x := range xs {
-							_, err := internal.BaseContext.Add(s, x, s)
-							if err != nil {
-								return nil, err
-							}
-						}
-
-						var d apd.Decimal
-						l := apd.New(int64(len(xs)), 0)
-						_, err := internal.BaseContext.Quo(&d, s, l)
-						if err != nil {
-							return nil, err
-						}
-						return &d, nil
-					}()
-				}
-			},
-		}, {
-			Name:   "Max",
-			Params: []kind{listKind},
-			Result: numKind,
-			Func: func(c *callCtxt) {
-				xs := c.decimalList(0)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						if 0 == len(xs) {
-							return nil, fmt.Errorf("empty list")
-						}
-
-						max := xs[0]
-						for _, x := range xs[1:] {
-							if -1 == max.Cmp(x) {
-								max = x
-							}
-						}
-						return max, nil
-					}()
-				}
-			},
-		}, {
-			Name:   "Min",
-			Params: []kind{listKind},
-			Result: numKind,
-			Func: func(c *callCtxt) {
-				xs := c.decimalList(0)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						if 0 == len(xs) {
-							return nil, fmt.Errorf("empty list")
-						}
-
-						min := xs[0]
-						for _, x := range xs[1:] {
-							if +1 == min.Cmp(x) {
-								min = x
-							}
-						}
-						return min, nil
-					}()
-				}
-			},
-		}, {
-			Name:   "Product",
-			Params: []kind{listKind},
-			Result: numKind,
-			Func: func(c *callCtxt) {
-				xs := c.decimalList(0)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						d := apd.New(1, 0)
-						for _, x := range xs {
-							_, err := internal.BaseContext.Mul(d, x, d)
-							if err != nil {
-								return nil, err
-							}
-						}
-						return d, nil
-					}()
-				}
-			},
-		}, {
-			Name:   "Range",
-			Params: []kind{numKind, numKind, numKind},
-			Result: listKind,
-			Func: func(c *callCtxt) {
-				start, limit, step := c.decimal(0), c.decimal(1), c.decimal(2)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						if step.IsZero() {
-							return nil, fmt.Errorf("step must be non zero")
-						}
-
-						if !step.Negative && +1 == start.Cmp(limit) {
-							return nil, fmt.Errorf("end must be greater than start when step is positive")
-						}
-
-						if step.Negative && -1 == start.Cmp(limit) {
-							return nil, fmt.Errorf("end must be less than start when step is negative")
-						}
-
-						var vals []*internal.Decimal
-						num := start
-						for {
-							if !step.Negative && -1 != num.Cmp(limit) {
-								break
-							}
-
-							if step.Negative && +1 != num.Cmp(limit) {
-								break
-							}
-
-							vals = append(vals, num)
-							d := apd.New(0, 0)
-							_, err := internal.BaseContext.Add(d, step, num)
-							if err != nil {
-								return nil, err
-							}
-							num = d
-						}
-						return vals, nil
-					}()
-				}
-			},
-		}, {
-			Name:   "Sum",
-			Params: []kind{listKind},
-			Result: numKind,
-			Func: func(c *callCtxt) {
-				xs := c.decimalList(0)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						d := apd.New(0, 0)
-						for _, x := range xs {
-							_, err := internal.BaseContext.Add(d, x, d)
-							if err != nil {
-								return nil, err
-							}
-						}
-						return d, nil
-					}()
-				}
-			},
-		}, {
-			Name:   "Sort",
-			Params: []kind{listKind, topKind},
-			Result: listKind,
-			Func: func(c *callCtxt) {
-				list, cmp := c.list(0), c.value(1)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						s := valueSorter{list, cmp, nil}
-
-						sort.Sort(&s)
-						return s.ret()
-					}()
-				}
-			},
-		}, {
-			Name:   "SortStable",
-			Params: []kind{listKind, topKind},
-			Result: listKind,
-			Func: func(c *callCtxt) {
-				list, cmp := c.list(0), c.value(1)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						s := valueSorter{list, cmp, nil}
-						sort.Stable(&s)
-						return s.ret()
-					}()
-				}
-			},
-		}, {
-			Name:   "SortStrings",
-			Params: []kind{listKind},
-			Result: listKind,
-			Func: func(c *callCtxt) {
-				a := c.strList(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						sort.Strings(a)
-						return a
-					}()
-				}
-			},
-		}, {
-			Name:   "IsSorted",
-			Params: []kind{listKind, topKind},
-			Result: boolKind,
-			Func: func(c *callCtxt) {
-				list, cmp := c.list(0), c.value(1)
-				if c.do() {
-					c.ret = func() interface{} {
-						s := valueSorter{list, cmp, nil}
-						return sort.IsSorted(&s)
-					}()
-				}
-			},
-		}, {
-			Name:   "IsSortedStrings",
-			Params: []kind{listKind},
-			Result: boolKind,
-			Func: func(c *callCtxt) {
-				a := c.strList(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return sort.StringsAreSorted(a)
-					}()
-				}
-			},
-		}},
-		cue: `{
-	Comparer: {
-		T:    _
-		less: bool
-		x:    T
-		y:    T
-	}
-	Ascending: {
-		T:    number | string
-		less: true && x < y
-		x:    T
-		y:    T
-		Comparer
-	}
-	Descending: {
-		T:    number | string
-		less: x > y
-		x:    T
-		y:    T
-		Comparer
-	}
-}`,
-	},
-	"math": {
-		native: []*builtin{{
-			Name:  "MaxExp",
-			Const: "2147483647",
-		}, {
-			Name:  "MinExp",
-			Const: "-2147483648",
-		}, {
-			Name:  "MaxPrec",
-			Const: "4294967295",
-		}, {
-			Name:  "ToNearestEven",
-			Const: "0",
-		}, {
-			Name:  "ToNearestAway",
-			Const: "1",
-		}, {
-			Name:  "ToZero",
-			Const: "2",
-		}, {
-			Name:  "AwayFromZero",
-			Const: "3",
-		}, {
-			Name:  "ToNegativeInf",
-			Const: "4",
-		}, {
-			Name:  "ToPositiveInf",
-			Const: "5",
-		}, {
-			Name:  "Below",
-			Const: "-1",
-		}, {
-			Name:  "Exact",
-			Const: "0",
-		}, {
-			Name:  "Above",
-			Const: "1",
-		}, {
-			Name:   "Jacobi",
-			Params: []kind{intKind, intKind},
-			Result: intKind,
-			Func: func(c *callCtxt) {
-				x, y := c.bigInt(0), c.bigInt(1)
-				if c.do() {
-					c.ret = func() interface{} {
-						return big.Jacobi(x, y)
-					}()
-				}
-			},
-		}, {
-			Name:  "MaxBase",
-			Const: "62",
-		}, {
-			Name:   "Floor",
-			Params: []kind{numKind},
-			Result: numKind,
-			Func: func(c *callCtxt) {
-				x := c.decimal(0)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						var d internal.Decimal
-						_, err := apdContext.Floor(&d, x)
-						return &d, err
-					}()
-				}
-			},
-		}, {
-			Name:   "Ceil",
-			Params: []kind{numKind},
-			Result: numKind,
-			Func: func(c *callCtxt) {
-				x := c.decimal(0)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						var d internal.Decimal
-						_, err := apdContext.Ceil(&d, x)
-						return &d, err
-					}()
-				}
-			},
-		}, {
-			Name:   "Trunc",
-			Params: []kind{numKind},
-			Result: numKind,
-			Func: func(c *callCtxt) {
-				x := c.decimal(0)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						var d internal.Decimal
-						_, err := roundTruncContext.RoundToIntegralExact(&d, x)
-						return &d, err
-					}()
-				}
-			},
-		}, {
-			Name:   "Round",
-			Params: []kind{numKind},
-			Result: numKind,
-			Func: func(c *callCtxt) {
-				x := c.decimal(0)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						var d internal.Decimal
-						_, err := roundUpContext.RoundToIntegralExact(&d, x)
-						return &d, err
-					}()
-				}
-			},
-		}, {
-			Name:   "RoundToEven",
-			Params: []kind{numKind},
-			Result: numKind,
-			Func: func(c *callCtxt) {
-				x := c.decimal(0)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						var d internal.Decimal
-						_, err := roundEvenContext.RoundToIntegralExact(&d, x)
-						return &d, err
-					}()
-				}
-			},
-		}, {
-			Name:   "MultipleOf",
-			Params: []kind{numKind, numKind},
-			Result: boolKind,
-			Func: func(c *callCtxt) {
-				x, y := c.decimal(0), c.decimal(1)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						var d apd.Decimal
-						cond, err := mulContext.Quo(&d, x, y)
-						return !cond.Inexact(), err
-					}()
-				}
-			},
-		}, {
-			Name:   "Abs",
-			Params: []kind{numKind},
-			Result: numKind,
-			Func: func(c *callCtxt) {
-				x := c.decimal(0)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						var d internal.Decimal
-						_, err := apdContext.Abs(&d, x)
-						return &d, err
-					}()
-				}
-			},
-		}, {
-			Name:   "Acosh",
-			Params: []kind{numKind},
-			Result: numKind,
-			Func: func(c *callCtxt) {
-				x := c.float64(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return math.Acosh(x)
-					}()
-				}
-			},
-		}, {
-			Name:   "Asin",
-			Params: []kind{numKind},
-			Result: numKind,
-			Func: func(c *callCtxt) {
-				x := c.float64(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return math.Asin(x)
-					}()
-				}
-			},
-		}, {
-			Name:   "Acos",
-			Params: []kind{numKind},
-			Result: numKind,
-			Func: func(c *callCtxt) {
-				x := c.float64(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return math.Acos(x)
-					}()
-				}
-			},
-		}, {
-			Name:   "Asinh",
-			Params: []kind{numKind},
-			Result: numKind,
-			Func: func(c *callCtxt) {
-				x := c.float64(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return math.Asinh(x)
-					}()
-				}
-			},
-		}, {
-			Name:   "Atan",
-			Params: []kind{numKind},
-			Result: numKind,
-			Func: func(c *callCtxt) {
-				x := c.float64(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return math.Atan(x)
-					}()
-				}
-			},
-		}, {
-			Name:   "Atan2",
-			Params: []kind{numKind, numKind},
-			Result: numKind,
-			Func: func(c *callCtxt) {
-				y, x := c.float64(0), c.float64(1)
-				if c.do() {
-					c.ret = func() interface{} {
-						return math.Atan2(y, x)
-					}()
-				}
-			},
-		}, {
-			Name:   "Atanh",
-			Params: []kind{numKind},
-			Result: numKind,
-			Func: func(c *callCtxt) {
-				x := c.float64(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return math.Atanh(x)
-					}()
-				}
-			},
-		}, {
-			Name:   "Cbrt",
-			Params: []kind{numKind},
-			Result: numKind,
-			Func: func(c *callCtxt) {
-				x := c.decimal(0)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						var d internal.Decimal
-						_, err := apdContext.Cbrt(&d, x)
-						return &d, err
-					}()
-				}
-			},
-		}, {
-			Name:  "E",
-			Const: "2.71828182845904523536028747135266249775724709369995957496696763",
-		}, {
-			Name:  "Pi",
-			Const: "3.14159265358979323846264338327950288419716939937510582097494459",
-		}, {
-			Name:  "Phi",
-			Const: "1.61803398874989484820458683436563811772030917980576286213544861",
-		}, {
-			Name:  "Sqrt2",
-			Const: "1.41421356237309504880168872420969807856967187537694807317667974",
-		}, {
-			Name:  "SqrtE",
-			Const: "1.64872127070012814684865078781416357165377610071014801157507931",
-		}, {
-			Name:  "SqrtPi",
-			Const: "1.77245385090551602729816748334114518279754945612238712821380779",
-		}, {
-			Name:  "SqrtPhi",
-			Const: "1.27201964951406896425242246173749149171560804184009624861664038",
-		}, {
-			Name:  "Ln2",
-			Const: "0.693147180559945309417232121458176568075500134360255254120680009",
-		}, {
-			Name:  "Log2E",
-			Const: "1.442695040888963407359924681001892137426645954152985934135449408",
-		}, {
-			Name:  "Ln10",
-			Const: "2.3025850929940456840179914546843642076011014886287729760333278",
-		}, {
-			Name:  "Log10E",
-			Const: "0.43429448190325182765112891891660508229439700580366656611445378",
-		}, {
-			Name:   "Copysign",
-			Params: []kind{numKind, numKind},
-			Result: numKind,
-			Func: func(c *callCtxt) {
-				x, y := c.decimal(0), c.decimal(1)
-				if c.do() {
-					c.ret = func() interface{} {
-						var d internal.Decimal
-						d.Set(x)
-						d.Negative = y.Negative
-						return &d
-					}()
-				}
-			},
-		}, {
-			Name:   "Dim",
-			Params: []kind{numKind, numKind},
-			Result: numKind,
-			Func: func(c *callCtxt) {
-				x, y := c.decimal(0), c.decimal(1)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						var d internal.Decimal
-						_, err := apdContext.Sub(&d, x, y)
-						if err != nil {
-							return nil, err
-						}
-						if d.Negative {
-							return zero, nil
-						}
-						return &d, nil
-					}()
-				}
-			},
-		}, {
-			Name:   "Erf",
-			Params: []kind{numKind},
-			Result: numKind,
-			Func: func(c *callCtxt) {
-				x := c.float64(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return math.Erf(x)
-					}()
-				}
-			},
-		}, {
-			Name:   "Erfc",
-			Params: []kind{numKind},
-			Result: numKind,
-			Func: func(c *callCtxt) {
-				x := c.float64(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return math.Erfc(x)
-					}()
-				}
-			},
-		}, {
-			Name:   "Erfinv",
-			Params: []kind{numKind},
-			Result: numKind,
-			Func: func(c *callCtxt) {
-				x := c.float64(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return math.Erfinv(x)
-					}()
-				}
-			},
-		}, {
-			Name:   "Erfcinv",
-			Params: []kind{numKind},
-			Result: numKind,
-			Func: func(c *callCtxt) {
-				x := c.float64(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return math.Erfcinv(x)
-					}()
-				}
-			},
-		}, {
-			Name:   "Exp",
-			Params: []kind{numKind},
-			Result: numKind,
-			Func: func(c *callCtxt) {
-				x := c.decimal(0)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						var d internal.Decimal
-						_, err := apdContext.Exp(&d, x)
-						return &d, err
-					}()
-				}
-			},
-		}, {
-			Name:   "Exp2",
-			Params: []kind{numKind},
-			Result: numKind,
-			Func: func(c *callCtxt) {
-				x := c.decimal(0)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						var d internal.Decimal
-						_, err := apdContext.Pow(&d, two, x)
-						return &d, err
-					}()
-				}
-			},
-		}, {
-			Name:   "Expm1",
-			Params: []kind{numKind},
-			Result: numKind,
-			Func: func(c *callCtxt) {
-				x := c.float64(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return math.Expm1(x)
-					}()
-				}
-			},
-		}, {
-			Name:   "Gamma",
-			Params: []kind{numKind},
-			Result: numKind,
-			Func: func(c *callCtxt) {
-				x := c.float64(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return math.Gamma(x)
-					}()
-				}
-			},
-		}, {
-			Name:   "Hypot",
-			Params: []kind{numKind, numKind},
-			Result: numKind,
-			Func: func(c *callCtxt) {
-				p, q := c.float64(0), c.float64(1)
-				if c.do() {
-					c.ret = func() interface{} {
-						return math.Hypot(p, q)
-					}()
-				}
-			},
-		}, {
-			Name:   "J0",
-			Params: []kind{numKind},
-			Result: numKind,
-			Func: func(c *callCtxt) {
-				x := c.float64(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return math.J0(x)
-					}()
-				}
-			},
-		}, {
-			Name:   "Y0",
-			Params: []kind{numKind},
-			Result: numKind,
-			Func: func(c *callCtxt) {
-				x := c.float64(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return math.Y0(x)
-					}()
-				}
-			},
-		}, {
-			Name:   "J1",
-			Params: []kind{numKind},
-			Result: numKind,
-			Func: func(c *callCtxt) {
-				x := c.float64(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return math.J1(x)
-					}()
-				}
-			},
-		}, {
-			Name:   "Y1",
-			Params: []kind{numKind},
-			Result: numKind,
-			Func: func(c *callCtxt) {
-				x := c.float64(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return math.Y1(x)
-					}()
-				}
-			},
-		}, {
-			Name:   "Jn",
-			Params: []kind{intKind, numKind},
-			Result: numKind,
-			Func: func(c *callCtxt) {
-				n, x := c.int(0), c.float64(1)
-				if c.do() {
-					c.ret = func() interface{} {
-						return math.Jn(n, x)
-					}()
-				}
-			},
-		}, {
-			Name:   "Yn",
-			Params: []kind{intKind, numKind},
-			Result: numKind,
-			Func: func(c *callCtxt) {
-				n, x := c.int(0), c.float64(1)
-				if c.do() {
-					c.ret = func() interface{} {
-						return math.Yn(n, x)
-					}()
-				}
-			},
-		}, {
-			Name:   "Ldexp",
-			Params: []kind{numKind, intKind},
-			Result: numKind,
-			Func: func(c *callCtxt) {
-				frac, exp := c.float64(0), c.int(1)
-				if c.do() {
-					c.ret = func() interface{} {
-						return math.Ldexp(frac, exp)
-					}()
-				}
-			},
-		}, {
-			Name:   "Log",
-			Params: []kind{numKind},
-			Result: numKind,
-			Func: func(c *callCtxt) {
-				x := c.decimal(0)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						var d internal.Decimal
-						_, err := apdContext.Ln(&d, x)
-						return &d, err
-					}()
-				}
-			},
-		}, {
-			Name:   "Log10",
-			Params: []kind{numKind},
-			Result: numKind,
-			Func: func(c *callCtxt) {
-				x := c.decimal(0)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						var d internal.Decimal
-						_, err := apdContext.Log10(&d, x)
-						return &d, err
-					}()
-				}
-			},
-		}, {
-			Name:   "Log2",
-			Params: []kind{numKind},
-			Result: numKind,
-			Func: func(c *callCtxt) {
-				x := c.decimal(0)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						var d, ln2 internal.Decimal
-						_, _ = apdContext.Ln(&ln2, two)
-						_, err := apdContext.Ln(&d, x)
-						if err != nil {
-							return &d, err
-						}
-						_, err = apdContext.Quo(&d, &d, &ln2)
-						return &d, nil
-					}()
-				}
-			},
-		}, {
-			Name:   "Log1p",
-			Params: []kind{numKind},
-			Result: numKind,
-			Func: func(c *callCtxt) {
-				x := c.float64(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return math.Log1p(x)
-					}()
-				}
-			},
-		}, {
-			Name:   "Logb",
-			Params: []kind{numKind},
-			Result: numKind,
-			Func: func(c *callCtxt) {
-				x := c.float64(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return math.Logb(x)
-					}()
-				}
-			},
-		}, {
-			Name:   "Ilogb",
-			Params: []kind{numKind},
-			Result: intKind,
-			Func: func(c *callCtxt) {
-				x := c.float64(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return math.Ilogb(x)
-					}()
-				}
-			},
-		}, {
-			Name:   "Mod",
-			Params: []kind{numKind, numKind},
-			Result: numKind,
-			Func: func(c *callCtxt) {
-				x, y := c.float64(0), c.float64(1)
-				if c.do() {
-					c.ret = func() interface{} {
-						return math.Mod(x, y)
-					}()
-				}
-			},
-		}, {
-			Name:   "Pow",
-			Params: []kind{numKind, numKind},
-			Result: numKind,
-			Func: func(c *callCtxt) {
-				x, y := c.decimal(0), c.decimal(1)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						var d internal.Decimal
-						_, err := apdContext.Pow(&d, x, y)
-						return &d, err
-					}()
-				}
-			},
-		}, {
-			Name:   "Pow10",
-			Params: []kind{intKind},
-			Result: numKind,
-			Func: func(c *callCtxt) {
-				n := c.int32(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return apd.New(1, n)
-					}()
-				}
-			},
-		}, {
-			Name:   "Remainder",
-			Params: []kind{numKind, numKind},
-			Result: numKind,
-			Func: func(c *callCtxt) {
-				x, y := c.float64(0), c.float64(1)
-				if c.do() {
-					c.ret = func() interface{} {
-						return math.Remainder(x, y)
-					}()
-				}
-			},
-		}, {
-			Name:   "Signbit",
-			Params: []kind{numKind},
-			Result: boolKind,
-			Func: func(c *callCtxt) {
-				x := c.decimal(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return x.Negative
-					}()
-				}
-			},
-		}, {
-			Name:   "Cos",
-			Params: []kind{numKind},
-			Result: numKind,
-			Func: func(c *callCtxt) {
-				x := c.float64(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return math.Cos(x)
-					}()
-				}
-			},
-		}, {
-			Name:   "Sin",
-			Params: []kind{numKind},
-			Result: numKind,
-			Func: func(c *callCtxt) {
-				x := c.float64(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return math.Sin(x)
-					}()
-				}
-			},
-		}, {
-			Name:   "Sinh",
-			Params: []kind{numKind},
-			Result: numKind,
-			Func: func(c *callCtxt) {
-				x := c.float64(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return math.Sinh(x)
-					}()
-				}
-			},
-		}, {
-			Name:   "Cosh",
-			Params: []kind{numKind},
-			Result: numKind,
-			Func: func(c *callCtxt) {
-				x := c.float64(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return math.Cosh(x)
-					}()
-				}
-			},
-		}, {
-			Name:   "Sqrt",
-			Params: []kind{numKind},
-			Result: numKind,
-			Func: func(c *callCtxt) {
-				x := c.float64(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return math.Sqrt(x)
-					}()
-				}
-			},
-		}, {
-			Name:   "Tan",
-			Params: []kind{numKind},
-			Result: numKind,
-			Func: func(c *callCtxt) {
-				x := c.float64(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return math.Tan(x)
-					}()
-				}
-			},
-		}, {
-			Name:   "Tanh",
-			Params: []kind{numKind},
-			Result: numKind,
-			Func: func(c *callCtxt) {
-				x := c.float64(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return math.Tanh(x)
-					}()
-				}
-			},
-		}},
-	},
-	"math/bits": {
-		native: []*builtin{{
-			Name:   "Lsh",
-			Params: []kind{intKind, intKind},
-			Result: intKind,
-			Func: func(c *callCtxt) {
-				x, n := c.bigInt(0), c.uint(1)
-				if c.do() {
-					c.ret = func() interface{} {
-						var z big.Int
-						z.Lsh(x, n)
-						return &z
-					}()
-				}
-			},
-		}, {
-			Name:   "Rsh",
-			Params: []kind{intKind, intKind},
-			Result: intKind,
-			Func: func(c *callCtxt) {
-				x, n := c.bigInt(0), c.uint(1)
-				if c.do() {
-					c.ret = func() interface{} {
-						var z big.Int
-						z.Rsh(x, n)
-						return &z
-					}()
-				}
-			},
-		}, {
-			Name:   "At",
-			Params: []kind{intKind, intKind},
-			Result: intKind,
-			Func: func(c *callCtxt) {
-				x, i := c.bigInt(0), c.uint(1)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						if i > math.MaxInt32 {
-							return 0, fmt.Errorf("bit index too large")
-						}
-						return x.Bit(int(i)), nil
-					}()
-				}
-			},
-		}, {
-			Name:   "Set",
-			Params: []kind{intKind, intKind, intKind},
-			Result: intKind,
-			Func: func(c *callCtxt) {
-				x, i, bit := c.bigInt(0), c.int(1), c.uint(2)
-				if c.do() {
-					c.ret = func() interface{} {
-						var z big.Int
-						z.SetBit(x, i, bit)
-						return &z
-					}()
-				}
-			},
-		}, {
-			Name:   "And",
-			Params: []kind{intKind, intKind},
-			Result: intKind,
-			Func: func(c *callCtxt) {
-				a, b := c.bigInt(0), c.bigInt(1)
-				if c.do() {
-					c.ret = func() interface{} {
-						var z big.Int
-						z.And(a, b)
-						return &z
-					}()
-				}
-			},
-		}, {
-			Name:   "Or",
-			Params: []kind{intKind, intKind},
-			Result: intKind,
-			Func: func(c *callCtxt) {
-				a, b := c.bigInt(0), c.bigInt(1)
-				if c.do() {
-					c.ret = func() interface{} {
-						var z big.Int
-						z.Or(a, b)
-						return &z
-					}()
-				}
-			},
-		}, {
-			Name:   "Xor",
-			Params: []kind{intKind, intKind},
-			Result: intKind,
-			Func: func(c *callCtxt) {
-				a, b := c.bigInt(0), c.bigInt(1)
-				if c.do() {
-					c.ret = func() interface{} {
-						var z big.Int
-						z.Xor(a, b)
-						return &z
-					}()
-				}
-			},
-		}, {
-			Name:   "Clear",
-			Params: []kind{intKind, intKind},
-			Result: intKind,
-			Func: func(c *callCtxt) {
-				a, b := c.bigInt(0), c.bigInt(1)
-				if c.do() {
-					c.ret = func() interface{} {
-						var z big.Int
-						z.AndNot(a, b)
-						return &z
-					}()
-				}
-			},
-		}, {
-			Name:   "OnesCount",
-			Params: []kind{intKind},
-			Result: intKind,
-			Func: func(c *callCtxt) {
-				x := c.bigInt(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						var count int
-						for _, w := range x.Bits() {
-							count += bits.OnesCount64(uint64(w))
-						}
-						return count
-					}()
-				}
-			},
-		}, {
-			Name:   "Len",
-			Params: []kind{intKind},
-			Result: intKind,
-			Func: func(c *callCtxt) {
-				x := c.bigInt(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return x.BitLen()
-					}()
-				}
-			},
-		}},
-	},
-	"net": {
-		native: []*builtin{{
-			Name:   "SplitHostPort",
-			Params: []kind{stringKind},
-			Result: listKind,
-			Func: func(c *callCtxt) {
-				s := c.string(0)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						host, port, err := net.SplitHostPort(s)
-						if err != nil {
-							return nil, err
-						}
-						return []string{host, port}, nil
-					}()
-				}
-			},
-		}, {
-			Name:   "JoinHostPort",
-			Params: []kind{topKind, topKind},
-			Result: stringKind,
-			Func: func(c *callCtxt) {
-				host, port := c.value(0), c.value(1)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						var err error
-						hostStr := ""
-						switch host.Kind() {
-						case ListKind:
-							ipdata := netGetIP(host)
-							if len(ipdata) != 4 && len(ipdata) != 16 {
-								err = fmt.Errorf("invalid host %q", host)
-							}
-							hostStr = ipdata.String()
-						case BytesKind:
-							var b []byte
-							b, err = host.Bytes()
-							hostStr = string(b)
-						default:
-							hostStr, err = host.String()
-						}
-						if err != nil {
-							return "", err
-						}
-
-						portStr := ""
-						switch port.Kind() {
-						case StringKind:
-							portStr, err = port.String()
-						case BytesKind:
-							var b []byte
-							b, err = port.Bytes()
-							portStr = string(b)
-						default:
-							var i int64
-							i, err = port.Int64()
-							portStr = strconv.Itoa(int(i))
-						}
-						if err != nil {
-							return "", err
-						}
-
-						return net.JoinHostPort(hostStr, portStr), nil
-					}()
-				}
-			},
-		}, {
-			Name:   "FQDN",
-			Params: []kind{stringKind},
-			Result: boolKind,
-			Func: func(c *callCtxt) {
-				s := c.string(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						for i := 0; i < len(s); i++ {
-							if s[i] >= utf8.RuneSelf {
-								return false
-							}
-						}
-						_, err := idnaProfile.ToASCII(s)
-						return err == nil
-					}()
-				}
-			},
-		}, {
-			Name:  "IPv4len",
-			Const: "4",
-		}, {
-			Name:  "IPv6len",
-			Const: "16",
-		}, {
-			Name:   "ParseIP",
-			Params: []kind{stringKind},
-			Result: listKind,
-			Func: func(c *callCtxt) {
-				s := c.string(0)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						goip := net.ParseIP(s)
-						if goip == nil {
-							return nil, fmt.Errorf("invalid IP address %q", s)
-						}
-						return netToList(goip), nil
-					}()
-				}
-			},
-		}, {
-			Name:   "IPv4",
-			Params: []kind{topKind},
-			Result: boolKind,
-			Func: func(c *callCtxt) {
-				ip := c.value(0)
-				if c.do() {
-					c.ret = func() interface{} {
-
-						return netGetIP(ip).To4() != nil
-					}()
-				}
-			},
-		}, {
-			Name:   "IP",
-			Params: []kind{topKind},
-			Result: boolKind,
-			Func: func(c *callCtxt) {
-				ip := c.value(0)
-				if c.do() {
-					c.ret = func() interface{} {
-
-						return netGetIP(ip) != nil
-					}()
-				}
-			},
-		}, {
-			Name:   "LoopbackIP",
-			Params: []kind{topKind},
-			Result: boolKind,
-			Func: func(c *callCtxt) {
-				ip := c.value(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return netGetIP(ip).IsLoopback()
-					}()
-				}
-			},
-		}, {
-			Name:   "MulticastIP",
-			Params: []kind{topKind},
-			Result: boolKind,
-			Func: func(c *callCtxt) {
-				ip := c.value(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return netGetIP(ip).IsMulticast()
-					}()
-				}
-			},
-		}, {
-			Name:   "InterfaceLocalMulticastIP",
-			Params: []kind{topKind},
-			Result: boolKind,
-			Func: func(c *callCtxt) {
-				ip := c.value(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return netGetIP(ip).IsInterfaceLocalMulticast()
-					}()
-				}
-			},
-		}, {
-			Name:   "LinkLocalMulticastIP",
-			Params: []kind{topKind},
-			Result: boolKind,
-			Func: func(c *callCtxt) {
-				ip := c.value(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return netGetIP(ip).IsLinkLocalMulticast()
-					}()
-				}
-			},
-		}, {
-			Name:   "LinkLocalUnicastIP",
-			Params: []kind{topKind},
-			Result: boolKind,
-			Func: func(c *callCtxt) {
-				ip := c.value(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return netGetIP(ip).IsLinkLocalUnicast()
-					}()
-				}
-			},
-		}, {
-			Name:   "GlobalUnicastIP",
-			Params: []kind{topKind},
-			Result: boolKind,
-			Func: func(c *callCtxt) {
-				ip := c.value(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return netGetIP(ip).IsGlobalUnicast()
-					}()
-				}
-			},
-		}, {
-			Name:   "UnspecifiedIP",
-			Params: []kind{topKind},
-			Result: boolKind,
-			Func: func(c *callCtxt) {
-				ip := c.value(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return netGetIP(ip).IsUnspecified()
-					}()
-				}
-			},
-		}, {
-			Name:   "ToIP4",
-			Params: []kind{topKind},
-			Result: listKind,
-			Func: func(c *callCtxt) {
-				ip := c.value(0)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						ipdata := netGetIP(ip)
-						if ipdata == nil {
-							return nil, fmt.Errorf("invalid IP %q", ip)
-						}
-						ipv4 := ipdata.To4()
-						if ipv4 == nil {
-							return nil, fmt.Errorf("cannot convert %q to IPv4", ipdata)
-						}
-						return netToList(ipv4), nil
-					}()
-				}
-			},
-		}, {
-			Name:   "ToIP16",
-			Params: []kind{topKind},
-			Result: listKind,
-			Func: func(c *callCtxt) {
-				ip := c.value(0)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						ipdata := netGetIP(ip)
-						if ipdata == nil {
-							return nil, fmt.Errorf("invalid IP %q", ip)
-						}
-						return netToList(ipdata), nil
-					}()
-				}
-			},
-		}, {
-			Name:   "IPString",
-			Params: []kind{topKind},
-			Result: stringKind,
-			Func: func(c *callCtxt) {
-				ip := c.value(0)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						ipdata := netGetIP(ip)
-						if ipdata == nil {
-							return "", fmt.Errorf("invalid IP %q", ip)
-						}
-						return ipdata.String(), nil
-					}()
-				}
-			},
-		}},
-	},
-	"path": {
-		native: []*builtin{{
-			Name:   "Split",
-			Params: []kind{stringKind},
-			Result: listKind,
-			Func: func(c *callCtxt) {
-				path := c.string(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						file, dir := split(path)
-						return []string{file, dir}
-					}()
-				}
-			},
-		}, {
-			Name:   "Match",
-			Params: []kind{stringKind, stringKind},
-			Result: boolKind,
-			Func: func(c *callCtxt) {
-				pattern, name := c.string(0), c.string(1)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						return path.Match(pattern, name)
-					}()
-				}
-			},
-		}, {
-			Name:   "Clean",
-			Params: []kind{stringKind},
-			Result: stringKind,
-			Func: func(c *callCtxt) {
-				path := c.string(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return pathClean(path)
-					}()
-				}
-			},
-		}, {
-			Name:   "Ext",
-			Params: []kind{stringKind},
-			Result: stringKind,
-			Func: func(c *callCtxt) {
-				path := c.string(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return pathExt(path)
-					}()
-				}
-			},
-		}, {
-			Name:   "Base",
-			Params: []kind{stringKind},
-			Result: stringKind,
-			Func: func(c *callCtxt) {
-				path := c.string(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return pathBase(path)
-					}()
-				}
-			},
-		}, {
-			Name:   "IsAbs",
-			Params: []kind{stringKind},
-			Result: boolKind,
-			Func: func(c *callCtxt) {
-				path := c.string(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return pathIsAbs(path)
-					}()
-				}
-			},
-		}, {
-			Name:   "Dir",
-			Params: []kind{stringKind},
-			Result: stringKind,
-			Func: func(c *callCtxt) {
-				path := c.string(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return pathDir(path)
-					}()
-				}
-			},
-		}},
-	},
-	"regexp": {
-		native: []*builtin{{
-			Name:   "Valid",
-			Params: []kind{stringKind},
-			Result: boolKind,
-			Func: func(c *callCtxt) {
-				pattern := c.string(0)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						_, err := regexp.Compile(pattern)
-						return err == nil, err
-					}()
-				}
-			},
-		}, {
-			Name:   "Find",
-			Params: []kind{stringKind, stringKind},
-			Result: stringKind,
-			Func: func(c *callCtxt) {
-				pattern, s := c.string(0), c.string(1)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						re, err := regexp.Compile(pattern)
-						if err != nil {
-							return "", err
-						}
-						m := re.FindStringIndex(s)
-						if m == nil {
-							return "", errNoMatch
-						}
-						return s[m[0]:m[1]], nil
-					}()
-				}
-			},
-		}, {
-			Name:   "FindAll",
-			Params: []kind{stringKind, stringKind, intKind},
-			Result: listKind,
-			Func: func(c *callCtxt) {
-				pattern, s, n := c.string(0), c.string(1), c.int(2)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						re, err := regexp.Compile(pattern)
-						if err != nil {
-							return nil, err
-						}
-						m := re.FindAllString(s, n)
-						if m == nil {
-							return nil, errNoMatch
-						}
-						return m, nil
-					}()
-				}
-			},
-		}, {
-			Name:   "FindSubmatch",
-			Params: []kind{stringKind, stringKind},
-			Result: listKind,
-			Func: func(c *callCtxt) {
-				pattern, s := c.string(0), c.string(1)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						re, err := regexp.Compile(pattern)
-						if err != nil {
-							return nil, err
-						}
-						m := re.FindStringSubmatch(s)
-						if m == nil {
-							return nil, errNoMatch
-						}
-						return m, nil
-					}()
-				}
-			},
-		}, {
-			Name:   "FindAllSubmatch",
-			Params: []kind{stringKind, stringKind, intKind},
-			Result: listKind,
-			Func: func(c *callCtxt) {
-				pattern, s, n := c.string(0), c.string(1), c.int(2)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						re, err := regexp.Compile(pattern)
-						if err != nil {
-							return nil, err
-						}
-						m := re.FindAllStringSubmatch(s, n)
-						if m == nil {
-							return nil, errNoMatch
-						}
-						return m, nil
-					}()
-				}
-			},
-		}, {
-			Name:   "FindNamedSubmatch",
-			Params: []kind{stringKind, stringKind},
-			Result: structKind,
-			Func: func(c *callCtxt) {
-				pattern, s := c.string(0), c.string(1)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						re, err := regexp.Compile(pattern)
-						if err != nil {
-							return nil, err
-						}
-						names := re.SubexpNames()
-						if len(names) == 0 {
-							return nil, errNoNamedGroup
-						}
-						m := re.FindStringSubmatch(s)
-						if m == nil {
-							return nil, errNoMatch
-						}
-						r := make(map[string]string, len(names)-1)
-						for k, name := range names {
-							if name != "" {
-								r[name] = m[k]
-							}
-						}
-						return r, nil
-					}()
-				}
-			},
-		}, {
-			Name:   "FindAllNamedSubmatch",
-			Params: []kind{stringKind, stringKind, intKind},
-			Result: listKind,
-			Func: func(c *callCtxt) {
-				pattern, s, n := c.string(0), c.string(1), c.int(2)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						re, err := regexp.Compile(pattern)
-						if err != nil {
-							return nil, err
-						}
-						names := re.SubexpNames()
-						if len(names) == 0 {
-							return nil, errNoNamedGroup
-						}
-						m := re.FindAllStringSubmatch(s, n)
-						if m == nil {
-							return nil, errNoMatch
-						}
-						result := make([]map[string]string, len(m))
-						for i, m := range m {
-							r := make(map[string]string, len(names)-1)
-							for k, name := range names {
-								if name != "" {
-									r[name] = m[k]
-								}
-							}
-							result[i] = r
-						}
-						return result, nil
-					}()
-				}
-			},
-		}, {
-			Name:   "Match",
-			Params: []kind{stringKind, stringKind},
-			Result: boolKind,
-			Func: func(c *callCtxt) {
-				pattern, s := c.string(0), c.string(1)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						return regexp.MatchString(pattern, s)
-					}()
-				}
-			},
-		}, {
-			Name:   "QuoteMeta",
-			Params: []kind{stringKind},
-			Result: stringKind,
-			Func: func(c *callCtxt) {
-				s := c.string(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return regexp.QuoteMeta(s)
-					}()
-				}
-			},
-		}},
-	},
-	"strconv": {
-		native: []*builtin{{
-			Name:   "Unquote",
-			Params: []kind{stringKind},
-			Result: stringKind,
-			Func: func(c *callCtxt) {
-				s := c.string(0)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						return literal.Unquote(s)
-					}()
-				}
-			},
-		}, {
-			Name:   "ParseBool",
-			Params: []kind{stringKind},
-			Result: boolKind,
-			Func: func(c *callCtxt) {
-				str := c.string(0)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						return strconv.ParseBool(str)
-					}()
-				}
-			},
-		}, {
-			Name:   "FormatBool",
-			Params: []kind{boolKind},
-			Result: stringKind,
-			Func: func(c *callCtxt) {
-				b := c.bool(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return strconv.FormatBool(b)
-					}()
-				}
-			},
-		}, {
-			Name:   "ParseFloat",
-			Params: []kind{stringKind, intKind},
-			Result: numKind,
-			Func: func(c *callCtxt) {
-				s, bitSize := c.string(0), c.int(1)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						return strconv.ParseFloat(s, bitSize)
-					}()
-				}
-			},
-		}, {
-			Name:  "IntSize",
-			Const: "64",
-		}, {
-			Name:   "ParseUint",
-			Params: []kind{stringKind, intKind, intKind},
-			Result: intKind,
-			Func: func(c *callCtxt) {
-				s, base, bitSize := c.string(0), c.int(1), c.int(2)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						return strconv.ParseUint(s, base, bitSize)
-					}()
-				}
-			},
-		}, {
-			Name:   "ParseInt",
-			Params: []kind{stringKind, intKind, intKind},
-			Result: intKind,
-			Func: func(c *callCtxt) {
-				s, base, bitSize := c.string(0), c.int(1), c.int(2)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						return strconv.ParseInt(s, base, bitSize)
-					}()
-				}
-			},
-		}, {
-			Name:   "Atoi",
-			Params: []kind{stringKind},
-			Result: intKind,
-			Func: func(c *callCtxt) {
-				s := c.string(0)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						return strconv.Atoi(s)
-					}()
-				}
-			},
-		}, {
-			Name:   "FormatFloat",
-			Params: []kind{numKind, intKind, intKind, intKind},
-			Result: stringKind,
-			Func: func(c *callCtxt) {
-				f, fmt, prec, bitSize := c.float64(0), c.byte(1), c.int(2), c.int(3)
-				if c.do() {
-					c.ret = func() interface{} {
-						return strconv.FormatFloat(f, fmt, prec, bitSize)
-					}()
-				}
-			},
-		}, {
-			Name:   "FormatUint",
-			Params: []kind{intKind, intKind},
-			Result: stringKind,
-			Func: func(c *callCtxt) {
-				i, base := c.uint64(0), c.int(1)
-				if c.do() {
-					c.ret = func() interface{} {
-						return strconv.FormatUint(i, base)
-					}()
-				}
-			},
-		}, {
-			Name:   "FormatInt",
-			Params: []kind{intKind, intKind},
-			Result: stringKind,
-			Func: func(c *callCtxt) {
-				i, base := c.int64(0), c.int(1)
-				if c.do() {
-					c.ret = func() interface{} {
-						return strconv.FormatInt(i, base)
-					}()
-				}
-			},
-		}, {
-			Name:   "Quote",
-			Params: []kind{stringKind},
-			Result: stringKind,
-			Func: func(c *callCtxt) {
-				s := c.string(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return strconv.Quote(s)
-					}()
-				}
-			},
-		}, {
-			Name:   "QuoteToASCII",
-			Params: []kind{stringKind},
-			Result: stringKind,
-			Func: func(c *callCtxt) {
-				s := c.string(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return strconv.QuoteToASCII(s)
-					}()
-				}
-			},
-		}, {
-			Name:   "QuoteToGraphic",
-			Params: []kind{stringKind},
-			Result: stringKind,
-			Func: func(c *callCtxt) {
-				s := c.string(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return strconv.QuoteToGraphic(s)
-					}()
-				}
-			},
-		}, {
-			Name:   "QuoteRune",
-			Params: []kind{intKind},
-			Result: stringKind,
-			Func: func(c *callCtxt) {
-				r := c.rune(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return strconv.QuoteRune(r)
-					}()
-				}
-			},
-		}, {
-			Name:   "QuoteRuneToASCII",
-			Params: []kind{intKind},
-			Result: stringKind,
-			Func: func(c *callCtxt) {
-				r := c.rune(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return strconv.QuoteRuneToASCII(r)
-					}()
-				}
-			},
-		}, {
-			Name:   "QuoteRuneToGraphic",
-			Params: []kind{intKind},
-			Result: stringKind,
-			Func: func(c *callCtxt) {
-				r := c.rune(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return strconv.QuoteRuneToGraphic(r)
-					}()
-				}
-			},
-		}, {
-			Name:   "IsPrint",
-			Params: []kind{intKind},
-			Result: boolKind,
-			Func: func(c *callCtxt) {
-				r := c.rune(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return strconv.IsPrint(r)
-					}()
-				}
-			},
-		}, {
-			Name:   "IsGraphic",
-			Params: []kind{intKind},
-			Result: boolKind,
-			Func: func(c *callCtxt) {
-				r := c.rune(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return strconv.IsGraphic(r)
-					}()
-				}
-			},
-		}},
-	},
-	"strings": {
-		native: []*builtin{{
-			Name:   "ByteAt",
-			Params: []kind{bytesKind | stringKind, intKind},
-			Result: intKind,
-			Func: func(c *callCtxt) {
-				b, i := c.bytes(0), c.int(1)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						if i < 0 || i >= len(b) {
-							return 0, fmt.Errorf("index out of range")
-						}
-						return b[i], nil
-					}()
-				}
-			},
-		}, {
-			Name:   "ByteSlice",
-			Params: []kind{bytesKind | stringKind, intKind, intKind},
-			Result: bytesKind | stringKind,
-			Func: func(c *callCtxt) {
-				b, start, end := c.bytes(0), c.int(1), c.int(2)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						if start < 0 || start > end || end > len(b) {
-							return nil, fmt.Errorf("index out of range")
-						}
-						return b[start:end], nil
-					}()
-				}
-			},
-		}, {
-			Name:   "Runes",
-			Params: []kind{stringKind},
-			Result: listKind,
-			Func: func(c *callCtxt) {
-				s := c.string(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return []rune(s)
-					}()
-				}
-			},
-		}, {
-			Name:   "MinRunes",
-			Params: []kind{stringKind, intKind},
-			Result: boolKind,
-			Func: func(c *callCtxt) {
-				s, min := c.string(0), c.int(1)
-				if c.do() {
-					c.ret = func() interface{} {
-
-						return len([]rune(s)) >= min
-					}()
-				}
-			},
-		}, {
-			Name:   "MaxRunes",
-			Params: []kind{stringKind, intKind},
-			Result: boolKind,
-			Func: func(c *callCtxt) {
-				s, max := c.string(0), c.int(1)
-				if c.do() {
-					c.ret = func() interface{} {
-
-						return len([]rune(s)) <= max
-					}()
-				}
-			},
-		}, {
-			Name:   "ToTitle",
-			Params: []kind{stringKind},
-			Result: stringKind,
-			Func: func(c *callCtxt) {
-				s := c.string(0)
-				if c.do() {
-					c.ret = func() interface{} {
-
-						prev := ' '
-						return strings.Map(
-							func(r rune) rune {
-								if unicode.IsSpace(prev) {
-									prev = r
-									return unicode.ToTitle(r)
-								}
-								prev = r
-								return r
-							},
-							s)
-					}()
-				}
-			},
-		}, {
-			Name:   "ToCamel",
-			Params: []kind{stringKind},
-			Result: stringKind,
-			Func: func(c *callCtxt) {
-				s := c.string(0)
-				if c.do() {
-					c.ret = func() interface{} {
-
-						prev := ' '
-						return strings.Map(
-							func(r rune) rune {
-								if unicode.IsSpace(prev) {
-									prev = r
-									return unicode.ToLower(r)
-								}
-								prev = r
-								return r
-							},
-							s)
-					}()
-				}
-			},
-		}, {
-			Name:   "SliceRunes",
-			Params: []kind{stringKind, intKind, intKind},
-			Result: stringKind,
-			Func: func(c *callCtxt) {
-				s, start, end := c.string(0), c.int(1), c.int(2)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						runes := []rune(s)
-						if start < 0 || start > end || end > len(runes) {
-							return "", fmt.Errorf("index out of range")
-						}
-						return string(runes[start:end]), nil
-					}()
-				}
-			},
-		}, {
-			Name:   "Compare",
-			Params: []kind{stringKind, stringKind},
-			Result: intKind,
-			Func: func(c *callCtxt) {
-				a, b := c.string(0), c.string(1)
-				if c.do() {
-					c.ret = func() interface{} {
-						return strings.Compare(a, b)
-					}()
-				}
-			},
-		}, {
-			Name:   "Count",
-			Params: []kind{stringKind, stringKind},
-			Result: intKind,
-			Func: func(c *callCtxt) {
-				s, substr := c.string(0), c.string(1)
-				if c.do() {
-					c.ret = func() interface{} {
-						return strings.Count(s, substr)
-					}()
-				}
-			},
-		}, {
-			Name:   "Contains",
-			Params: []kind{stringKind, stringKind},
-			Result: boolKind,
-			Func: func(c *callCtxt) {
-				s, substr := c.string(0), c.string(1)
-				if c.do() {
-					c.ret = func() interface{} {
-						return strings.Contains(s, substr)
-					}()
-				}
-			},
-		}, {
-			Name:   "ContainsAny",
-			Params: []kind{stringKind, stringKind},
-			Result: boolKind,
-			Func: func(c *callCtxt) {
-				s, chars := c.string(0), c.string(1)
-				if c.do() {
-					c.ret = func() interface{} {
-						return strings.ContainsAny(s, chars)
-					}()
-				}
-			},
-		}, {
-			Name:   "LastIndex",
-			Params: []kind{stringKind, stringKind},
-			Result: intKind,
-			Func: func(c *callCtxt) {
-				s, substr := c.string(0), c.string(1)
-				if c.do() {
-					c.ret = func() interface{} {
-						return strings.LastIndex(s, substr)
-					}()
-				}
-			},
-		}, {
-			Name:   "IndexAny",
-			Params: []kind{stringKind, stringKind},
-			Result: intKind,
-			Func: func(c *callCtxt) {
-				s, chars := c.string(0), c.string(1)
-				if c.do() {
-					c.ret = func() interface{} {
-						return strings.IndexAny(s, chars)
-					}()
-				}
-			},
-		}, {
-			Name:   "LastIndexAny",
-			Params: []kind{stringKind, stringKind},
-			Result: intKind,
-			Func: func(c *callCtxt) {
-				s, chars := c.string(0), c.string(1)
-				if c.do() {
-					c.ret = func() interface{} {
-						return strings.LastIndexAny(s, chars)
-					}()
-				}
-			},
-		}, {
-			Name:   "SplitN",
-			Params: []kind{stringKind, stringKind, intKind},
-			Result: listKind,
-			Func: func(c *callCtxt) {
-				s, sep, n := c.string(0), c.string(1), c.int(2)
-				if c.do() {
-					c.ret = func() interface{} {
-						return strings.SplitN(s, sep, n)
-					}()
-				}
-			},
-		}, {
-			Name:   "SplitAfterN",
-			Params: []kind{stringKind, stringKind, intKind},
-			Result: listKind,
-			Func: func(c *callCtxt) {
-				s, sep, n := c.string(0), c.string(1), c.int(2)
-				if c.do() {
-					c.ret = func() interface{} {
-						return strings.SplitAfterN(s, sep, n)
-					}()
-				}
-			},
-		}, {
-			Name:   "Split",
-			Params: []kind{stringKind, stringKind},
-			Result: listKind,
-			Func: func(c *callCtxt) {
-				s, sep := c.string(0), c.string(1)
-				if c.do() {
-					c.ret = func() interface{} {
-						return strings.Split(s, sep)
-					}()
-				}
-			},
-		}, {
-			Name:   "SplitAfter",
-			Params: []kind{stringKind, stringKind},
-			Result: listKind,
-			Func: func(c *callCtxt) {
-				s, sep := c.string(0), c.string(1)
-				if c.do() {
-					c.ret = func() interface{} {
-						return strings.SplitAfter(s, sep)
-					}()
-				}
-			},
-		}, {
-			Name:   "Fields",
-			Params: []kind{stringKind},
-			Result: listKind,
-			Func: func(c *callCtxt) {
-				s := c.string(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return strings.Fields(s)
-					}()
-				}
-			},
-		}, {
-			Name:   "Join",
-			Params: []kind{listKind, stringKind},
-			Result: stringKind,
-			Func: func(c *callCtxt) {
-				elems, sep := c.strList(0), c.string(1)
-				if c.do() {
-					c.ret = func() interface{} {
-						return strings.Join(elems, sep)
-					}()
-				}
-			},
-		}, {
-			Name:   "HasPrefix",
-			Params: []kind{stringKind, stringKind},
-			Result: boolKind,
-			Func: func(c *callCtxt) {
-				s, prefix := c.string(0), c.string(1)
-				if c.do() {
-					c.ret = func() interface{} {
-						return strings.HasPrefix(s, prefix)
-					}()
-				}
-			},
-		}, {
-			Name:   "HasSuffix",
-			Params: []kind{stringKind, stringKind},
-			Result: boolKind,
-			Func: func(c *callCtxt) {
-				s, suffix := c.string(0), c.string(1)
-				if c.do() {
-					c.ret = func() interface{} {
-						return strings.HasSuffix(s, suffix)
-					}()
-				}
-			},
-		}, {
-			Name:   "Repeat",
-			Params: []kind{stringKind, intKind},
-			Result: stringKind,
-			Func: func(c *callCtxt) {
-				s, count := c.string(0), c.int(1)
-				if c.do() {
-					c.ret = func() interface{} {
-						return strings.Repeat(s, count)
-					}()
-				}
-			},
-		}, {
-			Name:   "ToUpper",
-			Params: []kind{stringKind},
-			Result: stringKind,
-			Func: func(c *callCtxt) {
-				s := c.string(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return strings.ToUpper(s)
-					}()
-				}
-			},
-		}, {
-			Name:   "ToLower",
-			Params: []kind{stringKind},
-			Result: stringKind,
-			Func: func(c *callCtxt) {
-				s := c.string(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return strings.ToLower(s)
-					}()
-				}
-			},
-		}, {
-			Name:   "Trim",
-			Params: []kind{stringKind, stringKind},
-			Result: stringKind,
-			Func: func(c *callCtxt) {
-				s, cutset := c.string(0), c.string(1)
-				if c.do() {
-					c.ret = func() interface{} {
-						return strings.Trim(s, cutset)
-					}()
-				}
-			},
-		}, {
-			Name:   "TrimLeft",
-			Params: []kind{stringKind, stringKind},
-			Result: stringKind,
-			Func: func(c *callCtxt) {
-				s, cutset := c.string(0), c.string(1)
-				if c.do() {
-					c.ret = func() interface{} {
-						return strings.TrimLeft(s, cutset)
-					}()
-				}
-			},
-		}, {
-			Name:   "TrimRight",
-			Params: []kind{stringKind, stringKind},
-			Result: stringKind,
-			Func: func(c *callCtxt) {
-				s, cutset := c.string(0), c.string(1)
-				if c.do() {
-					c.ret = func() interface{} {
-						return strings.TrimRight(s, cutset)
-					}()
-				}
-			},
-		}, {
-			Name:   "TrimSpace",
-			Params: []kind{stringKind},
-			Result: stringKind,
-			Func: func(c *callCtxt) {
-				s := c.string(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return strings.TrimSpace(s)
-					}()
-				}
-			},
-		}, {
-			Name:   "TrimPrefix",
-			Params: []kind{stringKind, stringKind},
-			Result: stringKind,
-			Func: func(c *callCtxt) {
-				s, prefix := c.string(0), c.string(1)
-				if c.do() {
-					c.ret = func() interface{} {
-						return strings.TrimPrefix(s, prefix)
-					}()
-				}
-			},
-		}, {
-			Name:   "TrimSuffix",
-			Params: []kind{stringKind, stringKind},
-			Result: stringKind,
-			Func: func(c *callCtxt) {
-				s, suffix := c.string(0), c.string(1)
-				if c.do() {
-					c.ret = func() interface{} {
-						return strings.TrimSuffix(s, suffix)
-					}()
-				}
-			},
-		}, {
-			Name:   "Replace",
-			Params: []kind{stringKind, stringKind, stringKind, intKind},
-			Result: stringKind,
-			Func: func(c *callCtxt) {
-				s, old, new, n := c.string(0), c.string(1), c.string(2), c.int(3)
-				if c.do() {
-					c.ret = func() interface{} {
-						return strings.Replace(s, old, new, n)
-					}()
-				}
-			},
-		}, {
-			Name:   "Index",
-			Params: []kind{stringKind, stringKind},
-			Result: intKind,
-			Func: func(c *callCtxt) {
-				s, substr := c.string(0), c.string(1)
-				if c.do() {
-					c.ret = func() interface{} {
-						return strings.Index(s, substr)
-					}()
-				}
-			},
-		}},
-	},
-	"struct": {
-		native: []*builtin{{
-			Name:   "MinFields",
-			Params: []kind{structKind, intKind},
-			Result: boolKind,
-			Func: func(c *callCtxt) {
-				object, n := c.structVal(0), c.int(1)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						iter := object.Fields(Hidden(false), Optional(false))
-						count := 0
-						for iter.Next() {
-							count++
-						}
-						return count >= n, nil
-					}()
-				}
-			},
-		}, {
-			Name:   "MaxFields",
-			Params: []kind{structKind, intKind},
-			Result: boolKind,
-			Func: func(c *callCtxt) {
-				object, n := c.structVal(0), c.int(1)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						iter := object.Fields(Hidden(false), Optional(false))
-						count := 0
-						for iter.Next() {
-							count++
-						}
-						return count <= n, nil
-					}()
-				}
-			},
-		}},
-	},
-	"text/tabwriter": {
-		native: []*builtin{{
-			Name:   "Write",
-			Params: []kind{topKind},
-			Result: stringKind,
-			Func: func(c *callCtxt) {
-				data := c.value(0)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						buf := &bytes.Buffer{}
-						tw := tabwriter.NewWriter(buf, 0, 4, 1, ' ', 0)
-
-						write := func(v Value) error {
-							b, err := v.Bytes()
-							if err != nil {
-								return err
-							}
-							_, err = tw.Write(b)
-							if err != nil {
-								return err
-							}
-							return nil
-						}
-
-						switch data.Kind() {
-						case BytesKind, StringKind:
-							if err := write(data); err != nil {
-								return "", err
-							}
-						case ListKind:
-							for i, _ := data.List(); i.Next(); {
-								if err := write(i.Value()); err != nil {
-									return "", err
-								}
-								_, _ = tw.Write([]byte{'\n'})
-							}
-						default:
-							return "", fmt.Errorf("tabwriter.Write: unsupported type %v", data.Kind())
-						}
-
-						err := tw.Flush()
-						return buf.String(), err
-					}()
-				}
-			},
-		}},
-	},
-	"text/template": {
-		native: []*builtin{{
-			Name:   "Execute",
-			Params: []kind{stringKind, topKind},
-			Result: stringKind,
-			Func: func(c *callCtxt) {
-				templ, data := c.string(0), c.value(1)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						t, err := template.New("").Parse(templ)
-						if err != nil {
-							return "", err
-						}
-						var x interface{}
-						if err := data.Decode(&x); err != nil {
-							return "", err
-						}
-						buf := &bytes.Buffer{}
-						if err := t.Execute(buf, x); err != nil {
-							return "", err
-						}
-						return buf.String(), nil
-					}()
-				}
-			},
-		}, {
-			Name:   "HTMLEscape",
-			Params: []kind{stringKind},
-			Result: stringKind,
-			Func: func(c *callCtxt) {
-				s := c.string(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return template.HTMLEscapeString(s)
-					}()
-				}
-			},
-		}, {
-			Name:   "JSEscape",
-			Params: []kind{stringKind},
-			Result: stringKind,
-			Func: func(c *callCtxt) {
-				s := c.string(0)
-				if c.do() {
-					c.ret = func() interface{} {
-						return template.JSEscapeString(s)
-					}()
-				}
-			},
-		}},
-	},
-	"time": {
-		native: []*builtin{{
-			Name:  "Nanosecond",
-			Const: "1",
-		}, {
-			Name:  "Microsecond",
-			Const: "1000",
-		}, {
-			Name:  "Millisecond",
-			Const: "1000000",
-		}, {
-			Name:  "Second",
-			Const: "1000000000",
-		}, {
-			Name:  "Minute",
-			Const: "60000000000",
-		}, {
-			Name:  "Hour",
-			Const: "3600000000000",
-		}, {
-			Name:   "Duration",
-			Params: []kind{stringKind},
-			Result: boolKind,
-			Func: func(c *callCtxt) {
-				s := c.string(0)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						if _, err := time.ParseDuration(s); err != nil {
-							return false, err
-						}
-						return true, nil
-					}()
-				}
-			},
-		}, {
-			Name:   "ParseDuration",
-			Params: []kind{stringKind},
-			Result: intKind,
-			Func: func(c *callCtxt) {
-				s := c.string(0)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						d, err := time.ParseDuration(s)
-						if err != nil {
-							return 0, err
-						}
-						return int64(d), nil
-					}()
-				}
-			},
-		}, {
-			Name:  "ANSIC",
-			Const: "\"Mon Jan _2 15:04:05 2006\"",
-		}, {
-			Name:  "UnixDate",
-			Const: "\"Mon Jan _2 15:04:05 MST 2006\"",
-		}, {
-			Name:  "RubyDate",
-			Const: "\"Mon Jan 02 15:04:05 -0700 2006\"",
-		}, {
-			Name:  "RFC822",
-			Const: "\"02 Jan 06 15:04 MST\"",
-		}, {
-			Name:  "RFC822Z",
-			Const: "\"02 Jan 06 15:04 -0700\"",
-		}, {
-			Name:  "RFC850",
-			Const: "\"Monday, 02-Jan-06 15:04:05 MST\"",
-		}, {
-			Name:  "RFC1123",
-			Const: "\"Mon, 02 Jan 2006 15:04:05 MST\"",
-		}, {
-			Name:  "RFC1123Z",
-			Const: "\"Mon, 02 Jan 2006 15:04:05 -0700\"",
-		}, {
-			Name:  "RFC3339",
-			Const: "\"2006-01-02T15:04:05Z07:00\"",
-		}, {
-			Name:  "RFC3339Nano",
-			Const: "\"2006-01-02T15:04:05.999999999Z07:00\"",
-		}, {
-			Name:  "RFC3339Date",
-			Const: "\"2006-01-02\"",
-		}, {
-			Name:  "Kitchen",
-			Const: "\"3:04PM\"",
-		}, {
-			Name:  "Kitchen24",
-			Const: "\"15:04\"",
-		}, {
-			Name:  "January",
-			Const: "1",
-		}, {
-			Name:  "February",
-			Const: "2",
-		}, {
-			Name:  "March",
-			Const: "3",
-		}, {
-			Name:  "April",
-			Const: "4",
-		}, {
-			Name:  "May",
-			Const: "5",
-		}, {
-			Name:  "June",
-			Const: "6",
-		}, {
-			Name:  "July",
-			Const: "7",
-		}, {
-			Name:  "August",
-			Const: "8",
-		}, {
-			Name:  "September",
-			Const: "9",
-		}, {
-			Name:  "October",
-			Const: "10",
-		}, {
-			Name:  "November",
-			Const: "11",
-		}, {
-			Name:  "December",
-			Const: "12",
-		}, {
-			Name:  "Sunday",
-			Const: "0",
-		}, {
-			Name:  "Monday",
-			Const: "1",
-		}, {
-			Name:  "Tuesday",
-			Const: "2",
-		}, {
-			Name:  "Wednesday",
-			Const: "3",
-		}, {
-			Name:  "Thursday",
-			Const: "4",
-		}, {
-			Name:  "Friday",
-			Const: "5",
-		}, {
-			Name:  "Saturday",
-			Const: "6",
-		}, {
-			Name:   "Time",
-			Params: []kind{stringKind},
-			Result: boolKind,
-			Func: func(c *callCtxt) {
-				s := c.string(0)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						return timeFormat(s, time.RFC3339Nano)
-					}()
-				}
-			},
-		}, {
-			Name:   "Format",
-			Params: []kind{stringKind, stringKind},
-			Result: boolKind,
-			Func: func(c *callCtxt) {
-				value, layout := c.string(0), c.string(1)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						return timeFormat(value, layout)
-					}()
-				}
-			},
-		}, {
-			Name:   "Parse",
-			Params: []kind{stringKind, stringKind},
-			Result: stringKind,
-			Func: func(c *callCtxt) {
-				layout, value := c.string(0), c.string(1)
-				if c.do() {
-					c.ret, c.err = func() (interface{}, error) {
-						t, err := time.Parse(layout, value)
-						if err != nil {
-							return "", err
-						}
-						return t.UTC().Format(time.RFC3339Nano), nil
-					}()
-				}
-			},
-		}, {
-			Name:   "Unix",
-			Params: []kind{intKind, intKind},
-			Result: stringKind,
-			Func: func(c *callCtxt) {
-				sec, nsec := c.int64(0), c.int64(1)
-				if c.do() {
-					c.ret = func() interface{} {
-						t := time.Unix(sec, nsec)
-						return t.UTC().Format(time.RFC3339Nano)
-					}()
-				}
-			},
-		}},
-	},
-	"tool": {
-		native: []*builtin{},
-		cue: `{
-	Command: {
-		$usage?: string
-		$short?: string
-		$long?:  string
-		Tasks
-	}
-	Tasks: Task | {
-		[name=string]: Tasks
-	}
-	Task: {
-		$type:   "tool.Task"
-		$id:     =~"\\."
-		$after?: Task | [...Task]
-	}
-	Name: =~"^\\PL([-](\\PL|\\PN))*$"
-}`,
-	},
-	"tool/cli": {
-		native: []*builtin{},
-		cue: `{
-	Print: {
-		$id:  *"tool/cli.Print" | "print"
-		text: string
-	}
-}`,
-	},
-	"tool/exec": {
-		native: []*builtin{},
-		cue: `{
-	Run: {
-		$id: *"tool/exec.Run" | "exec"
-		cmd: string | [string, ...string]
-		env: {
-			[string]: string | [...=~"="]
-		}
-		stdout:  *null | string | bytes
-		stderr:  *null | string | bytes
-		stdin:   *null | string | bytes
-		success: bool
-	}
-}`,
-	},
-	"tool/file": {
-		native: []*builtin{},
-		cue: `{
-	Read: {
-		$id:      "tool/file.Read"
-		filename: !=""
-		contents: *bytes | string
-	}
-	Create: {
-		$id:         "tool/file.Create"
-		filename:    !=""
-		contents:    bytes | string
-		permissions: int | *420
-	}
-	Append: {
-		$id:         "tool/file.Append"
-		filename:    !=""
-		contents:    bytes | string
-		permissions: int | *420
-	}
-	Glob: {
-		$id:  "tool/file.Glob"
-		glob: !=""
-		files: [...string]
-	}
-}`,
-	},
-	"tool/http": {
-		native: []*builtin{},
-		cue: `{
-	Get: Do & {
-		method: "GET"
-	}
-	Do: {
-		$id:    *"tool/http.Do" | "http"
-		method: string
-		response: {
-			body: *bytes | string
-			header: {
-				[string]: string | [...string]
-			}
-			trailer: {
-				[string]: string | [...string]
-			}
-			status:     string
-			statusCode: int
-		}
-		url: string
-		request: {
-			body: *bytes | string
-			header: {
-				[string]: string | [...string]
-			}
-			trailer: {
-				[string]: string | [...string]
-			}
-		}
-	}
-	Post: Do & {
-		method: "POST"
-	}
-	Put: Do & {
-		method: "PUT"
-	}
-	Delete: Do & {
-		method: "DELETE"
-	}
-}`,
-	},
-	"tool/os": {
-		native: []*builtin{},
-		cue: `{
-	Name:  !="" & !~"^[$]"
-	Value: bool | number | *string | null
-	Setenv: {
-		$id: "tool/os.Setenv"
-		{[Name]: Value}
-	}
-	Getenv: {
-		$id: "tool/os.Getenv"
-		{[Name]: Value}
-	}
-	Environ: {
-		$id: "tool/os.Environ"
-		{[Name]: Value}
-	}
-	Clearenv: {
-		$id: "tool/os.Clearenv"
-	}
-}`,
-	},
-}
diff --git a/internal/legacy/cue/builtinutil.go b/internal/legacy/cue/builtinutil.go
deleted file mode 100644
index e226cfa..0000000
--- a/internal/legacy/cue/builtinutil.go
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright 2019 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/core/adt"
-	"cuelang.org/go/internal/core/convert"
-)
-
-// TODO: this code could be generated, but currently isn't.
-
-type valueSorter struct {
-	a   []Value
-	cmp Value
-	err error
-}
-
-func (s *valueSorter) ret() ([]Value, error) {
-	if s.err != nil {
-		return nil, s.err
-	}
-	// The input slice is already a copy and that we can modify it safely.
-	return s.a, nil
-}
-
-func (s *valueSorter) Len() int      { return len(s.a) }
-func (s *valueSorter) Swap(i, j int) { s.a[i], s.a[j] = s.a[j], s.a[i] }
-func (s *valueSorter) Less(i, j int) bool {
-	ctx := s.cmp.ctx()
-	x := fill(ctx, s.cmp.v, s.a[i], "x")
-	x = fill(ctx, x, s.a[j], "y")
-	ctx.opCtx.Unify(ctx.opCtx, x, adt.Finalized) // TODO: remove.
-	v := Value{s.cmp.idx, x}
-	isLess, err := v.Lookup("less").Bool()
-	if err != nil && s.err == nil {
-		s.err = err
-		return true
-	}
-	return isLess
-}
-
-// fill creates a new value with the old value unified with the given value.
-// TODO: consider making this a method on Value.
-func fill(ctx *context, v *adt.Vertex, x interface{}, path ...string) *adt.Vertex {
-	for i := len(path) - 1; i >= 0; i-- {
-		x = map[string]interface{}{path[i]: x}
-	}
-	value := convertVal(ctx, v, false, x)
-
-	w := adt.ToVertex(value)
-	n := &adt.Vertex{Label: v.Label}
-	n.AddConjunct(adt.MakeConjunct(nil, v))
-	n.AddConjunct(adt.MakeConjunct(nil, w))
-
-	// n.Add(v)
-	// n.Add(w)
-	return n
-}
-
-func convertVal(ctx *context, src source, nullIsTop bool, x interface{}) adt.Value {
-	return convert.GoValueToValue(ctx.opCtx, x, nullIsTop)
-}
diff --git a/internal/legacy/cue/context.go b/internal/legacy/cue/context.go
deleted file mode 100644
index 3f00329..0000000
--- a/internal/legacy/cue/context.go
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright 2018 The 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/core/adt"
-	"cuelang.org/go/internal/core/debug"
-	"cuelang.org/go/internal/core/eval"
-	"github.com/cockroachdb/apd/v2"
-)
-
-// context manages evaluation state.
-type context struct {
-	opCtx *adt.OpContext
-	*apd.Context
-	*index
-}
-
-var baseContext apd.Context
-
-func init() {
-	baseContext = apd.BaseContext
-	baseContext.Precision = 24
-}
-
-// newContext returns a new evaluation context.
-func (idx *index) newContext() *context {
-	c := &context{
-		Context: &baseContext,
-		index:   idx,
-	}
-	if idx != nil {
-		c.opCtx = eval.NewContext(idx.Runtime, nil)
-	}
-	return c
-}
-
-func debugStr(ctx *context, v adt.Node) string {
-	return debug.NodeString(ctx.opCtx, v, nil)
-}
-
-func (c *context) str(v adt.Node) string {
-	return debugStr(c, v)
-}
-
-func (c *context) mkErr(src source, args ...interface{}) *bottom {
-	return c.index.mkErr(src, args...)
-}
-
-func (c *context) vertex(v *adt.Vertex) *adt.Vertex {
-	return v
-}
-
-// vertex returns the evaluated vertex of v.
-func (v Value) vertex(ctx *context) *adt.Vertex {
-	return ctx.vertex(v.v)
-}
-
-// eval returns the evaluated value. This may not be the vertex.
-//
-// Deprecated: use ctx.value
-func (v Value) eval(ctx *context) adt.Value {
-	if v.v == nil {
-		panic("undefined value")
-	}
-	x := ctx.manifest(v.v)
-	switch x.Kind() {
-	case adt.StructKind, adt.ListKind:
-		return x
-	default:
-		return x.Value
-	}
-}
-
-// func (v Value) evalFull(u value) (Value, adt.Value) {
-// 	ctx := v.ctx()
-// 	x := ctx.manifest(u)
-// }
-
-// TODO: change from Vertex to Vertex.
-func (c *context) manifest(v *adt.Vertex) *adt.Vertex {
-	v.Finalize(c.opCtx)
-	return v
-}
diff --git a/internal/legacy/cue/errors.go b/internal/legacy/cue/errors.go
deleted file mode 100644
index 21ed886..0000000
--- a/internal/legacy/cue/errors.go
+++ /dev/null
@@ -1,182 +0,0 @@
-// Copyright 2018 The 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 (
-	"fmt"
-	"reflect"
-
-	"cuelang.org/go/cue/errors"
-	"cuelang.org/go/cue/token"
-	"cuelang.org/go/internal/core/adt"
-)
-
-func (v Value) appendErr(err errors.Error, b *bottom) errors.Error {
-	return &valueError{
-		v: v,
-		err: &adt.Bottom{
-			Err: errors.Append(err, b.Err),
-		},
-	}
-}
-
-func (v Value) toErr(b *bottom) (err errors.Error) {
-	return &valueError{v: v, err: b}
-}
-
-var _ errors.Error = &valueError{}
-
-// A valueError is returned as a result of evaluating a value.
-type valueError struct {
-	v   Value
-	err *bottom
-}
-
-func (e *valueError) Error() string {
-	return errors.String(e)
-}
-
-func (e *valueError) Position() token.Pos {
-	src := e.err.Source()
-	if src == nil {
-		return token.NoPos
-	}
-	return src.Pos()
-}
-
-func (e *valueError) InputPositions() []token.Pos {
-	if e.err.Err == nil {
-		return nil
-	}
-	return e.err.Err.InputPositions()
-}
-
-func (e *valueError) Msg() (string, []interface{}) {
-	if e.err.Err == nil {
-		return "", nil
-	}
-	return e.err.Err.Msg()
-}
-
-func (e *valueError) Path() (a []string) {
-	return e.v.appendPath(nil)
-}
-
-type errCode = adt.ErrorCode
-
-const (
-	codeNone       errCode = 0
-	codeFatal              = adt.EvalError
-	codeNotExist           = adt.NotExistError
-	codeTypeError          = adt.EvalError
-	codeIncomplete         = adt.IncompleteError
-	codeUser               = adt.UserError
-	codeCycle              = adt.CycleError
-)
-
-func isIncomplete(v value) bool {
-	if err, ok := v.(*bottom); ok {
-		return err.Code == codeIncomplete || err.Code == codeCycle
-	}
-	return false
-}
-
-func isLiteralBottom(v value) bool {
-	if err, ok := v.(*bottom); ok {
-		return err.Code == codeUser
-	}
-	return false
-}
-
-var errNotExists = &adt.Bottom{
-	Code: codeNotExist,
-	Err:  errors.Newf(token.NoPos, "undefined value"),
-}
-
-func exists(v value) bool {
-	if err, ok := v.(*bottom); ok {
-		return err.Code != codeNotExist
-	}
-	return true
-}
-
-func (idx *index) mkErr(src source, args ...interface{}) *bottom {
-	var e *adt.Bottom
-	var code errCode = -1
-outer:
-	for i, a := range args {
-		switch x := a.(type) {
-		case errCode:
-			code = x
-		case *bottom:
-			e = adt.CombineErrors(nil, e, x)
-		case []*bottom:
-			for _, b := range x {
-				e = adt.CombineErrors(nil, e, b)
-			}
-		case errors.Error:
-			e = adt.CombineErrors(nil, e, &adt.Bottom{Err: x})
-		case value:
-		case string:
-			args := args[i+1:]
-			// Do not expand message so that errors can be localized.
-			pos := pos(src)
-			if code < 0 {
-				code = 0
-			}
-			e = adt.CombineErrors(nil, e, &adt.Bottom{
-				Code: code,
-				Err:  errors.Newf(pos, x, args...),
-			})
-			break outer
-		}
-	}
-	if code >= 0 {
-		e.Code = code
-	}
-	return e
-}
-
-func fixArg(idx *index, x interface{}) interface{} {
-	switch x.(type) {
-	case uint, int, string:
-		return x
-	case value:
-		return x
-	}
-	t := reflect.TypeOf(x)
-	// Store all non-ptr types as is, as they cannot change.
-	if k := t.Kind(); k == reflect.String || k <= reflect.Complex128 {
-		return x
-	}
-	return fmt.Sprint(x)
-}
-
-func isBottom(x adt.Node) bool {
-	if x == nil {
-		return true
-	}
-	b, _ := x.(*adt.Bottom)
-	return b != nil
-}
-
-func firstBottom(v ...value) *bottom {
-	for _, b := range v {
-		if isBottom(b) {
-			return b.(*bottom)
-		}
-	}
-	return nil
-}
diff --git a/internal/legacy/cue/go.go b/internal/legacy/cue/go.go
deleted file mode 100644
index 28399d9..0000000
--- a/internal/legacy/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().Runtime, nil)
-		v := convert.GoValueToValue(ctx, x, nilIsTop)
-		n := adt.ToVertex(v)
-		return Value{r.idx, n}
-	}
-
-	internal.FromGoType = func(runtime, x interface{}) interface{} {
-		r := runtime.(*Runtime)
-		ctx := eval.NewContext(r.index().Runtime, nil)
-		expr, err := convert.GoTypeToExpr(ctx, x)
-		if err != nil {
-			expr = &adt.Bottom{Err: err}
-		}
-		n := &adt.Vertex{}
-		n.AddConjunct(adt.MakeConjunct(nil, expr))
-		return Value{r.idx, n}
-
-		// return convertType(runtime.(*Runtime), x)
-	}
-}
diff --git a/internal/legacy/cue/instance.go b/internal/legacy/cue/instance.go
deleted file mode 100644
index 5b954ea..0000000
--- a/internal/legacy/cue/instance.go
+++ /dev/null
@@ -1,363 +0,0 @@
-// Copyright 2018 The 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/cue/ast"
-	"cuelang.org/go/cue/build"
-	"cuelang.org/go/cue/errors"
-	"cuelang.org/go/internal"
-	"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"
-)
-
-// An Instance defines a single configuration based on a collection of
-// underlying CUE files.
-type Instance struct {
-	*index
-
-	root *adt.Vertex
-
-	ImportPath  string
-	Dir         string
-	PkgName     string
-	DisplayName string
-
-	Incomplete bool         // true if Pkg and all its dependencies are free of errors
-	Err        errors.Error // non-nil if the package had errors
-
-	inst *build.Instance
-
-	complete bool // for cycle detection
-}
-
-func (x *index) addInst(p *Instance) *Instance {
-	x.Index.AddInst(p.ImportPath, p.root, p)
-	p.index = x
-	return p
-}
-
-func (x *index) getImportFromNode(v *adt.Vertex) *Instance {
-	p := x.Index.GetImportFromNode(v)
-	if p == nil {
-		return nil
-	}
-	return p.(*Instance)
-}
-
-func (x *index) getImportFromPath(id string) *Instance {
-	node := x.Index.GetImportFromPath(id)
-	if node == nil {
-		return nil
-	}
-	return x.Index.GetImportFromNode(node).(*Instance)
-}
-
-func init() {
-	internal.MakeInstance = func(value interface{}) interface{} {
-		v := value.(Value)
-		x := v.eval(v.ctx())
-		st, ok := x.(*adt.Vertex)
-		if !ok {
-			st = &adt.Vertex{}
-			st.AddConjunct(adt.MakeConjunct(nil, x))
-		}
-		return v.ctx().index.addInst(&Instance{
-			root: st,
-		})
-	}
-}
-
-// newInstance creates a new instance. Use Insert to populate the instance.
-func newInstance(x *index, p *build.Instance, v *adt.Vertex) *Instance {
-	// TODO: associate root source with structLit.
-	i := &Instance{
-		root: v,
-		inst: p,
-	}
-	if p != nil {
-		i.ImportPath = p.ImportPath
-		i.Dir = p.Dir
-		i.PkgName = p.PkgName
-		i.DisplayName = p.ImportPath
-		if p.Err != nil {
-			i.setListOrError(p.Err)
-		}
-	}
-	return x.addInst(i)
-}
-
-func (inst *Instance) setListOrError(err errors.Error) {
-	inst.Incomplete = true
-	inst.Err = errors.Append(inst.Err, err)
-}
-
-func (inst *Instance) setError(err errors.Error) {
-	inst.Incomplete = true
-	inst.Err = errors.Append(inst.Err, err)
-}
-
-func (inst *Instance) eval(ctx *context) evaluated {
-	// TODO: remove manifest here?
-	v := ctx.manifest(inst.root)
-	return v
-}
-
-func init() {
-	internal.EvalExpr = func(value, expr interface{}) interface{} {
-		v := value.(Value)
-		e := expr.(ast.Expr)
-		ctx := v.idx.newContext()
-		return newValueRoot(ctx, evalExpr(ctx, v.vertex(ctx), e))
-	}
-}
-
-// evalExpr evaluates expr within scope.
-func evalExpr(ctx *context, scope *adt.Vertex, expr ast.Expr) evaluated {
-	cfg := &compile.Config{
-		Scope: scope,
-		Imports: func(x *ast.Ident) (pkgPath string) {
-			if _, ok := builtins[x.Name]; !ok {
-				return ""
-			}
-			return x.Name
-		},
-	}
-
-	c, err := compile.Expr(cfg, ctx.opCtx, expr)
-	if err != nil {
-		return &adt.Bottom{Err: err}
-	}
-	return adt.Resolve(ctx.opCtx, c)
-
-	// scope.Finalize(ctx.opCtx) // 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.opCtx
-
-	// 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))
-}
-
-// Doc returns the package comments for this instance.
-func (inst *Instance) Doc() []*ast.CommentGroup {
-	var docs []*ast.CommentGroup
-	if inst.inst == nil {
-		return nil
-	}
-	for _, f := range inst.inst.Files {
-		if c := internal.FileComment(f); c != nil {
-			docs = append(docs, c)
-		}
-	}
-	return docs
-}
-
-// Value returns the root value of the configuration. If the configuration
-// defines in emit value, it will be that value. Otherwise it will be all
-// top-level values.
-func (inst *Instance) Value() Value {
-	ctx := inst.newContext()
-	inst.root.Finalize(ctx.opCtx)
-	return newVertexRoot(ctx, inst.root)
-}
-
-// Eval evaluates an expression within an existing instance.
-//
-// Expressions may refer to builtin packages if they can be uniquely identified.
-func (inst *Instance) Eval(expr ast.Expr) Value {
-	ctx := inst.newContext()
-	v := inst.root
-	v.Finalize(ctx.opCtx)
-	result := evalExpr(ctx, v, expr)
-	return newValueRoot(ctx, result)
-}
-
-// Merge unifies the given instances into a single one.
-//
-// Errors regarding conflicts are included in the result, but not reported, so
-// that these will only surface during manifestation. This allows
-// non-conflicting parts to be used.
-func Merge(inst ...*Instance) *Instance {
-	v := &adt.Vertex{}
-
-	i := inst[0]
-	ctx := i.index.newContext().opCtx
-
-	// TODO: interesting test: use actual unification and then on K8s corpus.
-
-	for _, i := range inst {
-		w := i.Value()
-		v.AddConjunct(adt.MakeConjunct(nil, w.v.ToDataAll()))
-	}
-	v.Finalize(ctx)
-
-	p := i.index.addInst(&Instance{
-		root:     v,
-		complete: true,
-	})
-	return p
-}
-
-// Build creates a new instance from the build instances, allowing unbound
-// identifier to bind to the top-level field in inst. The top-level fields in
-// inst take precedence over predeclared identifier and builtin functions.
-func (inst *Instance) Build(p *build.Instance) *Instance {
-	p.Complete()
-
-	idx := inst.index
-	r := inst.index.Runtime
-
-	rErr := runtime.ResolveFiles(idx.Index, p, isBuiltin)
-
-	v, err := compile.Files(&compile.Config{Scope: inst.root}, r, p.Files...)
-
-	v.AddConjunct(adt.MakeConjunct(nil, inst.root))
-
-	i := newInstance(idx, p, v)
-	if rErr != nil {
-		i.setListOrError(err)
-	}
-	if i.Err != nil {
-		i.setListOrError(err)
-	}
-
-	if err != nil {
-		i.setListOrError(err)
-	}
-
-	i.complete = true
-
-	return i
-}
-
-func (inst *Instance) value() Value {
-	return newVertexRoot(inst.newContext(), inst.root)
-}
-
-// Lookup reports the value at a path starting from the top level struct. The
-// Exists method of the returned value will report false if the path did not
-// exist. The Err method reports if any error occurred during evaluation. The
-// empty path returns the top-level configuration struct. Use LookupDef for definitions or LookupField for
-// any kind of field.
-func (inst *Instance) Lookup(path ...string) Value {
-	return inst.value().Lookup(path...)
-}
-
-// LookupDef reports the definition with the given name within struct v. The
-// Exists method of the returned value will report false if the definition did
-// not exist. The Err method reports if any error occurred during evaluation.
-func (inst *Instance) LookupDef(path string) Value {
-	return inst.value().LookupDef(path)
-}
-
-// LookupField reports a Field at a path starting from v, or an error if the
-// path is not. The empty path returns v itself.
-//
-// It cannot look up hidden or unexported fields.
-//
-// Deprecated: this API does not work with new-style definitions. Use
-// FieldByName defined on inst.Value().
-func (inst *Instance) LookupField(path ...string) (f FieldInfo, err error) {
-	v := inst.value()
-	for _, k := range path {
-		s, err := v.Struct()
-		if err != nil {
-			return f, err
-		}
-
-		f, err = s.FieldByName(k, true)
-		if err != nil {
-			return f, err
-		}
-		if f.IsHidden {
-			return f, errNotFound
-		}
-		v = f.Value
-	}
-	return f, err
-}
-
-// Fill creates a new instance with the values of the old instance unified with
-// the given value. It is not possible to update the emit value.
-//
-// Values may be any Go value that can be converted to CUE, an ast.Expr or
-// a Value. In the latter case, it will panic if the Value is not from the same
-// Runtime.
-func (inst *Instance) Fill(x interface{}, path ...string) (*Instance, error) {
-	for i := len(path) - 1; i >= 0; i-- {
-		x = map[string]interface{}{path[i]: x}
-	}
-	a := make([]adt.Conjunct, len(inst.root.Conjuncts))
-	copy(a, inst.root.Conjuncts)
-	u := &adt.Vertex{Conjuncts: a}
-
-	if v, ok := x.(Value); ok {
-		if inst.index != v.idx {
-			panic("value of type Value is not created with same Runtime as Instance")
-		}
-		for _, c := range v.v.Conjuncts {
-			u.AddConjunct(c)
-		}
-	} else {
-		ctx := eval.NewContext(inst.index.Runtime, nil)
-		expr := convert.GoValueToExpr(ctx, true, x)
-		u.AddConjunct(adt.MakeConjunct(nil, expr))
-		u.Finalize(ctx)
-	}
-	inst = inst.index.addInst(&Instance{
-		root: u,
-		inst: nil,
-
-		// Omit ImportPath to indicate this is not an importable package.
-		Dir:        inst.Dir,
-		PkgName:    inst.PkgName,
-		Incomplete: inst.Incomplete,
-
-		complete: true,
-	})
-	return inst, nil
-}
diff --git a/internal/legacy/cue/marshal.go b/internal/legacy/cue/marshal.go
deleted file mode 100644
index c48d136..0000000
--- a/internal/legacy/cue/marshal.go
+++ /dev/null
@@ -1,223 +0,0 @@
-// Copyright 2019 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 (
-	"bytes"
-	"compress/gzip"
-	"encoding/gob"
-	"path/filepath"
-	"strings"
-
-	"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/format"
-	"cuelang.org/go/cue/token"
-	"cuelang.org/go/internal"
-	"cuelang.org/go/internal/core/export"
-)
-
-// root.
-type instanceData struct {
-	Root  bool
-	Path  string
-	Files []fileData
-}
-
-type fileData struct {
-	Name string
-	Data []byte
-}
-
-const version = 1
-
-type unmarshaller struct {
-	ctxt    *build.Context
-	imports map[string]*instanceData
-}
-
-func (b *unmarshaller) load(pos token.Pos, path string) *build.Instance {
-	bi := b.imports[path]
-	if bi == nil {
-		return nil
-	}
-	return b.build(bi)
-}
-
-func (b *unmarshaller) build(bi *instanceData) *build.Instance {
-	p := b.ctxt.NewInstance(bi.Path, b.load)
-	p.ImportPath = bi.Path
-	for _, f := range bi.Files {
-		_ = p.AddFile(f.Name, f.Data)
-	}
-	p.Complete()
-	return p
-}
-
-func compileInstances(r *Runtime, data []*instanceData) (instances []*Instance, err error) {
-	b := unmarshaller{
-		ctxt:    r.buildContext(),
-		imports: map[string]*instanceData{},
-	}
-	for _, i := range data {
-		if i.Path == "" {
-			if !i.Root {
-				return nil, errors.Newf(token.NoPos,
-					"data contains non-root package without import path")
-			}
-			continue
-		}
-		b.imports[i.Path] = i
-	}
-
-	builds := []*build.Instance{}
-	for _, i := range data {
-		if !i.Root {
-			continue
-		}
-		builds = append(builds, b.build(i))
-	}
-
-	return r.build(builds)
-}
-
-// Unmarshal creates an Instance from bytes generated by the MarshalBinary
-// method of an instance.
-func (r *Runtime) Unmarshal(b []byte) ([]*Instance, error) {
-	if len(b) == 0 {
-		return nil, errors.Newf(token.NoPos, "unmarshal failed: empty buffer")
-	}
-
-	switch b[0] {
-	case version:
-	default:
-		return nil, errors.Newf(token.NoPos,
-			"unmarshal failed: unsupported version %d, regenerate data", b[0])
-	}
-
-	reader, err := gzip.NewReader(bytes.NewReader(b[1:]))
-	if err != nil {
-		return nil, errors.Newf(token.NoPos, "unmarshal failed: %v", err)
-	}
-
-	data := []*instanceData{}
-	err = gob.NewDecoder(reader).Decode(&data)
-	if err != nil {
-		return nil, errors.Newf(token.NoPos, "unmarshal failed: %v", err)
-	}
-
-	return compileInstances(r, data)
-}
-
-// Marshal creates bytes from a group of instances. Imported instances will
-// be included in the emission.
-//
-// The stored instances are functionally the same, but preserving of file
-// information is only done on a best-effort basis.
-func (r *Runtime) Marshal(instances ...*Instance) (b []byte, err error) {
-	ctx := r.index().newContext()
-
-	staged := []instanceData{}
-	done := map[string]int{}
-
-	var errs errors.Error
-
-	var stageInstance func(i *Instance) (pos int)
-	stageInstance = func(i *Instance) (pos int) {
-		if p, ok := done[i.ImportPath]; ok {
-			return p
-		}
-		// TODO: support exporting instance
-		file, _ := export.Def(r.idx.Runtime, i.root)
-		imports := []string{}
-		for _, i := range internal.Imports(file) {
-			for _, spec := range i.(*ast.ImportDecl).Specs {
-				info, _ := astutil.ParseImportSpec(spec)
-				imports = append(imports, info.ID)
-			}
-		}
-
-		if i.PkgName != "" {
-			p, name, _ := internal.PackageInfo(file)
-			if p == nil {
-				pkg := &ast.Package{Name: ast.NewIdent(i.PkgName)}
-				file.Decls = append([]ast.Decl{pkg}, file.Decls...)
-			} else if name != i.PkgName {
-				// p is guaranteed to be generated by Def, so it is "safe" to
-				// modify.
-				p.Name = ast.NewIdent(i.PkgName)
-			}
-		}
-
-		b, err := format.Node(file)
-		errs = errors.Append(errs, errors.Promote(err, "marshal"))
-
-		filename := "unmarshal"
-		if i.inst != nil && len(i.inst.Files) == 1 {
-			filename = i.inst.Files[0].Filename
-
-			dir := i.Dir
-			if i.inst != nil && i.inst.Root != "" {
-				dir = i.inst.Root
-			}
-			if dir != "" {
-				filename = filepath.FromSlash(filename)
-				filename, _ = filepath.Rel(dir, filename)
-				filename = filepath.ToSlash(filename)
-			}
-		}
-		// TODO: this should probably be changed upstream, but as the path
-		// is for reference purposes only, this is safe.
-		importPath := filepath.ToSlash(i.ImportPath)
-
-		staged = append(staged, instanceData{
-			Path:  importPath,
-			Files: []fileData{{filename, b}},
-		})
-
-		p := len(staged) - 1
-
-		for _, imp := range imports {
-			i := ctx.getImportFromPath(imp)
-			if i == nil || !strings.Contains(imp, ".") {
-				continue // a builtin package.
-			}
-			stageInstance(i)
-		}
-
-		return p
-	}
-
-	for _, i := range instances {
-		staged[stageInstance(i)].Root = true
-	}
-
-	buf := &bytes.Buffer{}
-	buf.WriteByte(version)
-
-	zw := gzip.NewWriter(buf)
-	if err := gob.NewEncoder(zw).Encode(staged); err != nil {
-		return nil, err
-	}
-
-	if err := zw.Close(); err != nil {
-		return nil, err
-	}
-
-	return buf.Bytes(), nil
-
-}
diff --git a/internal/legacy/cue/marshal_test.go b/internal/legacy/cue/marshal_test.go
deleted file mode 100644
index 64775aa..0000000
--- a/internal/legacy/cue/marshal_test.go
+++ /dev/null
@@ -1,202 +0,0 @@
-// Copyright 2019 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 (
-	"fmt"
-	"strings"
-	"testing"
-
-	"github.com/google/go-cmp/cmp"
-)
-
-func TestMarshalling(t *testing.T) {
-	testCases := []struct {
-		filename string
-		input    string
-		pkg      string
-	}{{
-		filename: "foo.cue",
-		pkg:      "foo",
-		input: `package foo
-
-		A: int
-		B: string
-		`,
-	}, {
-		filename: "bar.cue",
-		pkg:      "bar",
-		input: `package bar
-
-		"Hello world!"
-		`,
-	}, {
-		filename: "qux.cue",
-		input: `
-			"Hello world!"
-		`,
-	}, {
-		filename: "baz.cue",
-		pkg:      "baz",
-		input: `package baz
-
-		import "strings"
-
-		a: strings.TrimSpace("  Hello world!  ")
-		`}}
-	for _, tc := range testCases {
-		t.Run(tc.filename, func(t *testing.T) {
-			r := &Runtime{}
-			inst, err := r.Compile(tc.filename, tc.input)
-			if err != nil {
-				t.Fatal(err)
-			}
-			inst.ImportPath = "test/pkg"
-			want := fmt.Sprint(inst.Value())
-
-			b, err := r.Marshal(inst)
-			if err != nil {
-				t.Fatal(err)
-			}
-
-			r2 := &Runtime{}
-			instances, err := r2.Unmarshal(b)
-			if err != nil {
-				t.Fatal(err)
-			}
-			inst = instances[0]
-
-			if inst.ImportPath != "test/pkg" {
-				t.Error("import path was not restored")
-			}
-			got := fmt.Sprint(inst.Value())
-
-			if got != want {
-				t.Errorf("\ngot:  %q;\nwant: %q", got, want)
-			}
-		})
-	}
-}
-
-func TestMarshalMultiPackage(t *testing.T) {
-	files := func(s ...string) (a []fileData) {
-		for i, s := range s {
-			a = append(a, fileData{fmt.Sprintf("file%d.cue", i), []byte(s)})
-		}
-		return a
-	}
-	insts := func(i ...*instanceData) []*instanceData { return i }
-	pkg1 := &instanceData{
-		true,
-		"example.com/foo/pkg1",
-		files(`
-		package pkg1
-
-		Object: "World"
-		`),
-	}
-	pkg2 := &instanceData{
-		true,
-		"example.com/foo/pkg2",
-		files(`
-		package pkg
-
-		Number: 12
-		`),
-	}
-
-	testCases := []struct {
-		instances []*instanceData
-		emit      string
-	}{{
-		insts(&instanceData{true, "", files(`test: "ok"`)}),
-		`{test: "ok"}`,
-	}, {
-		insts(&instanceData{true, "",
-			files(
-				`package test
-
-		import math2 "math"
-
-		"Pi: \(math2.Pi)!"`)}),
-		`"Pi: 3.14159265358979323846264338327950288419716939937510582097494459!"`,
-	}, {
-		insts(pkg1, &instanceData{true, "",
-			files(
-				`package test
-
-			import "example.com/foo/pkg1"
-
-			"Hello \(pkg1.Object)!"`),
-		}),
-		`"Hello World!"`,
-	}, {
-		insts(pkg1, &instanceData{true, "",
-			files(
-				`package test
-
-		import pkg2 "example.com/foo/pkg1"
-		pkg1: pkg2.Object
-
-		"Hello \(pkg1)!"`),
-		}),
-		`"Hello World!"`,
-	}, {
-		insts(pkg2, &instanceData{true, "",
-			files(
-				`package test
-
-		import "example.com/foo/pkg2"
-
-		"Hello \(pkg.Number)!"`),
-		}),
-		`"Hello 12!"`,
-	}}
-
-	strValue := func(a []*Instance) (ret []string) {
-		for _, i := range a {
-			ret = append(ret, strings.TrimSpace((fmt.Sprint(i.Value()))))
-		}
-		return ret
-	}
-
-	for _, tc := range testCases {
-		t.Run("", func(t *testing.T) {
-			r := &Runtime{}
-
-			insts, err := compileInstances(r, tc.instances)
-			if err != nil {
-				t.Fatal(err)
-			}
-			want := strValue(insts)
-
-			b, err := r.Marshal(insts...)
-			if err != nil {
-				t.Fatal(err)
-			}
-
-			r2 := &Runtime{}
-			insts, err = r2.Unmarshal(b)
-			if err != nil {
-				t.Fatal(err)
-			}
-			got := strValue(insts)
-
-			if !cmp.Equal(got, want) {
-				t.Error(cmp.Diff(got, want))
-			}
-		})
-	}
-}
diff --git a/internal/legacy/cue/op.go b/internal/legacy/cue/op.go
deleted file mode 100644
index b313289..0000000
--- a/internal/legacy/cue/op.go
+++ /dev/null
@@ -1,219 +0,0 @@
-// Copyright 2018 The 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/cue/token"
-	"cuelang.org/go/internal/core/adt"
-)
-
-// Op indicates the operation at the top of an expression tree of the expression
-// use to evaluate a value.
-type Op = adt.Op
-
-// Values of Op.
-const (
-	NoOp = adt.NoOp
-
-	AndOp = adt.AndOp
-	OrOp  = adt.OrOp
-
-	SelectorOp = adt.SelectorOp
-	IndexOp    = adt.IndexOp
-	SliceOp    = adt.SliceOp
-	CallOp     = adt.CallOp
-
-	BooleanAndOp = adt.BoolAndOp
-	BooleanOrOp  = adt.BoolOrOp
-
-	EqualOp            = adt.EqualOp
-	NotOp              = adt.NotOp
-	NotEqualOp         = adt.NotEqualOp
-	LessThanOp         = adt.LessThanOp
-	LessThanEqualOp    = adt.LessEqualOp
-	GreaterThanOp      = adt.GreaterThanOp
-	GreaterThanEqualOp = adt.GreaterEqualOp
-
-	RegexMatchOp    = adt.MatchOp
-	NotRegexMatchOp = adt.NotMatchOp
-
-	AddOp           = adt.AddOp
-	SubtractOp      = adt.SubtractOp
-	MultiplyOp      = adt.MultiplyOp
-	FloatQuotientOp = adt.FloatQuotientOp
-	IntQuotientOp   = adt.IntQuotientOp
-	IntRemainderOp  = adt.IntRemainderOp
-	IntDivideOp     = adt.IntDivideOp
-	IntModuloOp     = adt.IntModuloOp
-
-	InterpolationOp = adt.InterpolationOp
-)
-
-var opToOp = map[op]Op{
-	opUnify: AndOp,
-	// TODO(eval): opUnifyUnchecked is not the same as opUnify and should have its own
-	// category, if needed. More likely opUnifyUnchecked, should be
-	// represented as a separate embedding method.
-	opUnifyUnchecked: AndOp,
-	opDisjunction:    OrOp,
-	opLand:           BooleanAndOp,
-	opLor:            BooleanOrOp,
-	opEql:            EqualOp,
-	opNot:            NotOp,
-	opNeq:            NotEqualOp,
-	opLss:            LessThanOp,
-	opLeq:            LessThanEqualOp,
-	opGtr:            GreaterThanOp,
-	opGeq:            GreaterThanEqualOp,
-	opMat:            RegexMatchOp,
-	opNMat:           NotRegexMatchOp,
-	opAdd:            AddOp,
-	opSub:            SubtractOp,
-	opMul:            MultiplyOp,
-	opQuo:            FloatQuotientOp,
-	opIQuo:           IntQuotientOp,
-	opIRem:           IntRemainderOp,
-	opIDiv:           IntDivideOp,
-	opIMod:           IntModuloOp,
-}
-
-func opIn(op op, anyOf ...op) bool {
-	for _, o := range anyOf {
-		if o == op {
-			return true
-		}
-	}
-	return false
-}
-
-// isCmp reports whether an op is a comparator.
-func (op op) isCmp() bool {
-	return opEql <= op && op <= opGeq
-}
-
-func (op op) unifyType() (unchecked, ok bool) {
-	if op == opUnifyUnchecked {
-		return true, true
-	}
-	return false, op == opUnify
-}
-
-type op uint16
-
-const (
-	opUnknown op = iota
-
-	opUnify
-	opUnifyUnchecked
-	opDisjunction
-
-	opLand
-	opLor
-	opNot
-
-	opEql
-	opNeq
-	opMat
-	opNMat
-
-	opLss
-	opGtr
-	opLeq
-	opGeq
-
-	opAdd
-	opSub
-	opMul
-	opQuo
-	opRem
-
-	opIDiv
-	opIMod
-	opIQuo
-	opIRem
-)
-
-var opStrings = []string{
-	opUnknown: "??",
-
-	opUnify: "&",
-	// opUnifyUnchecked is internal only. Syntactically this is
-	// represented as embedding.
-	opUnifyUnchecked: "&!",
-	opDisjunction:    "|",
-
-	opLand: "&&",
-	opLor:  "||",
-	opNot:  "!",
-
-	opEql:  "==",
-	opNeq:  "!=",
-	opMat:  "=~",
-	opNMat: "!~",
-
-	opLss: "<",
-	opGtr: ">",
-	opLeq: "<=",
-	opGeq: ">=",
-
-	opAdd: "+",
-	opSub: "-",
-	opMul: "*",
-	opQuo: "/",
-
-	opIDiv: "div",
-	opIMod: "mod",
-	opIQuo: "quo",
-	opIRem: "rem",
-}
-
-func (op op) String() string { return opStrings[op] }
-
-var tokenMap = map[token.Token]op{
-	token.OR:  opDisjunction, // |
-	token.AND: opUnify,       // &
-
-	token.ADD: opAdd, // +
-	token.SUB: opSub, // -
-	token.MUL: opMul, // *
-	token.QUO: opQuo, // /
-
-	token.IDIV: opIDiv, // div
-	token.IMOD: opIMod, // mod
-	token.IQUO: opIQuo, // quo
-	token.IREM: opIRem, // rem
-
-	token.LAND: opLand, // &&
-	token.LOR:  opLor,  // ||
-
-	token.EQL: opEql, // ==
-	token.LSS: opLss, // <
-	token.GTR: opGtr, // >
-	token.NOT: opNot, // !
-
-	token.NEQ:  opNeq,  // !=
-	token.LEQ:  opLeq,  // <=
-	token.GEQ:  opGeq,  // >=
-	token.MAT:  opMat,  // =~
-	token.NMAT: opNMat, // !~
-}
-
-var opMap = map[op]token.Token{}
-
-func init() {
-	for t, o := range tokenMap {
-		opMap[o] = t
-	}
-}
diff --git a/internal/legacy/cue/resolve_test.go b/internal/legacy/cue/resolve_test.go
deleted file mode 100644
index b9ad808..0000000
--- a/internal/legacy/cue/resolve_test.go
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright 2018 The 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 (
-	"strings"
-	"testing"
-
-	"cuelang.org/go/internal/core/adt"
-)
-
-func TestX(t *testing.T) {
-	// Don't remove. For debugging.
-	in := `
-	`
-
-	if strings.TrimSpace(in) == "" {
-		t.Skip()
-	}
-}
-
-// var traceOn = flag.Bool("debug", false, "enable tracing")
-
-// func compileFileWithErrors(t *testing.T, body string) (*context, *structLit, error) {
-// 	t.Helper()
-// 	ctx, inst, err := compileInstance(t, body)
-// 	return ctx, inst.root, err
-// }
-
-// func compileFile(t *testing.T, body string) (*context, *structLit) {
-// 	t.Helper()
-// 	ctx, inst, errs := compileInstance(t, body)
-// 	if errs != nil {
-// 		t.Fatal(errs)
-// 	}
-// 	return ctx, inst.root
-// }
-
-func compileInstance(t *testing.T, body string) (*context, *Instance, error) {
-	var r Runtime
-	inst, err := r.Compile("test", body)
-
-	if err != nil {
-		x := newInstance(newIndex(sharedIndex), nil, &adt.Vertex{})
-		ctx := x.newContext()
-		return ctx, x, err
-	}
-
-	return r.index().newContext(), inst, nil
-}
diff --git a/internal/legacy/cue/types.go b/internal/legacy/cue/types.go
deleted file mode 100644
index 3e5d0c2..0000000
--- a/internal/legacy/cue/types.go
+++ /dev/null
@@ -1,2245 +0,0 @@
-// Copyright 2018 The 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 (
-	"bytes"
-	"encoding/json"
-	"fmt"
-	"io"
-	"math"
-	"math/big"
-	"strconv"
-	"strings"
-
-	"github.com/cockroachdb/apd/v2"
-
-	"cuelang.org/go/cue/ast"
-	"cuelang.org/go/cue/ast/astutil"
-	"cuelang.org/go/cue/errors"
-	"cuelang.org/go/cue/format"
-	"cuelang.org/go/cue/token"
-	"cuelang.org/go/internal"
-	"cuelang.org/go/internal/core/adt"
-	"cuelang.org/go/internal/core/convert"
-	"cuelang.org/go/internal/core/eval"
-	"cuelang.org/go/internal/core/export"
-	"cuelang.org/go/internal/core/subsume"
-	"cuelang.org/go/internal/core/validate"
-)
-
-// Kind determines the underlying type of a Value.
-type Kind = adt.Kind
-
-const BottomKind Kind = 0
-
-const (
-	// NullKind indicates a null value.
-	NullKind Kind = adt.NullKind
-
-	// BoolKind indicates a boolean value.
-	BoolKind = adt.BoolKind
-
-	// IntKind represents an integral number.
-	IntKind = adt.IntKind
-
-	// FloatKind represents a decimal float point number that cannot be
-	// converted to an integer. The underlying number may still be integral,
-	// but resulting from an operation that enforces the float type.
-	FloatKind = adt.FloatKind
-
-	// StringKind indicates any kind of string.
-	StringKind = adt.StringKind
-
-	// BytesKind is a blob of data.
-	BytesKind = adt.BytesKind
-
-	// StructKind is a kev-value map.
-	StructKind = adt.StructKind
-
-	// ListKind indicates a list of values.
-	ListKind = adt.ListKind
-
-	// _numberKind is used as a implementation detail inside
-	// Kind.String to indicate NumberKind.
-
-	// NumberKind represents any kind of number.
-	NumberKind = IntKind | FloatKind
-
-	TopKind = adt.TopKind
-)
-
-// An structValue represents a JSON object.
-//
-// TODO: remove
-type structValue struct {
-	ctx      *context
-	v        Value
-	obj      *adt.Vertex
-	features []adt.Feature
-}
-
-// Len reports the number of fields in this struct.
-func (o *structValue) Len() int {
-	if o.obj == nil {
-		return 0
-	}
-	return len(o.features)
-}
-
-// At reports the key and value of the ith field, i < o.Len().
-func (o *structValue) At(i int) (key string, v Value) {
-	f := o.features[i]
-	return o.ctx.LabelStr(f), newChildValue(o, i)
-}
-
-func (o *structValue) at(i int) (v *adt.Vertex, isOpt bool) {
-	f := o.features[i]
-	arc := o.obj.Lookup(f)
-	if arc == nil {
-		arc = &adt.Vertex{
-			Parent: o.v.v,
-			Label:  f,
-		}
-		o.obj.MatchAndInsert(o.ctx.opCtx, arc)
-		arc.Finalize(o.ctx.opCtx)
-		isOpt = true
-	}
-	return arc, isOpt
-}
-
-// Lookup reports the field for the given key. The returned Value is invalid
-// if it does not exist.
-func (o *structValue) Lookup(key string) Value {
-	f := o.ctx.StrLabel(key)
-	i := 0
-	len := o.Len()
-	for ; i < len; i++ {
-		if o.features[i] == f {
-			break
-		}
-	}
-	if i == len {
-		// TODO: better message.
-		ctx := o.ctx
-		x := ctx.mkErr(o.obj, codeNotExist, "value %q not found", key)
-		return newErrValue(o.v, x)
-	}
-	return newChildValue(o, i)
-}
-
-// MarshalJSON returns a valid JSON encoding or reports an error if any of the
-// fields is invalid.
-func (o *structValue) marshalJSON() (b []byte, err errors.Error) {
-	b = append(b, '{')
-	n := o.Len()
-	for i := 0; i < n; i++ {
-		k, v := o.At(i)
-		s, err := json.Marshal(k)
-		if err != nil {
-			return nil, unwrapJSONError(err)
-		}
-		b = append(b, s...)
-		b = append(b, ':')
-		bb, err := json.Marshal(v)
-		if err != nil {
-			return nil, unwrapJSONError(err)
-		}
-		b = append(b, bb...)
-		if i < n-1 {
-			b = append(b, ',')
-		}
-	}
-	b = append(b, '}')
-	return b, nil
-}
-
-var _ errors.Error = &marshalError{}
-
-type marshalError struct {
-	err errors.Error
-	b   *bottom
-}
-
-func toMarshalErr(v Value, b *bottom) error {
-	return &marshalError{v.toErr(b), b}
-}
-
-func marshalErrf(v Value, src source, code errCode, msg string, args ...interface{}) error {
-	arguments := append([]interface{}{code, msg}, args...)
-	b := v.idx.mkErr(src, arguments...)
-	return toMarshalErr(v, b)
-}
-
-func (e *marshalError) Error() string {
-	return fmt.Sprintf("cue: marshal error: %v", e.err)
-}
-
-func (e *marshalError) Path() []string               { return e.err.Path() }
-func (e *marshalError) Msg() (string, []interface{}) { return e.err.Msg() }
-func (e *marshalError) Position() token.Pos          { return e.err.Position() }
-func (e *marshalError) InputPositions() []token.Pos {
-	return e.err.InputPositions()
-}
-
-func unwrapJSONError(err error) errors.Error {
-	switch x := err.(type) {
-	case *json.MarshalerError:
-		return unwrapJSONError(x.Err)
-	case *marshalError:
-		return x
-	case errors.Error:
-		return &marshalError{x, nil}
-	default:
-		return &marshalError{errors.Wrapf(err, token.NoPos, "json error"), nil}
-	}
-}
-
-// An Iterator iterates over values.
-//
-type Iterator struct {
-	val   Value
-	ctx   *context
-	arcs  []field
-	p     int
-	cur   Value
-	f     label
-	isOpt bool
-}
-
-type field struct {
-	arc        *adt.Vertex
-	isOptional bool
-}
-
-// Next advances the iterator to the next value and reports whether there was
-// any. It must be called before the first call to Value or Key.
-func (i *Iterator) Next() bool {
-	if i.p >= len(i.arcs) {
-		i.cur = Value{}
-		return false
-	}
-	f := i.arcs[i.p]
-	f.arc.Finalize(i.ctx.opCtx)
-	i.cur = makeValue(i.val.idx, f.arc)
-	i.f = f.arc.Label
-	i.isOpt = f.isOptional
-	i.p++
-	return true
-}
-
-// Value returns the current value in the list. It will panic if Next advanced
-// past the last entry.
-func (i *Iterator) Value() Value {
-	return i.cur
-}
-
-func (i *Iterator) Feature() adt.Feature {
-	return i.f
-}
-
-// Label reports the label of the value if i iterates over struct fields and
-// "" otherwise.
-func (i *Iterator) Label() string {
-	if i.f == 0 {
-		return ""
-	}
-	return i.ctx.LabelStr(i.f)
-}
-
-// IsHidden reports if a field is hidden from the data model.
-func (i *Iterator) IsHidden() bool {
-	return i.f.IsHidden()
-}
-
-// IsOptional reports if a field is optional.
-func (i *Iterator) IsOptional() bool {
-	return i.isOpt
-}
-
-// IsDefinition reports if a field is a definition.
-func (i *Iterator) IsDefinition() bool {
-	return i.f.IsDef()
-}
-
-// marshalJSON iterates over the list and generates JSON output. HasNext
-// will return false after this operation.
-func marshalList(l *Iterator) (b []byte, err errors.Error) {
-	b = append(b, '[')
-	if l.Next() {
-		for i := 0; ; i++ {
-			x, err := json.Marshal(l.Value())
-			if err != nil {
-				return nil, unwrapJSONError(err)
-			}
-			b = append(b, x...)
-			if !l.Next() {
-				break
-			}
-			b = append(b, ',')
-		}
-	}
-	b = append(b, ']')
-	return b, nil
-}
-
-func (v Value) getNum(k kind) (*numLit, errors.Error) {
-	v, _ = v.Default()
-	ctx := v.ctx()
-	if err := v.checkKind(ctx, k); err != nil {
-		return nil, v.toErr(err)
-	}
-	n, _ := v.eval(ctx).(*numLit)
-	return n, nil
-}
-
-// MantExp breaks x into its mantissa and exponent components and returns the
-// exponent. If a non-nil mant argument is provided its value is set to the
-// mantissa of x. The components satisfy x == mant × 10**exp. It returns an
-// error if v is not a number.
-//
-// The components are not normalized. For instance, 2.00 is represented mant ==
-// 200 and exp == -2. Calling MantExp with a nil argument is an efficient way to
-// get the exponent of the receiver.
-func (v Value) MantExp(mant *big.Int) (exp int, err error) {
-	n, err := v.getNum(numKind)
-	if err != nil {
-		return 0, err
-	}
-	if n.X.Form != 0 {
-		return 0, ErrInfinite
-	}
-	if mant != nil {
-		mant.Set(&n.X.Coeff)
-		if n.X.Negative {
-			mant.Neg(mant)
-		}
-	}
-	return int(n.X.Exponent), nil
-}
-
-// AppendInt appends the string representation of x in the given base to buf and
-// returns the extended buffer, or an error if the underlying number was not
-// an integer.
-func (v Value) AppendInt(buf []byte, base int) ([]byte, error) {
-	i, err := v.Int(nil)
-	if err != nil {
-		return nil, err
-	}
-	return i.Append(buf, base), nil
-}
-
-// AppendFloat appends to buf the string form of the floating-point number x.
-// It returns an error if v is not a number.
-func (v Value) AppendFloat(buf []byte, fmt byte, prec int) ([]byte, error) {
-	n, err := v.getNum(numKind)
-	if err != nil {
-		return nil, err
-	}
-	ctx := apd.BaseContext
-	nd := int(apd.NumDigits(&n.X.Coeff)) + int(n.X.Exponent)
-	if n.X.Form == apd.Infinite {
-		if n.X.Negative {
-			buf = append(buf, '-')
-		}
-		return append(buf, string('∞')...), nil
-	}
-	if fmt == 'f' && nd > 0 {
-		ctx.Precision = uint32(nd + prec)
-	} else {
-		ctx.Precision = uint32(prec)
-	}
-	var d apd.Decimal
-	ctx.Round(&d, &n.X)
-	return d.Append(buf, fmt), nil
-}
-
-var (
-	// ErrBelow indicates that a value was rounded down in a conversion.
-	ErrBelow = errors.New("value was rounded down")
-
-	// ErrAbove indicates that a value was rounded up in a conversion.
-	ErrAbove = errors.New("value was rounded up")
-
-	// ErrInfinite indicates that a value is infinite.
-	ErrInfinite = errors.New("infinite")
-)
-
-// Int converts the underlying integral number to an big.Int. It reports an
-// error if the underlying value is not an integer type. If a non-nil *Int
-// argument z is provided, Int stores the result in z instead of allocating a
-// new Int.
-func (v Value) Int(z *big.Int) (*big.Int, error) {
-	n, err := v.getNum(intKind)
-	if err != nil {
-		return nil, err
-	}
-	if z == nil {
-		z = &big.Int{}
-	}
-	if n.X.Exponent != 0 {
-		panic("cue: exponent should always be nil for integer types")
-	}
-	z.Set(&n.X.Coeff)
-	if n.X.Negative {
-		z.Neg(z)
-	}
-	return z, nil
-}
-
-// Int64 converts the underlying integral number to int64. It reports an
-// error if the underlying value is not an integer type or cannot be represented
-// as an int64. The result is (math.MinInt64, ErrAbove) for x < math.MinInt64,
-// and (math.MaxInt64, ErrBelow) for x > math.MaxInt64.
-func (v Value) Int64() (int64, error) {
-	n, err := v.getNum(intKind)
-	if err != nil {
-		return 0, err
-	}
-	if !n.X.Coeff.IsInt64() {
-		if n.X.Negative {
-			return math.MinInt64, ErrAbove
-		}
-		return math.MaxInt64, ErrBelow
-	}
-	i := n.X.Coeff.Int64()
-	if n.X.Negative {
-		i = -i
-	}
-	return i, nil
-}
-
-// Uint64 converts the underlying integral number to uint64. It reports an
-// error if the underlying value is not an integer type or cannot be represented
-// as a uint64. The result is (0, ErrAbove) for x < 0, and
-// (math.MaxUint64, ErrBelow) for x > math.MaxUint64.
-func (v Value) Uint64() (uint64, error) {
-	n, err := v.getNum(intKind)
-	if err != nil {
-		return 0, err
-	}
-	if n.X.Negative {
-		return 0, ErrAbove
-	}
-	if !n.X.Coeff.IsUint64() {
-		return math.MaxUint64, ErrBelow
-	}
-	i := n.X.Coeff.Uint64()
-	return i, nil
-}
-
-// trimZeros trims 0's for better JSON respresentations.
-func trimZeros(s string) string {
-	n1 := len(s)
-	s2 := strings.TrimRight(s, "0")
-	n2 := len(s2)
-	if p := strings.IndexByte(s2, '.'); p != -1 {
-		if p == n2-1 {
-			return s[:len(s2)+1]
-		}
-		return s2
-	}
-	if n1-n2 <= 4 {
-		return s
-	}
-	return fmt.Sprint(s2, "e+", n1-n2)
-}
-
-var (
-	smallestPosFloat64 *apd.Decimal
-	smallestNegFloat64 *apd.Decimal
-	maxPosFloat64      *apd.Decimal
-	maxNegFloat64      *apd.Decimal
-)
-
-func init() {
-	const (
-		// math.SmallestNonzeroFloat64: 1 / 2**(1023 - 1 + 52)
-		smallest = "4.940656458412465441765687928682213723651e-324"
-		// math.MaxFloat64: 2**1023 * (2**53 - 1) / 2**52
-		max = "1.797693134862315708145274237317043567981e+308"
-	)
-	ctx := apd.BaseContext
-	ctx.Precision = 40
-
-	var err error
-	smallestPosFloat64, _, err = ctx.NewFromString(smallest)
-	if err != nil {
-		panic(err)
-	}
-	smallestNegFloat64, _, err = ctx.NewFromString("-" + smallest)
-	if err != nil {
-		panic(err)
-	}
-	maxPosFloat64, _, err = ctx.NewFromString(max)
-	if err != nil {
-		panic(err)
-	}
-	maxNegFloat64, _, err = ctx.NewFromString("-" + max)
-	if err != nil {
-		panic(err)
-	}
-}
-
-// Float64 returns the float64 value nearest to x. It reports an error if v is
-// not a number. If x is too small to be represented by a float64 (|x| <
-// math.SmallestNonzeroFloat64), the result is (0, ErrBelow) or (-0, ErrAbove),
-// respectively, depending on the sign of x. If x is too large to be represented
-// by a float64 (|x| > math.MaxFloat64), the result is (+Inf, ErrAbove) or
-// (-Inf, ErrBelow), depending on the sign of x.
-func (v Value) Float64() (float64, error) {
-	n, err := v.getNum(numKind)
-	if err != nil {
-		return 0, err
-	}
-	if n.X.Negative {
-		if n.X.Cmp(smallestNegFloat64) == 1 {
-			return -0, ErrAbove
-		}
-		if n.X.Cmp(maxNegFloat64) == -1 {
-			return math.Inf(-1), ErrBelow
-		}
-	} else {
-		if n.X.Cmp(smallestPosFloat64) == -1 {
-			return 0, ErrBelow
-		}
-		if n.X.Cmp(maxPosFloat64) == 1 {
-			return math.Inf(1), ErrAbove
-		}
-	}
-	f, _ := n.X.Float64()
-	return f, nil
-}
-
-func (v Value) appendPath(a []string) []string {
-	for _, f := range v.v.Path() {
-		switch f.Typ() {
-		case adt.IntLabel:
-			a = append(a, strconv.FormatInt(int64(f.Index()), 10))
-
-		case adt.StringLabel:
-			label := v.idx.LabelStr(f)
-			if !f.IsDef() && !f.IsHidden() {
-				if !ast.IsValidIdent(label) {
-					label = strconv.Quote(label)
-				}
-			}
-			a = append(a, label)
-		default:
-			a = append(a, f.SelectorString(v.idx.Index))
-		}
-	}
-	return a
-}
-
-// Value holds any value, which may be a Boolean, Error, List, Null, Number,
-// Struct, or String.
-type Value struct {
-	idx *index
-	v   *adt.Vertex
-}
-
-func newErrValue(v Value, b *bottom) Value {
-	node := &adt.Vertex{Value: b}
-	if v.v != nil {
-		node.Label = v.v.Label
-		node.Parent = v.v.Parent
-	}
-	node.UpdateStatus(adt.Finalized)
-	node.AddConjunct(adt.MakeConjunct(nil, b))
-	return makeValue(v.idx, node)
-}
-
-func newVertexRoot(ctx *context, x *adt.Vertex) Value {
-	if ctx.opCtx != nil {
-		// This is indicative of an zero Value. In some cases this is called
-		// with an error value.
-		x.Finalize(ctx.opCtx)
-	} else {
-		x.UpdateStatus(adt.Finalized)
-	}
-	return makeValue(ctx.index, x)
-}
-
-func newValueRoot(ctx *context, x value) Value {
-	if n, ok := x.(*adt.Vertex); ok {
-		return newVertexRoot(ctx, n)
-	}
-	node := &adt.Vertex{}
-	node.AddConjunct(adt.MakeConjunct(nil, x))
-	return newVertexRoot(ctx, node)
-}
-
-func newChildValue(o *structValue, i int) Value {
-	arc, _ := o.at(i)
-	return makeValue(o.v.idx, arc)
-}
-
-// Dereference reports the value v refers to if v is a reference or v itself
-// otherwise.
-func Dereference(v Value) Value {
-	n := v.v
-	if n == nil || len(n.Conjuncts) != 1 {
-		return v
-	}
-
-	c := n.Conjuncts[0]
-	r, _ := c.Expr().(adt.Resolver)
-	if r == nil {
-		return v
-	}
-
-	ctx := v.ctx()
-	n, b := ctx.opCtx.Resolve(c.Env, r)
-	if b != nil {
-		return newErrValue(v, b)
-	}
-	return makeValue(v.idx, n)
-}
-
-func makeValue(idx *index, v *adt.Vertex) Value {
-	if v.Status() == 0 || v.Value == nil {
-		panic(fmt.Sprintf("not properly initialized (state: %v, value: %T)",
-			v.Status(), v.Value))
-	}
-	return Value{idx, v}
-}
-
-func remakeValue(base Value, env *adt.Environment, v value) Value {
-	// TODO: right now this is necessary because disjunctions do not have
-	// populated conjuncts.
-	if v, ok := v.(*adt.Vertex); ok && v.Status() >= adt.Partial {
-		return Value{base.idx, v}
-	}
-	n := &adt.Vertex{Parent: base.v.Parent, Label: base.v.Label}
-	n.AddConjunct(adt.MakeConjunct(env, v))
-	n = base.ctx().manifest(n)
-	return makeValue(base.idx, n)
-}
-
-func remakeFinal(base Value, env *adt.Environment, v adt.Value) Value {
-	n := &adt.Vertex{Parent: base.v.Parent, Label: base.v.Label, Value: v}
-	n.UpdateStatus(adt.Finalized)
-	return makeValue(base.idx, n)
-}
-
-func (v Value) ctx() *context {
-	return v.idx.newContext()
-}
-
-func (v Value) makeChild(ctx *context, i uint32, a arc) Value {
-	a.Parent = v.v
-	return makeValue(v.idx, a)
-}
-
-// Eval resolves the references of a value and returns the result.
-// This method is not necessary to obtain concrete values.
-func (v Value) Eval() Value {
-	if v.v == nil {
-		return v
-	}
-	x := v.v
-	// x = eval.FinalizeValue(v.idx.Runtime, v.v)
-	// x.Finalize(v.ctx().opCtx)
-	x = x.ToDataSingle()
-	return makeValue(v.idx, x)
-	// return remakeValue(v, nil, ctx.value(x))
-}
-
-// Default reports the default value and whether it existed. It returns the
-// normal value if there is no default.
-func (v Value) Default() (Value, bool) {
-	if v.v == nil {
-		return v, false
-	}
-
-	d := v.v.Default()
-	if d == v.v {
-		return v, false
-	}
-	return makeValue(v.idx, d), true
-
-	// d, ok := v.v.Value.(*adt.Disjunction)
-	// if !ok {
-	// 	return v, false
-	// }
-
-	// var w *adt.Vertex
-
-	// switch d.NumDefaults {
-	// case 0:
-	// 	return v, false
-
-	// case 1:
-	// 	w = d.Values[0]
-
-	// default:
-	// 	x := *v.v
-	// 	x.Value = &adt.Disjunction{
-	// 		Src:         d.Src,
-	// 		Values:      d.Values[:d.NumDefaults],
-	// 		NumDefaults: 0,
-	// 	}
-	// 	w = &x
-	// }
-
-	// w.Conjuncts = nil
-	// for _, c := range v.v.Conjuncts {
-	// 	// TODO: preserve field information.
-	// 	expr, _ := stripNonDefaults(c.Expr())
-	// 	w.AddConjunct(adt.MakeConjunct(c.Env, expr))
-	// }
-
-	// return makeValue(v.idx, w), true
-
-	// if !stripped {
-	// 	return v, false
-	// }
-
-	// n := *v.v
-	// n.Conjuncts = conjuncts
-	// return Value{v.idx, &n}, true
-
-	// isDefault := false
-	// for _, c := range v.v.Conjuncts {
-	// 	if hasDisjunction(c.Expr()) {
-	// 		isDefault = true
-	// 		break
-	// 	}
-	// }
-
-	// if !isDefault {
-	// 	return v, false
-	// }
-
-	// TODO: record expanded disjunctions in output.
-	// - Rename Disjunction to DisjunctionExpr
-	// - Introduce Disjuncts with Values.
-	// - In Expr introduce Star
-	// - Don't pick default by default?
-
-	// Evaluate the value.
-	// 	x := eval.FinalizeValue(v.idx.Runtime, v.v)
-	// 	if b, _ := x.Value.(*adt.Bottom); b != nil { // && b.IsIncomplete() {
-	// 		return v, false
-	// 	}
-	// 	// Finalize and return here.
-	// 	return Value{v.idx, x}, isDefault
-}
-
-// TODO: this should go: record preexpanded disjunctions in Vertex.
-func hasDisjunction(expr adt.Expr) bool {
-	switch x := expr.(type) {
-	case *adt.DisjunctionExpr:
-		return true
-	case *adt.Conjunction:
-		for _, v := range x.Values {
-			if hasDisjunction(v) {
-				return true
-			}
-		}
-	case *adt.BinaryExpr:
-		switch x.Op {
-		case adt.OrOp:
-			return true
-		case adt.AndOp:
-			return hasDisjunction(x.X) || hasDisjunction(x.Y)
-		}
-	}
-	return false
-}
-
-// TODO: this should go: record preexpanded disjunctions in Vertex.
-func stripNonDefaults(expr adt.Expr) (r adt.Expr, stripped bool) {
-	switch x := expr.(type) {
-	case *adt.DisjunctionExpr:
-		if !x.HasDefaults {
-			return x, false
-		}
-		d := *x
-		d.Values = []adt.Disjunct{}
-		for _, v := range x.Values {
-			if v.Default {
-				d.Values = append(d.Values, v)
-			}
-		}
-		if len(d.Values) == 1 {
-			return d.Values[0].Val, true
-		}
-		return &d, true
-
-	case *adt.BinaryExpr:
-		if x.Op != adt.AndOp {
-			return x, false
-		}
-		a, sa := stripNonDefaults(x.X)
-		b, sb := stripNonDefaults(x.Y)
-		if sa || sb {
-			bin := *x
-			bin.X = a
-			bin.Y = b
-			return &bin, true
-		}
-		return x, false
-
-	default:
-		return x, false
-	}
-}
-
-// Label reports he label used to obtain this value from the enclosing struct.
-//
-// TODO: get rid of this somehow. Probably by including a FieldInfo struct
-// or the like.
-func (v Value) Label() (string, bool) {
-	if v.v == nil || v.v.Label == 0 {
-		return "", false
-	}
-	return v.idx.LabelStr(v.v.Label), true
-}
-
-// Kind returns the kind of value. It returns BottomKind for atomic values that
-// are not concrete. For instance, it will return BottomKind for the bounds
-// >=0.
-func (v Value) Kind() Kind {
-	if v.v == nil {
-		return BottomKind
-	}
-	c := v.v.Value
-	if !adt.IsConcrete(c) {
-		return BottomKind
-	}
-	if v.IncompleteKind() == adt.ListKind && !v.IsClosed() {
-		return BottomKind
-	}
-	return c.Kind()
-}
-
-// IncompleteKind returns a mask of all kinds that this value may be.
-func (v Value) IncompleteKind() Kind {
-	if v.v == nil {
-		return BottomKind
-	}
-	return v.v.Kind()
-}
-
-// MarshalJSON marshalls this value into valid JSON.
-func (v Value) MarshalJSON() (b []byte, err error) {
-	b, err = v.marshalJSON()
-	if err != nil {
-		return nil, unwrapJSONError(err)
-	}
-	return b, nil
-}
-
-func (v Value) marshalJSON() (b []byte, err error) {
-	v, _ = v.Default()
-	if v.v == nil {
-		return json.Marshal(nil)
-	}
-	ctx := v.idx.newContext()
-	x := v.eval(ctx)
-
-	if _, ok := x.(adt.Resolver); ok {
-		return nil, marshalErrf(v, x, codeIncomplete, "value %q contains unresolved references", ctx.str(x))
-	}
-	if !adt.IsConcrete(x) {
-		return nil, marshalErrf(v, x, codeIncomplete, "cannot convert incomplete value %q to JSON", ctx.str(x))
-	}
-
-	// TODO: implement marshalles in value.
-	switch k := x.Kind(); k {
-	case nullKind:
-		return json.Marshal(nil)
-	case boolKind:
-		return json.Marshal(x.(*boolLit).B)
-	case intKind, floatKind, numKind:
-		b, err := x.(*numLit).X.MarshalText()
-		b = bytes.TrimLeft(b, "+")
-		return b, err
-	case stringKind:
-		return json.Marshal(x.(*stringLit).Str)
-	case bytesKind:
-		return json.Marshal(x.(*bytesLit).B)
-	case listKind:
-		i, _ := v.List()
-		return marshalList(&i)
-	case structKind:
-		obj, err := v.structValData(ctx)
-		if err != nil {
-			return nil, toMarshalErr(v, err)
-		}
-		return obj.marshalJSON()
-	case bottomKind:
-		return nil, toMarshalErr(v, x.(*bottom))
-	default:
-		return nil, marshalErrf(v, x, 0, "cannot convert value %q of type %T to JSON", ctx.str(x), x)
-	}
-}
-
-// Syntax converts the possibly partially evaluated value into syntax. This
-// can use used to print the value with package format.
-func (v Value) Syntax(opts ...Option) ast.Node {
-	// TODO: the default should ideally be simplified representation that
-	// exactly represents the value. The latter can currently only be
-	// ensured with Raw().
-	if v.v == nil {
-		return nil
-	}
-	var o options = getOptions(opts)
-	// var inst *Instance
-
-	p := export.Profile{
-		Simplify:        !o.raw,
-		ShowOptional:    !o.omitOptional && !o.concrete,
-		ShowDefinitions: !o.omitDefinitions && !o.concrete,
-		ShowHidden:      !o.omitHidden && !o.concrete,
-		ShowAttributes:  !o.omitAttrs,
-		ShowDocs:        o.docs,
-	}
-
-	// var expr ast.Expr
-	var err error
-	var f *ast.File
-	if o.concrete || o.final {
-		// inst = v.instance()
-		var expr ast.Expr
-		expr, err = p.Value(v.idx.Runtime, v.v)
-		if err != nil {
-			return nil
-		}
-
-		// This introduces gratuitous unshadowing!
-		f, err = astutil.ToFile(expr)
-		if err != nil {
-			return nil
-		}
-		// return expr
-	} else {
-		f, err = p.Def(v.idx.Runtime, v.v)
-		if err != nil {
-			panic(err)
-		}
-	}
-
-	if d := internal.Imports(f); len(d) == 0 {
-		if len(f.Decls) == 1 {
-			if e, ok := f.Decls[0].(*ast.EmbedDecl); ok {
-				return e.Expr
-			}
-		}
-		return &ast.StructLit{
-			Elts: f.Decls,
-		}
-	}
-
-	return f
-}
-
-// Decode initializes x with Value v. If x is a struct, it will validate the
-// constraints specified in the field tags.
-func (v Value) Decode(x interface{}) error {
-	// TODO: optimize
-	b, err := v.MarshalJSON()
-	if err != nil {
-		return err
-	}
-	return json.Unmarshal(b, x)
-}
-
-// // EncodeJSON generates JSON for the given value.
-// func (v Value) EncodeJSON(w io.Writer, v Value) error {
-// 	return nil
-// }
-
-// Doc returns all documentation comments associated with the field from which
-// the current value originates.
-func (v Value) Doc() []*ast.CommentGroup {
-	if v.v == nil {
-		return nil
-	}
-	return export.ExtractDoc(v.v)
-}
-
-// Split returns a list of values from which v originated such that
-// the unification of all these values equals v and for all returned values.
-// It will also split unchecked unifications (embeddings), so unifying the
-// split values may fail if actually unified.
-// Source returns a non-nil value.
-//
-// Deprecated: use Expr.
-func (v Value) Split() []Value {
-	if v.v == nil {
-		return nil
-	}
-	a := []Value{}
-	for _, x := range v.v.Conjuncts {
-		a = append(a, remakeValue(v, x.Env, x.Expr()))
-	}
-	return a
-}
-
-// Source returns the original node for this value. The return value may not
-// be a syntax.Expr. For instance, a struct kind may be represented by a
-// struct literal, a field comprehension, or a file. It returns nil for
-// computed nodes. Use Split to get all source values that apply to a field.
-func (v Value) Source() ast.Node {
-	if v.v == nil {
-		return nil
-	}
-	if len(v.v.Conjuncts) == 1 {
-		return v.v.Conjuncts[0].Source()
-	}
-	return v.v.Value.Source()
-}
-
-// Err returns the error represented by v or nil v is not an error.
-func (v Value) Err() error {
-	if err := v.checkKind(v.ctx(), bottomKind); err != nil {
-		return v.toErr(err)
-	}
-	return nil
-}
-
-// Pos returns position information.
-func (v Value) Pos() token.Pos {
-	if v.v == nil || v.Source() == nil {
-		return token.NoPos
-	}
-	pos := v.Source().Pos()
-	return pos
-}
-
-// TODO: IsFinal: this value can never be changed.
-
-// IsClosed reports whether a list of struct is closed. It reports false when
-// when the value is not a list or struct.
-func (v Value) IsClosed() bool {
-	if v.v == nil {
-		return false
-	}
-	return v.v.IsClosed(v.ctx().opCtx)
-}
-
-// IsConcrete reports whether the current value is a concrete scalar value
-// (not relying on default values), a terminal error, a list, or a struct.
-// It does not verify that values of lists or structs are concrete themselves.
-// To check whether there is a concrete default, use v.Default().IsConcrete().
-func (v Value) IsConcrete() bool {
-	if v.v == nil {
-		return false // any is neither concrete, not a list or struct.
-	}
-	if b, ok := v.v.Value.(*adt.Bottom); ok {
-		return !b.IsIncomplete()
-	}
-	if !adt.IsConcrete(v.v) {
-		return false
-	}
-	if v.IncompleteKind() == adt.ListKind && !v.IsClosed() {
-		return false
-	}
-	return true
-}
-
-// // Deprecated: IsIncomplete
-// //
-// // It indicates that the value cannot be fully evaluated due to
-// // insufficient information.
-// func (v Value) IsIncomplete() bool {
-// 	panic("deprecated")
-// }
-
-// Exists reports whether this value existed in the configuration.
-func (v Value) Exists() bool {
-	if v.v == nil {
-		return false
-	}
-	return exists(v.v.Value)
-}
-
-func (v Value) checkKind(ctx *context, want kind) *bottom {
-	if v.v == nil {
-		return errNotExists
-	}
-	// TODO: use checkKind
-	x := v.eval(ctx)
-	if b, ok := x.(*bottom); ok {
-		return b
-	}
-	k := x.Kind()
-	if want != bottomKind {
-		if k&want == bottomKind {
-			return ctx.mkErr(x, "cannot use value %v (type %s) as %s",
-				ctx.opCtx.Str(x), k, want)
-		}
-		if !adt.IsConcrete(x) {
-			return ctx.mkErr(x, codeIncomplete, "non-concrete value %v", k)
-		}
-	}
-	return nil
-}
-
-func makeInt(v Value, x int64) Value {
-	n := &adt.Num{K: intKind}
-	n.X.SetInt64(int64(x))
-	return remakeFinal(v, nil, n)
-}
-
-// Len returns the number of items of the underlying value.
-// For lists it reports the capacity of the list. For structs it indicates the
-// number of fields, for bytes the number of bytes.
-func (v Value) Len() Value {
-	if v.v != nil {
-		switch x := v.eval(v.ctx()).(type) {
-		case *adt.Vertex:
-			if x.IsList() {
-				ctx := v.ctx()
-				n := &adt.Num{K: intKind}
-				n.X.SetInt64(int64(len(x.Elems())))
-				if x.IsClosed(ctx.opCtx) {
-					return remakeFinal(v, nil, n)
-				}
-				// Note: this HAS to be a Conjunction value and cannot be
-				// an adt.BinaryExpr, as the expressions would be considered
-				// to be self-contained and unresolvable when evaluated
-				// (can never become concrete).
-				c := &adt.Conjunction{Values: []adt.Value{
-					&adt.BasicType{K: adt.IntKind},
-					&adt.BoundValue{Op: adt.GreaterEqualOp, Value: n},
-				}}
-				return remakeFinal(v, nil, c)
-
-			}
-		case *bytesLit:
-			return makeInt(v, int64(len(x.B)))
-		case *stringLit:
-			return makeInt(v, int64(len([]rune(x.Str))))
-		}
-	}
-	const msg = "len not supported for type %v"
-	return remakeValue(v, nil, v.ctx().mkErr(v.v, msg, v.Kind()))
-
-}
-
-// Elem returns the value of undefined element types of lists and structs.
-func (v Value) Elem() (Value, bool) {
-	if v.v == nil {
-		return Value{}, false
-	}
-	ctx := v.ctx().opCtx
-	x := &adt.Vertex{
-		Parent: v.v,
-		Label:  0,
-	}
-	v.v.Finalize(ctx)
-	v.v.MatchAndInsert(ctx, x)
-	if len(x.Conjuncts) == 0 {
-		return Value{}, false
-	}
-	x.Finalize(ctx)
-	return makeValue(v.idx, x), true
-}
-
-// // BulkOptionals returns all bulk optional fields as key-value pairs.
-// // See also Elem and Template.
-// func (v Value) BulkOptionals() [][2]Value {
-// 	x, ok := v.path.cache.(*structLit)
-// 	if !ok {
-// 		return nil
-// 	}
-// 	return v.appendBulk(nil, x.optionals)
-// }
-
-// func (v Value) appendBulk(a [][2]Value, x *optionals) [][2]Value {
-// 	if x == nil {
-// 		return a
-// 	}
-// 	a = v.appendBulk(a, x.left)
-// 	a = v.appendBulk(a, x.right)
-// 	for _, set := range x.fields {
-// 		if set.key != nil {
-// 			ctx := v.ctx()
-// 			fn, ok := ctx.manifest(set.value).(*lambdaExpr)
-// 			if !ok {
-// 				// create error
-// 				continue
-// 			}
-// 			x := fn.call(ctx, set.value, &basicType{K: stringKind})
-
-// 			a = append(a, [2]Value{v.makeElem(set.key), v.makeElem(x)})
-// 		}
-// 	}
-// 	return a
-// }
-
-// List creates an iterator over the values of a list or reports an error if
-// v is not a list.
-func (v Value) List() (Iterator, error) {
-	v, _ = v.Default()
-	ctx := v.ctx()
-	if err := v.checkKind(ctx, listKind); err != nil {
-		return Iterator{ctx: ctx}, v.toErr(err)
-	}
-	arcs := []field{}
-	for _, a := range v.v.Elems() {
-		if a.Label.IsInt() {
-			arcs = append(arcs, field{arc: a})
-		}
-	}
-	return Iterator{ctx: ctx, val: v, arcs: arcs}, nil
-}
-
-// Null reports an error if v is not null.
-func (v Value) Null() error {
-	v, _ = v.Default()
-	if err := v.checkKind(v.ctx(), nullKind); err != nil {
-		return v.toErr(err)
-	}
-	return nil
-}
-
-// // IsNull reports whether v is null.
-// func (v Value) IsNull() bool {
-// 	return v.Null() == nil
-// }
-
-// Bool returns the bool value of v or false and an error if v is not a boolean.
-func (v Value) Bool() (bool, error) {
-	v, _ = v.Default()
-	ctx := v.ctx()
-	if err := v.checkKind(ctx, boolKind); err != nil {
-		return false, v.toErr(err)
-	}
-	return v.eval(ctx).(*boolLit).B, nil
-}
-
-// String returns the string value if v is a string or an error otherwise.
-func (v Value) String() (string, error) {
-	v, _ = v.Default()
-	ctx := v.ctx()
-	if err := v.checkKind(ctx, stringKind); err != nil {
-		return "", v.toErr(err)
-	}
-	return v.eval(ctx).(*stringLit).Str, nil
-}
-
-// Bytes returns a byte slice if v represents a list of bytes or an error
-// otherwise.
-func (v Value) Bytes() ([]byte, error) {
-	v, _ = v.Default()
-	ctx := v.ctx()
-	switch x := v.eval(ctx).(type) {
-	case *bytesLit:
-		return append([]byte(nil), x.B...), nil
-	case *stringLit:
-		return []byte(x.Str), nil
-	}
-	return nil, v.toErr(v.checkKind(ctx, bytesKind|stringKind))
-}
-
-// Reader returns a new Reader if v is a string or bytes type and an error
-// otherwise.
-func (v Value) Reader() (io.Reader, error) {
-	v, _ = v.Default()
-	ctx := v.ctx()
-	switch x := v.eval(ctx).(type) {
-	case *bytesLit:
-		return bytes.NewReader(x.B), nil
-	case *stringLit:
-		return strings.NewReader(x.Str), nil
-	}
-	return nil, v.toErr(v.checkKind(ctx, stringKind|bytesKind))
-}
-
-// TODO: distinguish between optional, hidden, etc. Probably the best approach
-// is to mark options in context and have a single function for creating
-// a structVal.
-
-// structVal returns an structVal or an error if v is not a struct.
-func (v Value) structValData(ctx *context) (structValue, *bottom) {
-	return v.structValOpts(ctx, options{
-		omitHidden:      true,
-		omitDefinitions: true,
-		omitOptional:    true,
-	})
-}
-
-func (v Value) structValFull(ctx *context) (structValue, *bottom) {
-	return v.structValOpts(ctx, options{})
-}
-
-// structVal returns an structVal or an error if v is not a struct.
-func (v Value) structValOpts(ctx *context, o options) (structValue, *bottom) {
-	v, _ = v.Default()
-
-	obj, err := v.getStruct()
-	if err != nil {
-		return structValue{}, err
-	}
-
-	features := export.VertexFeatures(obj)
-
-	k := 0
-	for _, f := range features {
-		if f.IsDef() && (o.omitDefinitions || o.concrete) {
-			continue
-		}
-		if f.IsHidden() && o.omitHidden {
-			continue
-		}
-		if arc := obj.Lookup(f); arc == nil {
-			if o.omitOptional {
-				continue
-			}
-			// ensure it really exists.
-			v := adt.Vertex{
-				Parent: obj,
-				Label:  f,
-			}
-			obj.MatchAndInsert(ctx.opCtx, &v)
-			if len(v.Conjuncts) == 0 {
-				continue
-			}
-		}
-		features[k] = f
-		k++
-	}
-	features = features[:k]
-	return structValue{ctx, v, obj, features}, nil
-}
-
-// Struct returns the underlying struct of a value or an error if the value
-// is not a struct.
-func (v Value) Struct() (*Struct, error) {
-	ctx := v.ctx()
-	obj, err := v.structValOpts(ctx, options{})
-	if err != nil {
-		return nil, v.toErr(err)
-	}
-	return &Struct{obj}, nil
-}
-
-func (v Value) getStruct() (*structLit, *bottom) {
-	ctx := v.ctx()
-	if err := v.checkKind(ctx, structKind); err != nil {
-		if !err.ChildError {
-			return nil, err
-		}
-	}
-	return v.v, nil
-}
-
-// Struct represents a CUE struct value.
-type Struct struct {
-	structValue
-}
-
-// FieldInfo contains information about a struct field.
-type FieldInfo struct {
-	Selector string
-	Name     string // Deprecated: use Selector
-	Pos      int
-	Value    Value
-
-	IsDefinition bool
-	IsOptional   bool
-	IsHidden     bool
-}
-
-func (s *Struct) Len() int {
-	return s.structValue.Len()
-}
-
-// field reports information about the ith field, i < o.Len().
-func (s *Struct) Field(i int) FieldInfo {
-	a, opt := s.at(i)
-	ctx := s.v.ctx()
-
-	v := makeValue(s.v.idx, a)
-	name := ctx.LabelStr(a.Label)
-	str := a.Label.SelectorString(ctx.opCtx)
-	return FieldInfo{str, name, i, v, a.Label.IsDef(), opt, a.Label.IsHidden()}
-}
-
-// FieldByName looks up a field for the given name. If isIdent is true, it will
-// look up a definition or hidden field (starting with `_` or `_#`). Otherwise
-// it interprets name as an arbitrary string for a regular field.
-func (s *Struct) FieldByName(name string, isIdent bool) (FieldInfo, error) {
-	f := s.v.ctx().Label(name, isIdent)
-	for i, a := range s.features {
-		if a == f {
-			return s.Field(i), nil
-		}
-	}
-	return FieldInfo{}, errNotFound
-}
-
-// Fields creates an iterator over the Struct's fields.
-func (s *Struct) Fields(opts ...Option) *Iterator {
-	iter, _ := s.v.Fields(opts...)
-	return iter
-}
-
-// Fields creates an iterator over v's fields if v is a struct or an error
-// otherwise.
-func (v Value) Fields(opts ...Option) (*Iterator, error) {
-	o := options{omitDefinitions: true, omitHidden: true, omitOptional: true}
-	o.updateOptions(opts)
-	ctx := v.ctx()
-	obj, err := v.structValOpts(ctx, o)
-	if err != nil {
-		return &Iterator{ctx: ctx}, v.toErr(err)
-	}
-
-	arcs := []field{}
-	for i := range obj.features {
-		arc, isOpt := obj.at(i)
-		arcs = append(arcs, field{arc: arc, isOptional: isOpt})
-	}
-	return &Iterator{ctx: ctx, val: v, arcs: arcs}, nil
-}
-
-// Lookup reports the value at a path starting from v. The empty path returns v
-// itself. Use LookupDef for definitions or LookupField for any kind of field.
-//
-// The Exists() method can be used to verify if the returned value existed.
-// Lookup cannot be used to look up hidden or optional fields or definitions.
-func (v Value) Lookup(path ...string) Value {
-	ctx := v.ctx()
-	for _, k := range path {
-		// TODO(eval) TODO(error): always search in full data and change error
-		// message if a field is found but is of the incorrect type.
-		obj, err := v.structValData(ctx)
-		if err != nil {
-			// TODO: return a Value at the same location and a new error?
-			return newErrValue(v, err)
-		}
-		v = obj.Lookup(k)
-	}
-	return v
-}
-
-// LookupDef reports the definition with the given name within struct v. The
-// Exists method of the returned value will report false if the definition did
-// not exist. The Err method reports if any error occurred during evaluation.
-func (v Value) LookupDef(name string) Value {
-	ctx := v.ctx()
-	o, err := v.structValFull(ctx)
-	if err != nil {
-		return newErrValue(v, err)
-	}
-
-	f := v.ctx().Label(name, true)
-	for i, a := range o.features {
-		if a == f {
-			if f.IsHidden() || !f.IsDef() { // optional not possible for now
-				break
-			}
-			return newChildValue(&o, i)
-		}
-	}
-	if !strings.HasPrefix(name, "#") {
-		alt := v.LookupDef("#" + name)
-		// Use the original error message if this resulted in an error as well.
-		if alt.Err() == nil {
-			return alt
-		}
-	}
-	return newErrValue(v, ctx.mkErr(v.v, "definition %q not found", name))
-}
-
-var errNotFound = errors.Newf(token.NoPos, "field not found")
-
-// FieldByName looks up a field for the given name. If isIdent is true, it will
-// look up a definition or hidden field (starting with `_` or `_#`). Otherwise
-// it interprets name as an arbitrary string for a regular field.
-func (v Value) FieldByName(name string, isIdent bool) (f FieldInfo, err error) {
-	s, err := v.Struct()
-	if err != nil {
-		return f, err
-	}
-	return s.FieldByName(name, isIdent)
-}
-
-// LookupField reports information about a field of v.
-//
-// Deprecated: this API does not work with new-style definitions. Use FieldByName.
-func (v Value) LookupField(name string) (FieldInfo, error) {
-	s, err := v.Struct()
-	if err != nil {
-		// TODO: return a Value at the same location and a new error?
-		return FieldInfo{}, err
-	}
-	f, err := s.FieldByName(name, true)
-	if err != nil {
-		return f, err
-	}
-	if f.IsHidden {
-		return f, errNotFound
-	}
-	return f, err
-}
-
-// TODO: expose this API?
-//
-// // EvalExpr evaluates an expression within the scope of v, which must be
-// // a struct.
-// //
-// // Expressions may refer to builtin packages if they can be uniquely identified.
-// func (v Value) EvalExpr(expr ast.Expr) Value {
-// 	ctx := v.ctx()
-// 	result := evalExpr(ctx, v.eval(ctx), expr)
-// 	return newValueRoot(ctx, result)
-// }
-
-// Fill creates a new value by unifying v with the value of x at the given path.
-//
-// Values may be any Go value that can be converted to CUE, an ast.Expr or
-// a Value. In the latter case, it will panic if the Value is not from the same
-// Runtime.
-//
-// Any reference in v referring to the value at the given path will resolve
-// to x in the newly created value. The resulting value is not validated.
-func (v Value) Fill(x interface{}, path ...string) Value {
-	if v.v == nil {
-		return v
-	}
-	ctx := v.ctx()
-	for i := len(path) - 1; i >= 0; i-- {
-		x = map[string]interface{}{path[i]: x}
-	}
-	var value = convert.GoValueToExpr(ctx.opCtx, true, x)
-	n := &adt.Vertex{Parent: v.v.Parent}
-	n.AddConjunct(adt.MakeConjunct(nil, value))
-	n.Finalize(ctx.opCtx)
-	w := makeValue(v.idx, n)
-	return v.Unify(w)
-}
-
-// Template returns a function that represents the template definition for a
-// struct in a configuration file. It returns nil if v is not a struct kind or
-// if there is no template associated with the struct.
-//
-// The returned function returns the value that would be unified with field
-// given its name.
-func (v Value) Template() func(label string) Value {
-	// TODO: rename to optional.
-	if v.v == nil {
-		return nil
-	}
-
-	types := v.v.OptionalTypes()
-	if types&(adt.HasAdditional|adt.HasPattern) == 0 {
-		return nil
-	}
-
-	parent := v.v
-	ctx := v.ctx().opCtx
-	return func(label string) Value {
-		f := ctx.StringLabel(label)
-		arc := &adt.Vertex{Parent: parent, Label: f}
-		v.v.MatchAndInsert(ctx, arc)
-		if len(arc.Conjuncts) == 0 {
-			return Value{}
-		}
-		arc.Finalize(ctx)
-		return makeValue(v.idx, arc)
-	}
-}
-
-// Subsume reports nil when w is an instance of v or an error otherwise.
-//
-// Without options, the entire value is considered for assumption, which means
-// Subsume tests whether  v is a backwards compatible (newer) API version of w.
-// Use the Final() to indicate that the subsumed value is data, and that
-//
-// Use the Final option to check subsumption if a w is known to be final,
-// and should assumed to be closed.
-//
-// Options are currently ignored and the function will panic if any are passed.
-//
-// Value v and w must be obtained from the same build.
-// TODO: remove this requirement.
-func (v Value) Subsume(w Value, opts ...Option) error {
-	o := getOptions(opts)
-	p := subsume.CUE
-	switch {
-	case o.final && o.ignoreClosedness:
-		p = subsume.FinalOpen
-	case o.final:
-		p = subsume.Final
-	case o.ignoreClosedness:
-		p = subsume.API
-	}
-	p.Defaults = true
-	ctx := v.ctx().opCtx
-	return p.Value(ctx, v.v, w.v)
-}
-
-// Deprecated: use Subsume.
-//
-// Subsumes reports whether w is an instance of v.
-//
-// Without options, Subsumes checks whether v is a backwards compatbile schema
-// of w.
-//
-// By default, Subsumes tests whether two values are compatible
-// Value v and w must be obtained from the same build.
-// TODO: remove this requirement.
-func (v Value) Subsumes(w Value) bool {
-	p := subsume.Profile{Defaults: true}
-	return p.Check(v.ctx().opCtx, v.v, w.v)
-}
-
-// Unify reports the greatest lower bound of v and w.
-//
-// Value v and w must be obtained from the same build.
-// TODO: remove this requirement.
-func (v Value) Unify(w Value) Value {
-	// ctx := v.ctx()
-	if v.v == nil {
-		return w
-	}
-	if w.v == nil {
-		return v
-	}
-	n := &adt.Vertex{Parent: v.v.Parent, Label: v.v.Label}
-	n.AddConjunct(adt.MakeConjunct(nil, v.v))
-	n.AddConjunct(adt.MakeConjunct(nil, w.v))
-
-	ctx := v.idx.newContext()
-	n.Finalize(ctx.opCtx)
-	return makeValue(v.idx, n)
-}
-
-// UnifyAccept is as v.Unify(w), but will disregard any field that is allowed
-// in the Value accept.
-func (v Value) UnifyAccept(w Value, accept Value) Value {
-	if v.v == nil {
-		return w
-	}
-	if w.v == nil {
-		return v
-	}
-	if accept.v == nil {
-		panic("accept must exist")
-	}
-
-	n := &adt.Vertex{Parent: v.v.Parent, Label: v.v.Label}
-	n.AddConjunct(adt.MakeConjunct(nil, v.v))
-	n.AddConjunct(adt.MakeConjunct(nil, w.v))
-
-	e := eval.New(v.idx.Runtime)
-	ctx := e.NewContext(n)
-	e.UnifyAccept(ctx, n, adt.Finalized, accept.v.Closed)
-
-	// ctx := v.idx.newContext()
-	n.Closed = accept.v.Closed
-	n.Finalize(ctx)
-	return makeValue(v.idx, n)
-}
-
-// Equals reports whether two values are equal, ignoring optional fields.
-// The result is undefined for incomplete values.
-func (v Value) Equals(other Value) bool {
-	if v.v == nil || other.v == nil {
-		return false
-	}
-	return eval.Equal(v.ctx().opCtx, v.v, other.v)
-
-}
-
-// Format prints a debug version of a value.
-func (v Value) Format(state fmt.State, verb rune) {
-	ctx := v.ctx()
-	if v.v == nil {
-		fmt.Fprint(state, "<nil>")
-		return
-	}
-	switch {
-	case state.Flag('#'):
-		_, _ = io.WriteString(state, ctx.str(v.v))
-	case state.Flag('+'):
-		_, _ = io.WriteString(state, debugStr(ctx, v.v))
-	default:
-		n, _ := export.Raw.Expr(v.idx.Runtime, v.v)
-		b, _ := format.Node(n)
-		_, _ = state.Write(b)
-	}
-}
-
-func (v Value) instance() *Instance {
-	if v.v == nil {
-		return nil
-	}
-	return v.ctx().getImportFromNode(v.v)
-}
-
-// Reference returns the instance and path referred to by this value such that
-// inst.Lookup(path) resolves to the same value, or no path if this value is not
-// a reference. If a reference contains index selection (foo[bar]), it will
-// only return a reference if the index resolves to a concrete value.
-func (v Value) Reference() (inst *Instance, path []string) {
-	// TODO: don't include references to hidden fields.
-	if v.v == nil || len(v.v.Conjuncts) != 1 {
-		return nil, nil
-	}
-	ctx := v.ctx()
-	c := v.v.Conjuncts[0]
-
-	return reference(ctx, c.Env, c.Expr())
-}
-
-func reference(c *context, env *adt.Environment, r adt.Expr) (inst *Instance, path []string) {
-	ctx := c.opCtx
-	defer ctx.PopState(ctx.PushState(env, r.Source()))
-
-	switch x := r.(type) {
-	case *adt.FieldReference:
-		env := ctx.Env(x.UpCount)
-		inst, path = mkPath(c, nil, env.Vertex)
-		path = append(path, x.Label.SelectorString(c.Index))
-
-	case *adt.LabelReference:
-		env := ctx.Env(x.UpCount)
-		return mkPath(c, nil, env.Vertex)
-
-	case *adt.DynamicReference:
-		env := ctx.Env(x.UpCount)
-		inst, path = mkPath(c, nil, env.Vertex)
-		v, _ := ctx.Evaluate(env, x.Label)
-		str := ctx.StringValue(v)
-		path = append(path, str)
-
-	case *adt.ImportReference:
-		imp := x.ImportPath.StringValue(ctx)
-		inst = c.index.getImportFromPath(imp)
-
-	case *adt.SelectorExpr:
-		inst, path = reference(c, env, x.X)
-		path = append(path, x.Sel.SelectorString(ctx))
-
-	case *adt.IndexExpr:
-		inst, path = reference(c, env, x.X)
-		v, _ := ctx.Evaluate(env, x.Index)
-		str := ctx.StringValue(v)
-		path = append(path, str)
-	}
-	if inst == nil {
-		return nil, nil
-	}
-	return inst, path
-}
-
-func mkPath(ctx *context, a []string, v *adt.Vertex) (inst *Instance, path []string) {
-	if v.Parent == nil {
-		return ctx.index.getImportFromNode(v), a
-	}
-	inst, path = mkPath(ctx, a, v.Parent)
-	path = append(path, v.Label.SelectorString(ctx.opCtx))
-	return inst, path
-}
-
-// // References reports all references used to evaluate this value. It does not
-// // report references for sub fields if v is a struct.
-// //
-// // Deprecated: can be implemented in terms of Reference and Expr.
-// func (v Value) References() [][]string {
-// 	panic("deprecated")
-// }
-
-type options struct {
-	concrete          bool // enforce that values are concrete
-	raw               bool // show original values
-	hasHidden         bool
-	omitHidden        bool
-	omitDefinitions   bool
-	omitOptional      bool
-	omitAttrs         bool
-	resolveReferences bool
-	final             bool
-	ignoreClosedness  bool // used for comparing APIs
-	docs              bool
-	disallowCycles    bool // implied by concrete
-}
-
-// An Option defines modes of evaluation.
-type Option option
-
-type option func(p *options)
-
-// Final indicates a value is final. It implicitly closes all structs and lists
-// in a value and selects defaults.
-func Final() Option {
-	return func(o *options) {
-		o.final = true
-		o.omitDefinitions = true
-		o.omitOptional = true
-		o.omitHidden = true
-	}
-}
-
-// Schema specifies the input is a Schema. Used by Subsume.
-func Schema() Option {
-	return func(o *options) {
-		o.ignoreClosedness = true
-	}
-}
-
-// Concrete ensures that all values are concrete.
-//
-// For Validate this means it returns an error if this is not the case.
-// In other cases a non-concrete value will be replaced with an error.
-func Concrete(concrete bool) Option {
-	return func(p *options) {
-		if concrete {
-			p.concrete = true
-			p.final = true
-			if !p.hasHidden {
-				p.omitHidden = true
-				p.omitDefinitions = true
-			}
-		}
-	}
-}
-
-// DisallowCycles forces validation in the precense of cycles, even if
-// non-concrete values are allowed. This is implied by Concrete(true).
-func DisallowCycles(disallow bool) Option {
-	return func(p *options) { p.disallowCycles = disallow }
-}
-
-// ResolveReferences forces the evaluation of references when outputting.
-// This implies the input cannot have cycles.
-func ResolveReferences(resolve bool) Option {
-	return func(p *options) { p.resolveReferences = resolve }
-}
-
-// Raw tells Syntax to generate the value as is without any simplifications.
-func Raw() Option {
-	return func(p *options) { p.raw = true }
-}
-
-// All indicates that all fields and values should be included in processing
-// even if they can be elided or omitted.
-func All() Option {
-	return func(p *options) {
-		p.omitAttrs = false
-		p.omitHidden = false
-		p.omitDefinitions = false
-		p.omitOptional = false
-	}
-}
-
-// Docs indicates whether docs should be included.
-func Docs(include bool) Option {
-	return func(p *options) { p.docs = true }
-}
-
-// Definitions indicates whether definitions should be included.
-//
-// Definitions may still be included for certain functions if they are referred
-// to by other other values.
-func Definitions(include bool) Option {
-	return func(p *options) {
-		p.hasHidden = true
-		p.omitDefinitions = !include
-	}
-}
-
-// Hidden indicates that definitions and hidden fields should be included.
-//
-// Deprecated: Hidden fields are deprecated.
-func Hidden(include bool) Option {
-	return func(p *options) {
-		p.hasHidden = true
-		p.omitHidden = !include
-		p.omitDefinitions = !include
-	}
-}
-
-// Optional indicates that optional fields should be included.
-func Optional(include bool) Option {
-	return func(p *options) { p.omitOptional = !include }
-}
-
-// Attributes indicates that attributes should be included.
-func Attributes(include bool) Option {
-	return func(p *options) { p.omitAttrs = !include }
-}
-
-func getOptions(opts []Option) (o options) {
-	o.updateOptions(opts)
-	return
-}
-
-func (o *options) updateOptions(opts []Option) {
-	for _, fn := range opts {
-		fn(o)
-	}
-}
-
-// Validate reports any errors, recursively. The returned error may represent
-// more than one error, retrievable with errors.Errors, if more than one
-// exists.
-func (v Value) Validate(opts ...Option) error {
-	o := options{}
-	o.updateOptions(opts)
-
-	cfg := &validate.Config{
-		Concrete:       o.concrete,
-		DisallowCycles: o.disallowCycles,
-		AllErrors:      true,
-	}
-
-	b := validate.Validate(v.ctx().opCtx, v.v, cfg)
-	if b != nil {
-		return b.Err
-	}
-	return nil
-}
-
-// Walk descends into all values of v, calling f. If f returns false, Walk
-// will not descent further. It only visits values that are part of the data
-// model, so this excludes optional fields, hidden fields, and definitions.
-func (v Value) Walk(before func(Value) bool, after func(Value)) {
-	ctx := v.ctx()
-	switch v.Kind() {
-	case StructKind:
-		if before != nil && !before(v) {
-			return
-		}
-		obj, _ := v.structValData(ctx)
-		for i := 0; i < obj.Len(); i++ {
-			_, v := obj.At(i)
-			v.Walk(before, after)
-		}
-	case ListKind:
-		if before != nil && !before(v) {
-			return
-		}
-		list, _ := v.List()
-		for list.Next() {
-			list.Value().Walk(before, after)
-		}
-	default:
-		if before != nil {
-			before(v)
-		}
-	}
-	if after != nil {
-		after(v)
-	}
-}
-
-// Attribute returns the attribute data for the given key.
-// The returned attribute will return an error for any of its methods if there
-// is no attribute for the requested key.
-func (v Value) Attribute(key string) Attribute {
-	// look up the attributes
-	if v.v == nil {
-		return Attribute{internal.NewNonExisting(key)}
-	}
-	// look up the attributes
-	for _, a := range export.ExtractFieldAttrs(v.v.Conjuncts) {
-		k, body := a.Split()
-		if key != k {
-			continue
-		}
-		return Attribute{internal.ParseAttrBody(token.NoPos, body)}
-	}
-
-	return Attribute{internal.NewNonExisting(key)}
-}
-
-// An Attribute contains meta data about a field.
-type Attribute struct {
-	attr internal.Attr
-}
-
-// Err returns the error associated with this Attribute or nil if this
-// attribute is valid.
-func (a *Attribute) Err() error {
-	return a.attr.Err
-}
-
-// String reports the possibly empty string value at the given position or
-// an error the attribute is invalid or if the position does not exist.
-func (a *Attribute) String(pos int) (string, error) {
-	return a.attr.String(pos)
-}
-
-// Int reports the integer at the given position or an error if the attribute is
-// invalid, the position does not exist, or the value at the given position is
-// not an integer.
-func (a *Attribute) Int(pos int) (int64, error) {
-	return a.attr.Int(pos)
-}
-
-// Flag reports whether an entry with the given name exists at position pos or
-// onwards or an error if the attribute is invalid or if the first pos-1 entries
-// are not defined.
-func (a *Attribute) Flag(pos int, key string) (bool, error) {
-	return a.attr.Flag(pos, key)
-}
-
-// Lookup searches for an entry of the form key=value from position pos onwards
-// and reports the value if found. It reports an error if the attribute is
-// invalid or if the first pos-1 entries are not defined.
-func (a *Attribute) Lookup(pos int, key string) (val string, found bool, err error) {
-	return a.attr.Lookup(pos, key)
-}
-
-// Expr reports the operation of the underlying expression and the values it
-// operates on.
-//
-// For unary expressions, it returns the single value of the expression.
-//
-// For binary expressions it returns first the left and right value, in that
-// order. For associative operations however, (for instance '&' and '|'), it may
-// return more than two values, where the operation is to be applied in
-// sequence.
-//
-// For selector and index expressions it returns the subject and then the index.
-// For selectors, the index is the string value of the identifier.
-//
-// For interpolations it returns a sequence of values to be concatenated, some
-// of which will be literal strings and some unevaluated expressions.
-//
-// A builtin call expression returns the value of the builtin followed by the
-// args of the call.
-func (v Value) Expr() (Op, []Value) {
-	// TODO: return v if this is complete? Yes for now
-	if v.v == nil {
-		return NoOp, nil
-	}
-
-	var expr adt.Expr
-	var env *adt.Environment
-
-	if v.v.IsData() {
-		switch x := v.v.Value.(type) {
-		case *adt.ListMarker, *adt.StructMarker:
-			expr = v.v
-		default:
-			expr = x
-		}
-
-	} else {
-		switch len(v.v.Conjuncts) {
-		case 0:
-			if v.v.Value == nil {
-				return NoOp, []Value{makeValue(v.idx, v.v)}
-			}
-			switch x := v.v.Value.(type) {
-			case *adt.ListMarker, *adt.StructMarker:
-				expr = v.v
-			default:
-				expr = x
-			}
-
-		case 1:
-			// the default case, processed below.
-			c := v.v.Conjuncts[0]
-			env = c.Env
-			expr = c.Expr()
-			if w, ok := expr.(*adt.Vertex); ok {
-				return Value{v.idx, w}.Expr()
-			}
-
-		default:
-			a := []Value{}
-			ctx := v.ctx().opCtx
-			for _, c := range v.v.Conjuncts {
-				n := &adt.Vertex{
-					Parent: v.v.Parent,
-					Label:  v.v.Label,
-				}
-				n.AddConjunct(c)
-				n.Finalize(ctx)
-				a = append(a, makeValue(v.idx, n))
-			}
-			return adt.AndOp, a
-		}
-	}
-
-	// TODO: replace appends with []Value{}. For not leave.
-	a := []Value{}
-	op := NoOp
-	switch x := expr.(type) {
-	case *binaryExpr:
-		a = append(a, remakeValue(v, env, x.X))
-		a = append(a, remakeValue(v, env, x.Y))
-		op = x.Op
-	case *unaryExpr:
-		a = append(a, remakeValue(v, env, x.X))
-		op = x.Op
-	case *boundExpr:
-		a = append(a, remakeValue(v, env, x.Expr))
-		op = x.Op
-	case *boundValue:
-		a = append(a, remakeValue(v, env, x.Value))
-		op = x.Op
-	case *adt.Conjunction:
-		// pre-expanded unification
-		for _, conjunct := range x.Values {
-			a = append(a, remakeValue(v, env, conjunct))
-		}
-		op = AndOp
-	case *adt.Disjunction:
-		count := 0
-	outer:
-		for i, disjunct := range x.Values {
-			if i < x.NumDefaults {
-				for _, n := range x.Values[x.NumDefaults:] {
-					if subsume.Value(v.ctx().opCtx, n, disjunct) == nil {
-						continue outer
-					}
-				}
-			}
-			count++
-			a = append(a, remakeValue(v, env, disjunct))
-		}
-		if count > 1 {
-			op = OrOp
-		}
-
-	case *adt.DisjunctionExpr:
-		// Filter defaults that are subsumed by another value.
-		count := 0
-	outerExpr:
-		for _, disjunct := range x.Values {
-			if disjunct.Default {
-				for _, n := range x.Values {
-					a := adt.Vertex{
-						Parent: v.v.Parent,
-						Label:  v.v.Label,
-						Closed: v.v.Closed,
-					}
-					b := a
-					a.AddConjunct(adt.MakeConjunct(env, n.Val))
-					b.AddConjunct(adt.MakeConjunct(env, disjunct.Val))
-
-					e := eval.New(v.idx.Runtime)
-					ctx := e.NewContext(nil)
-					e.UnifyAccept(ctx, &a, adt.Finalized, v.v.Closed)
-					e.UnifyAccept(ctx, &b, adt.Finalized, v.v.Closed)
-					if !n.Default && subsume.Value(ctx, &a, &b) == nil {
-						continue outerExpr
-					}
-				}
-			}
-			count++
-			a = append(a, remakeValue(v, env, disjunct.Val))
-		}
-		if count > 1 {
-			op = adt.OrOp
-		}
-
-	case *interpolation:
-		for _, p := range x.Parts {
-			a = append(a, remakeValue(v, env, p))
-		}
-		op = InterpolationOp
-
-	case *adt.FieldReference:
-		// TODO: allow hard link
-		ctx := v.ctx().opCtx
-		f := ctx.PushState(env, x.Src)
-		env := ctx.Env(x.UpCount)
-		a = append(a, remakeValue(v, nil, &adt.NodeLink{Node: env.Vertex}))
-		a = append(a, remakeValue(v, nil, ctx.NewString(x.Label.SelectorString(ctx))))
-		_ = ctx.PopState(f)
-		op = SelectorOp
-
-	case *selectorExpr:
-		a = append(a, remakeValue(v, env, x.X))
-		// A string selector is quoted.
-		a = append(a, remakeValue(v, env, &adt.String{
-			Str: x.Sel.SelectorString(v.idx.Index),
-		}))
-		op = SelectorOp
-
-	case *indexExpr:
-		a = append(a, remakeValue(v, env, x.X))
-		a = append(a, remakeValue(v, env, x.Index))
-		op = IndexOp
-	case *sliceExpr:
-		a = append(a, remakeValue(v, env, x.X))
-		a = append(a, remakeValue(v, env, x.Lo))
-		a = append(a, remakeValue(v, env, x.Hi))
-		op = SliceOp
-	case *callExpr:
-		a = append(a, remakeValue(v, env, x.Fun))
-		for _, arg := range x.Args {
-			a = append(a, remakeValue(v, env, arg))
-		}
-		op = CallOp
-	case *customValidator:
-		a = append(a, remakeValue(v, env, x.Builtin))
-		for _, arg := range x.Args {
-			a = append(a, remakeValue(v, env, arg))
-		}
-		op = CallOp
-
-	case *adt.StructLit:
-		// Simulate old embeddings.
-		envEmbed := &adt.Environment{
-			Up:     env,
-			Vertex: v.v,
-		}
-		fields := []adt.Decl{}
-		ctx := v.ctx().opCtx
-		for _, d := range x.Decls {
-			switch x := d.(type) {
-			case adt.Expr:
-				// embedding
-				n := &adt.Vertex{
-					Parent: v.v.Parent,
-					Label:  v.v.Label}
-				c := adt.MakeConjunct(envEmbed, x)
-				n.AddConjunct(c)
-				n.Finalize(ctx)
-				a = append(a, makeValue(v.idx, n))
-
-			default:
-				fields = append(fields, d)
-			}
-		}
-		if len(a) == 0 {
-			a = append(a, v)
-			break
-		}
-
-		if len(fields) > 0 {
-			n := &adt.Vertex{
-				Parent: v.v.Parent,
-				Label:  v.v.Label,
-			}
-			c := adt.MakeConjunct(env, &adt.StructLit{
-				Decls: fields,
-			})
-			n.AddConjunct(c)
-			n.Finalize(ctx)
-			a = append(a, makeValue(v.idx, n))
-		}
-
-		op = adt.AndOp
-
-	default:
-		a = append(a, v)
-	}
-	return op, a
-}
diff --git a/internal/legacy/cue/types_test.go b/internal/legacy/cue/types_test.go
deleted file mode 100644
index b36c6c5..0000000
--- a/internal/legacy/cue/types_test.go
+++ /dev/null
@@ -1,2958 +0,0 @@
-// Copyright 2018 The 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 (
-	"bytes"
-	"fmt"
-	"io/ioutil"
-	"math"
-	"math/big"
-	"reflect"
-	"strconv"
-	"strings"
-	"testing"
-
-	"github.com/google/go-cmp/cmp"
-
-	"cuelang.org/go/cue/ast"
-	"cuelang.org/go/cue/errors"
-	"cuelang.org/go/internal"
-	"cuelang.org/go/internal/core/adt"
-	"cuelang.org/go/internal/core/debug"
-)
-
-func getInstance(t *testing.T, body ...string) *Instance {
-	t.Helper()
-
-	insts := Build(makeInstances([]*bimport{{files: body}}))
-	if insts[0].Err != nil {
-		t.Fatalf("unexpected parse error: %v", insts[0].Err)
-	}
-	return insts[0]
-}
-
-func TestValueType(t *testing.T) {
-	testCases := []struct {
-		value          string
-		kind           Kind
-		incompleteKind Kind
-		json           string
-		valid          bool
-		concrete       bool
-		closed         bool
-		// pos            token.Pos
-	}{{ // Not a concrete value.
-		value:          `v: _`,
-		kind:           BottomKind,
-		incompleteKind: TopKind,
-	}, {
-		value:          `v: _|_`,
-		kind:           BottomKind,
-		incompleteKind: BottomKind,
-		concrete:       true,
-	}, {
-		value:          `v: 1&2`,
-		kind:           BottomKind,
-		incompleteKind: BottomKind,
-		concrete:       true,
-	}, {
-		value:          `v: b, b: 1&2`,
-		kind:           BottomKind,
-		incompleteKind: BottomKind,
-		concrete:       true,
-	}, {
-		value:          `v: (b[a]), b: 1, a: 1`,
-		kind:           BottomKind,
-		incompleteKind: BottomKind,
-		concrete:       true,
-	}, { // TODO: should be error{
-		value: `v: (b)
-			b: bool`,
-		kind:           BottomKind,
-		incompleteKind: BoolKind,
-	}, {
-		value:          `v: ([][b]), b: "d"`,
-		kind:           BottomKind,
-		incompleteKind: BottomKind,
-		concrete:       true,
-	}, {
-		value:          `v: null`,
-		kind:           NullKind,
-		incompleteKind: NullKind,
-		concrete:       true,
-	}, {
-		value:          `v: true`,
-		kind:           BoolKind,
-		incompleteKind: BoolKind,
-		concrete:       true,
-	}, {
-		value:          `v: false`,
-		kind:           BoolKind,
-		incompleteKind: BoolKind,
-		concrete:       true,
-	}, {
-		value:          `v: bool`,
-		kind:           BottomKind,
-		incompleteKind: BoolKind,
-	}, {
-		value:          `v: 2`,
-		kind:           IntKind,
-		incompleteKind: IntKind,
-		concrete:       true,
-	}, {
-		value:          `v: 2.0`,
-		kind:           FloatKind,
-		incompleteKind: FloatKind,
-		concrete:       true,
-	}, {
-		value:          `v: 2.0Mi`,
-		kind:           IntKind,
-		incompleteKind: IntKind,
-		concrete:       true,
-	}, {
-		value:          `v: 14_000`,
-		kind:           IntKind,
-		incompleteKind: IntKind,
-		concrete:       true,
-	}, {
-		value:          `v: >=0 & <5`,
-		kind:           BottomKind,
-		incompleteKind: NumberKind,
-	}, {
-		value:          `v: float`,
-		kind:           BottomKind,
-		incompleteKind: FloatKind,
-	}, {
-		value:          `v: "str"`,
-		kind:           StringKind,
-		incompleteKind: StringKind,
-		concrete:       true,
-	}, {
-		value:          "v: '''\n'''",
-		kind:           BytesKind,
-		incompleteKind: BytesKind,
-		concrete:       true,
-	}, {
-		value:          "v: string",
-		kind:           BottomKind,
-		incompleteKind: StringKind,
-	}, {
-		value:          `v: {}`,
-		kind:           StructKind,
-		incompleteKind: StructKind,
-		concrete:       true,
-	}, {
-		value:          `v: close({})`,
-		kind:           StructKind,
-		incompleteKind: StructKind,
-		concrete:       true,
-		closed:         true,
-	}, {
-		value:          `v: []`,
-		kind:           ListKind,
-		incompleteKind: ListKind,
-		concrete:       true,
-		closed:         true,
-	}, {
-		value:          `v: [...int]`,
-		kind:           BottomKind,
-		incompleteKind: ListKind,
-		concrete:       false,
-	}, {
-		value:    `v: {a: int, b: [1][a]}.b`,
-		kind:     BottomKind,
-		concrete: false,
-	}, {
-		value: `import "time"
-		v: time.Time`,
-		kind:           BottomKind,
-		incompleteKind: StringKind,
-		concrete:       false,
-	}, {
-		value: `import "time"
-		v: {a: time.Time}.a`,
-		kind:           BottomKind,
-		incompleteKind: StringKind,
-		concrete:       false,
-	}, {
-		value: `import "time"
-			v: {a: time.Time & string}.a`,
-		kind:           BottomKind,
-		incompleteKind: StringKind,
-		concrete:       false,
-	}, {
-		value: `import "strings"
-			v: {a: strings.ContainsAny("D")}.a`,
-		kind:           BottomKind,
-		incompleteKind: StringKind,
-		concrete:       false,
-	}, {
-		value: `import "struct"
-		v: {a: struct.MaxFields(2) & {}}.a`,
-		kind:           StructKind, // Can determine a valid struct already.
-		incompleteKind: StructKind,
-		concrete:       true,
-	}}
-	for _, tc := range testCases {
-		t.Run(tc.value, func(t *testing.T) {
-			inst := getInstance(t, tc.value)
-			v := inst.Lookup("v")
-			if got := v.Kind(); got != tc.kind {
-				t.Errorf("Kind: got %x; want %x", int(got), int(tc.kind))
-			}
-			want := tc.incompleteKind | BottomKind
-			if got := v.IncompleteKind(); got != want {
-				t.Errorf("IncompleteKind: got %x; want %x", int(got), int(want))
-			}
-			if got := v.IsConcrete(); got != tc.concrete {
-				t.Errorf("IsConcrete: got %v; want %v", got, tc.concrete)
-			}
-			if got := v.IsClosed(); got != tc.closed {
-				t.Errorf("IsClosed: got %v; want %v", got, tc.closed)
-			}
-		})
-	}
-}
-
-func TestInt(t *testing.T) {
-	testCases := []struct {
-		value  string
-		int    int64
-		uint   uint64
-		base   int
-		err    string
-		errU   string
-		notInt bool
-	}{{
-		value: "1",
-		int:   1,
-		uint:  1,
-	}, {
-		value: "-1",
-		int:   -1,
-		uint:  0,
-		errU:  ErrAbove.Error(),
-	}, {
-		value: "-111222333444555666777888999000",
-		int:   math.MinInt64,
-		uint:  0,
-		err:   ErrAbove.Error(),
-		errU:  ErrAbove.Error(),
-	}, {
-		value: "111222333444555666777888999000",
-		int:   math.MaxInt64,
-		uint:  math.MaxUint64,
-		err:   ErrBelow.Error(),
-		errU:  ErrBelow.Error(),
-	}, {
-		value:  "1.0",
-		err:    "cannot use value 1.0 (type float) as int",
-		errU:   "cannot use value 1.0 (type float) as int",
-		notInt: true,
-	}, {
-		value:  "int",
-		err:    "non-concrete value int",
-		errU:   "non-concrete value int",
-		notInt: true,
-	}, {
-		value:  "_|_",
-		err:    "from source",
-		errU:   "from source",
-		notInt: true,
-	}}
-	for _, tc := range testCases {
-		t.Run(tc.value, func(t *testing.T) {
-			n := getInstance(t, tc.value).Value()
-			base := 10
-			if tc.base > 0 {
-				base = tc.base
-			}
-			b, err := n.AppendInt(nil, base)
-			if checkFailed(t, err, tc.err, "append") {
-				want := tc.value
-				if got := string(b); got != want {
-					t.Errorf("append: got %v; want %v", got, want)
-				}
-			}
-
-			vi, err := n.Int64()
-			checkErr(t, err, tc.err, "Int64")
-			if vi != tc.int {
-				t.Errorf("Int64: got %v; want %v", vi, tc.int)
-			}
-
-			vu, err := n.Uint64()
-			checkErr(t, err, tc.errU, "Uint64")
-			if vu != uint64(tc.uint) {
-				t.Errorf("Uint64: got %v; want %v", vu, tc.uint)
-			}
-		})
-	}
-}
-
-func TestFloat(t *testing.T) {
-	testCases := []struct {
-		value   string
-		float   string
-		float64 float64
-		mant    string
-		exp     int
-		fmt     byte
-		prec    int
-		kind    Kind
-		err     string
-	}{{
-		value:   "1",
-		float:   "1",
-		mant:    "1",
-		exp:     0,
-		float64: 1,
-		fmt:     'g',
-		kind:    IntKind,
-	}, {
-		value:   "-1",
-		float:   "-1",
-		mant:    "-1",
-		exp:     0,
-		float64: -1,
-		fmt:     'g',
-		kind:    IntKind,
-	}, {
-		value:   "1.0",
-		float:   "1.0",
-		mant:    "10",
-		exp:     -1,
-		float64: 1.0,
-		fmt:     'g',
-		kind:    FloatKind,
-	}, {
-		value:   "2.6",
-		float:   "2.6",
-		mant:    "26",
-		exp:     -1,
-		float64: 2.6,
-		fmt:     'g',
-		kind:    FloatKind,
-	}, {
-		value:   "20.600",
-		float:   "20.60",
-		mant:    "20600",
-		exp:     -3,
-		float64: 20.60,
-		prec:    2,
-		fmt:     'f',
-		kind:    FloatKind,
-	}, {
-		value:   "1/0",
-		float:   "",
-		float64: 0,
-		prec:    2,
-		fmt:     'f',
-		err:     "division by zero",
-		kind:    BottomKind,
-	}, {
-		value:   "1.797693134862315708145274237317043567982e+308",
-		float:   "1.8e+308",
-		mant:    "1797693134862315708145274237317043567982",
-		exp:     269,
-		float64: math.Inf(1),
-		prec:    2,
-		fmt:     'g',
-		err:     ErrAbove.Error(),
-		kind:    FloatKind,
-	}, {
-		value:   "-1.797693134862315708145274237317043567982e+308",
-		float:   "-1.8e+308",
-		mant:    "-1797693134862315708145274237317043567982",
-		exp:     269,
-		float64: math.Inf(-1),
-		prec:    2,
-		fmt:     'g',
-		kind:    FloatKind,
-		err:     ErrBelow.Error(),
-	}, {
-		value:   "4.940656458412465441765687928682213723650e-324",
-		float:   "4.941e-324",
-		mant:    "4940656458412465441765687928682213723650",
-		exp:     -363,
-		float64: 0,
-		prec:    4,
-		fmt:     'g',
-		kind:    FloatKind,
-		err:     ErrBelow.Error(),
-	}, {
-		value:   "-4.940656458412465441765687928682213723650e-324",
-		float:   "-4.940656458412465441765687928682213723650e-324",
-		mant:    "-4940656458412465441765687928682213723650",
-		exp:     -363,
-		float64: 0,
-		prec:    -1,
-		fmt:     'g',
-		kind:    FloatKind,
-		err:     ErrAbove.Error(),
-	}}
-	for _, tc := range testCases {
-		t.Run(tc.value, func(t *testing.T) {
-			n := getInstance(t, tc.value).Value()
-			if n.Kind() != tc.kind {
-				t.Fatal("Not a number")
-			}
-
-			var mant big.Int
-			exp, err := n.MantExp(&mant)
-			mstr := ""
-			if err == nil {
-				mstr = mant.String()
-			}
-			if exp != tc.exp || mstr != tc.mant {
-				t.Errorf("mantExp: got %s %d; want %s %d", mstr, exp, tc.mant, tc.exp)
-			}
-
-			b, _ := n.AppendFloat(nil, tc.fmt, tc.prec)
-			want := tc.float
-			if got := string(b); got != want {
-				t.Errorf("append: got %v; want %v", got, want)
-			}
-
-			f, err := n.Float64()
-			checkErr(t, err, tc.err, "Float64")
-			if f != tc.float64 {
-				t.Errorf("Float64: got %v; want %v", f, tc.float64)
-			}
-		})
-	}
-}
-
-func TestString(t *testing.T) {
-	testCases := []struct {
-		value string
-		str   string
-		err   string
-	}{{
-		value: `""`,
-		str:   ``,
-	}, {
-		value: `"Hello world!"`,
-		str:   `Hello world!`,
-	}, {
-		value: `"Hello \(#world)!"
-		#world: "world"`,
-		str: `Hello world!`,
-	}, {
-		value: `string`,
-		err:   "non-concrete value string",
-	}}
-	for _, tc := range testCases {
-		t.Run(tc.value, func(t *testing.T) {
-			str, err := getInstance(t, tc.value).Value().String()
-			checkFatal(t, err, tc.err, "init")
-			if str != tc.str {
-				t.Errorf("String: got %q; want %q", str, tc.str)
-			}
-
-			b, err := getInstance(t, tc.value).Value().Bytes()
-			checkFatal(t, err, tc.err, "init")
-			if got := string(b); got != tc.str {
-				t.Errorf("Bytes: got %q; want %q", got, tc.str)
-			}
-
-			r, err := getInstance(t, tc.value).Value().Reader()
-			checkFatal(t, err, tc.err, "init")
-			b, _ = ioutil.ReadAll(r)
-			if got := string(b); got != tc.str {
-				t.Errorf("Reader: got %q; want %q", got, tc.str)
-			}
-		})
-	}
-}
-
-func TestError(t *testing.T) {
-	testCases := []struct {
-		value string
-		err   string
-	}{{
-		value: `_|_`,
-		err:   "from source",
-	}, {
-		value: `"Hello world!"`,
-	}, {
-		value: `string`,
-		err:   "",
-	}}
-	for _, tc := range testCases {
-		t.Run(tc.value, func(t *testing.T) {
-			err := getInstance(t, tc.value).Value().Err()
-			checkErr(t, err, tc.err, "init")
-		})
-	}
-}
-
-func TestNull(t *testing.T) {
-	testCases := []struct {
-		value string
-		err   string
-	}{{
-		value: `v: _|_`,
-		err:   "from source",
-	}, {
-		value: `v: "str"`,
-		err:   "cannot use value \"str\" (type string) as null",
-	}, {
-		value: `v: null`,
-	}, {
-		value: `v: _`,
-		err:   "non-concrete value _",
-	}}
-	for _, tc := range testCases {
-		t.Run(tc.value, func(t *testing.T) {
-			err := getInstance(t, tc.value).Lookup("v").Null()
-			checkErr(t, err, tc.err, "init")
-		})
-	}
-}
-
-func TestBool(t *testing.T) {
-	testCases := []struct {
-		value string
-		bool  bool
-		err   string
-	}{{
-		value: `_|_`,
-		err:   "from source",
-	}, {
-		value: `"str"`,
-		err:   "cannot use value \"str\" (type string) as bool",
-	}, {
-		value: `true`,
-		bool:  true,
-	}, {
-		value: `false`,
-	}, {
-		value: `bool`,
-		err:   "non-concrete value bool",
-	}}
-	for _, tc := range testCases {
-		t.Run(tc.value, func(t *testing.T) {
-			got, err := getInstance(t, tc.value).Value().Bool()
-			if checkErr(t, err, tc.err, "init") {
-				if got != tc.bool {
-					t.Errorf("got %v; want %v", got, tc.bool)
-				}
-			}
-		})
-	}
-}
-
-func TestList(t *testing.T) {
-	testCases := []struct {
-		value string
-		res   string
-		err   string
-	}{{
-		value: `_|_`,
-		err:   "from source",
-	}, {
-		value: `"str"`,
-		err:   "cannot use value \"str\" (type string) as list",
-	}, {
-		value: `[]`,
-		res:   "[]",
-	}, {
-		value: `[1,2,3]`,
-		res:   "[1,2,3,]",
-	}, {
-		value: `>=5*[1,2,3, ...int]`,
-		err:   "non-concrete value >=5 in operand to *",
-	}, {
-		value: `[for x in #y if x > 1 { x }]
-		#y: [1,2,3]`,
-		res: "[2,3,]",
-	}, {
-		value: `[int]`,
-		err:   "cannot convert incomplete value",
-	}}
-	for _, tc := range testCases {
-		t.Run(tc.value, func(t *testing.T) {
-			l, err := getInstance(t, tc.value).Value().List()
-			checkFatal(t, err, tc.err, "init")
-
-			buf := []byte{'['}
-			for l.Next() {
-				b, err := l.Value().MarshalJSON()
-				checkFatal(t, err, tc.err, "list.Value")
-				buf = append(buf, b...)
-				buf = append(buf, ',')
-			}
-			buf = append(buf, ']')
-			if got := string(buf); got != tc.res {
-				t.Errorf("got %v; want %v", got, tc.res)
-			}
-		})
-	}
-}
-
-func TestFields(t *testing.T) {
-	testCases := []struct {
-		value string
-		res   string
-		err   string
-	}{{
-		value: `{ #def: 1, _hidden: 2, opt?: 3, reg: 4 }`,
-		res:   "{reg:4,}",
-	}, {
-		value: `_|_`,
-		err:   "from source",
-	}, {
-		value: `"str"`,
-		err:   "cannot use value \"str\" (type string) as struct",
-	}, {
-		value: `{}`,
-		res:   "{}",
-	}, {
-		value: `{a:1,b:2,c:3}`,
-		res:   "{a:1,b:2,c:3,}",
-	}, {
-		value: `{a:1,"_b":2,c:3,_d:4}`,
-		res:   "{a:1,_b:2,c:3,}",
-	}, {
-		value: `{_a:"a"}`,
-		res:   "{}",
-	}, {
-		value: `{ for k, v in #y if v > 1 {"\(k)": v} }
-		#y: {a:1,b:2,c:3}`,
-		res: "{b:2,c:3,}",
-	}, {
-		value: `{ #def: 1, _hidden: 2, opt?: 3, reg: 4 }`,
-		res:   "{reg:4,}",
-	}, {
-		value: `{a:1,b:2,c:int}`,
-		err:   "cannot convert incomplete value",
-	}}
-	for _, tc := range testCases {
-		t.Run(tc.value, func(t *testing.T) {
-			obj := getInstance(t, tc.value).Value()
-
-			iter, err := obj.Fields()
-			checkFatal(t, err, tc.err, "init")
-
-			buf := []byte{'{'}
-			for iter.Next() {
-				buf = append(buf, iter.Label()...)
-				buf = append(buf, ':')
-				b, err := iter.Value().MarshalJSON()
-				checkFatal(t, err, tc.err, "Obj.At")
-				buf = append(buf, b...)
-				buf = append(buf, ',')
-			}
-			buf = append(buf, '}')
-			if got := string(buf); got != tc.res {
-				t.Errorf("got %v; want %v", got, tc.res)
-			}
-
-			iter, _ = obj.Fields()
-			for iter.Next() {
-				want, err := iter.Value().MarshalJSON()
-				checkFatal(t, err, tc.err, "Obj.At2")
-
-				got, err := obj.Lookup(iter.Label()).MarshalJSON()
-				checkFatal(t, err, tc.err, "Obj.At2")
-
-				if !bytes.Equal(got, want) {
-					t.Errorf("Lookup: got %q; want %q", got, want)
-				}
-			}
-			v := obj.Lookup("non-existing")
-			checkErr(t, v.Err(), "not found", "non-existing")
-		})
-	}
-}
-
-func TestAllFields(t *testing.T) {
-	testCases := []struct {
-		value string
-		res   string
-		err   string
-	}{{
-		value: `{a:1,"_b":2,c:3,_d:4}`,
-		res:   "{a:1,_b:2,c:3,_d:4,}",
-	}, {
-		value: `{_a:"a"}`,
-		res:   `{_a:"a",}`,
-	}, {
-		value: `{_a:"a", b?: "b", #c: 3}`,
-		res:   `{_a:"a",b?:"b",#c:3,}`,
-	}}
-	for _, tc := range testCases {
-		t.Run(tc.value, func(t *testing.T) {
-			obj := getInstance(t, tc.value).Value()
-
-			var iter *Iterator // Verify that the returned iterator is a pointer.
-			iter, err := obj.Fields(All())
-			checkFatal(t, err, tc.err, "init")
-
-			buf := []byte{'{'}
-			for iter.Next() {
-				buf = append(buf, iter.Label()...)
-				if iter.IsOptional() {
-					buf = append(buf, '?')
-				}
-				buf = append(buf, ':')
-				b, err := iter.Value().MarshalJSON()
-				checkFatal(t, err, tc.err, "Obj.At")
-				buf = append(buf, b...)
-				buf = append(buf, ',')
-			}
-			buf = append(buf, '}')
-			if got := string(buf); got != tc.res {
-				t.Errorf("got %v; want %v", got, tc.res)
-			}
-		})
-	}
-}
-
-func TestLookup(t *testing.T) {
-	var runtime = new(Runtime)
-	inst, err := runtime.Compile("x.cue", `
-#V: {
-	x: int
-}
-#X: {
-	[string]: int64
-} & #V
-v: #X
-`)
-	if err != nil {
-		t.Fatalf("compile: %v", err)
-	}
-	// expr, err := parser.ParseExpr("lookup.cue", `v`, parser.DeclarationErrors, parser.AllErrors)
-	// if err != nil {
-	// 	log.Fatalf("parseExpr: %v", err)
-	// }
-	// v := inst.Eval(expr)
-	testCases := []struct {
-		ref  []string
-		raw  string
-		eval string
-	}{{
-		ref:  []string{"v", "x"},
-		raw:  ">=-9223372036854775808 & <=9223372036854775807 & int",
-		eval: "int64",
-	}}
-	for _, tc := range testCases {
-		v := inst.Lookup(tc.ref...)
-
-		if got := fmt.Sprint(v); got != tc.raw {
-			t.Errorf("got %v; want %v", got, tc.raw)
-		}
-
-		got := fmt.Sprint(internal.DebugStr(v.Eval().Syntax()))
-		if got != tc.eval {
-			t.Errorf("got %v; want %v", got, tc.eval)
-		}
-
-		v = inst.Lookup()
-		for _, ref := range tc.ref {
-			s, err := v.Struct()
-			if err != nil {
-				t.Fatal(err)
-			}
-			fi, err := s.FieldByName(ref, false)
-			if err != nil {
-				t.Fatal(err)
-			}
-			v = fi.Value
-		}
-
-		if got := fmt.Sprint(v); got != tc.raw {
-			t.Errorf("got %v; want %v", got, tc.raw)
-		}
-
-		got = fmt.Sprint(internal.DebugStr(v.Eval().Syntax()))
-		if got != tc.eval {
-			t.Errorf("got %v; want %v", got, tc.eval)
-		}
-	}
-}
-
-func compileT(t *testing.T, r *Runtime, s string) *Instance {
-	t.Helper()
-	inst, err := r.Compile("", s)
-	if err != nil {
-		t.Fatal(err)
-	}
-	return inst
-}
-
-func goValue(v Value) interface{} {
-	var x interface{}
-	err := v.Decode(&x)
-	if err != nil {
-		return err
-	}
-	return x
-}
-
-// TODO: Exporting of Vertex as Conjunct
-func TestFill(t *testing.T) {
-	r := &Runtime{}
-
-	inst, err := r.CompileExpr(ast.NewStruct("bar", ast.NewString("baz")))
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	testCases := []struct {
-		in   string
-		x    interface{}
-		path string // comma-separated path
-		out  string
-	}{{
-		in: `
-		foo: int
-		bar: foo
-		`,
-		x:    3,
-		path: "foo",
-		out: `
-		foo: 3
-		bar: 3
-		`,
-	}, {
-		in: `
-		string
-		`,
-		x:    "foo",
-		path: "",
-		out: `
-		"foo"
-		`,
-	}, {
-		in: `
-		foo: _
-		`,
-		x:    inst.Value(),
-		path: "foo",
-		out: `
-		{foo: {bar: "baz"}}
-		`,
-	}}
-
-	for _, tc := range testCases {
-		var path []string
-		if tc.path != "" {
-			path = strings.Split(tc.path, ",")
-		}
-
-		v := compileT(t, r, tc.in).Value()
-		v = v.Fill(tc.x, path...)
-
-		w := compileT(t, r, tc.out).Value()
-
-		if !cmp.Equal(goValue(v), goValue(w)) {
-			t.Error(cmp.Diff(goValue(v), goValue(w)))
-			t.Errorf("\ngot:  %s\nwant: %s", v, w)
-		}
-	}
-}
-
-func TestFill2(t *testing.T) {
-	r := &Runtime{}
-
-	root, err := r.Compile("test", `
-	#Provider: {
-		ID: string
-		notConcrete: bool
-		a: int
-		b: int
-	}
-	`)
-
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	spec := root.LookupDef("#Provider")
-	providerInstance := spec.Fill("12345", "ID")
-	root, err = root.Fill(providerInstance, "providers", "myprovider")
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	got := fmt.Sprint(root.Value())
-	want := `{
-	#Provider: {
-		ID:          string
-		notConcrete: bool
-		a:           int
-		b:           int
-	}
-	providers: {
-		myprovider: {
-			ID:          "12345"
-			notConcrete: bool
-			a:           int
-			b:           int
-		}
-	}
-}`
-	if got != want {
-		t.Errorf("got:  %s\nwant: %s", got, want)
-	}
-}
-
-func TestValue_LookupDef(t *testing.T) {
-	r := &Runtime{}
-
-	testCases := []struct {
-		in     string
-		def    string // comma-separated path
-		exists bool
-		out    string
-	}{{
-		in:  `#foo: 3`,
-		def: "#foo",
-		out: `3`,
-	}, {
-		in:  `_foo: 3`,
-		def: "_foo",
-		out: `_|_ // definition "_foo" not found`,
-	}, {
-		in:  `_#foo: 3`,
-		def: "_#foo",
-		out: `_|_ // definition "_#foo" not found`,
-	}}
-
-	for _, tc := range testCases {
-		t.Run(tc.def, func(t *testing.T) {
-			v := compileT(t, r, tc.in).Value()
-			v = v.LookupDef(tc.def)
-			got := fmt.Sprint(v)
-
-			if got != tc.out {
-				t.Errorf("\ngot:  %s\nwant: %s", got, tc.out)
-			}
-		})
-	}
-}
-
-// TODO: trim down to individual defaults?
-func TestDefaults(t *testing.T) {
-	testCases := []struct {
-		value string
-		def   string
-		val   string
-		ok    bool
-	}{{
-		value: `number | *1`,
-		def:   "1",
-		val:   "number",
-		ok:    true,
-	}, {
-		value: `1 | 2 | *3`,
-		def:   "3",
-		val:   "1|2|3",
-		ok:    true,
-	}, {
-		value: `*{a:1,b:2}|{a:1}|{b:2}`,
-		def:   "{a:1,b:2}",
-		val:   "{a: 1}|{b: 2}",
-		ok:    true,
-	}, {
-		value: `{a:1}&{b:2}`,
-		def:   `({a:1} & {b:2})`,
-		val:   ``,
-		ok:    false,
-	}}
-	for _, tc := range testCases {
-		t.Run(tc.value, func(t *testing.T) {
-			v := getInstance(t, "a: "+tc.value).Lookup("a")
-
-			d, ok := v.Default()
-			if ok != tc.ok {
-				t.Errorf("hasDefault: got %v; want %v", ok, tc.ok)
-			}
-
-			if got := compactRawStr(d); got != tc.def {
-				t.Errorf("default: got %v; want %v", got, tc.def)
-			}
-
-			op, val := d.Expr()
-			if op != OrOp {
-				return
-			}
-			vars := []string{}
-			for _, v := range val {
-				vars = append(vars, fmt.Sprint(v))
-			}
-			if got := strings.Join(vars, "|"); got != tc.val {
-				t.Errorf("value: got %v; want %v", got, tc.val)
-			}
-		})
-	}
-}
-
-func TestLen(t *testing.T) {
-	testCases := []struct {
-		input  string
-		length string
-	}{{
-		input:  "[1, 3]",
-		length: "2",
-	}, {
-		input:  "[1, 3, ...]",
-		length: "int & >=2",
-	}, {
-		input:  `"foo"`,
-		length: "3",
-	}, {
-		input:  `'foo'`,
-		length: "3",
-		// TODO: Currently not supported.
-		// }, {
-		// 	input:  "{a:1, b:3, a:1, c?: 3, _hidden: 4}",
-		// 	length: "2",
-	}, {
-		input:  "3",
-		length: "_|_ // len not supported for type int",
-	}}
-	for _, tc := range testCases {
-		t.Run(tc.input, func(t *testing.T) {
-			v := getInstance(t, "a: "+tc.input).Lookup("a")
-
-			length := v.Len()
-			if got := fmt.Sprint(length); got != tc.length {
-				t.Errorf("length: got %v; want %v", got, tc.length)
-			}
-		})
-	}
-}
-
-func TestTemplate(t *testing.T) {
-	testCases := []struct {
-		value string
-		path  []string
-		want  string
-	}{{
-		value: `
-		a: [Name=string]: Name
-		`,
-		path: []string{"a", ""},
-		want: `"label"`,
-	}, {
-		value: `
-		[Name=string]: { a: Name }
-		`,
-		path: []string{"", "a"},
-		want: `"label"`,
-	}, {
-		value: `
-		[Name=string]: { a: Name }
-		`,
-		path: []string{""},
-		want: `{"a":"label"}`,
-	}, {
-		value: `
-		a: [Foo=string]: [Bar=string]: { b: Foo+Bar }
-		`,
-		path: []string{"a", "", ""},
-		want: `{"b":"labellabel"}`,
-	}, {
-		value: `
-		a: [Foo=string]: b: [Bar=string]: { c: Foo+Bar }
-		a: foo: b: [Bar=string]: { d: Bar }
-		`,
-		path: []string{"a", "foo", "b", ""},
-		want: `{"d":"label","c":"foolabel"}`,
-	}}
-	for _, tc := range testCases {
-		t.Run("", func(t *testing.T) {
-			v := getInstance(t, tc.value).Value()
-			for _, p := range tc.path {
-				if p == "" {
-					v = v.Template()("label")
-				} else {
-					v = v.Lookup(p)
-				}
-			}
-			b, err := v.MarshalJSON()
-			if err != nil {
-				t.Fatal(err)
-			}
-			if got := string(b); got != tc.want {
-				t.Errorf("\n got: %q\nwant: %q", got, tc.want)
-			}
-		})
-	}
-}
-
-func TestElem(t *testing.T) {
-	testCases := []struct {
-		value string
-		path  []string
-		want  string
-	}{{
-		value: `
-		a: [...int]
-		`,
-		path: []string{"a", ""},
-		want: `int`,
-	}, {
-		value: `
-		[Name=string]: { a: Name }
-		`,
-		path: []string{"", "a"},
-		want: `string`,
-	}, {
-		value: `
-		[Name=string]: { a: Name }
-		`,
-		path: []string{""},
-		want: "{\n\ta: string\n}",
-	}, {
-		value: `
-		a: [Foo=string]: [Bar=string]: { b: Foo+Bar }
-		`,
-		path: []string{"a", "", ""},
-		want: "{\n\tb: string + string\n}",
-	}, {
-		value: `
-		a: [Foo=string]: b: [Bar=string]: { c: Foo+Bar }
-		a: foo: b: [Bar=string]: { d: Bar }
-		`,
-		path: []string{"a", "foo", "b", ""},
-		want: "{\n\td: string\n\tc: string + string\n}",
-	}}
-	for _, tc := range testCases {
-		t.Run("", func(t *testing.T) {
-			v := getInstance(t, tc.value).Value()
-			v.v.Finalize(v.ctx().opCtx) // TODO: do in instance.
-			for _, p := range tc.path {
-				if p == "" {
-					var ok bool
-					v, ok = v.Elem()
-					if !ok {
-						t.Fatal("expected element")
-					}
-				} else {
-					v = v.Lookup(p)
-				}
-			}
-			got := fmt.Sprint(v)
-			// got := debug.NodeString(v.ctx().opCtx, v.v, &debug.Config{Compact: true})
-			if got != tc.want {
-				t.Errorf("\n got: %q\nwant: %q", got, tc.want)
-			}
-		})
-	}
-}
-
-func TestSubsumes(t *testing.T) {
-	a := []string{"a"}
-	b := []string{"b"}
-	testCases := []struct {
-		value string
-		pathA []string
-		pathB []string
-		want  bool
-	}{{
-		value: `4`,
-		want:  true,
-	}, {
-		value: `a: string, b: "foo"`,
-		pathA: a,
-		pathB: b,
-		want:  true,
-	}, {
-		value: `a: string, b: "foo"`,
-		pathA: b,
-		pathB: a,
-		want:  false,
-	}, {
-		value: `a: {a: string, b: 4}, b: {a: "foo", b: 4}`,
-		pathA: a,
-		pathB: b,
-		want:  true,
-	}, {
-		value: `a: [string,  4], b: ["foo", 4]`,
-		pathA: a,
-		pathB: b,
-		want:  true,
-	}}
-	for _, tc := range testCases {
-		t.Run(tc.value, func(t *testing.T) {
-			v := getInstance(t, tc.value)
-			a := v.Lookup(tc.pathA...)
-			b := v.Lookup(tc.pathB...)
-			got := a.Subsumes(b)
-			if got != tc.want {
-				t.Errorf("got %v (%v); want %v (%v)", got, a, tc.want, b)
-			}
-		})
-	}
-}
-
-func TestUnify(t *testing.T) {
-	a := []string{"a"}
-	b := []string{"b"}
-	testCases := []struct {
-		value string
-		pathA []string
-		pathB []string
-		want  string
-	}{{
-		value: `4`,
-		want:  `4`,
-	}, {
-		value: `a: string, b: "foo"`,
-		pathA: a,
-		pathB: b,
-		want:  `"foo"`,
-	}, {
-		value: `a: string, b: "foo"`,
-		pathA: b,
-		pathB: a,
-		want:  `"foo"`,
-	}, {
-		value: `a: {a: string, b: 4}, b: {a: "foo", b: 4}`,
-		pathA: a,
-		pathB: b,
-		want:  `{"a":"foo","b":4}`,
-	}, {
-		value: `a: [string,  4], b: ["foo", 4]`,
-		pathA: a,
-		pathB: b,
-		want:  `["foo",4]`,
-	}}
-	for _, tc := range testCases {
-		t.Run(tc.value, func(t *testing.T) {
-			v := getInstance(t, tc.value).Value()
-			x := v.Lookup(tc.pathA...)
-			y := v.Lookup(tc.pathB...)
-			b, err := x.Unify(y).MarshalJSON()
-			if err != nil {
-				t.Fatal(err)
-			}
-			if got := string(b); got != tc.want {
-				t.Errorf("got %v; want %v", got, tc.want)
-			}
-		})
-	}
-}
-
-func TestEquals(t *testing.T) {
-	testCases := []struct {
-		a, b string
-		want bool
-	}{{
-		`4`, `4`, true,
-	}, {
-		`"str"`, `2`, false,
-	}, {
-		`2`, `3`, false,
-	}, {
-		`[1]`, `[3]`, false,
-	}, {
-		`[{a: 1,...}]`, `[{a: 1,...}]`, true,
-	}, {
-		`[]`, `[]`, true,
-	}, {
-		`{
-			a: b,
-			b: a,
-		}`,
-		`{
-			a: b,
-			b: a,
-		}`,
-		true,
-	}, {
-		`{
-			a: "foo",
-			b: "bar",
-		}`,
-		`{
-			a: "foo",
-		}`,
-		false,
-	}}
-	for _, tc := range testCases {
-		t.Run("", func(t *testing.T) {
-			var r Runtime
-			a, err := r.Compile("a", tc.a)
-			if err != nil {
-				t.Fatal(err)
-			}
-			b, err := r.Compile("b", tc.b)
-			if err != nil {
-				t.Fatal(err)
-			}
-			got := a.Value().Equals(b.Value())
-			if got != tc.want {
-				t.Errorf("got %v; want %v", got, tc.want)
-			}
-		})
-	}
-}
-
-func TestDecode(t *testing.T) {
-	type fields struct {
-		A int `json:"A"`
-		B int `json:"B"`
-		C int `json:"C"`
-	}
-	intList := func(ints ...int) *[]int {
-		ints = append([]int{}, ints...)
-		return &ints
-	}
-	testCases := []struct {
-		value string
-		dst   interface{}
-		want  interface{}
-		err   string
-	}{{
-		value: `_|_`,
-		err:   "from source",
-	}, {
-		value: `"str"`,
-		dst:   new(string),
-		want:  "str",
-	}, {
-		value: `"str"`,
-		dst:   new(int),
-		err:   "cannot unmarshal string into Go value of type int",
-	}, {
-		value: `{}`,
-		dst:   &fields{},
-		want:  fields{},
-	}, {
-		value: `{a:1,b:2,c:3}`,
-		dst:   &fields{},
-		want:  fields{A: 1, B: 2, C: 3},
-	}, {
-		value: `{for k, v in y if v > 1 {"\(k)": v} }
-		y: {a:1,b:2,c:3}`,
-		dst:  &fields{},
-		want: fields{B: 2, C: 3},
-	}, {
-		value: `{a:1,b:2,c:int}`,
-		dst:   new(fields),
-		err:   "cannot convert incomplete value",
-	}, {
-		value: `[]`,
-		dst:   intList(),
-		want:  *intList(),
-	}, {
-		value: `[1,2,3]`,
-		dst:   intList(),
-		want:  *intList(1, 2, 3),
-	}, {
-		value: `[for x in #y if x > 1 { x }]
-				#y: [1,2,3]`,
-		dst:  intList(),
-		want: *intList(2, 3),
-	}, {
-		value: `[int]`,
-		err:   "cannot convert incomplete value",
-	}}
-	for _, tc := range testCases {
-		t.Run(tc.value, func(t *testing.T) {
-			err := getInstance(t, tc.value).Value().Decode(tc.dst)
-			checkFatal(t, err, tc.err, "init")
-
-			got := reflect.ValueOf(tc.dst).Elem().Interface()
-			if !cmp.Equal(got, tc.want) {
-				t.Error(cmp.Diff(got, tc.want))
-				t.Errorf("\n%#v\n%#v", got, tc.want)
-			}
-		})
-	}
-}
-
-// TODO: options: disallow cycles.
-func TestValidate(t *testing.T) {
-	testCases := []struct {
-		desc string
-		in   string
-		err  bool
-		opts []Option
-	}{{
-		desc: "issue #51",
-		in: `
-		a: [string]: foo
-		a: b: {}
-		`,
-		err: true,
-	}, {
-		desc: "concrete",
-		in: `
-		a: 1
-		b: { c: 2, d: 3 }
-		c: d: e: f: 5
-		g?: int
-		`,
-		opts: []Option{Concrete(true)},
-	}, {
-		desc: "definition error",
-		in: `
-			#b: 1 & 2
-			`,
-		opts: []Option{},
-		err:  true,
-	}, {
-		desc: "definition error okay if optional",
-		in: `
-			#b?: 1 & 2
-			`,
-		opts: []Option{},
-	}, {
-		desc: "definition with optional",
-		in: `
-			#b: {
-				a: int
-				b?: >=0
-			}
-		`,
-		opts: []Option{Concrete(true)},
-	}, {
-		desc: "disjunction",
-		in:   `a: 1 | 2`,
-	}, {
-		desc: "disjunction concrete",
-		in:   `a: 1 | 2`,
-		opts: []Option{Concrete(true)},
-		err:  true,
-	}, {
-		desc: "incomplete concrete",
-		in:   `a: string`,
-	}, {
-		desc: "incomplete",
-		in:   `a: string`,
-		opts: []Option{Concrete(true)},
-		err:  true,
-	}, {
-		desc: "list",
-		in:   `a: [{b: string}, 3]`,
-	}, {
-		desc: "list concrete",
-		in:   `a: [{b: string}, 3]`,
-		opts: []Option{Concrete(true)},
-		err:  true,
-	}, {
-		desc: "allow cycles",
-		in: `
-			a: b - 100
-			b: a + 100
-			c: [c[1], c[0]]
-			`,
-	}, {
-		desc: "disallow cycles",
-		in: `
-			a: b - 100
-			b: a + 100
-			c: [c[1], c[0]]
-			`,
-		opts: []Option{DisallowCycles(true)},
-		err:  true,
-	}, {
-		desc: "builtins are okay",
-		in: `
-		import "time"
-
-		a: { b: time.Duration } | { c: time.Duration }
-		`,
-	}, {
-		desc: "comprehension error",
-		in: `
-			a: { if b == "foo" { field: 2 } }
-			`,
-		err: true,
-	}, {
-		desc: "ignore optional in schema",
-		in: `
-		#Schema1: {
-			a?: int
-		}
-		instance1: #Schema1
-		`,
-		opts: []Option{Concrete(true)},
-	}, {
-		desc: "issue324",
-		in: `
-		import "encoding/yaml"
-
-		x: string
-		a: b: c: *["\(x)"] | _
-		d: yaml.Marshal(a.b)
-		`,
-	}, {
-		desc: "allow non-concrete values for definitions",
-		in: `
-		variables: #variables
-
-		{[!~"^[.]"]: #job}
-
-		#variables: [string]: int | string
-
-		#job: ({a: int} | {b: int}) & {
-			"variables"?: #variables
-		}
-		`,
-	}}
-	for _, tc := range testCases {
-		t.Run(tc.desc, func(t *testing.T) {
-			r := Runtime{}
-			inst, err := r.Parse("validate", tc.in)
-			if err == nil {
-				err = inst.Value().Validate(tc.opts...)
-			}
-			if gotErr := err != nil; gotErr != tc.err {
-				t.Errorf("got %v; want %v", err, tc.err)
-			}
-		})
-	}
-}
-
-func TestPath(t *testing.T) {
-	config := `
-	a: b: c: 5
-	b: {
-		b1: 3
-		b2: 4
-		"b 3": 5
-		"4b": 6
-		l: [
-			{a: 2},
-			{c: 2},
-		]
-	}
-	`
-	mkpath := func(p ...string) []string { return p }
-	testCases := [][]string{
-		mkpath("a", "b", "c"),
-		mkpath("b", "l", "1", "c"),
-		mkpath("b", `"b 3"`),
-		mkpath("b", `"4b"`),
-	}
-	for _, tc := range testCases {
-		r := Runtime{}
-		inst, err := r.Parse("config", config)
-		if err != nil {
-			t.Fatal(err)
-		}
-		t.Run(strings.Join(tc, "."), func(t *testing.T) {
-			v := inst.Lookup(tc[0])
-			for _, e := range tc[1:] {
-				if '0' <= e[0] && e[0] <= '9' {
-					i, err := strconv.Atoi(e)
-					if err != nil {
-						t.Fatal(err)
-					}
-					iter, err := v.List()
-					if err != nil {
-						t.Fatal(err)
-					}
-					for c := 0; iter.Next(); c++ {
-						if c == i {
-							v = iter.Value()
-							break
-						}
-					}
-				} else if e[0] == '"' {
-					v = v.Lookup(e[1 : len(e)-1])
-				} else {
-					v = v.Lookup(e)
-				}
-			}
-			got := v.appendPath(nil)
-			if !reflect.DeepEqual(got, tc) {
-				t.Errorf("got %v; want %v", got, tc)
-			}
-		})
-	}
-}
-
-func TestValueLookup(t *testing.T) {
-	config := `
-		a: {
-			a: 0
-			b: 1
-			c: 2
-		}
-		b: {
-			d: a.a
-			e: int
-		}
-	`
-
-	strList := func(s ...string) []string { return s }
-
-	testCases := []struct {
-		config    string
-		path      []string
-		str       string
-		notExists bool
-	}{{
-		config: "_|_",
-		path:   strList(""),
-		str:    "from source",
-	}, {
-		config: "_|_",
-		path:   strList("a"),
-		str:    "from source",
-	}, {
-		config: config,
-		path:   strList(),
-		str:    "{a:{a:0,b:1,c:2},b:{d:0,e:int}",
-	}, {
-		config: config,
-		path:   strList("a", "a"),
-		str:    "0",
-	}, {
-		config: config,
-		path:   strList("a"),
-		str:    "{a:0,b:1,c:2}",
-	}, {
-		config: config,
-		path:   strList("b", "d"),
-		str:    "0",
-	}, {
-		config:    config,
-		path:      strList("c", "non-existing"),
-		str:       "not found",
-		notExists: true,
-	}, {
-		config: config,
-		path:   strList("b", "d", "lookup in non-struct"),
-		str:    "cannot use value 0 (type int) as struct",
-	}}
-	for _, tc := range testCases {
-		t.Run(tc.str, func(t *testing.T) {
-			v := getInstance(t, tc.config).Value().Lookup(tc.path...)
-			if got := !v.Exists(); got != tc.notExists {
-				t.Errorf("exists: got %v; want %v", got, tc.notExists)
-			}
-
-			got := v.ctx().opCtx.Str(v.v)
-			if tc.str == "" {
-				t.Fatalf("str empty, got %q", got)
-			}
-			if !strings.Contains(got, tc.str) {
-				t.Errorf("\n got %v\nwant %v", got, tc.str)
-			}
-		})
-	}
-}
-
-func cmpError(a, b error) bool {
-	if a == nil {
-		return b == nil
-	}
-	if b == nil {
-		return a == nil
-	}
-	return a.Error() == b.Error()
-}
-
-func TestAttributeErr(t *testing.T) {
-	const config = `
-	a: {
-		a: 0 @foo(a,b,c=1)
-		b: 1 @bar(a,b,c,d=1) @foo(a,,d=1)
-	}
-	`
-	testCases := []struct {
-		path string
-		attr string
-		err  error
-	}{{
-		path: "a",
-		attr: "foo",
-		err:  nil,
-	}, {
-		path: "a",
-		attr: "bar",
-		err:  errors.New(`attribute "bar" does not exist`),
-	}, {
-		path: "xx",
-		attr: "bar",
-		err:  errors.New(`attribute "bar" does not exist`),
-	}, {
-		path: "e",
-		attr: "bar",
-		err:  errors.New(`attribute "bar" does not exist`),
-	}}
-	for _, tc := range testCases {
-		t.Run(tc.path+"-"+tc.attr, func(t *testing.T) {
-			v := getInstance(t, config).Value().Lookup("a", tc.path)
-			a := v.Attribute(tc.attr)
-			err := a.Err()
-			if !cmpError(err, tc.err) {
-				t.Errorf("got %v; want %v", err, tc.err)
-			}
-		})
-	}
-}
-
-func TestAttributeString(t *testing.T) {
-	const config = `
-	a: {
-		a: 0 @foo(a,b,c=1)
-		b: 1 @bar(a,b,c,d=1) @foo(a,,d=1)
-	}
-	`
-	testCases := []struct {
-		path string
-		attr string
-		pos  int
-		str  string
-		err  error
-	}{{
-		path: "a",
-		attr: "foo",
-		pos:  0,
-		str:  "a",
-	}, {
-		path: "a",
-		attr: "foo",
-		pos:  2,
-		str:  "c=1",
-	}, {
-		path: "b",
-		attr: "bar",
-		pos:  3,
-		str:  "d=1",
-	}, {
-		path: "e",
-		attr: "bar",
-		err:  errors.New(`attribute "bar" does not exist`),
-	}, {
-		path: "b",
-		attr: "foo",
-		pos:  4,
-		err:  errors.New("field does not exist"),
-	}}
-	for _, tc := range testCases {
-		t.Run(fmt.Sprintf("%s.%s:%d", tc.path, tc.attr, tc.pos), func(t *testing.T) {
-			v := getInstance(t, config).Value().Lookup("a", tc.path)
-			a := v.Attribute(tc.attr)
-			got, err := a.String(tc.pos)
-			if !cmpError(err, tc.err) {
-				t.Errorf("err: got %v; want %v", err, tc.err)
-			}
-			if got != tc.str {
-				t.Errorf("str: got %v; want %v", got, tc.str)
-			}
-		})
-	}
-}
-
-func TestAttributeInt(t *testing.T) {
-	const config = `
-	a: {
-		a: 0 @foo(1,3,c=1)
-		b: 1 @bar(a,-4,c,d=1) @foo(a,,d=1)
-	}
-	`
-	testCases := []struct {
-		path string
-		attr string
-		pos  int
-		val  int64
-		err  error
-	}{{
-		path: "a",
-		attr: "foo",
-		pos:  0,
-		val:  1,
-	}, {
-		path: "b",
-		attr: "bar",
-		pos:  1,
-		val:  -4,
-	}, {
-		path: "e",
-		attr: "bar",
-		err:  errors.New(`attribute "bar" does not exist`),
-	}, {
-		path: "b",
-		attr: "foo",
-		pos:  4,
-		err:  errors.New("field does not exist"),
-	}, {
-		path: "a",
-		attr: "foo",
-		pos:  2,
-		err:  errors.New(`strconv.ParseInt: parsing "c=1": invalid syntax`),
-	}}
-	for _, tc := range testCases {
-		t.Run(fmt.Sprintf("%s.%s:%d", tc.path, tc.attr, tc.pos), func(t *testing.T) {
-			v := getInstance(t, config).Value().Lookup("a", tc.path)
-			a := v.Attribute(tc.attr)
-			got, err := a.Int(tc.pos)
-			if !cmpError(err, tc.err) {
-				t.Errorf("err: got %v; want %v", err, tc.err)
-			}
-			if got != tc.val {
-				t.Errorf("val: got %v; want %v", got, tc.val)
-			}
-		})
-	}
-}
-
-func TestAttributeFlag(t *testing.T) {
-	const config = `
-	a: {
-		a: 0 @foo(a,b,c=1)
-		b: 1 @bar(a,b,c,d=1) @foo(a,,d=1)
-	}
-	`
-	testCases := []struct {
-		path string
-		attr string
-		pos  int
-		flag string
-		val  bool
-		err  error
-	}{{
-		path: "a",
-		attr: "foo",
-		pos:  0,
-		flag: "a",
-		val:  true,
-	}, {
-		path: "b",
-		attr: "bar",
-		pos:  1,
-		flag: "a",
-		val:  false,
-	}, {
-		path: "b",
-		attr: "bar",
-		pos:  0,
-		flag: "c",
-		val:  true,
-	}, {
-		path: "e",
-		attr: "bar",
-		err:  errors.New(`attribute "bar" does not exist`),
-	}, {
-		path: "b",
-		attr: "foo",
-		pos:  4,
-		err:  errors.New("field does not exist"),
-	}}
-	for _, tc := range testCases {
-		t.Run(fmt.Sprintf("%s.%s:%d", tc.path, tc.attr, tc.pos), func(t *testing.T) {
-			v := getInstance(t, config).Value().Lookup("a", tc.path)
-			a := v.Attribute(tc.attr)
-			got, err := a.Flag(tc.pos, tc.flag)
-			if !cmpError(err, tc.err) {
-				t.Errorf("err: got %v; want %v", err, tc.err)
-			}
-			if got != tc.val {
-				t.Errorf("val: got %v; want %v", got, tc.val)
-			}
-		})
-	}
-}
-
-func TestAttributeLookup(t *testing.T) {
-	const config = `
-	a: {
-		a: 0 @foo(a,b,c=1)
-		b: 1 @bar(a,b,e=-5,d=1) @foo(a,,d=1)
-	}
-	`
-	testCases := []struct {
-		path string
-		attr string
-		pos  int
-		key  string
-		val  string
-		err  error
-	}{{
-		path: "a",
-		attr: "foo",
-		pos:  0,
-		key:  "c",
-		val:  "1",
-	}, {
-		path: "b",
-		attr: "bar",
-		pos:  1,
-		key:  "a",
-		val:  "",
-	}, {
-		path: "b",
-		attr: "bar",
-		pos:  0,
-		key:  "e",
-		val:  "-5",
-	}, {
-		path: "b",
-		attr: "bar",
-		pos:  0,
-		key:  "d",
-		val:  "1",
-	}, {
-		path: "b",
-		attr: "foo",
-		pos:  2,
-		key:  "d",
-		val:  "1",
-	}, {
-		path: "b",
-		attr: "foo",
-		pos:  2,
-		key:  "f",
-		val:  "",
-	}, {
-		path: "e",
-		attr: "bar",
-		err:  errors.New(`attribute "bar" does not exist`),
-	}, {
-		path: "b",
-		attr: "foo",
-		pos:  4,
-		err:  errors.New("field does not exist"),
-	}}
-	for _, tc := range testCases {
-		t.Run(fmt.Sprintf("%s.%s:%d", tc.path, tc.attr, tc.pos), func(t *testing.T) {
-			v := getInstance(t, config).Value().Lookup("a", tc.path)
-			a := v.Attribute(tc.attr)
-			got, _, err := a.Lookup(tc.pos, tc.key)
-			if !cmpError(err, tc.err) {
-				t.Errorf("err: got %v; want %v", err, tc.err)
-			}
-			if got != tc.val {
-				t.Errorf("val: got %v; want %v", got, tc.val)
-			}
-		})
-	}
-}
-
-// TODO: duplicate docs.
-func TestValueDoc(t *testing.T) {
-	const config = `
-	// foobar defines at least foo.
-	package foobar
-
-	// A Foo fooses stuff.
-	Foo: {
-		// field1 is an int.
-		field1: int
-
-		field2: int
-
-		// duplicate field comment
-		dup3: int
-	}
-
-	// foos are instances of Foo.
-	foos: [string]: Foo
-
-	// My first little foo.
-	foos: MyFoo: {
-		// local field comment.
-		field1: 0
-
-		// Dangling comment.
-
-		// other field comment.
-		field2: 1
-
-		// duplicate field comment
-		dup3: int
-	}
-
-	bar: {
-		// comment from bar on field 1
-		field1: int
-		// comment from bar on field 2
-		field2: int // don't include this
-	}
-
-	baz: bar & {
-		// comment from baz on field 1
-		field1: int
-		field2: int
-	}
-	`
-	config2 := `
-	// Another Foo.
-	Foo: {}
-	`
-	var r Runtime
-	getInst := func(name, body string) *Instance {
-		inst, err := r.Compile("dir/file1.cue", body)
-		if err != nil {
-			t.Fatal(err)
-		}
-		return inst
-	}
-
-	inst := getInst("config", config)
-
-	v1 := inst.Value()
-	v2 := getInst("config2", config2).Value()
-	both := v1.Unify(v2)
-
-	testCases := []struct {
-		val  Value
-		path string
-		doc  string
-	}{{
-		val:  v1,
-		path: "foos",
-		doc:  "foos are instances of Foo.\n",
-	}, {
-		val:  v1,
-		path: "foos MyFoo",
-		doc:  "My first little foo.\n",
-	}, {
-		val:  v1,
-		path: "foos MyFoo field1",
-		doc: `local field comment.
-
-field1 is an int.
-`,
-	}, {
-		val:  v1,
-		path: "foos MyFoo field2",
-		doc:  "other field comment.\n",
-	}, {
-		// Duplicates are now removed.
-		val:  v1,
-		path: "foos MyFoo dup3",
-		doc:  "duplicate field comment\n",
-	}, {
-		val:  v1,
-		path: "bar field1",
-		doc:  "comment from bar on field 1\n",
-	}, {
-		val:  v1,
-		path: "baz field1",
-		doc: `comment from bar on field 1
-
-comment from baz on field 1
-`,
-	}, {
-		val:  v1,
-		path: "baz field2",
-		doc:  "comment from bar on field 2\n",
-	}, {
-		val:  v2,
-		path: "Foo",
-		doc: `Another Foo.
-`,
-	}, {
-		val:  both,
-		path: "Foo",
-		doc: `A Foo fooses stuff.
-
-Another Foo.
-`,
-	}}
-	for _, tc := range testCases {
-		t.Run("field:"+tc.path, func(t *testing.T) {
-			v := tc.val.Lookup(strings.Split(tc.path, " ")...)
-			doc := docStr(v.Doc())
-			if doc != tc.doc {
-				t.Errorf("doc: got:\n%vwant:\n%v", doc, tc.doc)
-			}
-		})
-	}
-	want := "foobar defines at least foo.\n"
-	if got := docStr(inst.Doc()); got != want {
-		t.Errorf("pkg: got:\n%vwant:\n%v", got, want)
-	}
-}
-
-func docStr(docs []*ast.CommentGroup) string {
-	doc := ""
-	for _, d := range docs {
-		if doc != "" {
-			doc += "\n"
-		}
-		doc += d.Text()
-	}
-	return doc
-}
-
-// TODO: unwrap marshal error
-// TODO: improve error messages
-func TestMarshalJSON(t *testing.T) {
-	testCases := []struct {
-		value string
-		json  string
-		err   string
-	}{{
-		value: `""`,
-		json:  `""`,
-	}, {
-		value: `null`,
-		json:  `null`,
-	}, {
-		value: `_|_`,
-		err:   "from source",
-	}, {
-		value: `(a.b)
-		a: {}`,
-		err: "undefined field",
-	}, {
-		value: `true`,
-		json:  `true`,
-	}, {
-		value: `false`,
-		json:  `false`,
-	}, {
-		value: `bool`,
-		err:   "cannot convert incomplete value",
-	}, {
-		value: `"str"`,
-		json:  `"str"`,
-	}, {
-		value: `12_000`,
-		json:  `12000`,
-	}, {
-		value: `12.000`,
-		json:  `12.000`,
-	}, {
-		value: `12M`,
-		json:  `12000000`,
-	}, {
-		value: `3.0e100`,
-		json:  `3.0E+100`,
-	}, {
-		value: `0/0`,
-		err:   "division undefined",
-	}, {
-		value: `[]`,
-		json:  `[]`,
-	}, {
-		value: `[1, 2, 3]`,
-		json:  `[1,2,3]`,
-	}, {
-		value: `[int]`,
-		err:   `0: cannot convert incomplete value`,
-	}, {
-		value: `(>=3 * [1, 2])`,
-		err:   "cue: marshal error: non-concrete value >=3 in operand to *",
-	}, {
-		value: `{}`,
-		json:  `{}`,
-	}, {
-		value: `{a: 2, b: 3, c: ["A", "B"]}`,
-		json:  `{"a":2,"b":3,"c":["A","B"]}`,
-	}, {
-		value: `{a: 2, b: 3, c: [string, "B"]}`,
-		err:   `c.0: cannot convert incomplete value`,
-	}, {
-		value: `{a: [{b: [0, {c: string}] }] }`,
-		err:   `a.0.b.1.c: cannot convert incomplete value`,
-	}, {
-		value: `{foo?: 1, bar?: 2, baz: 3}`,
-		json:  `{"baz":3}`,
-	}, {
-		// Has an unresolved cycle, but should not matter as all fields involved
-		// are optional
-		value: `{foo?: bar, bar?: foo, baz: 3}`,
-		json:  `{"baz":3}`,
-	}, {
-		// Issue #107
-		value: `a: 1.0/1`,
-		json:  `{"a":1.0}`,
-	}, {
-		// Issue #108
-		value: `
-		a: int
-		a: >0
-		a: <2
-
-		b: int
-		b: >=0.9
-		b: <1.1
-
-		c: int
-		c: >1
-		c: <=2
-
-		d: int
-		d: >=1
-		d: <=1.5
-
-		e: int
-		e: >=1
-		e: <=1.32
-
-		f: >=1.1 & <=1.1
-		`,
-		json: `{"a":1,"b":1,"c":2,"d":1,"e":1,"f":1.1}`,
-	}, {
-		value: `
-		#Task: {
-			{
-				op:          "pull"
-				tag:         *"latest" | string
-				tagInString: tag + "dd"
-			} | {
-				op: "scratch"
-			}
-		}
-
-		foo: #Task & {"op": "pull"}
-		`,
-		json: `{"foo":{"op":"pull","tag":"latest","tagInString":"latestdd"}}`,
-	}, {
-		// Issue #326
-		value: `x: "\(string)": "v"`,
-		err:   `x: invalid interpolation`,
-	}, {
-		// Issue #326
-		value: `x: "\(bool)": "v"`,
-		err:   `invalid interpolation`,
-	}, {
-		// Issue #326
-		value: `
-		x: {
-			for k, v in y {
-				"\(k)": v
-			}
-		}
-		y: {}
-		`,
-		json: `{"x":{},"y":{}}`,
-	}, {
-		// Issue #326
-		value: `
-		x: {
-			for k, v in y {
-				"\(k)": v
-			}
-		}
-		y: _
-		`,
-		err: `x: incomplete feed source`,
-	}}
-	for i, tc := range testCases {
-		t.Run(fmt.Sprintf("%d/%v", i, tc.value), func(t *testing.T) {
-			inst := getInstance(t, tc.value)
-			b, err := inst.Value().MarshalJSON()
-			checkFatal(t, err, tc.err, "init")
-
-			if got := string(b); got != tc.json {
-				t.Errorf("\n got %v;\nwant %v", got, tc.json)
-			}
-		})
-	}
-}
-
-func TestWalk(t *testing.T) {
-	testCases := []struct {
-		value string
-		out   string
-	}{{
-		value: `""`,
-		out:   `""`,
-	}, {
-		value: `null`,
-		out:   `null`,
-	}, {
-		value: `_|_`,
-		out:   "_|_(from source)",
-	}, {
-		value: `(a.b)
-			a: {}`,
-		out: `_|_(undefined field b)`,
-	}, {
-		value: `true`,
-		out:   `true`,
-	}, {
-		value: `false`,
-		out:   `false`,
-	}, {
-		value: `bool`,
-		out:   "bool",
-	}, {
-		value: `"str"`,
-		out:   `"str"`,
-	}, {
-		value: `12_000`,
-		out:   `12000`,
-		// out:   `12_000`,
-	}, {
-		value: `12.000`,
-		out:   `12.000`,
-	}, {
-		value: `12M`,
-		out:   `12000000`,
-		// out:   `12M`,
-	}, {
-		value: `3.0e100`,
-		out:   `3.0e+100`,
-		// out:   `3.0e100`,
-	}, {
-		value: `[]`,
-		out:   `[]`,
-	}, {
-		value: `[1, 2, 3]`,
-		out:   `[1,2,3]`,
-	}, {
-		value: `[int]`,
-		out:   `[int]`,
-	}, {
-		value: `3 * [1, 2]`,
-		out:   `[1,2,1,2,1,2]`,
-	}, {
-		value: `{}`,
-		out:   `{}`,
-	}, {
-		value: `{a: 2, b: 3, c: ["A", "B"]}`,
-		out:   `{a:2,b:3,c:["A","B"]}`,
-	}}
-	for i, tc := range testCases {
-		t.Run(fmt.Sprintf("%d/%v", i, tc.value), func(t *testing.T) {
-			inst := getInstance(t, tc.value)
-			buf := []byte{}
-			stripComma := func() {
-				if n := len(buf) - 1; buf[n] == ',' {
-					buf = buf[:n]
-				}
-			}
-			inst.Value().Walk(func(v Value) bool {
-				v = v.Eval()
-				if !v.v.Label.IsInt() {
-					if k, ok := v.Label(); ok {
-						buf = append(buf, k+":"...)
-					}
-				}
-				switch v.Kind() {
-				case StructKind:
-					buf = append(buf, '{')
-				case ListKind:
-					buf = append(buf, '[')
-				default:
-					if b, _ := v.v.Value.(*adt.Bottom); b != nil {
-						s := debugStr(v.ctx(), b)
-						buf = append(buf, fmt.Sprint(s, ",")...)
-						return true
-					}
-					buf = append(buf, fmt.Sprint(v, ",")...)
-				}
-				return true
-			}, func(v Value) {
-				switch v.Kind() {
-				case StructKind:
-					stripComma()
-					buf = append(buf, "},"...)
-				case ListKind:
-					stripComma()
-					buf = append(buf, "],"...)
-				}
-			})
-			stripComma()
-			if got := string(buf); got != tc.out {
-				t.Errorf("\n got %v;\nwant %v", got, tc.out)
-			}
-		})
-	}
-}
-
-func TestTrimZeros(t *testing.T) {
-	testCases := []struct {
-		in  string
-		out string
-	}{
-		{"", ""},
-		{"2", "2"},
-		{"2.0", "2.0"},
-		{"2.000000000000", "2.0"},
-		{"2000000000000", "2e+12"},
-		{"2000000", "2e+6"},
-	}
-	for _, tc := range testCases {
-		t.Run(tc.in, func(t *testing.T) {
-			if got := trimZeros(tc.in); got != tc.out {
-				t.Errorf("got %q; want %q", got, tc.out)
-			}
-		})
-	}
-}
-
-func TestReference(t *testing.T) {
-	testCases := []struct {
-		input string
-		want  string
-		alt   string
-	}{{
-		input: "v: w: x: _|_",
-		want:  "",
-	}, {
-		input: "v: w: x: 2",
-		want:  "",
-	}, {
-		input: "v: w: x: a, a: 1",
-		want:  "a",
-	}, {
-		input: "v: w: x: a.b.c, a: b: c: 1",
-		want:  "a b c",
-	}, {
-		input: "v: w: x: w.a.b.c, v: w: a: b: c: 1",
-		want:  "v w a b c",
-	}, {
-		input: `v: w: x: w.a.b.c, v: w: a: b: c: 1, #D: 3, opt?: 3, "v\(#D)": 3, X: {a: 3}, X`,
-		want:  "v w a b c",
-	}, {
-		input: `v: w: x: w.a[bb]["c"], v: w: a: b: c: 1, bb: "b"`,
-		want:  "v w a b c",
-	}, {
-		input: `v: {
-			for t in src {
-				w: "t\(t)": 1
-				w: "\(t)": w["t\(t)"]
-			}
-		},
-		src: ["x", "y"]`,
-		want: "v w tx",
-	}, {
-		input: `
-		v: w: x: a
-		a: 1
-		for i in [] {
-		}
-		`,
-		want: "a",
-	}, {
-		input: `
-		v: w: close({x: a})
-		a: 1
-		`,
-		want: "a",
-	}, {
-		input: `
-		import "math"
-
-		v: w: x: math.Pi
-		`,
-		want: "Pi",
-		alt:  "3.14159265358979323846264338327950288419716939937510582097494459",
-	}}
-	for _, tc := range testCases {
-		t.Run("", func(t *testing.T) {
-			var r Runtime
-			inst, _ := r.Compile("in", tc.input) // getInstance(t, tc.input)
-			v := inst.Lookup("v", "w", "x")
-			inst, a := v.Reference()
-			if got := strings.Join(a, " "); got != tc.want {
-				t.Errorf("\n got %v;\nwant %v", got, tc.want)
-			}
-
-			if tc.want != "" {
-				want := "1"
-				if tc.alt != "" {
-					want = tc.alt
-				}
-				v := fmt.Sprint(inst.Lookup(a...))
-				if v != want {
-					t.Errorf("path resolved to %s; want %s", v, want)
-				}
-			}
-		})
-	}
-}
-
-// TODO: stack overflow
-func TestPathCorrection(t *testing.T) {
-	testCases := []struct {
-		input  string
-		lookup func(i *Instance) Value
-		want   string
-		skip   bool
-	}{{
-		// // TODO: structural cycle.
-		// input: `
-		// a: b: {
-		// 	c: d: b
-		// }
-		// `,
-		// lookup: func(i *Instance) Value {
-		// 	_, a := i.Lookup("a", "b", "c", "d").Expr()
-		// 	return a[0].Lookup("b", "c", "d")
-		// },
-		// want: "a.b",
-		// }, {
-
-		// TODO: embedding: have field operators.
-		// input: `
-		// 	a: {
-		// 		c: 3
-		// 		{x: c}
-		// 	}
-		// 	`,
-		// lookup: func(i *Instance) Value {
-		// 	_, a := i.Lookup("a").Expr()
-		// 	return a[1].Lookup("x")
-		// },
-		// want: "a.c",
-		// }, {
-
-		// TODO: implement proper Elem()
-		input: `
-			a: b: [...T]
-			a: b: [...T]
-			T: int
-			`,
-		lookup: func(i *Instance) Value {
-			v, _ := i.Lookup("a", "b").Elem()
-			_, a := v.Expr()
-			return a[0]
-		},
-		want: "T",
-	}, {
-		input: `
-				#S: {
-					b?: [...#T]
-					b?: [...#T]
-				}
-				#T: int
-				`,
-		lookup: func(i *Instance) Value {
-			v := i.LookupDef("#S")
-			f, _ := v.LookupField("b")
-			v, _ = f.Value.Elem()
-			_, a := v.Expr()
-			return a[0]
-		},
-		want: "#T",
-	}, {
-		input: `
-		#S: {
-			a?: [...#T]
-			b?: [...#T]
-		}
-		#T: int
-		`,
-		lookup: func(i *Instance) Value {
-			v := i.LookupDef("#S")
-			f, _ := v.LookupField("a")
-			x := f.Value
-			f, _ = v.LookupField("b")
-			y := f.Value
-			u := x.Unify(y)
-			v, _ = u.Elem()
-			_, a := v.Expr()
-			return a[0]
-		},
-		want: "#T",
-		// }, {
-		// 	input: `
-		// 		#a: {
-		// 			#T: {b: 3}
-		// 			close({}) | close({c: #T}) | close({d: string})
-		// 		}
-		// 		`,
-		// 	lookup: func(i *Instance) Value {
-		// 		f, _ := i.LookupField("#a")
-		// 		_, a := f.Value.Expr() // &
-		// 		_, a = a[1].Expr()     // |
-		// 		return a[1].Lookup("c")
-		// 	},
-		// 	want: "#a.#T",
-	}, {
-		// TODO: iterate over Definitions
-		// input: `
-		// 	package foo
-
-		// 	#Struct: {
-		// 		#T: int
-
-		// 		{b?: #T}
-		// 	}`,
-		// want: "#Struct.#T",
-		// lookup: func(inst *Instance) Value {
-		// 	// Locate Struct
-		// 	i, _ := inst.Value().Fields(Definitions(true))
-		// 	if !i.Next() {
-		// 		t.Fatal("no fields")
-		// 	}
-		// 	// Locate b
-		// 	i, _ = i.Value().Fields(Definitions(true), Optional(true))
-		// 	if !(i.Next() && i.Next()) {
-		// 		t.Fatal("no fields")
-		// 	}
-		// 	v := i.Value()
-		// 	return v
-		// },
-		// }, {
-
-		input: `
-		package foo
-
-		#A: #B: #T
-
-		#T: {
-			a: #S.#U
-			#S: #U: {}
-		}
-		`,
-		want: "#T.#S.#U",
-		lookup: func(inst *Instance) Value {
-			f, _ := inst.Value().LookupField("#A")
-			f, _ = f.Value.LookupField("#B")
-			v := f.Value
-			v = Dereference(v)
-			v = v.Lookup("a")
-			return v
-		},
-		// }, {
-
-		// TODO: record additionalItems in list
-		// input: `
-		// 	package foo
-
-		// 	#A: #B: #T
-
-		// 	#T: {
-		// 		a: [...#S]
-		// 		#S: {}
-		// 	}
-		// 	`,
-		// want: "#T.#S",
-		// lookup: func(inst *Instance) Value {
-		// 	f, _ := inst.Value().LookupField("#A")
-		// 	f, _ = f.Value.LookupField("#B")
-		// 	v := f.Value
-		// 	v = Dereference(v)
-		// 	v, _ = v.Lookup("a").Elem()
-		// 	return v
-		// },
-		// }, {
-
-		// YAY: works.
-		// input: `
-		// 	#A: {
-		// 		b: #T
-		// 	}
-
-		// 	#T: {
-		// 		a: #S
-		// 		#S: {}
-		// 	}
-		// 	`,
-		// want: "#T.#S",
-		// lookup: func(inst *Instance) Value {
-		// 	f, _ := inst.Value().LookupField("#A")
-		// 	v := f.Value.Lookup("b")
-		// 	v = Dereference(v)
-		// 	v = v.Lookup("a")
-		// 	return v
-		// },
-		// }, {
-
-		// 	// TODO(eval): embedded structs are currently represented at the same
-		// 	// level as the enclosing struct. This means that the parent of an
-		// 	// embedded struct skips the struct in which it is embedded. Treat
-		// 	// embedded structs as "anonymous" fields.
-		// 	// This could perhaps be made fixed with dereferencing as well.
-		// 	skip: true,
-		// input: `
-		// 	#Tracing: {
-		// 		#T: { address?: string }
-		// 		#S: { ip?: string }
-
-		// 		close({}) | close({
-		// 			t: #T
-		// 		}) | close({
-		// 			s: #S
-		// 		})
-		// 	}
-		// 	#X: {}
-		// 	#X // Disconnect top-level struct from the one visible by close.
-		// 	`,
-		// want: "",
-		// lookup: func(inst *Instance) Value {
-		// 	f, _ := inst.Value().LookupField("#Tracing")
-		// 	v := f.Value.Eval()
-		// 	_, args := v.Expr()
-		// 	v = args[1].Lookup("t")
-		// 	v = Dereference(v)
-		// 	return v
-		// },
-	}}
-	for _, tc := range testCases {
-		if tc.skip {
-			continue
-		}
-		t.Run("", func(t *testing.T) {
-			var r Runtime
-			inst, err := r.Compile("in", tc.input)
-			if err != nil {
-				t.Fatal(err)
-			}
-			v := tc.lookup(inst)
-			gotInst, ref := v.Reference()
-			if gotInst != inst {
-				t.Error("reference not in original instance")
-			}
-			gotPath := strings.Join(ref, ".")
-			if gotPath != tc.want {
-				t.Errorf("got path %s; want %s", gotPath, tc.want)
-			}
-		})
-	}
-}
-
-// func TestReferences(t *testing.T) {
-// 	config1 := `
-// 	a: {
-// 		b: 3
-// 	}
-// 	c: {
-// 		d: a.b
-// 		e: c.d
-// 		f: a
-// 	}
-// 	`
-// 	config2 := `
-// 	a: { c: 3 }
-// 	b: { c: int, d: 4 }
-// 	r: (a & b).c
-// 	c: {args: s1 + s2}.args
-// 	s1: string
-// 	s2: string
-// 	d: ({arg: b}).arg.c
-// 	e: f.arg.c
-// 	f: {arg: b}
-// 	`
-// 	testCases := []struct {
-// 		config string
-// 		in     string
-// 		out    string
-// 	}{
-// 		{config1, "c.d", "a.b"},
-// 		{config1, "c.e", "c.d"},
-// 		{config1, "c.f", "a"},
-
-// 		{config2, "r", "a.c b.c"},
-// 		{config2, "c", "s1 s2"},
-// 		// {config2, "d", "b.c"}, // TODO: make this work as well.
-// 		{config2, "e", "f.arg.c"}, // TODO: should also report b.c.
-// 	}
-// 	for _, tc := range testCases {
-// 		t.Run(tc.in, func(t *testing.T) {
-// 			ctx, st := compileFile(t, tc.config)
-// 			v := newValueRoot(ctx, st)
-// 			for _, k := range strings.Split(tc.in, ".") {
-// 				obj, err := v.structValFull(ctx)
-// 				if err != nil {
-// 					t.Fatal(err)
-// 				}
-// 				v = obj.Lookup(k)
-// 			}
-// 			got := []string{}
-// 			for _, r := range v.References() {
-// 				got = append(got, strings.Join(r, "."))
-// 			}
-// 			want := strings.Split(tc.out, " ")
-// 			if !reflect.DeepEqual(got, want) {
-// 				t.Errorf("got %v; want %v", got, want)
-// 			}
-// 		})
-// 	}
-// }
-
-func checkErr(t *testing.T, err error, str, name string) bool {
-	t.Helper()
-	if err == nil {
-		if str != "" {
-			t.Errorf(`err:%s: got ""; want %q`, name, str)
-		}
-		return true
-	}
-	return checkFailed(t, err, str, name)
-}
-
-func checkFatal(t *testing.T, err error, str, name string) {
-	t.Helper()
-	if !checkFailed(t, err, str, name) {
-		t.SkipNow()
-	}
-}
-
-func checkFailed(t *testing.T, err error, str, name string) bool {
-	t.Helper()
-	if err != nil {
-		got := err.Error()
-		if str == "" {
-			t.Fatalf(`err:%s: got %q; want ""`, name, got)
-		}
-		if !strings.Contains(got, str) {
-			t.Errorf(`err:%s: got %q; want %q`, name, got, str)
-		}
-		return false
-	}
-	return true
-}
-
-func TestExpr(t *testing.T) {
-	testCases := []struct {
-		input string
-		want  string
-	}{{
-		input: "v: 3",
-		want:  "3",
-	}, {
-		input: "v: 3 + 4",
-		want:  "+(3 4)",
-	}, {
-		input: "v: !a, a: bool",
-		want:  `!(.(〈〉 "a"))`,
-	}, {
-		input: "v: !a, a: 3", // TODO: Should still look up.
-		want:  `!(.(〈〉 "a"))`,
-	}, {
-		input: "v: 1 | 2 | 3 | *4",
-		want:  "|(1 2 3 4)",
-	}, {
-		input: "v: 2 & 5", // Allow even with error.
-		want:  "&(2 5)",
-	}, {
-		input: "v: 2 | 5",
-		want:  "|(2 5)",
-	}, {
-		input: "v: 2 && 5",
-		want:  "&&(2 5)",
-	}, {
-		input: "v: 2 || 5",
-		want:  "||(2 5)",
-	}, {
-		input: "v: 2 == 5",
-		want:  "==(2 5)",
-	}, {
-		input: "v: !b, b: true",
-		want:  `!(.(〈〉 "b"))`,
-	}, {
-		input: "v: 2 != 5",
-		want:  "!=(2 5)",
-	}, {
-		input: "v: <5",
-		want:  "<(5)",
-	}, {
-		input: "v: 2 <= 5",
-		want:  "<=(2 5)",
-	}, {
-		input: "v: 2 > 5",
-		want:  ">(2 5)",
-	}, {
-		input: "v: 2 >= 5",
-		want:  ">=(2 5)",
-	}, {
-		input: "v: 2 =~ 5",
-		want:  "=~(2 5)",
-	}, {
-		input: "v: 2 !~ 5",
-		want:  "!~(2 5)",
-	}, {
-		input: "v: 2 + 5",
-		want:  "+(2 5)",
-	}, {
-		input: "v: 2 - 5",
-		want:  "-(2 5)",
-	}, {
-		input: "v: 2 * 5",
-		want:  "*(2 5)",
-	}, {
-		input: "v: 2 / 5",
-		want:  "/(2 5)",
-	}, {
-		input: "v: 2 quo 5",
-		want:  "quo(2 5)",
-	}, {
-		input: "v: 2 rem 5",
-		want:  "rem(2 5)",
-	}, {
-		input: "v: 2 div 5",
-		want:  "div(2 5)",
-	}, {
-		input: "v: 2 mod 5",
-		want:  "mod(2 5)",
-	}, {
-		input: "v: a.b, a: b: 4",
-		want:  `.(.(〈〉 "a") "b")`,
-	}, {
-		input: `v: a["b"], a: b: 3 `,
-		want:  `[](.(〈〉 "a") "b")`,
-	}, {
-		input: "v: a[2:5], a: [1, 2, 3, 4, 5]",
-		want:  `[:](.(〈〉 "a") 2 5)`,
-	}, {
-		input: "v: len([])",
-		want:  "()(len [])",
-	}, {
-		input: "v: a.b, a: { b: string }",
-		want:  `.(.(〈〉 "a") "b")`,
-	}, {
-		input: `v: "Hello, \(x)! Welcome to \(place)", place: string, x: string`,
-		want:  `\()("Hello, " .(〈〉 "x") "! Welcome to " .(〈〉 "place") "")`,
-	}, {
-		input: `v: { a, b: 1 }, a: 2`,
-		want:  `&(.(〈〉 "a") {b:1})`,
-	}, {
-		input: `v: { {c: a}, b: a }, a: int`,
-		want:  `&({c:a} {b:a})`,
-	}, {
-		input: `v: [...number] | *[1, 2, 3]`,
-		want:  `([...number]|*[1,2,3])`,
-	}}
-	for _, tc := range testCases {
-		t.Run(tc.input, func(t *testing.T) {
-			v := getInstance(t, tc.input).Lookup("v")
-			got := exprStr(v)
-			if got != tc.want {
-				t.Errorf("\n got %v;\nwant %v", got, tc.want)
-			}
-		})
-	}
-}
-
-func exprStr(v Value) string {
-	op, operands := v.Expr()
-	if op == NoOp {
-		return compactRawStr(v)
-	}
-	s := op.String()
-	s += "("
-	for i, v := range operands {
-		if i > 0 {
-			s += " "
-		}
-		s += exprStr(v)
-	}
-	s += ")"
-	return s
-}
-
-func compactRawStr(v Value) string {
-	ctx := v.ctx()
-	cfg := &debug.Config{Compact: true, Raw: true}
-	return debug.NodeString(ctx.opCtx, v.v, cfg)
-}
-
-func compactValueStr(v Value) string {
-	ctx := v.ctx()
-	cfg := &debug.Config{Compact: true}
-	return debug.NodeString(ctx.opCtx, v.v, cfg)
-}
diff --git a/internal/task/task.go b/internal/task/task.go
index 5322a47..a6a54d2 100644
--- a/internal/task/task.go
+++ b/internal/task/task.go
@@ -20,8 +20,8 @@
 	"io"
 	"sync"
 
+	"cuelang.org/go/cue"
 	"cuelang.org/go/cue/errors"
-	"cuelang.org/go/internal/legacy/cue"
 )
 
 // A Context provides context for running a task.
diff --git a/internal/walk/walk.go b/internal/walk/walk.go
index b74f56e..8e3c9f9 100644
--- a/internal/walk/walk.go
+++ b/internal/walk/walk.go
@@ -21,7 +21,7 @@
 // satisfactory API has been established, it can be made public.
 package walk
 
-import "cuelang.org/go/internal/legacy/cue"
+import "cuelang.org/go/cue"
 
 // TODO:
 // - allow overriding options for descendants.
diff --git a/pkg/encoding/base64/manual.go b/pkg/encoding/base64/manual.go
index 178f105..b292424 100644
--- a/pkg/encoding/base64/manual.go
+++ b/pkg/encoding/base64/manual.go
@@ -19,7 +19,7 @@
 	"encoding/base64"
 	"fmt"
 
-	"cuelang.org/go/internal/legacy/cue"
+	"cuelang.org/go/cue"
 )
 
 // EncodedLen returns the length in bytes of the base64 encoding
diff --git a/pkg/encoding/csv/manual.go b/pkg/encoding/csv/manual.go
index f8b31d0..99e2cf1 100644
--- a/pkg/encoding/csv/manual.go
+++ b/pkg/encoding/csv/manual.go
@@ -19,7 +19,7 @@
 	"encoding/csv"
 	"io"
 
-	"cuelang.org/go/internal/legacy/cue"
+	"cuelang.org/go/cue"
 )
 
 // Encode encode the given list of lists to CSV.
diff --git a/pkg/encoding/json/manual.go b/pkg/encoding/json/manual.go
index 591724b..96a9721 100644
--- a/pkg/encoding/json/manual.go
+++ b/pkg/encoding/json/manual.go
@@ -19,10 +19,10 @@
 	"encoding/json"
 	"fmt"
 
+	"cuelang.org/go/cue"
 	"cuelang.org/go/cue/ast"
 	"cuelang.org/go/cue/parser"
 	"cuelang.org/go/internal"
-	"cuelang.org/go/internal/legacy/cue"
 )
 
 // Compact generates the JSON-encoded src with insignificant space characters
diff --git a/pkg/encoding/yaml/manual.go b/pkg/encoding/yaml/manual.go
index 16d6d38..60b7318 100644
--- a/pkg/encoding/yaml/manual.go
+++ b/pkg/encoding/yaml/manual.go
@@ -18,10 +18,10 @@
 	"bytes"
 	"io"
 
+	"cuelang.org/go/cue"
 	"cuelang.org/go/cue/ast"
 	"cuelang.org/go/internal"
 	cueyaml "cuelang.org/go/internal/encoding/yaml"
-	"cuelang.org/go/internal/legacy/cue"
 	"cuelang.org/go/internal/third_party/yaml"
 )
 
diff --git a/pkg/list/list.go b/pkg/list/list.go
index db6c2d3..be8493b 100644
--- a/pkg/list/list.go
+++ b/pkg/list/list.go
@@ -19,7 +19,7 @@
 	"fmt"
 	"sort"
 
-	"cuelang.org/go/internal/legacy/cue"
+	"cuelang.org/go/cue"
 )
 
 // Drop reports the suffix of list x after the first n elements,
diff --git a/pkg/list/sort.go b/pkg/list/sort.go
index f39a407..ac33f4f 100644
--- a/pkg/list/sort.go
+++ b/pkg/list/sort.go
@@ -21,7 +21,7 @@
 import (
 	"sort"
 
-	"cuelang.org/go/internal/legacy/cue"
+	"cuelang.org/go/cue"
 )
 
 // valueSorter defines a sort.Interface; implemented in cue/builtinutil.go.
diff --git a/pkg/net/host.go b/pkg/net/host.go
index 9a357c7..6018da4 100644
--- a/pkg/net/host.go
+++ b/pkg/net/host.go
@@ -22,7 +22,7 @@
 
 	"golang.org/x/net/idna"
 
-	"cuelang.org/go/internal/legacy/cue"
+	"cuelang.org/go/cue"
 )
 
 var idnaProfile = idna.New(
diff --git a/pkg/net/ip.go b/pkg/net/ip.go
index 5f9aeef..6b658e3 100644
--- a/pkg/net/ip.go
+++ b/pkg/net/ip.go
@@ -19,7 +19,7 @@
 	"fmt"
 	"net"
 
-	"cuelang.org/go/internal/legacy/cue"
+	"cuelang.org/go/cue"
 )
 
 // IP address lengths (bytes).
diff --git a/pkg/struct/struct.go b/pkg/struct/struct.go
index 5b51254..00094e1 100644
--- a/pkg/struct/struct.go
+++ b/pkg/struct/struct.go
@@ -16,7 +16,7 @@
 package structs
 
 import (
-	"cuelang.org/go/internal/legacy/cue"
+	"cuelang.org/go/cue"
 )
 
 // MinFields validates the minimum number of fields that are part of a struct.
diff --git a/pkg/text/tabwriter/manual.go b/pkg/text/tabwriter/manual.go
index 5512565..42f90aa 100644
--- a/pkg/text/tabwriter/manual.go
+++ b/pkg/text/tabwriter/manual.go
@@ -19,7 +19,7 @@
 	"fmt"
 	"text/tabwriter"
 
-	"cuelang.org/go/internal/legacy/cue"
+	"cuelang.org/go/cue"
 )
 
 // Write formats text in columns. See golang.org/pkg/text/tabwriter for more
diff --git a/pkg/text/template/manual.go b/pkg/text/template/manual.go
index fd8116c..646f5e8 100644
--- a/pkg/text/template/manual.go
+++ b/pkg/text/template/manual.go
@@ -18,7 +18,7 @@
 	"bytes"
 	"text/template"
 
-	"cuelang.org/go/internal/legacy/cue"
+	"cuelang.org/go/cue"
 )
 
 // Execute executes a Go-style template.
diff --git a/pkg/tool/cli/cli.go b/pkg/tool/cli/cli.go
index 01d9e28..8ba4878 100644
--- a/pkg/tool/cli/cli.go
+++ b/pkg/tool/cli/cli.go
@@ -20,7 +20,7 @@
 import (
 	"fmt"
 
-	"cuelang.org/go/internal/legacy/cue"
+	"cuelang.org/go/cue"
 	"cuelang.org/go/internal/task"
 )
 
diff --git a/pkg/tool/exec/exec.go b/pkg/tool/exec/exec.go
index c29e754..62c2cec 100644
--- a/pkg/tool/exec/exec.go
+++ b/pkg/tool/exec/exec.go
@@ -24,8 +24,8 @@
 
 	"golang.org/x/xerrors"
 
+	"cuelang.org/go/cue"
 	"cuelang.org/go/cue/errors"
-	"cuelang.org/go/internal/legacy/cue"
 	"cuelang.org/go/internal/task"
 )
 
diff --git a/pkg/tool/exec/exec_test.go b/pkg/tool/exec/exec_test.go
index eaf21c6..69e9484 100644
--- a/pkg/tool/exec/exec_test.go
+++ b/pkg/tool/exec/exec_test.go
@@ -20,7 +20,7 @@
 
 	"github.com/google/go-cmp/cmp"
 
-	"cuelang.org/go/internal/legacy/cue"
+	"cuelang.org/go/cue"
 	"cuelang.org/go/internal/task"
 )
 
diff --git a/pkg/tool/file/file.go b/pkg/tool/file/file.go
index bfdb8f0..7c206ca 100644
--- a/pkg/tool/file/file.go
+++ b/pkg/tool/file/file.go
@@ -22,7 +22,7 @@
 	"os"
 	"path/filepath"
 
-	"cuelang.org/go/internal/legacy/cue"
+	"cuelang.org/go/cue"
 	"cuelang.org/go/internal/task"
 )
 
diff --git a/pkg/tool/file/file_test.go b/pkg/tool/file/file_test.go
index aa04bdd..c9bc38f 100644
--- a/pkg/tool/file/file_test.go
+++ b/pkg/tool/file/file_test.go
@@ -22,9 +22,9 @@
 	"reflect"
 	"testing"
 
+	"cuelang.org/go/cue"
 	"cuelang.org/go/cue/parser"
 	"cuelang.org/go/internal"
-	"cuelang.org/go/internal/legacy/cue"
 	"cuelang.org/go/internal/task"
 )
 
diff --git a/pkg/tool/http/http.go b/pkg/tool/http/http.go
index b7c5f23..4c6f9e6 100644
--- a/pkg/tool/http/http.go
+++ b/pkg/tool/http/http.go
@@ -22,7 +22,7 @@
 	"io/ioutil"
 	"net/http"
 
-	"cuelang.org/go/internal/legacy/cue"
+	"cuelang.org/go/cue"
 	"cuelang.org/go/internal/task"
 )
 
diff --git a/pkg/tool/os/env.go b/pkg/tool/os/env.go
index 137a08c..0d0a535 100644
--- a/pkg/tool/os/env.go
+++ b/pkg/tool/os/env.go
@@ -21,10 +21,10 @@
 	"os"
 	"strings"
 
+	"cuelang.org/go/cue"
 	"cuelang.org/go/cue/ast"
 	"cuelang.org/go/cue/errors"
 	"cuelang.org/go/internal/cli"
-	"cuelang.org/go/internal/legacy/cue"
 	"cuelang.org/go/internal/task"
 )
 
diff --git a/pkg/tool/os/env_test.go b/pkg/tool/os/env_test.go
index 1a1d636..8a6d9fb 100644
--- a/pkg/tool/os/env_test.go
+++ b/pkg/tool/os/env_test.go
@@ -21,12 +21,12 @@
 	"github.com/google/go-cmp/cmp"
 	"github.com/google/go-cmp/cmp/cmpopts"
 
+	"cuelang.org/go/cue"
 	"cuelang.org/go/cue/ast"
 	"cuelang.org/go/cue/errors"
 	"cuelang.org/go/cue/parser"
 	"cuelang.org/go/cue/token"
 	"cuelang.org/go/internal"
-	"cuelang.org/go/internal/legacy/cue"
 	"cuelang.org/go/internal/task"
 )
 
diff --git a/tools/trim/trim.go b/tools/trim/trim.go
index 4ac7cc9..4af47a4 100644
--- a/tools/trim/trim.go
+++ b/tools/trim/trim.go
@@ -67,7 +67,7 @@
 	"cuelang.org/go/internal"
 
 	// "cuelang.org/go/cue"
-	"cuelang.org/go/internal/legacy/cue"
+	"cuelang.org/go/cue"
 )
 
 type Runtime = cue.Runtime
diff --git a/tools/trim/trim_test.go b/tools/trim/trim_test.go
index e3ede7f..28010bc 100644
--- a/tools/trim/trim_test.go
+++ b/tools/trim/trim_test.go
@@ -18,12 +18,12 @@
 	"flag"
 	"testing"
 
+	"cuelang.org/go/cue"
 	"cuelang.org/go/cue/ast"
 	"cuelang.org/go/cue/errors"
 	"cuelang.org/go/cue/format"
 	"cuelang.org/go/cue/parser"
 	"cuelang.org/go/internal/cuetxtar"
-	"cuelang.org/go/internal/legacy/cue"
 	"github.com/rogpeppe/go-internal/txtar"
 )