This repository has been archived on 2024-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
dagger/compiler/compiler.go

144 lines
2.9 KiB
Go
Raw Normal View History

package compiler
import (
"errors"
"sync"
"cuelang.org/go/cue"
"cuelang.org/go/cue/cuecontext"
cueerrors "cuelang.org/go/cue/errors"
cuejson "cuelang.org/go/encoding/json"
cueyaml "cuelang.org/go/encoding/yaml"
)
var (
// DefaultCompiler is the default Compiler and is used by Compile
DefaultCompiler = New()
)
func Compile(name string, src string) (*Value, error) {
return DefaultCompiler.Compile(name, src)
}
func NewValue() *Value {
return DefaultCompiler.NewValue()
}
func NewValueWithContent(x interface{}, selectors ...cue.Selector) (*Value, error) {
return DefaultCompiler.NewValueWithContent(x, selectors...)
}
// FIXME can be refactored away now?
func Wrap(v cue.Value) *Value {
return DefaultCompiler.Wrap(v)
}
func Err(err error) error {
return DefaultCompiler.Err(err)
}
func DecodeJSON(path string, data []byte) (*Value, error) {
return DefaultCompiler.DecodeJSON(path, data)
}
func DecodeYAML(path string, data []byte) (*Value, error) {
return DefaultCompiler.DecodeYAML(path, data)
}
// Polyfill for a cue runtime
// (we call it compiler to avoid confusion with dagger runtime)
// Use this instead of cue.Runtime
type Compiler struct {
l sync.RWMutex
*cue.Context
}
func New() *Compiler {
return &Compiler{
Context: cuecontext.New(),
}
}
func (c *Compiler) lock() {
c.l.Lock()
}
func (c *Compiler) unlock() {
c.l.Unlock()
}
func (c *Compiler) rlock() {
c.l.RLock()
}
func (c *Compiler) runlock() {
c.l.RUnlock()
}
// Compile an empty value
func (c *Compiler) NewValue() *Value {
empty, err := c.Compile("", "_")
if err != nil {
panic(err)
}
return empty
}
func (c *Compiler) NewValueWithContent(x interface{}, selectors ...cue.Selector) (*Value, error) {
v := c.NewValue()
if err := v.FillPath(cue.MakePath(selectors...), x); err != nil {
return nil, err
}
return v, nil
}
func (c *Compiler) Compile(name string, src string) (*Value, error) {
c.lock()
defer c.unlock()
v := c.Context.CompileString(src, cue.Filename(name))
if v.Err() != nil {
// FIXME: cleaner way to unwrap cue error details?
return nil, Err(v.Err())
}
return c.Wrap(v), nil
}
func (c *Compiler) DecodeJSON(path string, data []byte) (*Value, error) {
expr, err := cuejson.Extract(path, data)
if err != nil {
return nil, Err(err)
}
v := c.Context.BuildExpr(expr, cue.Filename(path))
if err := v.Err(); err != nil {
return nil, Err(err)
}
return c.Wrap(v), nil
}
func (c *Compiler) DecodeYAML(path string, data []byte) (*Value, error) {
f, err := cueyaml.Extract(path, data)
if err != nil {
return nil, Err(err)
}
v := c.Context.BuildFile(f, cue.Filename(path))
if err := v.Err(); err != nil {
return nil, Err(err)
}
return c.Wrap(v), nil
}
func (c *Compiler) Wrap(v cue.Value) *Value {
return &Value{
val: v,
cc: c,
}
}
func (c *Compiler) Err(err error) error {
if err == nil {
return nil
}
return errors.New(cueerrors.Details(err, &cueerrors.Config{}))
}