blob: ff81001bb59396eb11452cfcd8020bbba2899873 [file] [log] [blame]
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +01001// Copyright 2018 The CUE Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package cue
16
17import (
18 "github.com/cockroachdb/apd"
19)
20
21// context manages evaluation state.
22type context struct {
23 *apd.Context
24
25 *index
26
27 forwardMap []scope // pairs
28 oldSize []int
29
30 // constraints are to be evaluated at the end values to be evaluated later.
Marcel van Lohuizen50eea6b2019-02-19 18:30:15 +010031 constraints []*binaryExpr
Marcel van Lohuizen94d845d2019-05-10 00:28:03 +020032 evalStack []bottom
33
34 inSum int
35 cycleErr bool
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +010036
Marcel van Lohuizen0e2bcd52019-04-03 22:33:14 +020037 noManifest bool
38
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +010039 // for debug strings
40 nodeRefs map[scope]string
41
42 // tracing
43 trace bool
44 level int
45}
46
Marcel van Lohuizen94d845d2019-05-10 00:28:03 +020047func (c *context) incEvalDepth() {
48 if len(c.evalStack) > 0 {
49 c.evalStack[len(c.evalStack)-1].exprDepth++
50 }
51}
52
53func (c *context) decEvalDepth() {
54 if len(c.evalStack) > 0 {
55 c.evalStack[len(c.evalStack)-1].exprDepth--
56 }
57}
58
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +010059var baseContext apd.Context
60
61func init() {
62 baseContext = apd.BaseContext
63 baseContext.Precision = 24
64}
65
66// newContext returns a new evaluation context.
67func (idx *index) newContext() *context {
68 c := &context{
69 Context: &baseContext,
70 index: idx,
71 }
72 return c
73}
74
75// delayConstraint schedules constraint to be evaluated and returns ret. If
76// delaying constraints is currently not allowed, it returns an error instead.
Marcel van Lohuizen50eea6b2019-02-19 18:30:15 +010077func (c *context) delayConstraint(ret evaluated, constraint *binaryExpr) evaluated {
78 c.cycleErr = true
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +010079 c.constraints = append(c.constraints, constraint)
80 return ret
81}
82
83func (c *context) processDelayedConstraints() evaluated {
84 cons := c.constraints
85 c.constraints = c.constraints[:0]
86 for _, dc := range cons {
Marcel van Lohuizen50eea6b2019-02-19 18:30:15 +010087 v := binOp(c, dc, dc.op, dc.left.evalPartial(c), dc.right.evalPartial(c))
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +010088 if isBottom(v) {
Marcel van Lohuizen50eea6b2019-02-19 18:30:15 +010089 return v
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +010090 }
91 }
92 return nil
93}
94
95func (c *context) deref(f scope) scope {
96outer:
97 for {
98 for i := 0; i < len(c.forwardMap); i += 2 {
99 if c.forwardMap[i] == f {
100 f = c.forwardMap[i+1]
101 continue outer
102 }
103 }
104 return f
105 }
106}
107
108func (c *context) pushForwards(pairs ...scope) *context {
109 c.oldSize = append(c.oldSize, len(c.forwardMap))
110 c.forwardMap = append(c.forwardMap, pairs...)
111 return c
112}
113
114func (c *context) popForwards() {
115 last := len(c.oldSize) - 1
116 c.forwardMap = c.forwardMap[:c.oldSize[last]]
117 c.oldSize = c.oldSize[:last]
118}