// 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 (
	"fmt"
	"log"
	"os"
	"reflect"
	"regexp"

	"github.com/cockroachdb/apd/v2"
	"golang.org/x/text/encoding/unicode"

	"cuelang.org/go/cue/ast"
	"cuelang.org/go/cue/errors"
	"cuelang.org/go/cue/token"
)

// Debug sets whether extra aggressive checking should be done.
// This should typically default to true for pre-releases and default to
// false otherwise.
var Debug bool = os.Getenv("CUE_DEBUG") != "0"

// Verbosity sets the log level. There are currently only two levels:
//   0: no logging
//   1: logging
var Verbosity int

// Assert panics if the condition is false. Assert can be used to check for
// conditions that are considers to break an internal variant or unexpected
// condition, but that nonetheless probably will be handled correctly down the
// line. For instance, a faulty condition could lead to to error being caught
// down the road, but resulting in an inaccurate error message. In production
// code it is better to deal with the bad error message than to panic.
//
// It is advisable for each use of Assert to document how the error is expected
// to be handled down the line.
func Assertf(b bool, format string, args ...interface{}) {
	if Debug && !b {
		panic(fmt.Sprintf("assertion failed: "+format, args...))
	}
}

// Assertf either panics or reports an error to c if the condition is not met.
func (c *OpContext) Assertf(pos token.Pos, b bool, format string, args ...interface{}) {
	if !b {
		if Debug {
			panic(fmt.Sprintf("assertion failed: "+format, args...))
		}
		c.addErrf(0, pos, format, args...)
	}
}

func init() {
	log.SetFlags(log.Lshortfile)
}

func Logf(format string, args ...interface{}) {
	if Verbosity == 0 {
		return
	}
	s := fmt.Sprintf(format, args...)
	_ = log.Output(2, s)
}

var pMap = map[*Vertex]int{}

func (c *OpContext) Logf(v *Vertex, format string, args ...interface{}) {
	if Verbosity == 0 {
		return
	}
	p := pMap[v]
	if p == 0 {
		p = len(pMap) + 1
		pMap[v] = p
	}
	a := append([]interface{}{
		p,
		v.Label.SelectorString(c),
		v.Path(),
	}, args...)
	for i := 2; i < len(a); i++ {
		switch x := a[i].(type) {
		case Node:
			a[i] = c.Str(x)
		case Feature:
			a[i] = x.SelectorString(c)
		}
	}
	s := fmt.Sprintf(" [%d] %s/%v"+format, a...)
	_ = log.Output(2, s)
}

// Runtime defines an interface for low-level representation conversion and
// lookup.
type Runtime interface {
	// StringIndexer allows for converting string labels to and from a
	// canonical numeric representation.
	StringIndexer

	// LoadImport loads a unique Vertex associated with a given import path. It
	// returns an error if no import for this package could be found.
	LoadImport(importPath string) (*Vertex, errors.Error)

	// StoreType associates a CUE expression with a Go type.
	StoreType(t reflect.Type, src ast.Expr, expr Expr)

	// LoadType retrieves a previously stored CUE expression for a given Go
	// type if available.
	LoadType(t reflect.Type) (src ast.Expr, expr Expr, ok bool)
}

type Config struct {
	Runtime
	Format func(Node) string
}

// New creates an operation context.
func New(v *Vertex, cfg *Config) *OpContext {
	if cfg.Runtime == nil {
		panic("nil Runtime")
	}
	ctx := &OpContext{
		Runtime: cfg.Runtime,
		Format:  cfg.Format,
		vertex:  v,
	}
	if v != nil {
		ctx.e = &Environment{Up: nil, Vertex: v}
	}
	return ctx
}

// An OpContext implements CUE's unification operation. It's operations only
// operation on values that are created with the Runtime with which an OpContext
// is associated. An OpContext is not goroutine save and only one goroutine may
// use an OpContext at a time.
//
type OpContext struct {
	Runtime
	Format func(Node) string

	stats        Stats
	freeListNode *nodeContext

	e         *Environment
	src       ast.Node
	errs      *Bottom
	positions []Node // keep track of error positions

	// vertex is used to determine the path location in case of error. Turning
	// this into a stack could also allow determining the cyclic path for
	// structural cycle errors.
	vertex *Vertex

	nonMonotonicLookupNest int32
	nonMonotonicRejectNest int32
	nonMonotonicInsertNest int32
	nonMonotonicGeneration int32

	// These fields are used associate scratch fields for computing closedness
	// of a Vertex. These fields could have been included in StructInfo (like
	// Tomabechi's unification algorithm), but we opted for an indirection to
	// allow concurrent unification.
	//
	// TODO(perf): have two generations: one for each pass of the closedness
	// algorithm, so that the results of the first pass can be reused for all
	// features of a node.
	generation int
	closed     map[*closeInfo]*closeStats
	todo       *closeStats

	// inDisjunct indicates that non-monotonic checks should be skipped.
	// This is used if we want to do some extra work to eliminate disjunctions
	// early. The result of unificantion should be thrown away if this check is
	// used.
	//
	// TODO: replace this with a mechanism to determine the correct set (per
	// conjunct) of StructInfos to include in closedness checking.
	inDisjunct int

	// inConstaint overrides inDisjunct as field matching should always be
	// enabled.
	inConstraint int
}

func (n *nodeContext) skipNonMonotonicChecks() bool {
	if n.ctx.inConstraint > 0 {
		return false
	}
	return n.ctx.inDisjunct > 0
}

// Impl is for internal use only. This will go.
func (c *OpContext) Impl() Runtime {
	return c.Runtime
}

func (c *OpContext) Pos() token.Pos {
	if c.src == nil {
		return token.NoPos
	}
	return c.src.Pos()
}

func (c *OpContext) Source() ast.Node {
	return c.src
}

// NewContext creates an operation context.
func NewContext(r Runtime, v *Vertex) *OpContext {
	return New(v, &Config{Runtime: r})
}

func (c *OpContext) pos() token.Pos {
	if c.src == nil {
		return token.NoPos
	}
	return c.src.Pos()
}

func (c *OpContext) spawn(node *Vertex) *Environment {
	node.Parent = c.e.Vertex // TODO: Is this necessary?
	return &Environment{
		Up:     c.e,
		Vertex: node,

		// Copy cycle data.
		Cyclic: c.e.Cyclic,
		Deref:  c.e.Deref,
		Cycles: c.e.Cycles,
	}
}

func (c *OpContext) Env(upCount int32) *Environment {
	e := c.e
	for ; upCount > 0; upCount-- {
		e = e.Up
	}
	return e
}

func (c *OpContext) relNode(upCount int32) *Vertex {
	e := c.e
	for ; upCount > 0; upCount-- {
		e = e.Up
	}
	c.Unify(e.Vertex, Partial)
	return e.Vertex
}

func (c *OpContext) relLabel(upCount int32) Feature {
	// locate current label.
	e := c.e
	for ; upCount > 0; upCount-- {
		e = e.Up
	}
	return e.DynamicLabel
}

func (c *OpContext) concreteIsPossible(op Op, x Expr) bool {
	if !AssertConcreteIsPossible(op, x) {
		// No need to take position of expression.
		c.AddErr(c.NewPosf(token.NoPos,
			"invalid operand %s ('%s' requires concrete value)", x, op))
		return false
	}
	return true
}

// Assert that the given expression can evaluate to a concrete value.
func AssertConcreteIsPossible(op Op, x Expr) bool {
	switch v := x.(type) {
	case *Bottom:
	case *BoundExpr:
		return false
	case Value:
		return v.Concreteness() == Concrete
	}
	return true
}

// HasErr reports whether any error was reported, including whether value
// was incomplete.
func (c *OpContext) HasErr() bool {
	return c.errs != nil
}

func (c *OpContext) Err() *Bottom {
	b := c.errs
	c.errs = nil
	return b
}

func (c *OpContext) addErrf(code ErrorCode, pos token.Pos, msg string, args ...interface{}) {
	err := c.NewPosf(pos, msg, args...)
	c.addErr(code, err)
}

func (c *OpContext) addErr(code ErrorCode, err errors.Error) {
	c.AddBottom(&Bottom{Code: code, Err: err})
}

// AddBottom records an error in OpContext.
func (c *OpContext) AddBottom(b *Bottom) {
	c.errs = CombineErrors(c.src, c.errs, b)
}

// AddErr records an error in OpContext. It returns errors collected so far.
func (c *OpContext) AddErr(err errors.Error) *Bottom {
	if err != nil {
		c.AddBottom(&Bottom{Err: err})
	}
	return c.errs
}

// NewErrf creates a *Bottom value and returns it. The returned uses the
// current source as the point of origin of the error.
func (c *OpContext) NewErrf(format string, args ...interface{}) *Bottom {
	// TODO: consider renaming ot NewBottomf: this is now confusing as we also
	// have Newf.
	err := c.Newf(format, args...)
	return &Bottom{Src: c.src, Err: err, Code: EvalError}
}

// AddErrf records an error in OpContext. It returns errors collected so far.
func (c *OpContext) AddErrf(format string, args ...interface{}) *Bottom {
	return c.AddErr(c.Newf(format, args...))
}

type frame struct {
	env *Environment
	err *Bottom
	src ast.Node
}

func (c *OpContext) PushState(env *Environment, src ast.Node) (saved frame) {
	saved.env = c.e
	saved.err = c.errs
	saved.src = c.src

	c.errs = nil
	if src != nil {
		c.src = src
	}
	c.e = env

	return saved
}

func (c *OpContext) PopState(s frame) *Bottom {
	err := c.errs
	c.e = s.env
	c.errs = s.err
	c.src = s.src
	return err
}

// PushArc signals c that arc v is currently being processed for the purpose
// of error reporting. PopArc should be called with the returned value once
// processing of v is completed.
func (c *OpContext) PushArc(v *Vertex) (saved *Vertex) {
	c.vertex, saved = v, c.vertex
	return saved
}

// PopArc signals completion of processing the current arc.
func (c *OpContext) PopArc(saved *Vertex) {
	c.vertex = saved
}

// Resolve finds a node in the tree.
//
// Should only be used to insert Conjuncts. TODO: perhaps only return Conjuncts
// and error.
func (c *OpContext) Resolve(env *Environment, r Resolver) (*Vertex, *Bottom) {
	s := c.PushState(env, r.Source())

	arc := r.resolve(c, Partial)

	err := c.PopState(s)
	if err != nil {
		return nil, err
	}

	if arc.ChildErrors != nil && arc.ChildErrors.Code == StructuralCycleError {
		return nil, arc.ChildErrors
	}

	for {
		x, ok := arc.BaseValue.(*Vertex)
		if !ok {
			break
		}
		arc = x
	}

	return arc, err
}

// Validate calls validates value for the given validator.
//
// TODO(errors): return boolean instead: only the caller has enough information
// to generate a proper error message.
func (c *OpContext) Validate(check Validator, value Value) *Bottom {
	// TODO: use a position stack to push both values.
	saved := c.src
	c.src = check.Source()

	err := check.validate(c, value)

	c.src = saved

	return err
}

// Yield evaluates a Yielder and calls f for each result.
func (c *OpContext) Yield(env *Environment, y Yielder, f YieldFunc) *Bottom {
	s := c.PushState(env, y.Source())

	y.yield(c, f)

	return c.PopState(s)

}

// Concrete returns the concrete value of x after evaluating it.
// msg is used to mention the context in which an error occurred, if any.
func (c *OpContext) Concrete(env *Environment, x Expr, msg interface{}) (result Value, complete bool) {

	w, complete := c.Evaluate(env, x)

	w, ok := c.getDefault(w)
	if !ok {
		return w, false
	}
	v := Unwrap(w)

	if !IsConcrete(v) {
		complete = false
		b := c.NewErrf("non-concrete value %v in operand to %s", w, msg)
		b.Code = IncompleteError
		v = b
	}

	if !complete {
		return v, complete
	}

	return v, true
}

// getDefault resolves a disjunction to a single value. If there is no default
// value, or if there is more than one default value, it reports an "incomplete"
// error and return false. In all other cases it will return true, even if
// v is already an error. v may be nil, in which case it will also return nil.
func (c *OpContext) getDefault(v Value) (result Value, ok bool) {
	var d *Disjunction
	switch x := v.(type) {
	default:
		return v, true

	case *Vertex:
		// TODO: return vertex if not disjunction.
		switch t := x.BaseValue.(type) {
		case *Disjunction:
			d = t

		case *Vertex:
			return c.getDefault(t)

		default:
			return x, true
		}

	case *Disjunction:
		d = x
	}

	if d.NumDefaults != 1 {
		c.addErrf(IncompleteError, c.pos(),
			"unresolved disjunction %s (type %s)", d, d.Kind())
		return nil, false
	}
	return c.getDefault(d.Values[0])
}

// Evaluate evaluates an expression within the given environment and indicates
// whether the result is complete. It will always return a non-nil result.
func (c *OpContext) Evaluate(env *Environment, x Expr) (result Value, complete bool) {
	s := c.PushState(env, x.Source())

	val := c.evalState(x, Partial)

	complete = true

	if err, _ := val.(*Bottom); err != nil && err.IsIncomplete() {
		complete = false
	}
	if val == nil {
		complete = false
		// TODO ENSURE THIS DOESN"T HAPPEN>
		val = &Bottom{
			Code: IncompleteError,
			Err:  c.Newf("UNANTICIPATED ERROR"),
		}

	}

	_ = c.PopState(s)

	if !complete || val == nil {
		return val, false
	}

	return val, true
}

func (c *OpContext) evaluateRec(env *Environment, x Expr, state VertexStatus) Value {
	s := c.PushState(env, x.Source())

	val := c.evalState(x, state)
	if val == nil {
		// Be defensive: this never happens, but just in case.
		Assertf(false, "nil return value: unspecified error")
		val = &Bottom{
			Code: IncompleteError,
			Err:  c.Newf("UNANTICIPATED ERROR"),
		}
	}
	_ = c.PopState(s)

	return val
}

// value evaluates expression v within the current environment. The result may
// be nil if the result is incomplete. value leaves errors untouched to that
// they can be collected by the caller.
func (c *OpContext) value(x Expr) (result Value) {
	v := c.evalState(x, Partial)

	v, _ = c.getDefault(v)
	v = Unwrap(v)
	return v
}

func (c *OpContext) evalState(v Expr, state VertexStatus) (result Value) {
	savedSrc := c.src
	c.src = v.Source()
	err := c.errs
	c.errs = nil

	defer func() {
		c.errs = CombineErrors(c.src, c.errs, err)

		if v, ok := result.(*Vertex); ok {
			if b, _ := v.BaseValue.(*Bottom); b != nil {
				switch b.Code {
				case IncompleteError:
				case CycleError:
					if state == Partial {
						break
					}
					fallthrough
				default:
					result = b
				}
			}
		}

		// TODO: remove this when we handle errors more principally.
		if b, ok := result.(*Bottom); ok {
			if c.src != nil &&
				b.Code == CycleError &&
				len(errors.Positions(b.Err)) == 0 {
				bb := *b
				bb.Err = errors.Wrapf(b.Err, c.src.Pos(), "")
				result = &bb
			}
			if c.errs != result {
				c.errs = CombineErrors(c.src, c.errs, result)
			}
		}
		if c.errs != nil {
			result = c.errs
		}
		c.src = savedSrc
	}()

	switch x := v.(type) {
	case Value:
		return x

	case Evaluator:
		v := x.evaluate(c)
		return v

	case Resolver:
		arc := x.resolve(c, state)
		if c.HasErr() {
			return nil
		}
		if arc == nil {
			return nil
		}

		v := c.evaluate(arc, state)
		return v

	default:
		// This can only happen, really, if v == nil, which is not allowed.
		panic(fmt.Sprintf("unexpected Expr type %T", v))
	}
}

// unifyNode returns a possibly partially evaluated node value.
//
// TODO: maybe return *Vertex, *Bottom
//
func (c *OpContext) unifyNode(v Expr, state VertexStatus) (result Value) {
	savedSrc := c.src
	c.src = v.Source()
	err := c.errs
	c.errs = nil

	defer func() {
		c.errs = CombineErrors(c.src, c.errs, err)

		if v, ok := result.(*Vertex); ok {
			if b, _ := v.BaseValue.(*Bottom); b != nil {
				switch b.Code {
				case IncompleteError:
				case CycleError:
					if state == Partial {
						break
					}
					fallthrough
				default:
					result = b
				}
			}
		}

		// TODO: remove this when we handle errors more principally.
		if b, ok := result.(*Bottom); ok {
			if c.src != nil &&
				b.Code == CycleError &&
				b.Err.Position() == token.NoPos &&
				len(b.Err.InputPositions()) == 0 {
				bb := *b
				bb.Err = errors.Wrapf(b.Err, c.src.Pos(), "")
				result = &bb
			}
			c.errs = CombineErrors(c.src, c.errs, result)
		}
		if c.errs != nil {
			result = c.errs
		}
		c.src = savedSrc
	}()

	switch x := v.(type) {
	case Value:
		return x

	case Evaluator:
		v := x.evaluate(c)
		return v

	case Resolver:
		v := x.resolve(c, state)
		if c.HasErr() {
			return nil
		}
		if v == nil {
			return nil
		}

		if v.isUndefined() {
			// Use node itself to allow for cycle detection.
			c.Unify(v, AllArcs)
		}

		return v

	default:
		// This can only happen, really, if v == nil, which is not allowed.
		panic(fmt.Sprintf("unexpected Expr type %T", v))
	}
}

func (c *OpContext) lookup(x *Vertex, pos token.Pos, l Feature, state VertexStatus) *Vertex {
	if l == InvalidLabel || x == nil {
		// TODO: is it possible to have an invalid label here? Maybe through the
		// API?
		return &Vertex{}
	}

	// var kind Kind
	// if x.BaseValue != nil {
	// 	kind = x.BaseValue.Kind()
	// }

	switch x.BaseValue.(type) {
	case *StructMarker:
		if l.Typ() == IntLabel {
			c.addErrf(0, pos, "invalid struct selector %s (type int)", l)
			return nil
		}

	case *ListMarker:
		switch {
		case l.Typ() == IntLabel:
			switch {
			case l.Index() < 0:
				c.addErrf(0, pos, "invalid list index %s (index must be non-negative)", l)
				return nil
			case l.Index() > len(x.Arcs):
				c.addErrf(0, pos, "invalid list index %s (out of bounds)", l)
				return nil
			}

		case l.IsDef(), l.IsHidden():

		default:
			c.addErrf(0, pos, "invalid list index %s (type string)", l)
			return nil
		}

	case nil:
		// c.addErrf(IncompleteError, pos, "incomplete value %s", x)
		// return nil

	case *Bottom:

	default:
		kind := x.BaseValue.Kind()
		if kind&(ListKind|StructKind) != 0 {
			// c.addErrf(IncompleteError, pos,
			// 	"cannot look up %s in incomplete type %s (type %s)",
			// 	l, x.Source(), kind)
			// return nil
		} else if !l.IsDef() && !l.IsHidden() {
			c.addErrf(0, pos,
				"invalid selector %s for value of type %s", l, kind)
			return nil
		}
	}

	a := x.Lookup(l)

	var hasCycle bool
outer:
	switch {
	case c.nonMonotonicLookupNest == 0 && c.nonMonotonicRejectNest == 0:
	case a != nil:
		if state == Partial {
			a.nonMonotonicLookupGen = c.nonMonotonicGeneration
		}

	case x.state != nil && state == Partial:
		for _, e := range x.state.exprs {
			if isCyclePlaceholder(e.err) {
				hasCycle = true
			}
		}
		for _, a := range x.state.usedArcs {
			if a.Label == l {
				a.nonMonotonicLookupGen = c.nonMonotonicGeneration
				if c.nonMonotonicRejectNest > 0 {
					a.nonMonotonicReject = true
				}
				break outer
			}
		}
		a := &Vertex{Label: l, nonMonotonicLookupGen: c.nonMonotonicGeneration}
		if c.nonMonotonicRejectNest > 0 {
			a.nonMonotonicReject = true
		}
		x.state.usedArcs = append(x.state.usedArcs, a)
	}
	if a == nil {
		if x.state != nil {
			for _, e := range x.state.exprs {
				if isCyclePlaceholder(e.err) {
					hasCycle = true
				}
			}
		}
		code := IncompleteError
		if !x.Accept(c, l) {
			code = 0
		} else if hasCycle {
			code = CycleError
		}
		// TODO: if the struct was a literal struct, we can also treat it as
		// closed and make this a permanent error.
		label := l.SelectorString(c.Runtime)

		// TODO(errors): add path reference and make message
		//       "undefined field %s in %s"
		if l.IsInt() {
			c.addErrf(code, pos, "index out of range [%d] with length %d",
				l.Index(), len(x.Elems()))
		} else {
			if code != 0 && x.IsOptional(l) {
				c.addErrf(code, pos,
					"cannot reference optional field: %s", label)
			} else {
				c.addErrf(code, pos, "undefined field: %s", label)
			}
		}
	}
	return a
}

func (c *OpContext) Label(src Expr, x Value) Feature {
	return labelFromValue(c, src, x)
}

func (c *OpContext) typeError(v Value, k Kind) {
	if isError(v) {
		return
	}
	if !IsConcrete(v) && v.Kind()&k != 0 {
		c.addErrf(IncompleteError, pos(v), "incomplete %s: %s", k, v)
	} else {
		c.AddErrf("cannot use %s (type %s) as type %s", v, v.Kind(), k)
	}
}

func (c *OpContext) typeErrorAs(v Value, k Kind, as interface{}) {
	if as == nil {
		c.typeError(v, k)
		return
	}
	if isError(v) {
		return
	}
	if !IsConcrete(v) && v.Kind()&k != 0 {
		c.addErrf(IncompleteError, pos(v),
			"incomplete %s in %v: %s", k, as, v)
	} else {
		c.AddErrf("cannot use %s (type %s) as type %s in %v", v, v.Kind(), k, as)
	}
}

var emptyNode = &Vertex{}

func pos(x Node) token.Pos {
	if x.Source() == nil {
		return token.NoPos
	}
	return x.Source().Pos()
}

func (c *OpContext) node(orig Node, x Expr, scalar bool, state VertexStatus) *Vertex {
	// TODO: always get the vertex. This allows a whole bunch of trickery
	// down the line.
	v := c.unifyNode(x, state)

	v, ok := c.getDefault(v)
	if !ok {
		// Error already generated by getDefault.
		return emptyNode
	}

	// The two if blocks below are rather subtle. If we have an error of
	// the sentinel value cycle, we have earlier determined that the cycle is
	// allowed and that it can be ignored here. Any other CycleError is an
	// annotated cycle error that could be taken as is.
	// TODO: do something simpler.
	if scalar {
		if w := Unwrap(v); !isCyclePlaceholder(w) {
			v = w
		}
	}

	node, ok := v.(*Vertex)
	if ok && !isCyclePlaceholder(node.BaseValue) {
		v = node.Value()
	}

	switch nv := v.(type) {
	case nil:
		switch orig.(type) {
		case *ForClause:
			c.addErrf(IncompleteError, pos(x),
				"cannot range over %s (incomplete)", x)
		default:
			c.addErrf(IncompleteError, pos(x),
				"%s undefined (%s is incomplete)", orig, x)
		}
		return emptyNode

	case *Bottom:
		// TODO: this is a bit messy. In some cases errors are already added
		// and in some cases not. Not a huge deal, as errors will be uniqued
		// down the line, but could be better.
		c.AddBottom(nv)
		return emptyNode

	case *Vertex:
		if node == nil {
			panic("unexpected markers with nil node")
		}

	default:
		if kind := v.Kind(); kind&StructKind != 0 {
			switch orig.(type) {
			case *ForClause:
				c.addErrf(IncompleteError, pos(x),
					"cannot range over %s (incomplete type %s)", x, kind)
			default:
				c.addErrf(IncompleteError, pos(x),
					"%s undefined as %s is incomplete (type %s)", orig, x, kind)
			}
			return emptyNode

		} else if !ok {
			c.addErrf(0, pos(x), // TODO(error): better message.
				"invalid operand %s (found %s, want list or struct)",
				x.Source(), v.Kind())
			return emptyNode
		}
	}

	return node
}

// Elems returns the elements of a list.
func (c *OpContext) Elems(v Value) []*Vertex {
	list := c.list(v)
	return list.Elems()
}

func (c *OpContext) list(v Value) *Vertex {
	x, ok := v.(*Vertex)
	if !ok || !x.IsList() {
		c.typeError(v, ListKind)
		return emptyNode
	}
	return x
}

func (c *OpContext) scalar(v Value) Value {
	v = Unwrap(v)
	switch v.(type) {
	case *Null, *Bool, *Num, *String, *Bytes:
	default:
		c.typeError(v, ScalarKinds)
	}
	return v
}

var zero = &Num{K: NumKind}

func (c *OpContext) Num(v Value, as interface{}) *Num {
	v = Unwrap(v)
	if isError(v) {
		return zero
	}
	x, ok := v.(*Num)
	if !ok {
		c.typeErrorAs(v, NumKind, as)
		return zero
	}
	return x
}

func (c *OpContext) Int64(v Value) int64 {
	v = Unwrap(v)
	if isError(v) {
		return 0
	}
	x, ok := v.(*Num)
	if !ok {
		c.typeError(v, IntKind)
		return 0
	}
	i, err := x.X.Int64()
	if err != nil {
		c.AddErrf("number is not an int64: %v", err)
		return 0
	}
	return i
}

func (c *OpContext) uint64(v Value, as string) uint64 {
	v = Unwrap(v)
	if isError(v) {
		return 0
	}
	x, ok := v.(*Num)
	if !ok {
		c.typeErrorAs(v, IntKind, as)
		return 0
	}
	if x.X.Negative {
		// TODO: improve message
		c.AddErrf("cannot convert negative number to uint64")
		return 0
	}
	if !x.X.Coeff.IsUint64() {
		// TODO: improve message
		c.AddErrf("cannot convert number %s to uint64", x.X)
		return 0
	}
	return x.X.Coeff.Uint64()
}

func (c *OpContext) BoolValue(v Value) bool {
	return c.boolValue(v, nil)
}

func (c *OpContext) boolValue(v Value, as interface{}) bool {
	v = Unwrap(v)
	if isError(v) {
		return false
	}
	x, ok := v.(*Bool)
	if !ok {
		c.typeErrorAs(v, BoolKind, as)
		return false
	}
	return x.B
}

func (c *OpContext) StringValue(v Value) string {
	return c.stringValue(v, nil)
}

// ToBytes returns the bytes value of a scalar value.
func (c *OpContext) ToBytes(v Value) []byte {
	if x, ok := v.(*Bytes); ok {
		return x.B
	}
	return []byte(c.ToString(v))
}

// ToString returns the string value of a scalar value.
func (c *OpContext) ToString(v Value) string {
	return c.toStringValue(v, StringKind|NumKind|BytesKind|BoolKind, nil)

}

func (c *OpContext) stringValue(v Value, as interface{}) string {
	return c.toStringValue(v, StringKind, as)
}

func (c *OpContext) toStringValue(v Value, k Kind, as interface{}) string {
	v = Unwrap(v)
	if isError(v) {
		return ""
	}
	if v.Kind()&k == 0 {
		if as == nil {
			c.typeError(v, k)
		} else {
			c.typeErrorAs(v, k, as)
		}
		return ""
	}
	switch x := v.(type) {
	case *String:
		return x.Str

	case *Bytes:
		return bytesToString(x.B)

	case *Num:
		return x.X.String()

	case *Bool:
		if x.B {
			return "true"
		}
		return "false"

	default:
		c.addErrf(IncompleteError, c.pos(),
			"non-concrete value %s (type %s)", v, v.Kind())
	}
	return ""
}

func bytesToString(b []byte) string {
	b, _ = unicode.UTF8.NewDecoder().Bytes(b)
	return string(b)
}

func (c *OpContext) bytesValue(v Value, as interface{}) []byte {
	v = Unwrap(v)
	if isError(v) {
		return nil
	}
	x, ok := v.(*Bytes)
	if !ok {
		c.typeErrorAs(v, BytesKind, as)
		return nil
	}
	return x.B
}

var matchNone = regexp.MustCompile("^$")

func (c *OpContext) regexp(v Value) *regexp.Regexp {
	v = Unwrap(v)
	if isError(v) {
		return matchNone
	}
	switch x := v.(type) {
	case *String:
		if x.RE != nil {
			return x.RE
		}
		// TODO: synchronization
		p, err := regexp.Compile(x.Str)
		if err != nil {
			// FatalError? How to cache error
			c.AddErrf("invalid regexp: %s", err)
			x.RE = matchNone
		} else {
			x.RE = p
		}
		return x.RE

	case *Bytes:
		if x.RE != nil {
			return x.RE
		}
		// TODO: synchronization
		p, err := regexp.Compile(string(x.B))
		if err != nil {
			c.AddErrf("invalid regexp: %s", err)
			x.RE = matchNone
		} else {
			x.RE = p
		}
		return x.RE

	default:
		c.typeError(v, StringKind|BytesKind)
		return matchNone
	}
}

// newNum creates a new number of the given kind. It reports an error value
// instead if any error occurred.
func (c *OpContext) newNum(d *apd.Decimal, k Kind, sources ...Node) Value {
	if c.HasErr() {
		return c.Err()
	}
	return &Num{Src: c.src, X: *d, K: k}
}

func (c *OpContext) NewInt64(n int64, sources ...Node) Value {
	if c.HasErr() {
		return c.Err()
	}
	d := apd.New(n, 0)
	return &Num{Src: c.src, X: *d, K: IntKind}
}

func (c *OpContext) NewString(s string) Value {
	if c.HasErr() {
		return c.Err()
	}
	return &String{Src: c.src, Str: s}
}

func (c *OpContext) newBytes(b []byte) Value {
	if c.HasErr() {
		return c.Err()
	}
	return &Bytes{Src: c.src, B: b}
}

func (c *OpContext) newBool(b bool) Value {
	if c.HasErr() {
		return c.Err()
	}
	return &Bool{Src: c.src, B: b}
}

func (c *OpContext) newList(src ast.Node, parent *Vertex) *Vertex {
	return &Vertex{Parent: parent, BaseValue: &ListMarker{}}
}

// Str reports a debug string of x.
func (c *OpContext) Str(x Node) string {
	if c.Format == nil {
		return fmt.Sprintf("%T", x)
	}
	return c.Format(x)
}

// NewList returns a new list for the given values.
func (c *OpContext) NewList(values ...Value) *Vertex {
	// TODO: consider making this a literal list instead.
	list := &ListLit{}
	v := &Vertex{
		Conjuncts: []Conjunct{{Env: nil, x: list}},
	}

	for _, x := range values {
		list.Elems = append(list.Elems, x)
	}
	c.Unify(v, Finalized)
	return v
}
