internal/core/runtime: add Build method
Build recursively compiles build.Instances and adds them
to the index.
Change-Id: I86da737449f66dee7d9f8124b68813b2d11d074a
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/6510
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
Reviewed-by: CUE cueckoo <cueckoo@gmail.com>
diff --git a/internal/core/runtime/runtime.go b/internal/core/runtime/runtime.go
index 00a68d1..258314a 100644
--- a/internal/core/runtime/runtime.go
+++ b/internal/core/runtime/runtime.go
@@ -16,10 +16,14 @@
import (
"reflect"
+ "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/internal/core/adt"
+ "cuelang.org/go/internal/core/compile"
)
// A Runtime maintains data structures for indexing and resuse for evaluation.
@@ -46,6 +50,66 @@
return x.index.StringToIndex(s)
}
+func (x *Runtime) Build(b *build.Instance) (v *adt.Vertex, errs errors.Error) {
+ if s := b.ImportPath; s != "" {
+ // Use cached result, if available.
+ if v, err := x.LoadImport(s); v != nil || err != nil {
+ return v, err
+ }
+ // Cache the result if any.
+ defer func() {
+ if errs == nil && v != nil {
+ x.index.AddInst(b.ImportPath, v, b)
+ }
+ }()
+ }
+
+ // Build transitive dependencies.
+ for _, file := range b.Files {
+ for _, d := range file.Decls {
+ switch g := d.(type) {
+ case *ast.Package:
+ case *ast.ImportDecl:
+ for _, s := range g.Specs {
+ errs = errors.Append(errs, x.buildSpec(b, s))
+ }
+ case *ast.CommentGroup:
+ default:
+ break
+ }
+ }
+ }
+
+ if errs != nil {
+ return nil, errs
+ }
+
+ return compile.Files(nil, x, b.Files...)
+}
+
+func (x *Runtime) buildSpec(b *build.Instance, spec *ast.ImportSpec) (errs errors.Error) {
+ info, err := astutil.ParseImportSpec(spec)
+ if err != nil {
+ return errors.Promote(err, "invalid import path")
+ }
+
+ pkg := b.LookupImport(info.ID)
+ if pkg == nil {
+ if strings.Contains(info.ID, ".") {
+ return errors.Newf(spec.Pos(),
+ "package %q imported but not defined in %s",
+ info.ID, b.ImportPath)
+ }
+ return nil // TODO: check the builtin package exists here.
+ }
+
+ if _, err := x.Build(pkg); err != nil {
+ return err
+ }
+
+ return nil
+}
+
func (x *Runtime) LoadImport(importPath string) (*adt.Vertex, errors.Error) {
v := x.index.GetImportFromPath(importPath)
if v == nil {