blob: adf3476c971ade01d68278876927e764457115a5 [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 "fmt"
19 "strings"
20)
21
22type rewriteMode int
23
24const (
25 evalRaw rewriteMode = iota
26 evalSimplify
27 evalPartial // all but disjunctions
28 evalFull
29)
30
31// testResolve recursively
32func testResolve(ctx *context, v value, m rewriteMode) (result value) {
33 if m == evalRaw || v == nil {
34 return v
35 }
36 return rewriteRec(ctx, v, v.evalPartial(ctx), m)
37}
38
39var indentLevel int
40
41func (c *context) ind() int {
42 old := indentLevel
43 indentLevel += 2
44 return old
45}
46
47func (c *context) unindent(old int) {
48 indentLevel = old
49}
50
51func (c *context) printIndent(args ...interface{}) {
52 fmt.Print(strings.Repeat(" ", indentLevel))
53 c.println(args...)
54}
55
56func rewriteRec(ctx *context, raw value, eval evaluated, m rewriteMode) (result value) {
57 if m >= evalPartial {
58 if isIncomplete(eval) {
59 return raw
60 }
61 if m == evalFull {
62 eval = ctx.manifest(eval)
63 if isBottom(eval) {
64 return eval
65 }
66 }
67 }
68 switch x := eval.(type) {
69 case *structLit:
70 if m == evalFull {
71 e := ctx.manifest(x)
72 if isBottom(e) {
73 return e
74 }
75 x = e.(*structLit)
76 }
Marcel van Lohuizen7f48df72019-02-01 17:24:59 +010077 x = x.expandFields(ctx)
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +010078 arcs := make(arcs, len(x.arcs))
79 for i, a := range x.arcs {
80 v := x.at(ctx, i)
Marcel van Lohuizen08a0ef22019-03-28 09:12:19 +010081 a.setValue(rewriteRec(ctx, a.v, v, m))
82 arcs[i] = a
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +010083 }
84 t := x.template
85 if t != nil {
86 v := rewriteRec(ctx, t, t.evalPartial(ctx), m)
87 if isBottom(v) {
88 return v
89 }
Marcel van Lohuizen66db9202018-12-17 19:02:08 +010090 t = v
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +010091 }
92 emit := testResolve(ctx, x.emit, m)
Marcel van Lohuizen7f48df72019-02-01 17:24:59 +010093 obj := &structLit{x.baseValue, emit, t, nil, arcs, nil}
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +010094 return obj
95 case *list:
Marcel van Lohuizen9ee652d2019-04-25 17:16:01 +020096 elm := rewriteRec(ctx, x.elem, x.elem, m).(*structLit)
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +010097 len := rewriteRec(ctx, x.len, x.len.(evaluated), m)
98 typ := rewriteRec(ctx, x.typ, x.typ.(evaluated), m)
Marcel van Lohuizen9ee652d2019-04-25 17:16:01 +020099 return &list{x.baseValue, elm, typ, len}
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100100 default:
101 return eval
102 }
103}