Skip to content

Commit

Permalink
internal/legacy/cue: update to new build
Browse files Browse the repository at this point in the history
Change-Id: I11752ef0df425970ca96dda73d362e10250d7059
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/6519
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
  • Loading branch information
mpvl committed Jul 22, 2020
1 parent 8912ee5 commit 7d54042
Show file tree
Hide file tree
Showing 19 changed files with 1,961 additions and 4,699 deletions.
11 changes: 11 additions & 0 deletions internal/core/convert/go.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,10 @@ import (
"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/runtime"
)

// This file contains functionality for converting Go to CUE.
Expand Down Expand Up @@ -220,6 +222,15 @@ func isNil(x reflect.Value) bool {
}

func convertRec(ctx *adt.OpContext, nilIsTop bool, x interface{}) adt.Value {
if internal.CoreValue != nil {
if ii, iv := internal.CoreValue(x); ii != nil {
i := ii.(*runtime.Index)
v := iv.(*adt.Vertex)
// TODO: panic if nto the same runtime.
_ = i
return v
}
}
src := ctx.Source()
switch v := x.(type) {
case nil:
Expand Down
10 changes: 6 additions & 4 deletions internal/core/convert/go_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

package convert
package convert_test

import (
"math/big"
Expand All @@ -25,9 +25,11 @@ import (

"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 }
Expand Down Expand Up @@ -187,7 +189,7 @@ func TestConvert(t *testing.T) {
e := eval.New(r)
ctx := adt.NewContext(r, e, &adt.Vertex{})
t.Run("", func(t *testing.T) {
v := GoValueToValue(ctx, tc.goVal, true)
v := convert.GoValueToValue(ctx, tc.goVal, true)
got := debug.NodeString(ctx, v, nil)
if got != tc.want {
t.Error(cmp.Diff(got, tc.want))
Expand All @@ -205,7 +207,7 @@ func TestX(t *testing.T) {
e := eval.New(r)
ctx := adt.NewContext(r, e, &adt.Vertex{})

v := GoValueToValue(ctx, x, false)
v := convert.GoValueToValue(ctx, x, false)
// if err != nil {
// t.Fatal(err)
// }
Expand Down Expand Up @@ -327,7 +329,7 @@ func TestConvertType(t *testing.T) {
t.Run("", func(t *testing.T) {
e := eval.New(r)
ctx := adt.NewContext(r, e, &adt.Vertex{})
v, _ := GoTypeToExpr(ctx, tc.goTyp)
v, _ := convert.GoTypeToExpr(ctx, tc.goTyp)
got := debug.NodeString(ctx, v, nil)
if got != tc.want {
t.Errorf("\n got %q;\nwant %q", got, tc.want)
Expand Down
4 changes: 4 additions & 0 deletions internal/internal.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@ var GetRuntime func(instance interface{}) interface{}
// GetRuntime reports the runtime for an Instance or Value.
var GetRuntimeNew func(instance interface{}) interface{}

// CoreValue returns an *runtime.Index and *adt.Vertex for a cue.Value.
// It returns nil if value is not a cue.Value.
var CoreValue func(value interface{}) (runtime, vertex interface{})

// MakeInstance makes a new instance from a value.
var MakeInstance func(value interface{}) (instance interface{})

Expand Down
35 changes: 15 additions & 20 deletions internal/legacy/cue/alias.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,34 +19,34 @@ import "cuelang.org/go/internal/core/adt"
type (
bottom = adt.Bottom
source = adt.Node
errCode = adt.ErrorCode
kind = adt.Kind
nullLit = adt.Null
boolLit = adt.Bool
numLit = adt.Num
stringLit = adt.String
bytesLit = adt.Bytes
context = adt.OpContext
structLit = adt.Vertex

arc = *adt.Vertex
value = adt.Expr
evaluated = adt.Value
label = adt.Feature
Op = adt.Op

listLit = adt.ListLit
top = adt.Top
basicType = adt.BasicType
boundExpr = adt.BoundExpr
boundValue = adt.BoundValue
selectorExpr = adt.SelectorExpr
indexExpr = adt.IndexExpr
sliceExpr = adt.SliceExpr
interpolation = adt.Interpolation
unaryExpr = adt.UnaryExpr
binaryExpr = adt.BinaryExpr
callExpr = adt.CallExpr
listLit = adt.ListLit
top = adt.Top
basicType = adt.BasicType
boundExpr = adt.BoundExpr
boundValue = adt.BoundValue
selectorExpr = adt.SelectorExpr
indexExpr = adt.IndexExpr
sliceExpr = adt.SliceExpr
interpolation = adt.Interpolation
unaryExpr = adt.UnaryExpr
binaryExpr = adt.BinaryExpr
callExpr = adt.CallExpr
disjunction = adt.DisjunctionExpr
dValue = adt.Disjunct
customValidator = adt.BuiltinValidator
)

const (
Expand All @@ -61,9 +61,4 @@ const (
listKind = adt.ListKind
structKind = adt.StructKind
bottomKind = adt.BottomKind

NoOp = adt.NoOp

codeIncomplete = adt.IncompleteError
codeNotExist = adt.IncompleteError
)
147 changes: 120 additions & 27 deletions internal/legacy/cue/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package cue

import (
"strings"
"sync"

"cuelang.org/go/cue/ast"
Expand All @@ -23,6 +24,8 @@ import (
"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"
)

Expand All @@ -38,7 +41,7 @@ type Runtime struct {
}

func init() {
internal.GetRuntime = func(instance interface{}) interface{} {
internal.GetRuntimeNew = func(instance interface{}) interface{} {
switch x := instance.(type) {
case Value:
return &Runtime{idx: x.idx}
Expand All @@ -51,14 +54,21 @@ func init() {
}
}

internal.CheckAndForkRuntime = func(runtime, value interface{}) interface{} {
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 }
Expand Down Expand Up @@ -192,6 +202,7 @@ func (r *Runtime) FromExpr(expr ast.Expr) (*Instance, error) {
//
// All instances belonging to the same package should share this index.
type index struct {
adt.Runtime
*runtime.Index

loaded map[*build.Instance]*Instance
Expand All @@ -201,16 +212,35 @@ type index struct {
// 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 {
Expand All @@ -219,30 +249,93 @@ func isBuiltin(s string) bool {
}

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
}

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
}

inst.complete = true
return inst
v.addErr(visitInstances(pkg, v.f))
}

0 comments on commit 7d54042

Please sign in to comment.