blob: 44dc9825ae300a7e74e44e6ac0302d6b0856bd4c [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
17// TODO: nodeRefs are currently not updated if the structs they point to are
18// updated. Handing this in uses of rewrite is tedious and hard to get correct.
19// Make this a general mechanism. This can be done using a Tomabechi-like
20// approach of associating copies with nodes in one pass, and then make a
21// complete copy in a second.
22
23type rewriteFunc func(ctx *context, v value) (value, bool)
24
25func rewrite(ctx *context, v value, fn rewriteFunc) value {
26 v, descend := fn(ctx, v)
27 if !descend {
28 return v
29 }
30 return v.rewrite(ctx, fn)
31}
32
33func (x *nodeRef) rewrite(ctx *context, fn rewriteFunc) value {
34 return x
35}
36
37func (x *structLit) rewrite(ctx *context, fn rewriteFunc) value {
38 emit := x.emit
39 if emit != nil {
40 emit = rewrite(ctx, x.emit, fn)
41 }
42 arcs := make(arcs, len(x.arcs))
43 obj := &structLit{baseValue: x.baseValue, emit: emit, arcs: arcs}
44 changed := emit == x.emit
45 for i, a := range x.arcs {
Marcel van Lohuizen08a0ef22019-03-28 09:12:19 +010046 a.setValue(rewrite(ctx, a.v, fn))
47 changed = changed || arcs[i].v != a.v
48 arcs[i] = a
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +010049 }
50 if !changed {
51 return x
52 }
53 return obj
54}
55
56func (x *selectorExpr) rewrite(ctx *context, fn rewriteFunc) value {
57 v := rewrite(ctx, x.x, fn)
58 if v == x.x {
59 return x
60 }
61 return &selectorExpr{x.baseValue, v, x.feature}
62}
63
64func (x *indexExpr) rewrite(ctx *context, fn rewriteFunc) value {
65 v := rewrite(ctx, x.x, fn)
66 index := rewrite(ctx, x.index, fn)
67 if v == x.x && index == x.index {
68 return x
69 }
70 return &indexExpr{x.baseValue, v, index}
71}
72
73// Even more boring stuff below.
74
75func (x *builtin) rewrite(ctx *context, fn rewriteFunc) value { return x }
76func (x *top) rewrite(ctx *context, fn rewriteFunc) value { return x }
77func (x *bottom) rewrite(ctx *context, fn rewriteFunc) value { return x }
78func (x *basicType) rewrite(ctx *context, fn rewriteFunc) value { return x }
79func (x *nullLit) rewrite(ctx *context, fn rewriteFunc) value { return x }
80func (x *boolLit) rewrite(ctx *context, fn rewriteFunc) value { return x }
81func (x *stringLit) rewrite(ctx *context, fn rewriteFunc) value { return x }
82func (x *bytesLit) rewrite(ctx *context, fn rewriteFunc) value { return x }
83func (x *numLit) rewrite(ctx *context, fn rewriteFunc) value { return x }
84func (x *durationLit) rewrite(ctx *context, fn rewriteFunc) value { return x }
85
Marcel van Lohuizen7d0797b2019-02-07 18:35:28 +010086func (x *bound) rewrite(ctx *context, fn rewriteFunc) value {
87 v := rewrite(ctx, x.value, fn)
88 if v == x.value {
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +010089 return x
90 }
Marcel van Lohuizen4a360992019-05-11 18:18:31 +020091 return newBound(x.baseValue, x.op, x.k, v)
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +010092}
93
94func (x *interpolation) rewrite(ctx *context, fn rewriteFunc) value {
95 parts := make([]value, len(x.parts))
96 changed := false
97 for i, p := range x.parts {
98 parts[i] = rewrite(ctx, p, fn)
99 changed = changed || parts[i] != p
100 }
101 if !changed {
102 return x
103 }
104 return &interpolation{x.baseValue, x.k, parts}
105}
106
107func (x *list) rewrite(ctx *context, fn rewriteFunc) value {
Marcel van Lohuizen9ee652d2019-04-25 17:16:01 +0200108 elem := rewrite(ctx, x.elem, fn).(*structLit)
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100109 typ := rewrite(ctx, x.typ, fn)
110 len := rewrite(ctx, x.len, fn)
Marcel van Lohuizen9ee652d2019-04-25 17:16:01 +0200111 if elem == x.elem && typ == x.typ && len == x.len {
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100112 return x
113 }
Marcel van Lohuizen9ee652d2019-04-25 17:16:01 +0200114 return &list{x.baseValue, elem, typ, len}
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100115}
116
117func (x *sliceExpr) rewrite(ctx *context, fn rewriteFunc) value {
118 v := rewrite(ctx, x.x, fn)
119 lo := rewrite(ctx, x.lo, fn)
120 hi := rewrite(ctx, x.hi, fn)
121 if v == x.x && lo == x.lo && hi == x.hi {
122 return x
123 }
124 return &sliceExpr{x.baseValue, v, lo, hi}
125}
126
127func (x *callExpr) rewrite(ctx *context, fn rewriteFunc) value {
128 args := make([]value, len(x.args))
129 changed := false
130 for i, a := range x.args {
131 v := rewrite(ctx, a, fn)
132 args[i] = v
133 changed = changed || v != a
134 }
135 v := rewrite(ctx, x.x, fn)
136 if !changed && v == x.x {
137 return x
138 }
139 return &callExpr{baseValue: x.baseValue, x: v, args: args}
140}
141
142func (x *lambdaExpr) rewrite(ctx *context, fn rewriteFunc) value {
143 arcs := make([]arc, len(x.arcs))
144 changed := false
145 for i, a := range x.arcs {
146 v := rewrite(ctx, a.v, fn)
147 arcs[i] = arc{feature: a.feature, v: v}
148 changed = changed || v != a.v
149 }
150 value := rewrite(ctx, x.value, fn)
151 if !changed && value == x.value {
152 return x
153 }
154 return &lambdaExpr{x.baseValue, &params{arcs}, value}
155}
156
157func (x *unaryExpr) rewrite(ctx *context, fn rewriteFunc) value {
158 v := rewrite(ctx, x.x, fn)
159 if v == x.x {
160 return x
161 }
162 return &unaryExpr{x.baseValue, x.op, v}
163}
164
165func (x *binaryExpr) rewrite(ctx *context, fn rewriteFunc) value {
166 left := rewrite(ctx, x.left, fn)
167 right := rewrite(ctx, x.right, fn)
168 if left == x.left && right == x.right {
169 return x
170 }
171 return &binaryExpr{x.baseValue, x.op, left, right}
172}
173
Marcel van Lohuizen7d0797b2019-02-07 18:35:28 +0100174func (x *unification) rewrite(ctx *context, fn rewriteFunc) value {
Marcel van Lohuizen39822d72019-04-03 12:24:17 +0200175 values := make([]evaluated, len(x.values))
176 changed := false
177 for i, v := range x.values {
178 values[i] = rewrite(ctx, v, fn).(evaluated)
179 changed = changed || v != values[i]
180 }
181 if !changed {
182 return x
183 }
184 return &unification{x.baseValue, values}
Marcel van Lohuizen7d0797b2019-02-07 18:35:28 +0100185}
186
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100187func (x *disjunction) rewrite(ctx *context, fn rewriteFunc) value {
188 values := make([]dValue, len(x.values))
189 changed := false
190 for i, d := range x.values {
191 v := rewrite(ctx, d.val, fn)
Marcel van Lohuizenc9b3cb22019-01-30 11:32:41 +0100192 values[i] = dValue{v, d.marked}
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100193 changed = changed || v != d.val
194 }
195 if !changed {
196 return x
197 }
Marcel van Lohuizen94d845d2019-05-10 00:28:03 +0200198 return &disjunction{x.baseValue, values, x.hasDefaults}
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100199}
200
201func (x *listComprehension) rewrite(ctx *context, fn rewriteFunc) value {
202 clauses := rewrite(ctx, x.clauses, fn).(yielder)
203 if clauses == x.clauses {
204 return x
205 }
206 return &listComprehension{x.baseValue, clauses}
207}
208
Marcel van Lohuizen66db9202018-12-17 19:02:08 +0100209func (x *fieldComprehension) rewrite(ctx *context, fn rewriteFunc) value {
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100210 clauses := rewrite(ctx, x.clauses, fn).(yielder)
211 if clauses == x.clauses {
212 return x
213 }
Marcel van Lohuizen66db9202018-12-17 19:02:08 +0100214 return &fieldComprehension{x.baseValue, clauses, x.isTemplate}
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100215}
216
217func (x *yield) rewrite(ctx *context, fn rewriteFunc) value {
218 key := x.key
219 if key != nil {
220 key = rewrite(ctx, x.key, fn)
221 }
222 value := rewrite(ctx, x.value, fn)
223 if key == x.key && value == x.value {
224 return x
225 }
Marcel van Lohuizen08a0ef22019-03-28 09:12:19 +0100226 return &yield{x.baseValue, x.opt, key, value}
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100227}
228
229func (x *guard) rewrite(ctx *context, fn rewriteFunc) value {
230 condition := rewrite(ctx, x.condition, fn)
231 value := rewrite(ctx, x.value, fn).(yielder)
232 if condition == x.condition && value == x.value {
233 return x
234 }
235 return &guard{x.baseValue, condition, value}
236}
237
238func (x *feed) rewrite(ctx *context, fn rewriteFunc) value {
239 source := rewrite(ctx, x.source, fn)
240 lambda := rewrite(ctx, x.fn, fn).(*lambdaExpr)
241 if source == x.source && lambda == x.fn {
242 return x
243 }
244 return &feed{x.baseValue, source, lambda}
245}