Marcel van Lohuizen | 6a08830 | 2020-07-03 14:42:05 +0200 | [diff] [blame] | 1 | // Copyright 2020 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 | |
| 15 | package adt |
| 16 | |
Marcel van Lohuizen | 1d29ac3 | 2020-07-15 15:02:14 +0200 | [diff] [blame] | 17 | import ( |
| 18 | "cuelang.org/go/cue/ast" |
| 19 | "cuelang.org/go/cue/token" |
| 20 | ) |
| 21 | |
| 22 | func Resolve(ctx *OpContext, c Conjunct) *Vertex { |
| 23 | env := c.Env |
| 24 | // TODO: also allow resolution in parent scopes. The following will set up |
| 25 | // the environments. But the compiler also needs to resolve accordingly. |
| 26 | // |
| 27 | // // Set up environments for parent scopes, if any. |
| 28 | // root := env |
| 29 | // for p := scope; p != nil; p = p.Parent { |
| 30 | // root.Up = &Environment{Vertex: p.Parent} |
| 31 | // root = root.Up |
| 32 | // } |
| 33 | |
| 34 | var v Value |
| 35 | |
| 36 | expr := c.Expr() |
| 37 | switch x := expr.(type) { |
| 38 | case Value: |
| 39 | v = x |
| 40 | |
| 41 | case Resolver: |
| 42 | r, err := ctx.Resolve(env, x) |
| 43 | if err != nil { |
| 44 | v = err |
| 45 | break |
| 46 | } |
Marcel van Lohuizen | bedb047 | 2021-02-01 14:17:19 +0100 | [diff] [blame] | 47 | // r.Finalize(ctx) // TODO: Finalize here? |
Marcel van Lohuizen | 1d29ac3 | 2020-07-15 15:02:14 +0200 | [diff] [blame] | 48 | return r |
| 49 | |
| 50 | case Evaluator: |
| 51 | // TODO: have a way to evaluate, but not strip down to the value. |
| 52 | v, _ = ctx.Evaluate(env, expr) |
| 53 | |
| 54 | default: |
| 55 | // Unknown type. |
| 56 | v = ctx.NewErrf( |
Marcel van Lohuizen | 276ce26 | 2021-04-20 10:05:35 +0200 | [diff] [blame] | 57 | "could not evaluate expression %s of type %T", c.Expr(), c) |
Marcel van Lohuizen | 1d29ac3 | 2020-07-15 15:02:14 +0200 | [diff] [blame] | 58 | } |
| 59 | |
| 60 | return ToVertex(v) |
| 61 | } |
Marcel van Lohuizen | 6a08830 | 2020-07-03 14:42:05 +0200 | [diff] [blame] | 62 | |
| 63 | // A Node is any abstract data type representing an value or expression. |
| 64 | type Node interface { |
| 65 | Source() ast.Node |
| 66 | node() // enforce internal. |
| 67 | } |
| 68 | |
| 69 | // A Decl represents all valid StructLit elements. |
| 70 | type Decl interface { |
| 71 | Node |
| 72 | declNode() |
| 73 | } |
| 74 | |
| 75 | // An Elem represents all value ListLit elements. |
| 76 | // |
| 77 | // All Elem values can be used as a Decl. |
| 78 | type Elem interface { |
| 79 | Decl |
| 80 | elemNode() |
| 81 | } |
| 82 | |
| 83 | // An Expr corresponds to an ast.Expr. |
| 84 | // |
| 85 | // All Expr values can be used as an Elem or Decl. |
| 86 | type Expr interface { |
| 87 | Elem |
| 88 | expr() |
| 89 | } |
| 90 | |
Marcel van Lohuizen | 08a1652 | 2020-11-26 19:00:03 +0100 | [diff] [blame] | 91 | // A BaseValue is any Value or a *Marker. It indicates the type of a Vertex. |
| 92 | type BaseValue interface { |
| 93 | Kind() Kind |
| 94 | } |
| 95 | |
Marcel van Lohuizen | 6a08830 | 2020-07-03 14:42:05 +0200 | [diff] [blame] | 96 | // A Value represents a node in the evaluated data graph. |
| 97 | // |
| 98 | // All Values values can also be used as a Expr. |
| 99 | type Value interface { |
| 100 | Expr |
| 101 | Concreteness() Concreteness |
| 102 | Kind() Kind |
| 103 | } |
| 104 | |
| 105 | // An Evaluator provides a method to convert to a value. |
| 106 | type Evaluator interface { |
| 107 | Node |
Marcel van Lohuizen | 08a1652 | 2020-11-26 19:00:03 +0100 | [diff] [blame] | 108 | |
| 109 | // evaluate evaluates the underlying expression. If the expression |
| 110 | // is incomplete, it may record the error in ctx and return nil. |
Marcel van Lohuizen | 0f935f8 | 2020-06-09 09:13:01 +0200 | [diff] [blame] | 111 | evaluate(ctx *OpContext) Value |
Marcel van Lohuizen | 6a08830 | 2020-07-03 14:42:05 +0200 | [diff] [blame] | 112 | } |
| 113 | |
| 114 | // A Resolver represents a reference somewhere else within a tree that resolves |
| 115 | // a value. |
| 116 | type Resolver interface { |
| 117 | Node |
Marcel van Lohuizen | d0124e2 | 2021-01-26 11:57:45 +0100 | [diff] [blame] | 118 | resolve(ctx *OpContext, state VertexStatus) *Vertex |
Marcel van Lohuizen | 6a08830 | 2020-07-03 14:42:05 +0200 | [diff] [blame] | 119 | } |
| 120 | |
Marcel van Lohuizen | 0f935f8 | 2020-06-09 09:13:01 +0200 | [diff] [blame] | 121 | type YieldFunc func(env *Environment, s *StructLit) |
| 122 | |
Marcel van Lohuizen | 6a08830 | 2020-07-03 14:42:05 +0200 | [diff] [blame] | 123 | // A Yielder represents 0 or more labeled values of structs or lists. |
| 124 | type Yielder interface { |
| 125 | Node |
Marcel van Lohuizen | 0f935f8 | 2020-06-09 09:13:01 +0200 | [diff] [blame] | 126 | yield(ctx *OpContext, fn YieldFunc) |
Marcel van Lohuizen | 6a08830 | 2020-07-03 14:42:05 +0200 | [diff] [blame] | 127 | } |
| 128 | |
| 129 | // A Validator validates a Value. All Validators are Values. |
| 130 | type Validator interface { |
Marcel van Lohuizen | 6a08830 | 2020-07-03 14:42:05 +0200 | [diff] [blame] | 131 | Value |
Marcel van Lohuizen | 0f935f8 | 2020-06-09 09:13:01 +0200 | [diff] [blame] | 132 | validate(c *OpContext, v Value) *Bottom |
Marcel van Lohuizen | 6a08830 | 2020-07-03 14:42:05 +0200 | [diff] [blame] | 133 | } |
| 134 | |
Marcel van Lohuizen | 1d29ac3 | 2020-07-15 15:02:14 +0200 | [diff] [blame] | 135 | // Pos returns the file position of n, or token.NoPos if it is unknown. |
| 136 | func Pos(n Node) token.Pos { |
| 137 | src := n.Source() |
| 138 | if src == nil { |
| 139 | return token.NoPos |
| 140 | } |
| 141 | return src.Pos() |
| 142 | } |
| 143 | |
Marcel van Lohuizen | 6a08830 | 2020-07-03 14:42:05 +0200 | [diff] [blame] | 144 | // Value |
| 145 | |
| 146 | func (x *Vertex) Concreteness() Concreteness { |
| 147 | // Depends on concreteness of value. |
Marcel van Lohuizen | 41afc87 | 2020-11-26 20:20:58 +0100 | [diff] [blame] | 148 | switch v := x.BaseValue.(type) { |
Marcel van Lohuizen | 37293f9 | 2020-11-26 17:06:18 +0100 | [diff] [blame] | 149 | case nil: |
Marcel van Lohuizen | 6a08830 | 2020-07-03 14:42:05 +0200 | [diff] [blame] | 150 | return Concrete // Should be indetermined. |
Marcel van Lohuizen | 37293f9 | 2020-11-26 17:06:18 +0100 | [diff] [blame] | 151 | |
| 152 | case Value: |
| 153 | return v.Concreteness() |
| 154 | |
| 155 | default: // *StructMarker, *ListMarker: |
| 156 | return Concrete |
Marcel van Lohuizen | 6a08830 | 2020-07-03 14:42:05 +0200 | [diff] [blame] | 157 | } |
Marcel van Lohuizen | 6a08830 | 2020-07-03 14:42:05 +0200 | [diff] [blame] | 158 | } |
| 159 | |
Marcel van Lohuizen | 08a1652 | 2020-11-26 19:00:03 +0100 | [diff] [blame] | 160 | func (x *NodeLink) Concreteness() Concreteness { return Concrete } |
Marcel van Lohuizen | 6a08830 | 2020-07-03 14:42:05 +0200 | [diff] [blame] | 161 | |
Marcel van Lohuizen | 0cfe411 | 2020-06-27 15:01:34 +0200 | [diff] [blame] | 162 | func (*Conjunction) Concreteness() Concreteness { return Constraint } |
| 163 | func (*Disjunction) Concreteness() Concreteness { return Constraint } |
| 164 | func (*BoundValue) Concreteness() Concreteness { return Constraint } |
| 165 | |
Marcel van Lohuizen | f62bfed | 2020-12-04 14:17:34 +0100 | [diff] [blame] | 166 | func (*Builtin) Concreteness() Concreteness { return Concrete } |
Marcel van Lohuizen | 6a08830 | 2020-07-03 14:42:05 +0200 | [diff] [blame] | 167 | func (*BuiltinValidator) Concreteness() Concreteness { return Constraint } |
| 168 | |
| 169 | // Value and Expr |
| 170 | |
| 171 | func (*Bottom) Concreteness() Concreteness { return BottomLevel } |
| 172 | func (*Null) Concreteness() Concreteness { return Concrete } |
| 173 | func (*Bool) Concreteness() Concreteness { return Concrete } |
| 174 | func (*Num) Concreteness() Concreteness { return Concrete } |
| 175 | func (*String) Concreteness() Concreteness { return Concrete } |
| 176 | func (*Bytes) Concreteness() Concreteness { return Concrete } |
| 177 | func (*Top) Concreteness() Concreteness { return Any } |
| 178 | func (*BasicType) Concreteness() Concreteness { return Type } |
| 179 | |
| 180 | // Expr |
| 181 | |
| 182 | func (*StructLit) expr() {} |
| 183 | func (*ListLit) expr() {} |
| 184 | func (*DisjunctionExpr) expr() {} |
| 185 | |
| 186 | // Expr and Value |
| 187 | |
| 188 | func (*Bottom) expr() {} |
| 189 | func (*Null) expr() {} |
| 190 | func (*Bool) expr() {} |
| 191 | func (*Num) expr() {} |
| 192 | func (*String) expr() {} |
| 193 | func (*Bytes) expr() {} |
| 194 | func (*Top) expr() {} |
| 195 | func (*BasicType) expr() {} |
| 196 | func (*Vertex) expr() {} |
| 197 | func (*ListMarker) expr() {} |
| 198 | func (*StructMarker) expr() {} |
| 199 | func (*Conjunction) expr() {} |
| 200 | func (*Disjunction) expr() {} |
| 201 | func (*BoundValue) expr() {} |
| 202 | func (*BuiltinValidator) expr() {} |
Marcel van Lohuizen | 0cfe411 | 2020-06-27 15:01:34 +0200 | [diff] [blame] | 203 | func (*Builtin) expr() {} |
Marcel van Lohuizen | 6a08830 | 2020-07-03 14:42:05 +0200 | [diff] [blame] | 204 | |
| 205 | // Expr and Resolver |
| 206 | |
Marcel van Lohuizen | 0cfe411 | 2020-06-27 15:01:34 +0200 | [diff] [blame] | 207 | func (*NodeLink) expr() {} |
Marcel van Lohuizen | 6a08830 | 2020-07-03 14:42:05 +0200 | [diff] [blame] | 208 | func (*FieldReference) expr() {} |
| 209 | func (*LabelReference) expr() {} |
| 210 | func (*DynamicReference) expr() {} |
| 211 | func (*ImportReference) expr() {} |
| 212 | func (*LetReference) expr() {} |
| 213 | |
| 214 | // Expr and Evaluator |
| 215 | |
| 216 | func (*BoundExpr) expr() {} |
| 217 | func (*SelectorExpr) expr() {} |
| 218 | func (*IndexExpr) expr() {} |
| 219 | func (*SliceExpr) expr() {} |
| 220 | func (*Interpolation) expr() {} |
| 221 | func (*UnaryExpr) expr() {} |
| 222 | func (*BinaryExpr) expr() {} |
| 223 | func (*CallExpr) expr() {} |
| 224 | |
| 225 | // Decl and Expr (so allow attaching original source in Conjunct) |
| 226 | |
| 227 | func (*Field) declNode() {} |
| 228 | func (x *Field) expr() Expr { return x.Value } |
| 229 | func (*OptionalField) declNode() {} |
| 230 | func (x *OptionalField) expr() Expr { return x.Value } |
| 231 | func (*BulkOptionalField) declNode() {} |
| 232 | func (x *BulkOptionalField) expr() Expr { return x.Value } |
| 233 | func (*DynamicField) declNode() {} |
| 234 | func (x *DynamicField) expr() Expr { return x.Value } |
| 235 | |
| 236 | // Decl and Yielder |
| 237 | |
Marcel van Lohuizen | 0f935f8 | 2020-06-09 09:13:01 +0200 | [diff] [blame] | 238 | func (*LetClause) declNode() {} |
Marcel van Lohuizen | 6a08830 | 2020-07-03 14:42:05 +0200 | [diff] [blame] | 239 | |
| 240 | // Decl and Elem |
| 241 | |
| 242 | func (*StructLit) declNode() {} |
| 243 | func (*StructLit) elemNode() {} |
| 244 | func (*ListLit) declNode() {} |
| 245 | func (*ListLit) elemNode() {} |
| 246 | func (*Ellipsis) elemNode() {} |
| 247 | func (*Ellipsis) declNode() {} |
| 248 | func (*Bottom) declNode() {} |
| 249 | func (*Bottom) elemNode() {} |
| 250 | func (*Null) declNode() {} |
| 251 | func (*Null) elemNode() {} |
| 252 | func (*Bool) declNode() {} |
| 253 | func (*Bool) elemNode() {} |
| 254 | func (*Num) declNode() {} |
| 255 | func (*Num) elemNode() {} |
| 256 | func (*String) declNode() {} |
| 257 | func (*String) elemNode() {} |
| 258 | func (*Bytes) declNode() {} |
| 259 | func (*Bytes) elemNode() {} |
| 260 | func (*Top) declNode() {} |
| 261 | func (*Top) elemNode() {} |
| 262 | func (*BasicType) declNode() {} |
| 263 | func (*BasicType) elemNode() {} |
| 264 | func (*BoundExpr) declNode() {} |
| 265 | func (*BoundExpr) elemNode() {} |
| 266 | func (*Vertex) declNode() {} |
| 267 | func (*Vertex) elemNode() {} |
| 268 | func (*ListMarker) declNode() {} |
| 269 | func (*ListMarker) elemNode() {} |
| 270 | func (*StructMarker) declNode() {} |
| 271 | func (*StructMarker) elemNode() {} |
| 272 | func (*Conjunction) declNode() {} |
| 273 | func (*Conjunction) elemNode() {} |
| 274 | func (*Disjunction) declNode() {} |
| 275 | func (*Disjunction) elemNode() {} |
| 276 | func (*BoundValue) declNode() {} |
| 277 | func (*BoundValue) elemNode() {} |
| 278 | func (*BuiltinValidator) declNode() {} |
| 279 | func (*BuiltinValidator) elemNode() {} |
Marcel van Lohuizen | 0cfe411 | 2020-06-27 15:01:34 +0200 | [diff] [blame] | 280 | func (*NodeLink) declNode() {} |
| 281 | func (*NodeLink) elemNode() {} |
Marcel van Lohuizen | 6a08830 | 2020-07-03 14:42:05 +0200 | [diff] [blame] | 282 | func (*FieldReference) declNode() {} |
| 283 | func (*FieldReference) elemNode() {} |
| 284 | func (*LabelReference) declNode() {} |
| 285 | func (*LabelReference) elemNode() {} |
| 286 | func (*DynamicReference) declNode() {} |
| 287 | func (*DynamicReference) elemNode() {} |
| 288 | func (*ImportReference) declNode() {} |
| 289 | func (*ImportReference) elemNode() {} |
| 290 | func (*LetReference) declNode() {} |
| 291 | func (*LetReference) elemNode() {} |
| 292 | func (*SelectorExpr) declNode() {} |
| 293 | func (*SelectorExpr) elemNode() {} |
| 294 | func (*IndexExpr) declNode() {} |
| 295 | func (*IndexExpr) elemNode() {} |
| 296 | func (*SliceExpr) declNode() {} |
| 297 | func (*SliceExpr) elemNode() {} |
| 298 | func (*Interpolation) declNode() {} |
| 299 | func (*Interpolation) elemNode() {} |
| 300 | func (*UnaryExpr) declNode() {} |
| 301 | func (*UnaryExpr) elemNode() {} |
| 302 | func (*BinaryExpr) declNode() {} |
| 303 | func (*BinaryExpr) elemNode() {} |
| 304 | func (*CallExpr) declNode() {} |
| 305 | func (*CallExpr) elemNode() {} |
Marcel van Lohuizen | 0cfe411 | 2020-06-27 15:01:34 +0200 | [diff] [blame] | 306 | func (*Builtin) declNode() {} |
| 307 | func (*Builtin) elemNode() {} |
Marcel van Lohuizen | 6a08830 | 2020-07-03 14:42:05 +0200 | [diff] [blame] | 308 | func (*DisjunctionExpr) declNode() {} |
| 309 | func (*DisjunctionExpr) elemNode() {} |
| 310 | |
| 311 | // Decl, Elem, and Yielder |
| 312 | |
Marcel van Lohuizen | 0f935f8 | 2020-06-09 09:13:01 +0200 | [diff] [blame] | 313 | func (*ForClause) declNode() {} |
| 314 | func (*ForClause) elemNode() {} |
| 315 | func (*IfClause) declNode() {} |
| 316 | func (*IfClause) elemNode() {} |
Marcel van Lohuizen | 6a08830 | 2020-07-03 14:42:05 +0200 | [diff] [blame] | 317 | |
Marcel van Lohuizen | 0f935f8 | 2020-06-09 09:13:01 +0200 | [diff] [blame] | 318 | // Yielder only: ValueClause |
Marcel van Lohuizen | 6a08830 | 2020-07-03 14:42:05 +0200 | [diff] [blame] | 319 | |
| 320 | // Node |
| 321 | |
| 322 | func (*Vertex) node() {} |
| 323 | func (*Conjunction) node() {} |
| 324 | func (*Disjunction) node() {} |
| 325 | func (*BoundValue) node() {} |
Marcel van Lohuizen | 0cfe411 | 2020-06-27 15:01:34 +0200 | [diff] [blame] | 326 | func (*Builtin) node() {} |
Marcel van Lohuizen | 6a08830 | 2020-07-03 14:42:05 +0200 | [diff] [blame] | 327 | func (*BuiltinValidator) node() {} |
| 328 | func (*Bottom) node() {} |
| 329 | func (*Null) node() {} |
| 330 | func (*Bool) node() {} |
| 331 | func (*Num) node() {} |
| 332 | func (*String) node() {} |
| 333 | func (*Bytes) node() {} |
| 334 | func (*Top) node() {} |
| 335 | func (*BasicType) node() {} |
| 336 | func (*StructLit) node() {} |
| 337 | func (*ListLit) node() {} |
| 338 | func (*BoundExpr) node() {} |
Marcel van Lohuizen | 0cfe411 | 2020-06-27 15:01:34 +0200 | [diff] [blame] | 339 | func (*NodeLink) node() {} |
Marcel van Lohuizen | 6a08830 | 2020-07-03 14:42:05 +0200 | [diff] [blame] | 340 | func (*FieldReference) node() {} |
| 341 | func (*LabelReference) node() {} |
| 342 | func (*DynamicReference) node() {} |
| 343 | func (*ImportReference) node() {} |
| 344 | func (*LetReference) node() {} |
| 345 | func (*SelectorExpr) node() {} |
| 346 | func (*IndexExpr) node() {} |
| 347 | func (*SliceExpr) node() {} |
| 348 | func (*Interpolation) node() {} |
| 349 | func (*UnaryExpr) node() {} |
| 350 | func (*BinaryExpr) node() {} |
| 351 | func (*CallExpr) node() {} |
| 352 | func (*DisjunctionExpr) node() {} |
| 353 | func (*Field) node() {} |
| 354 | func (*OptionalField) node() {} |
| 355 | func (*BulkOptionalField) node() {} |
| 356 | func (*DynamicField) node() {} |
| 357 | func (*Ellipsis) node() {} |
| 358 | func (*ForClause) node() {} |
| 359 | func (*IfClause) node() {} |
| 360 | func (*LetClause) node() {} |
| 361 | func (*ValueClause) node() {} |