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/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/alias.go b/internal/legacy/cue/alias.go
deleted file mode 100644
index 83146a6..0000000
--- a/internal/legacy/cue/alias.go
+++ /dev/null
@@ -1,64 +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/core/adt"
-
-type (
- bottom = adt.Bottom
- source = adt.Node
- kind = adt.Kind
- nullLit = adt.Null
- boolLit = adt.Bool
- numLit = adt.Num
- stringLit = adt.String
- bytesLit = adt.Bytes
- structLit = adt.Vertex
-
- arc = *adt.Vertex
- value = adt.Expr
- evaluated = adt.Value
- label = adt.Feature
-
- 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 (
- topKind = adt.TopKind
- nullKind = adt.NullKind
- boolKind = adt.BoolKind
- numKind = adt.NumKind
- intKind = adt.IntKind
- floatKind = adt.FloatKind
- stringKind = adt.StringKind
- bytesKind = adt.BytesKind
- listKind = adt.ListKind
- structKind = adt.StructKind
- bottomKind = adt.BottomKind
-)
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/cue.go b/internal/legacy/cue/cue.go
deleted file mode 100644
index 2e0a031..0000000
--- a/internal/legacy/cue/cue.go
+++ /dev/null
@@ -1,17 +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 is a transition package for supporting the cue.Value API.
-// It aims to be plugin compatible with the old API.
-package cue
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.