blob: 90d3d51126f5ec117ba56798f399ceda0f0bdfe8 [file] [log] [blame]
// 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 adt
import (
"cuelang.org/go/cue/ast"
"cuelang.org/go/cue/token"
)
func Resolve(ctx *OpContext, c Conjunct) *Vertex {
env := c.Env
// TODO: also allow resolution in parent scopes. The following will set up
// the environments. But the compiler also needs to resolve accordingly.
//
// // Set up environments for parent scopes, if any.
// root := env
// for p := scope; p != nil; p = p.Parent {
// root.Up = &Environment{Vertex: p.Parent}
// root = root.Up
// }
var v Value
expr := c.Expr()
switch x := expr.(type) {
case Value:
v = x
case Resolver:
r, err := ctx.Resolve(env, x)
if err != nil {
v = err
break
}
return r
case Evaluator:
// TODO: have a way to evaluate, but not strip down to the value.
v, _ = ctx.Evaluate(env, expr)
default:
// Unknown type.
v = ctx.NewErrf(
"could not evaluate expression %s of type %T", ctx.Str(c.Expr()), c)
}
return ToVertex(v)
}
// A Node is any abstract data type representing an value or expression.
type Node interface {
Source() ast.Node
node() // enforce internal.
}
// A Decl represents all valid StructLit elements.
type Decl interface {
Node
declNode()
}
// An Elem represents all value ListLit elements.
//
// All Elem values can be used as a Decl.
type Elem interface {
Decl
elemNode()
}
// An Expr corresponds to an ast.Expr.
//
// All Expr values can be used as an Elem or Decl.
type Expr interface {
Elem
expr()
}
// A Value represents a node in the evaluated data graph.
//
// All Values values can also be used as a Expr.
type Value interface {
Expr
Concreteness() Concreteness
Kind() Kind
}
// An Evaluator provides a method to convert to a value.
type Evaluator interface {
Node
evaluate(ctx *OpContext) Value
}
// A Resolver represents a reference somewhere else within a tree that resolves
// a value.
type Resolver interface {
Node
resolve(ctx *OpContext) *Vertex
}
type YieldFunc func(env *Environment, s *StructLit)
// A Yielder represents 0 or more labeled values of structs or lists.
type Yielder interface {
Node
yield(ctx *OpContext, fn YieldFunc)
}
// A Validator validates a Value. All Validators are Values.
type Validator interface {
Value
validate(c *OpContext, v Value) *Bottom
}
// Pos returns the file position of n, or token.NoPos if it is unknown.
func Pos(n Node) token.Pos {
src := n.Source()
if src == nil {
return token.NoPos
}
return src.Pos()
}
// Value
func (x *Vertex) Concreteness() Concreteness {
// Depends on concreteness of value.
if x.Value == nil {
return Concrete // Should be indetermined.
}
return x.Value.Concreteness()
}
func (x *NodeLink) Concreteness() Concreteness { return Concrete }
func (x *ListMarker) Concreteness() Concreteness { return Concrete }
func (x *StructMarker) Concreteness() Concreteness { return Concrete }
func (*Conjunction) Concreteness() Concreteness { return Constraint }
func (*Disjunction) Concreteness() Concreteness { return Constraint }
func (*BoundValue) Concreteness() Concreteness { return Constraint }
// Constraint only applies if Builtin is used as constraint.
func (*Builtin) Concreteness() Concreteness { return Constraint }
func (*BuiltinValidator) Concreteness() Concreteness { return Constraint }
// Value and Expr
func (*Bottom) Concreteness() Concreteness { return BottomLevel }
func (*Null) Concreteness() Concreteness { return Concrete }
func (*Bool) Concreteness() Concreteness { return Concrete }
func (*Num) Concreteness() Concreteness { return Concrete }
func (*String) Concreteness() Concreteness { return Concrete }
func (*Bytes) Concreteness() Concreteness { return Concrete }
func (*Top) Concreteness() Concreteness { return Any }
func (*BasicType) Concreteness() Concreteness { return Type }
// Expr
func (*StructLit) expr() {}
func (*ListLit) expr() {}
func (*DisjunctionExpr) expr() {}
// Expr and Value
func (*Bottom) expr() {}
func (*Null) expr() {}
func (*Bool) expr() {}
func (*Num) expr() {}
func (*String) expr() {}
func (*Bytes) expr() {}
func (*Top) expr() {}
func (*BasicType) expr() {}
func (*Vertex) expr() {}
func (*ListMarker) expr() {}
func (*StructMarker) expr() {}
func (*Conjunction) expr() {}
func (*Disjunction) expr() {}
func (*BoundValue) expr() {}
func (*BuiltinValidator) expr() {}
func (*Builtin) expr() {}
// Expr and Resolver
func (*NodeLink) expr() {}
func (*FieldReference) expr() {}
func (*LabelReference) expr() {}
func (*DynamicReference) expr() {}
func (*ImportReference) expr() {}
func (*LetReference) expr() {}
// Expr and Evaluator
func (*BoundExpr) expr() {}
func (*SelectorExpr) expr() {}
func (*IndexExpr) expr() {}
func (*SliceExpr) expr() {}
func (*Interpolation) expr() {}
func (*UnaryExpr) expr() {}
func (*BinaryExpr) expr() {}
func (*CallExpr) expr() {}
// Decl and Expr (so allow attaching original source in Conjunct)
func (*Field) declNode() {}
func (x *Field) expr() Expr { return x.Value }
func (*OptionalField) declNode() {}
func (x *OptionalField) expr() Expr { return x.Value }
func (*BulkOptionalField) declNode() {}
func (x *BulkOptionalField) expr() Expr { return x.Value }
func (*DynamicField) declNode() {}
func (x *DynamicField) expr() Expr { return x.Value }
// Decl and Yielder
func (*LetClause) declNode() {}
// Decl and Elem
func (*StructLit) declNode() {}
func (*StructLit) elemNode() {}
func (*ListLit) declNode() {}
func (*ListLit) elemNode() {}
func (*Ellipsis) elemNode() {}
func (*Ellipsis) declNode() {}
func (*Bottom) declNode() {}
func (*Bottom) elemNode() {}
func (*Null) declNode() {}
func (*Null) elemNode() {}
func (*Bool) declNode() {}
func (*Bool) elemNode() {}
func (*Num) declNode() {}
func (*Num) elemNode() {}
func (*String) declNode() {}
func (*String) elemNode() {}
func (*Bytes) declNode() {}
func (*Bytes) elemNode() {}
func (*Top) declNode() {}
func (*Top) elemNode() {}
func (*BasicType) declNode() {}
func (*BasicType) elemNode() {}
func (*BoundExpr) declNode() {}
func (*BoundExpr) elemNode() {}
func (*Vertex) declNode() {}
func (*Vertex) elemNode() {}
func (*ListMarker) declNode() {}
func (*ListMarker) elemNode() {}
func (*StructMarker) declNode() {}
func (*StructMarker) elemNode() {}
func (*Conjunction) declNode() {}
func (*Conjunction) elemNode() {}
func (*Disjunction) declNode() {}
func (*Disjunction) elemNode() {}
func (*BoundValue) declNode() {}
func (*BoundValue) elemNode() {}
func (*BuiltinValidator) declNode() {}
func (*BuiltinValidator) elemNode() {}
func (*NodeLink) declNode() {}
func (*NodeLink) elemNode() {}
func (*FieldReference) declNode() {}
func (*FieldReference) elemNode() {}
func (*LabelReference) declNode() {}
func (*LabelReference) elemNode() {}
func (*DynamicReference) declNode() {}
func (*DynamicReference) elemNode() {}
func (*ImportReference) declNode() {}
func (*ImportReference) elemNode() {}
func (*LetReference) declNode() {}
func (*LetReference) elemNode() {}
func (*SelectorExpr) declNode() {}
func (*SelectorExpr) elemNode() {}
func (*IndexExpr) declNode() {}
func (*IndexExpr) elemNode() {}
func (*SliceExpr) declNode() {}
func (*SliceExpr) elemNode() {}
func (*Interpolation) declNode() {}
func (*Interpolation) elemNode() {}
func (*UnaryExpr) declNode() {}
func (*UnaryExpr) elemNode() {}
func (*BinaryExpr) declNode() {}
func (*BinaryExpr) elemNode() {}
func (*CallExpr) declNode() {}
func (*CallExpr) elemNode() {}
func (*Builtin) declNode() {}
func (*Builtin) elemNode() {}
func (*DisjunctionExpr) declNode() {}
func (*DisjunctionExpr) elemNode() {}
// Decl, Elem, and Yielder
func (*ForClause) declNode() {}
func (*ForClause) elemNode() {}
func (*IfClause) declNode() {}
func (*IfClause) elemNode() {}
// Yielder only: ValueClause
// Node
func (*Vertex) node() {}
func (*Conjunction) node() {}
func (*Disjunction) node() {}
func (*BoundValue) node() {}
func (*Builtin) node() {}
func (*BuiltinValidator) node() {}
func (*Bottom) node() {}
func (*Null) node() {}
func (*Bool) node() {}
func (*Num) node() {}
func (*String) node() {}
func (*Bytes) node() {}
func (*Top) node() {}
func (*BasicType) node() {}
func (*StructLit) node() {}
func (*ListLit) node() {}
func (*BoundExpr) node() {}
func (*NodeLink) node() {}
func (*FieldReference) node() {}
func (*LabelReference) node() {}
func (*DynamicReference) node() {}
func (*ImportReference) node() {}
func (*LetReference) node() {}
func (*SelectorExpr) node() {}
func (*IndexExpr) node() {}
func (*SliceExpr) node() {}
func (*Interpolation) node() {}
func (*UnaryExpr) node() {}
func (*BinaryExpr) node() {}
func (*CallExpr) node() {}
func (*DisjunctionExpr) node() {}
func (*Field) node() {}
func (*OptionalField) node() {}
func (*BulkOptionalField) node() {}
func (*DynamicField) node() {}
func (*Ellipsis) node() {}
func (*ForClause) node() {}
func (*IfClause) node() {}
func (*LetClause) node() {}
func (*ValueClause) node() {}