From 8638a212876ee2cda4759e6286cc7428f878ea0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw=20Barzowski?= Date: Fri, 22 Sep 2017 18:02:05 -0400 Subject: [PATCH] Object invariants (#62) * Object invariants --- desugarer.go | 31 +- interpreter.go | 11 +- testdata/object_invariant.golden | 1 + testdata/object_invariant.input | 1 + testdata/object_invariant10.golden | 1 + testdata/object_invariant10.input | 1 + testdata/object_invariant11.golden | 1 + testdata/object_invariant11.input | 1 + testdata/object_invariant12.golden | 1 + testdata/object_invariant12.input | 1 + testdata/object_invariant13.golden | 1 + testdata/object_invariant13.input | 1 + testdata/object_invariant14.golden | 1 + testdata/object_invariant14.input | 1 + testdata/object_invariant2.golden | 1 + testdata/object_invariant2.input | 1 + testdata/object_invariant3.golden | 1 + testdata/object_invariant3.input | 1 + testdata/object_invariant4.golden | 1 + testdata/object_invariant4.input | 1 + testdata/object_invariant5.golden | 1 + testdata/object_invariant5.input | 1 + testdata/object_invariant6.golden | 3 + testdata/object_invariant6.input | 1 + testdata/object_invariant7.golden | 1 + testdata/object_invariant7.input | 1 + testdata/object_invariant8.golden | 1 + testdata/object_invariant8.input | 1 + testdata/object_invariant9.golden | 1 + testdata/object_invariant9.input | 1 + testdata/object_invariant_perf.golden | 455 ++++ testdata/object_invariant_perf.input | 2 + testdata/object_invariant_plus.golden | 1 + testdata/object_invariant_plus.input | 1 + testdata/object_invariant_plus2.golden | 1 + testdata/object_invariant_plus2.input | 1 + testdata/object_invariant_plus3.golden | 1 + testdata/object_invariant_plus3.input | 1 + testdata/object_invariant_plus4.golden | 3 + testdata/object_invariant_plus4.input | 1 + testdata/object_invariant_plus5.golden | 3 + testdata/object_invariant_plus5.input | 1 + testdata/object_invariant_plus6.golden | 1 + testdata/object_invariant_plus6.input | 1 + testdata/object_invariant_plus7.golden | 3 + testdata/object_invariant_plus7.input | 2 + testdata/std.makeArray_recursive.golden | 2003 +++++++++++++++++ testdata/std.makeArray_recursive.input | 1 + ...recursive_evalutation_order_matters.golden | 1 + ..._recursive_evalutation_order_matters.input | 1 + thunks.go | 2 +- value.go | 79 +- 52 files changed, 2615 insertions(+), 22 deletions(-) create mode 100644 testdata/object_invariant.golden create mode 100644 testdata/object_invariant.input create mode 100644 testdata/object_invariant10.golden create mode 100644 testdata/object_invariant10.input create mode 100644 testdata/object_invariant11.golden create mode 100644 testdata/object_invariant11.input create mode 100644 testdata/object_invariant12.golden create mode 100644 testdata/object_invariant12.input create mode 100644 testdata/object_invariant13.golden create mode 100644 testdata/object_invariant13.input create mode 100644 testdata/object_invariant14.golden create mode 100644 testdata/object_invariant14.input create mode 100644 testdata/object_invariant2.golden create mode 100644 testdata/object_invariant2.input create mode 100644 testdata/object_invariant3.golden create mode 100644 testdata/object_invariant3.input create mode 100644 testdata/object_invariant4.golden create mode 100644 testdata/object_invariant4.input create mode 100644 testdata/object_invariant5.golden create mode 100644 testdata/object_invariant5.input create mode 100644 testdata/object_invariant6.golden create mode 100644 testdata/object_invariant6.input create mode 100644 testdata/object_invariant7.golden create mode 100644 testdata/object_invariant7.input create mode 100644 testdata/object_invariant8.golden create mode 100644 testdata/object_invariant8.input create mode 100644 testdata/object_invariant9.golden create mode 100644 testdata/object_invariant9.input create mode 100644 testdata/object_invariant_perf.golden create mode 100644 testdata/object_invariant_perf.input create mode 100644 testdata/object_invariant_plus.golden create mode 100644 testdata/object_invariant_plus.input create mode 100644 testdata/object_invariant_plus2.golden create mode 100644 testdata/object_invariant_plus2.input create mode 100644 testdata/object_invariant_plus3.golden create mode 100644 testdata/object_invariant_plus3.input create mode 100644 testdata/object_invariant_plus4.golden create mode 100644 testdata/object_invariant_plus4.input create mode 100644 testdata/object_invariant_plus5.golden create mode 100644 testdata/object_invariant_plus5.input create mode 100644 testdata/object_invariant_plus6.golden create mode 100644 testdata/object_invariant_plus6.input create mode 100644 testdata/object_invariant_plus7.golden create mode 100644 testdata/object_invariant_plus7.input create mode 100644 testdata/std.makeArray_recursive.golden create mode 100644 testdata/std.makeArray_recursive.input create mode 100644 testdata/std.makeArray_recursive_evalutation_order_matters.golden create mode 100644 testdata/std.makeArray_recursive_evalutation_order_matters.input diff --git a/desugarer.go b/desugarer.go index c3c92f6..b14e073 100644 --- a/desugarer.go +++ b/desugarer.go @@ -110,26 +110,23 @@ func desugarFields(location ast.LocationRange, fields *ast.ObjectFields, objLeve // Simplify asserts // TODO(dcunnin): this - for _, field := range *fields { + for i := range *fields { + field := &(*fields)[i] if field.Kind != ast.ObjectAssert { continue } - /* - AST *msg = field.expr3 - field.expr3 = nil - if (msg == nil) { - auto msg_str = U"Object assertion failed." - msg = alloc->make(field.expr2->location, msg_str, - ast.LiteralString::DOUBLE, "") - } - - // if expr2 then true else error msg - field.expr2 = alloc->make( - ast->location, - field.expr2, - alloc->make(E, true), - alloc->make(msg->location, msg)) - */ + msg := field.Expr3 + if msg == nil { + msg = buildLiteralString("Object assertion failed.") + } + field.Expr3 = nil + onFailure := &ast.Error{Expr: msg} + assertion := &ast.Conditional{ + Cond: field.Expr2, + BranchTrue: &ast.LiteralBoolean{Value: true}, // ignored anyway + BranchFalse: onFailure, + } + field.Expr2 = assertion } // Remove methods diff --git a/interpreter.go b/interpreter.go index 82d21cc..6f10a53 100644 --- a/interpreter.go +++ b/interpreter.go @@ -326,8 +326,12 @@ func (i *interpreter) evaluate(a ast.Node, context *TraceContext) (value, error) } fields[fieldName] = valueSimpleObjectField{field.Hide, &codeUnboundField{field.Body}} } + var asserts []unboundField + for _, assert := range ast.Asserts { + asserts = append(asserts, &codeUnboundField{assert}) + } upValues := i.capture(ast.FreeVariables()) - return makeValueSimpleObject(upValues, fields, ast.Asserts), nil + return makeValueSimpleObject(upValues, fields, asserts), nil case *ast.Error: msgVal, err := e.evalInCurrentContext(ast.Expr) @@ -570,6 +574,11 @@ func (i *interpreter) manifestJSON(trace *TraceElement, v value, multiline bool, fieldNames := objectFields(v, true) sort.Strings(fieldNames) + err := checkAssertions(e, v) + if err != nil { + return err + } + if len(fieldNames) == 0 { buf.WriteString("{ }") } else { diff --git a/testdata/object_invariant.golden b/testdata/object_invariant.golden new file mode 100644 index 0000000..ffcd441 --- /dev/null +++ b/testdata/object_invariant.golden @@ -0,0 +1 @@ +{ } diff --git a/testdata/object_invariant.input b/testdata/object_invariant.input new file mode 100644 index 0000000..e69c232 --- /dev/null +++ b/testdata/object_invariant.input @@ -0,0 +1 @@ +{ assert true } diff --git a/testdata/object_invariant10.golden b/testdata/object_invariant10.golden new file mode 100644 index 0000000..a866347 --- /dev/null +++ b/testdata/object_invariant10.golden @@ -0,0 +1 @@ +RUNTIME ERROR: Object assertion failed. diff --git a/testdata/object_invariant10.input b/testdata/object_invariant10.input new file mode 100644 index 0000000..edeb847 --- /dev/null +++ b/testdata/object_invariant10.input @@ -0,0 +1 @@ +{ assert true, assert false } diff --git a/testdata/object_invariant11.golden b/testdata/object_invariant11.golden new file mode 100644 index 0000000..a866347 --- /dev/null +++ b/testdata/object_invariant11.golden @@ -0,0 +1 @@ +RUNTIME ERROR: Object assertion failed. diff --git a/testdata/object_invariant11.input b/testdata/object_invariant11.input new file mode 100644 index 0000000..2cf7699 --- /dev/null +++ b/testdata/object_invariant11.input @@ -0,0 +1 @@ +{ assert false }.x diff --git a/testdata/object_invariant12.golden b/testdata/object_invariant12.golden new file mode 100644 index 0000000..ffcd441 --- /dev/null +++ b/testdata/object_invariant12.golden @@ -0,0 +1 @@ +{ } diff --git a/testdata/object_invariant12.input b/testdata/object_invariant12.input new file mode 100644 index 0000000..14f3dde --- /dev/null +++ b/testdata/object_invariant12.input @@ -0,0 +1 @@ +{ assert 5 == 5 } diff --git a/testdata/object_invariant13.golden b/testdata/object_invariant13.golden new file mode 100644 index 0000000..57d4eaa --- /dev/null +++ b/testdata/object_invariant13.golden @@ -0,0 +1 @@ +RUNTIME ERROR: x diff --git a/testdata/object_invariant13.input b/testdata/object_invariant13.input new file mode 100644 index 0000000..35ad3e5 --- /dev/null +++ b/testdata/object_invariant13.input @@ -0,0 +1 @@ +{ assert error "x" } diff --git a/testdata/object_invariant14.golden b/testdata/object_invariant14.golden new file mode 100644 index 0000000..7bc34d8 --- /dev/null +++ b/testdata/object_invariant14.golden @@ -0,0 +1 @@ +RUNTIME ERROR: xxx diff --git a/testdata/object_invariant14.input b/testdata/object_invariant14.input new file mode 100644 index 0000000..124af5d --- /dev/null +++ b/testdata/object_invariant14.input @@ -0,0 +1 @@ +{ assert false: "xxx" } diff --git a/testdata/object_invariant2.golden b/testdata/object_invariant2.golden new file mode 100644 index 0000000..a866347 --- /dev/null +++ b/testdata/object_invariant2.golden @@ -0,0 +1 @@ +RUNTIME ERROR: Object assertion failed. diff --git a/testdata/object_invariant2.input b/testdata/object_invariant2.input new file mode 100644 index 0000000..f17e5f2 --- /dev/null +++ b/testdata/object_invariant2.input @@ -0,0 +1 @@ +{ assert false } diff --git a/testdata/object_invariant3.golden b/testdata/object_invariant3.golden new file mode 100644 index 0000000..1e3ec72 --- /dev/null +++ b/testdata/object_invariant3.golden @@ -0,0 +1 @@ +[ ] diff --git a/testdata/object_invariant3.input b/testdata/object_invariant3.input new file mode 100644 index 0000000..d321856 --- /dev/null +++ b/testdata/object_invariant3.input @@ -0,0 +1 @@ +std.objectFields({assert false}) diff --git a/testdata/object_invariant4.golden b/testdata/object_invariant4.golden new file mode 100644 index 0000000..c508d53 --- /dev/null +++ b/testdata/object_invariant4.golden @@ -0,0 +1 @@ +false diff --git a/testdata/object_invariant4.input b/testdata/object_invariant4.input new file mode 100644 index 0000000..f4a429b --- /dev/null +++ b/testdata/object_invariant4.input @@ -0,0 +1 @@ +std.objectHas({assert false}, "x") diff --git a/testdata/object_invariant5.golden b/testdata/object_invariant5.golden new file mode 100644 index 0000000..b5ffc7c --- /dev/null +++ b/testdata/object_invariant5.golden @@ -0,0 +1 @@ +"object" diff --git a/testdata/object_invariant5.input b/testdata/object_invariant5.input new file mode 100644 index 0000000..6fa8d12 --- /dev/null +++ b/testdata/object_invariant5.input @@ -0,0 +1 @@ +std.type({assert false}) diff --git a/testdata/object_invariant6.golden b/testdata/object_invariant6.golden new file mode 100644 index 0000000..73d64fd --- /dev/null +++ b/testdata/object_invariant6.golden @@ -0,0 +1,3 @@ +{ + "x": 5 +} diff --git a/testdata/object_invariant6.input b/testdata/object_invariant6.input new file mode 100644 index 0000000..e38f09d --- /dev/null +++ b/testdata/object_invariant6.input @@ -0,0 +1 @@ +{assert self.x == 5, x: 5} diff --git a/testdata/object_invariant7.golden b/testdata/object_invariant7.golden new file mode 100644 index 0000000..449e312 --- /dev/null +++ b/testdata/object_invariant7.golden @@ -0,0 +1 @@ +RUNTIME ERROR: Field does not exist: x diff --git a/testdata/object_invariant7.input b/testdata/object_invariant7.input new file mode 100644 index 0000000..2ea00a6 --- /dev/null +++ b/testdata/object_invariant7.input @@ -0,0 +1 @@ +{ x: 5, assert super.x == 5 } diff --git a/testdata/object_invariant8.golden b/testdata/object_invariant8.golden new file mode 100644 index 0000000..a866347 --- /dev/null +++ b/testdata/object_invariant8.golden @@ -0,0 +1 @@ +RUNTIME ERROR: Object assertion failed. diff --git a/testdata/object_invariant8.input b/testdata/object_invariant8.input new file mode 100644 index 0000000..b79ea06 --- /dev/null +++ b/testdata/object_invariant8.input @@ -0,0 +1 @@ +{ x: 5, assert self.x == 4 } diff --git a/testdata/object_invariant9.golden b/testdata/object_invariant9.golden new file mode 100644 index 0000000..a866347 --- /dev/null +++ b/testdata/object_invariant9.golden @@ -0,0 +1 @@ +RUNTIME ERROR: Object assertion failed. diff --git a/testdata/object_invariant9.input b/testdata/object_invariant9.input new file mode 100644 index 0000000..3e6f2b7 --- /dev/null +++ b/testdata/object_invariant9.input @@ -0,0 +1 @@ +{ assert true, assert false } diff --git a/testdata/object_invariant_perf.golden b/testdata/object_invariant_perf.golden new file mode 100644 index 0000000..c5e032b --- /dev/null +++ b/testdata/object_invariant_perf.golden @@ -0,0 +1,455 @@ +[ + { + "v": -1 + }, + { + "v": 0 + }, + { + "v": 1 + }, + { + "v": 2 + }, + { + "v": 3 + }, + { + "v": 4 + }, + { + "v": 5 + }, + { + "v": 6 + }, + { + "v": 7 + }, + { + "v": 8 + }, + { + "v": 9 + }, + { + "v": 10 + }, + { + "v": 11 + }, + { + "v": 12 + }, + { + "v": 13 + }, + { + "v": 14 + }, + { + "v": 15 + }, + { + "v": 16 + }, + { + "v": 17 + }, + { + "v": 18 + }, + { + "v": 19 + }, + { + "v": 20 + }, + { + "v": 21 + }, + { + "v": 22 + }, + { + "v": 23 + }, + { + "v": 24 + }, + { + "v": 25 + }, + { + "v": 26 + }, + { + "v": 27 + }, + { + "v": 28 + }, + { + "v": 29 + }, + { + "v": 30 + }, + { + "v": 31 + }, + { + "v": 32 + }, + { + "v": 33 + }, + { + "v": 34 + }, + { + "v": 35 + }, + { + "v": 36 + }, + { + "v": 37 + }, + { + "v": 38 + }, + { + "v": 39 + }, + { + "v": 40 + }, + { + "v": 41 + }, + { + "v": 42 + }, + { + "v": 43 + }, + { + "v": 44 + }, + { + "v": 45 + }, + { + "v": 46 + }, + { + "v": 47 + }, + { + "v": 48 + }, + { + "v": 49 + }, + { + "v": 50 + }, + { + "v": 51 + }, + { + "v": 52 + }, + { + "v": 53 + }, + { + "v": 54 + }, + { + "v": 55 + }, + { + "v": 56 + }, + { + "v": 57 + }, + { + "v": 58 + }, + { + "v": 59 + }, + { + "v": 60 + }, + { + "v": 61 + }, + { + "v": 62 + }, + { + "v": 63 + }, + { + "v": 64 + }, + { + "v": 65 + }, + { + "v": 66 + }, + { + "v": 67 + }, + { + "v": 68 + }, + { + "v": 69 + }, + { + "v": 70 + }, + { + "v": 71 + }, + { + "v": 72 + }, + { + "v": 73 + }, + { + "v": 74 + }, + { + "v": 75 + }, + { + "v": 76 + }, + { + "v": 77 + }, + { + "v": 78 + }, + { + "v": 79 + }, + { + "v": 80 + }, + { + "v": 81 + }, + { + "v": 82 + }, + { + "v": 83 + }, + { + "v": 84 + }, + { + "v": 85 + }, + { + "v": 86 + }, + { + "v": 87 + }, + { + "v": 88 + }, + { + "v": 89 + }, + { + "v": 90 + }, + { + "v": 91 + }, + { + "v": 92 + }, + { + "v": 93 + }, + { + "v": 94 + }, + { + "v": 95 + }, + { + "v": 96 + }, + { + "v": 97 + }, + { + "v": 98 + }, + { + "v": 99 + }, + { + "v": 100 + }, + { + "v": 101 + }, + { + "v": 102 + }, + { + "v": 103 + }, + { + "v": 104 + }, + { + "v": 105 + }, + { + "v": 106 + }, + { + "v": 107 + }, + { + "v": 108 + }, + { + "v": 109 + }, + { + "v": 110 + }, + { + "v": 111 + }, + { + "v": 112 + }, + { + "v": 113 + }, + { + "v": 114 + }, + { + "v": 115 + }, + { + "v": 116 + }, + { + "v": 117 + }, + { + "v": 118 + }, + { + "v": 119 + }, + { + "v": 120 + }, + { + "v": 121 + }, + { + "v": 122 + }, + { + "v": 123 + }, + { + "v": 124 + }, + { + "v": 125 + }, + { + "v": 126 + }, + { + "v": 127 + }, + { + "v": 128 + }, + { + "v": 129 + }, + { + "v": 130 + }, + { + "v": 131 + }, + { + "v": 132 + }, + { + "v": 133 + }, + { + "v": 134 + }, + { + "v": 135 + }, + { + "v": 136 + }, + { + "v": 137 + }, + { + "v": 138 + }, + { + "v": 139 + }, + { + "v": 140 + }, + { + "v": 141 + }, + { + "v": 142 + }, + { + "v": 143 + }, + { + "v": 144 + }, + { + "v": 145 + }, + { + "v": 146 + }, + { + "v": 147 + }, + { + "v": 148 + }, + { + "v": 149 + } +] diff --git a/testdata/object_invariant_perf.input b/testdata/object_invariant_perf.input new file mode 100644 index 0000000..d2f4e8f --- /dev/null +++ b/testdata/object_invariant_perf.input @@ -0,0 +1,2 @@ +local arr = [{v: -1}] + std.makeArray(150, function(x) { v: x, assert arr[x].v == self.v - 1 }); +arr diff --git a/testdata/object_invariant_plus.golden b/testdata/object_invariant_plus.golden new file mode 100644 index 0000000..a866347 --- /dev/null +++ b/testdata/object_invariant_plus.golden @@ -0,0 +1 @@ +RUNTIME ERROR: Object assertion failed. diff --git a/testdata/object_invariant_plus.input b/testdata/object_invariant_plus.input new file mode 100644 index 0000000..83d3594 --- /dev/null +++ b/testdata/object_invariant_plus.input @@ -0,0 +1 @@ +{assert false} + {assert true} diff --git a/testdata/object_invariant_plus2.golden b/testdata/object_invariant_plus2.golden new file mode 100644 index 0000000..a866347 --- /dev/null +++ b/testdata/object_invariant_plus2.golden @@ -0,0 +1 @@ +RUNTIME ERROR: Object assertion failed. diff --git a/testdata/object_invariant_plus2.input b/testdata/object_invariant_plus2.input new file mode 100644 index 0000000..4861a65 --- /dev/null +++ b/testdata/object_invariant_plus2.input @@ -0,0 +1 @@ +{assert true} + {assert false} diff --git a/testdata/object_invariant_plus3.golden b/testdata/object_invariant_plus3.golden new file mode 100644 index 0000000..ffcd441 --- /dev/null +++ b/testdata/object_invariant_plus3.golden @@ -0,0 +1 @@ +{ } diff --git a/testdata/object_invariant_plus3.input b/testdata/object_invariant_plus3.input new file mode 100644 index 0000000..02d9b41 --- /dev/null +++ b/testdata/object_invariant_plus3.input @@ -0,0 +1 @@ +{assert true} + {assert true} diff --git a/testdata/object_invariant_plus4.golden b/testdata/object_invariant_plus4.golden new file mode 100644 index 0000000..73d64fd --- /dev/null +++ b/testdata/object_invariant_plus4.golden @@ -0,0 +1,3 @@ +{ + "x": 5 +} diff --git a/testdata/object_invariant_plus4.input b/testdata/object_invariant_plus4.input new file mode 100644 index 0000000..518aa94 --- /dev/null +++ b/testdata/object_invariant_plus4.input @@ -0,0 +1 @@ +{assert self.x == 5} { x: 5 } diff --git a/testdata/object_invariant_plus5.golden b/testdata/object_invariant_plus5.golden new file mode 100644 index 0000000..0ae9c7f --- /dev/null +++ b/testdata/object_invariant_plus5.golden @@ -0,0 +1,3 @@ +{ + "x": 3 +} diff --git a/testdata/object_invariant_plus5.input b/testdata/object_invariant_plus5.input new file mode 100644 index 0000000..284a558 --- /dev/null +++ b/testdata/object_invariant_plus5.input @@ -0,0 +1 @@ +{x: 1, assert self.x == 3} {x: 2, assert super.x == 1} {x: 3, assert super.x == 2} diff --git a/testdata/object_invariant_plus6.golden b/testdata/object_invariant_plus6.golden new file mode 100644 index 0000000..2e2b708 --- /dev/null +++ b/testdata/object_invariant_plus6.golden @@ -0,0 +1 @@ +RUNTIME ERROR: yyy diff --git a/testdata/object_invariant_plus6.input b/testdata/object_invariant_plus6.input new file mode 100644 index 0000000..182cbcf --- /dev/null +++ b/testdata/object_invariant_plus6.input @@ -0,0 +1 @@ +{ assert false: "xxx" } { assert false: "yyy" } diff --git a/testdata/object_invariant_plus7.golden b/testdata/object_invariant_plus7.golden new file mode 100644 index 0000000..e1e6de9 --- /dev/null +++ b/testdata/object_invariant_plus7.golden @@ -0,0 +1,3 @@ +{ + "x": 4 +} diff --git a/testdata/object_invariant_plus7.input b/testdata/object_invariant_plus7.input new file mode 100644 index 0000000..1b6e452 --- /dev/null +++ b/testdata/object_invariant_plus7.input @@ -0,0 +1,2 @@ +({x: 1} {x: 2, assert 1 == super.x}) + +({x: 3, assert 2 == super.x} {x: 4, assert 3 == super.x}) diff --git a/testdata/std.makeArray_recursive.golden b/testdata/std.makeArray_recursive.golden new file mode 100644 index 0000000..4122dea --- /dev/null +++ b/testdata/std.makeArray_recursive.golden @@ -0,0 +1,2003 @@ +[ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 59, + 60, + 61, + 62, + 63, + 64, + 65, + 66, + 67, + 68, + 69, + 70, + 71, + 72, + 73, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 82, + 83, + 84, + 85, + 86, + 87, + 88, + 89, + 90, + 91, + 92, + 93, + 94, + 95, + 96, + 97, + 98, + 99, + 100, + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120, + 121, + 122, + 123, + 124, + 125, + 126, + 127, + 128, + 129, + 130, + 131, + 132, + 133, + 134, + 135, + 136, + 137, + 138, + 139, + 140, + 141, + 142, + 143, + 144, + 145, + 146, + 147, + 148, + 149, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, + 159, + 160, + 161, + 162, + 163, + 164, + 165, + 166, + 167, + 168, + 169, + 170, + 171, + 172, + 173, + 174, + 175, + 176, + 177, + 178, + 179, + 180, + 181, + 182, + 183, + 184, + 185, + 186, + 187, + 188, + 189, + 190, + 191, + 192, + 193, + 194, + 195, + 196, + 197, + 198, + 199, + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, + 209, + 210, + 211, + 212, + 213, + 214, + 215, + 216, + 217, + 218, + 219, + 220, + 221, + 222, + 223, + 224, + 225, + 226, + 227, + 228, + 229, + 230, + 231, + 232, + 233, + 234, + 235, + 236, + 237, + 238, + 239, + 240, + 241, + 242, + 243, + 244, + 245, + 246, + 247, + 248, + 249, + 250, + 251, + 252, + 253, + 254, + 255, + 256, + 257, + 258, + 259, + 260, + 261, + 262, + 263, + 264, + 265, + 266, + 267, + 268, + 269, + 270, + 271, + 272, + 273, + 274, + 275, + 276, + 277, + 278, + 279, + 280, + 281, + 282, + 283, + 284, + 285, + 286, + 287, + 288, + 289, + 290, + 291, + 292, + 293, + 294, + 295, + 296, + 297, + 298, + 299, + 300, + 301, + 302, + 303, + 304, + 305, + 306, + 307, + 308, + 309, + 310, + 311, + 312, + 313, + 314, + 315, + 316, + 317, + 318, + 319, + 320, + 321, + 322, + 323, + 324, + 325, + 326, + 327, + 328, + 329, + 330, + 331, + 332, + 333, + 334, + 335, + 336, + 337, + 338, + 339, + 340, + 341, + 342, + 343, + 344, + 345, + 346, + 347, + 348, + 349, + 350, + 351, + 352, + 353, + 354, + 355, + 356, + 357, + 358, + 359, + 360, + 361, + 362, + 363, + 364, + 365, + 366, + 367, + 368, + 369, + 370, + 371, + 372, + 373, + 374, + 375, + 376, + 377, + 378, + 379, + 380, + 381, + 382, + 383, + 384, + 385, + 386, + 387, + 388, + 389, + 390, + 391, + 392, + 393, + 394, + 395, + 396, + 397, + 398, + 399, + 400, + 401, + 402, + 403, + 404, + 405, + 406, + 407, + 408, + 409, + 410, + 411, + 412, + 413, + 414, + 415, + 416, + 417, + 418, + 419, + 420, + 421, + 422, + 423, + 424, + 425, + 426, + 427, + 428, + 429, + 430, + 431, + 432, + 433, + 434, + 435, + 436, + 437, + 438, + 439, + 440, + 441, + 442, + 443, + 444, + 445, + 446, + 447, + 448, + 449, + 450, + 451, + 452, + 453, + 454, + 455, + 456, + 457, + 458, + 459, + 460, + 461, + 462, + 463, + 464, + 465, + 466, + 467, + 468, + 469, + 470, + 471, + 472, + 473, + 474, + 475, + 476, + 477, + 478, + 479, + 480, + 481, + 482, + 483, + 484, + 485, + 486, + 487, + 488, + 489, + 490, + 491, + 492, + 493, + 494, + 495, + 496, + 497, + 498, + 499, + 500, + 501, + 502, + 503, + 504, + 505, + 506, + 507, + 508, + 509, + 510, + 511, + 512, + 513, + 514, + 515, + 516, + 517, + 518, + 519, + 520, + 521, + 522, + 523, + 524, + 525, + 526, + 527, + 528, + 529, + 530, + 531, + 532, + 533, + 534, + 535, + 536, + 537, + 538, + 539, + 540, + 541, + 542, + 543, + 544, + 545, + 546, + 547, + 548, + 549, + 550, + 551, + 552, + 553, + 554, + 555, + 556, + 557, + 558, + 559, + 560, + 561, + 562, + 563, + 564, + 565, + 566, + 567, + 568, + 569, + 570, + 571, + 572, + 573, + 574, + 575, + 576, + 577, + 578, + 579, + 580, + 581, + 582, + 583, + 584, + 585, + 586, + 587, + 588, + 589, + 590, + 591, + 592, + 593, + 594, + 595, + 596, + 597, + 598, + 599, + 600, + 601, + 602, + 603, + 604, + 605, + 606, + 607, + 608, + 609, + 610, + 611, + 612, + 613, + 614, + 615, + 616, + 617, + 618, + 619, + 620, + 621, + 622, + 623, + 624, + 625, + 626, + 627, + 628, + 629, + 630, + 631, + 632, + 633, + 634, + 635, + 636, + 637, + 638, + 639, + 640, + 641, + 642, + 643, + 644, + 645, + 646, + 647, + 648, + 649, + 650, + 651, + 652, + 653, + 654, + 655, + 656, + 657, + 658, + 659, + 660, + 661, + 662, + 663, + 664, + 665, + 666, + 667, + 668, + 669, + 670, + 671, + 672, + 673, + 674, + 675, + 676, + 677, + 678, + 679, + 680, + 681, + 682, + 683, + 684, + 685, + 686, + 687, + 688, + 689, + 690, + 691, + 692, + 693, + 694, + 695, + 696, + 697, + 698, + 699, + 700, + 701, + 702, + 703, + 704, + 705, + 706, + 707, + 708, + 709, + 710, + 711, + 712, + 713, + 714, + 715, + 716, + 717, + 718, + 719, + 720, + 721, + 722, + 723, + 724, + 725, + 726, + 727, + 728, + 729, + 730, + 731, + 732, + 733, + 734, + 735, + 736, + 737, + 738, + 739, + 740, + 741, + 742, + 743, + 744, + 745, + 746, + 747, + 748, + 749, + 750, + 751, + 752, + 753, + 754, + 755, + 756, + 757, + 758, + 759, + 760, + 761, + 762, + 763, + 764, + 765, + 766, + 767, + 768, + 769, + 770, + 771, + 772, + 773, + 774, + 775, + 776, + 777, + 778, + 779, + 780, + 781, + 782, + 783, + 784, + 785, + 786, + 787, + 788, + 789, + 790, + 791, + 792, + 793, + 794, + 795, + 796, + 797, + 798, + 799, + 800, + 801, + 802, + 803, + 804, + 805, + 806, + 807, + 808, + 809, + 810, + 811, + 812, + 813, + 814, + 815, + 816, + 817, + 818, + 819, + 820, + 821, + 822, + 823, + 824, + 825, + 826, + 827, + 828, + 829, + 830, + 831, + 832, + 833, + 834, + 835, + 836, + 837, + 838, + 839, + 840, + 841, + 842, + 843, + 844, + 845, + 846, + 847, + 848, + 849, + 850, + 851, + 852, + 853, + 854, + 855, + 856, + 857, + 858, + 859, + 860, + 861, + 862, + 863, + 864, + 865, + 866, + 867, + 868, + 869, + 870, + 871, + 872, + 873, + 874, + 875, + 876, + 877, + 878, + 879, + 880, + 881, + 882, + 883, + 884, + 885, + 886, + 887, + 888, + 889, + 890, + 891, + 892, + 893, + 894, + 895, + 896, + 897, + 898, + 899, + 900, + 901, + 902, + 903, + 904, + 905, + 906, + 907, + 908, + 909, + 910, + 911, + 912, + 913, + 914, + 915, + 916, + 917, + 918, + 919, + 920, + 921, + 922, + 923, + 924, + 925, + 926, + 927, + 928, + 929, + 930, + 931, + 932, + 933, + 934, + 935, + 936, + 937, + 938, + 939, + 940, + 941, + 942, + 943, + 944, + 945, + 946, + 947, + 948, + 949, + 950, + 951, + 952, + 953, + 954, + 955, + 956, + 957, + 958, + 959, + 960, + 961, + 962, + 963, + 964, + 965, + 966, + 967, + 968, + 969, + 970, + 971, + 972, + 973, + 974, + 975, + 976, + 977, + 978, + 979, + 980, + 981, + 982, + 983, + 984, + 985, + 986, + 987, + 988, + 989, + 990, + 991, + 992, + 993, + 994, + 995, + 996, + 997, + 998, + 999, + 1000, + 1001, + 1002, + 1003, + 1004, + 1005, + 1006, + 1007, + 1008, + 1009, + 1010, + 1011, + 1012, + 1013, + 1014, + 1015, + 1016, + 1017, + 1018, + 1019, + 1020, + 1021, + 1022, + 1023, + 1024, + 1025, + 1026, + 1027, + 1028, + 1029, + 1030, + 1031, + 1032, + 1033, + 1034, + 1035, + 1036, + 1037, + 1038, + 1039, + 1040, + 1041, + 1042, + 1043, + 1044, + 1045, + 1046, + 1047, + 1048, + 1049, + 1050, + 1051, + 1052, + 1053, + 1054, + 1055, + 1056, + 1057, + 1058, + 1059, + 1060, + 1061, + 1062, + 1063, + 1064, + 1065, + 1066, + 1067, + 1068, + 1069, + 1070, + 1071, + 1072, + 1073, + 1074, + 1075, + 1076, + 1077, + 1078, + 1079, + 1080, + 1081, + 1082, + 1083, + 1084, + 1085, + 1086, + 1087, + 1088, + 1089, + 1090, + 1091, + 1092, + 1093, + 1094, + 1095, + 1096, + 1097, + 1098, + 1099, + 1100, + 1101, + 1102, + 1103, + 1104, + 1105, + 1106, + 1107, + 1108, + 1109, + 1110, + 1111, + 1112, + 1113, + 1114, + 1115, + 1116, + 1117, + 1118, + 1119, + 1120, + 1121, + 1122, + 1123, + 1124, + 1125, + 1126, + 1127, + 1128, + 1129, + 1130, + 1131, + 1132, + 1133, + 1134, + 1135, + 1136, + 1137, + 1138, + 1139, + 1140, + 1141, + 1142, + 1143, + 1144, + 1145, + 1146, + 1147, + 1148, + 1149, + 1150, + 1151, + 1152, + 1153, + 1154, + 1155, + 1156, + 1157, + 1158, + 1159, + 1160, + 1161, + 1162, + 1163, + 1164, + 1165, + 1166, + 1167, + 1168, + 1169, + 1170, + 1171, + 1172, + 1173, + 1174, + 1175, + 1176, + 1177, + 1178, + 1179, + 1180, + 1181, + 1182, + 1183, + 1184, + 1185, + 1186, + 1187, + 1188, + 1189, + 1190, + 1191, + 1192, + 1193, + 1194, + 1195, + 1196, + 1197, + 1198, + 1199, + 1200, + 1201, + 1202, + 1203, + 1204, + 1205, + 1206, + 1207, + 1208, + 1209, + 1210, + 1211, + 1212, + 1213, + 1214, + 1215, + 1216, + 1217, + 1218, + 1219, + 1220, + 1221, + 1222, + 1223, + 1224, + 1225, + 1226, + 1227, + 1228, + 1229, + 1230, + 1231, + 1232, + 1233, + 1234, + 1235, + 1236, + 1237, + 1238, + 1239, + 1240, + 1241, + 1242, + 1243, + 1244, + 1245, + 1246, + 1247, + 1248, + 1249, + 1250, + 1251, + 1252, + 1253, + 1254, + 1255, + 1256, + 1257, + 1258, + 1259, + 1260, + 1261, + 1262, + 1263, + 1264, + 1265, + 1266, + 1267, + 1268, + 1269, + 1270, + 1271, + 1272, + 1273, + 1274, + 1275, + 1276, + 1277, + 1278, + 1279, + 1280, + 1281, + 1282, + 1283, + 1284, + 1285, + 1286, + 1287, + 1288, + 1289, + 1290, + 1291, + 1292, + 1293, + 1294, + 1295, + 1296, + 1297, + 1298, + 1299, + 1300, + 1301, + 1302, + 1303, + 1304, + 1305, + 1306, + 1307, + 1308, + 1309, + 1310, + 1311, + 1312, + 1313, + 1314, + 1315, + 1316, + 1317, + 1318, + 1319, + 1320, + 1321, + 1322, + 1323, + 1324, + 1325, + 1326, + 1327, + 1328, + 1329, + 1330, + 1331, + 1332, + 1333, + 1334, + 1335, + 1336, + 1337, + 1338, + 1339, + 1340, + 1341, + 1342, + 1343, + 1344, + 1345, + 1346, + 1347, + 1348, + 1349, + 1350, + 1351, + 1352, + 1353, + 1354, + 1355, + 1356, + 1357, + 1358, + 1359, + 1360, + 1361, + 1362, + 1363, + 1364, + 1365, + 1366, + 1367, + 1368, + 1369, + 1370, + 1371, + 1372, + 1373, + 1374, + 1375, + 1376, + 1377, + 1378, + 1379, + 1380, + 1381, + 1382, + 1383, + 1384, + 1385, + 1386, + 1387, + 1388, + 1389, + 1390, + 1391, + 1392, + 1393, + 1394, + 1395, + 1396, + 1397, + 1398, + 1399, + 1400, + 1401, + 1402, + 1403, + 1404, + 1405, + 1406, + 1407, + 1408, + 1409, + 1410, + 1411, + 1412, + 1413, + 1414, + 1415, + 1416, + 1417, + 1418, + 1419, + 1420, + 1421, + 1422, + 1423, + 1424, + 1425, + 1426, + 1427, + 1428, + 1429, + 1430, + 1431, + 1432, + 1433, + 1434, + 1435, + 1436, + 1437, + 1438, + 1439, + 1440, + 1441, + 1442, + 1443, + 1444, + 1445, + 1446, + 1447, + 1448, + 1449, + 1450, + 1451, + 1452, + 1453, + 1454, + 1455, + 1456, + 1457, + 1458, + 1459, + 1460, + 1461, + 1462, + 1463, + 1464, + 1465, + 1466, + 1467, + 1468, + 1469, + 1470, + 1471, + 1472, + 1473, + 1474, + 1475, + 1476, + 1477, + 1478, + 1479, + 1480, + 1481, + 1482, + 1483, + 1484, + 1485, + 1486, + 1487, + 1488, + 1489, + 1490, + 1491, + 1492, + 1493, + 1494, + 1495, + 1496, + 1497, + 1498, + 1499, + 1500, + 1501, + 1502, + 1503, + 1504, + 1505, + 1506, + 1507, + 1508, + 1509, + 1510, + 1511, + 1512, + 1513, + 1514, + 1515, + 1516, + 1517, + 1518, + 1519, + 1520, + 1521, + 1522, + 1523, + 1524, + 1525, + 1526, + 1527, + 1528, + 1529, + 1530, + 1531, + 1532, + 1533, + 1534, + 1535, + 1536, + 1537, + 1538, + 1539, + 1540, + 1541, + 1542, + 1543, + 1544, + 1545, + 1546, + 1547, + 1548, + 1549, + 1550, + 1551, + 1552, + 1553, + 1554, + 1555, + 1556, + 1557, + 1558, + 1559, + 1560, + 1561, + 1562, + 1563, + 1564, + 1565, + 1566, + 1567, + 1568, + 1569, + 1570, + 1571, + 1572, + 1573, + 1574, + 1575, + 1576, + 1577, + 1578, + 1579, + 1580, + 1581, + 1582, + 1583, + 1584, + 1585, + 1586, + 1587, + 1588, + 1589, + 1590, + 1591, + 1592, + 1593, + 1594, + 1595, + 1596, + 1597, + 1598, + 1599, + 1600, + 1601, + 1602, + 1603, + 1604, + 1605, + 1606, + 1607, + 1608, + 1609, + 1610, + 1611, + 1612, + 1613, + 1614, + 1615, + 1616, + 1617, + 1618, + 1619, + 1620, + 1621, + 1622, + 1623, + 1624, + 1625, + 1626, + 1627, + 1628, + 1629, + 1630, + 1631, + 1632, + 1633, + 1634, + 1635, + 1636, + 1637, + 1638, + 1639, + 1640, + 1641, + 1642, + 1643, + 1644, + 1645, + 1646, + 1647, + 1648, + 1649, + 1650, + 1651, + 1652, + 1653, + 1654, + 1655, + 1656, + 1657, + 1658, + 1659, + 1660, + 1661, + 1662, + 1663, + 1664, + 1665, + 1666, + 1667, + 1668, + 1669, + 1670, + 1671, + 1672, + 1673, + 1674, + 1675, + 1676, + 1677, + 1678, + 1679, + 1680, + 1681, + 1682, + 1683, + 1684, + 1685, + 1686, + 1687, + 1688, + 1689, + 1690, + 1691, + 1692, + 1693, + 1694, + 1695, + 1696, + 1697, + 1698, + 1699, + 1700, + 1701, + 1702, + 1703, + 1704, + 1705, + 1706, + 1707, + 1708, + 1709, + 1710, + 1711, + 1712, + 1713, + 1714, + 1715, + 1716, + 1717, + 1718, + 1719, + 1720, + 1721, + 1722, + 1723, + 1724, + 1725, + 1726, + 1727, + 1728, + 1729, + 1730, + 1731, + 1732, + 1733, + 1734, + 1735, + 1736, + 1737, + 1738, + 1739, + 1740, + 1741, + 1742, + 1743, + 1744, + 1745, + 1746, + 1747, + 1748, + 1749, + 1750, + 1751, + 1752, + 1753, + 1754, + 1755, + 1756, + 1757, + 1758, + 1759, + 1760, + 1761, + 1762, + 1763, + 1764, + 1765, + 1766, + 1767, + 1768, + 1769, + 1770, + 1771, + 1772, + 1773, + 1774, + 1775, + 1776, + 1777, + 1778, + 1779, + 1780, + 1781, + 1782, + 1783, + 1784, + 1785, + 1786, + 1787, + 1788, + 1789, + 1790, + 1791, + 1792, + 1793, + 1794, + 1795, + 1796, + 1797, + 1798, + 1799, + 1800, + 1801, + 1802, + 1803, + 1804, + 1805, + 1806, + 1807, + 1808, + 1809, + 1810, + 1811, + 1812, + 1813, + 1814, + 1815, + 1816, + 1817, + 1818, + 1819, + 1820, + 1821, + 1822, + 1823, + 1824, + 1825, + 1826, + 1827, + 1828, + 1829, + 1830, + 1831, + 1832, + 1833, + 1834, + 1835, + 1836, + 1837, + 1838, + 1839, + 1840, + 1841, + 1842, + 1843, + 1844, + 1845, + 1846, + 1847, + 1848, + 1849, + 1850, + 1851, + 1852, + 1853, + 1854, + 1855, + 1856, + 1857, + 1858, + 1859, + 1860, + 1861, + 1862, + 1863, + 1864, + 1865, + 1866, + 1867, + 1868, + 1869, + 1870, + 1871, + 1872, + 1873, + 1874, + 1875, + 1876, + 1877, + 1878, + 1879, + 1880, + 1881, + 1882, + 1883, + 1884, + 1885, + 1886, + 1887, + 1888, + 1889, + 1890, + 1891, + 1892, + 1893, + 1894, + 1895, + 1896, + 1897, + 1898, + 1899, + 1900, + 1901, + 1902, + 1903, + 1904, + 1905, + 1906, + 1907, + 1908, + 1909, + 1910, + 1911, + 1912, + 1913, + 1914, + 1915, + 1916, + 1917, + 1918, + 1919, + 1920, + 1921, + 1922, + 1923, + 1924, + 1925, + 1926, + 1927, + 1928, + 1929, + 1930, + 1931, + 1932, + 1933, + 1934, + 1935, + 1936, + 1937, + 1938, + 1939, + 1940, + 1941, + 1942, + 1943, + 1944, + 1945, + 1946, + 1947, + 1948, + 1949, + 1950, + 1951, + 1952, + 1953, + 1954, + 1955, + 1956, + 1957, + 1958, + 1959, + 1960, + 1961, + 1962, + 1963, + 1964, + 1965, + 1966, + 1967, + 1968, + 1969, + 1970, + 1971, + 1972, + 1973, + 1974, + 1975, + 1976, + 1977, + 1978, + 1979, + 1980, + 1981, + 1982, + 1983, + 1984, + 1985, + 1986, + 1987, + 1988, + 1989, + 1990, + 1991, + 1992, + 1993, + 1994, + 1995, + 1996, + 1997, + 1998, + 1999, + 2000 +] diff --git a/testdata/std.makeArray_recursive.input b/testdata/std.makeArray_recursive.input new file mode 100644 index 0000000..99bc382 --- /dev/null +++ b/testdata/std.makeArray_recursive.input @@ -0,0 +1 @@ +local arr = [0] + std.makeArray(2000, function(i) arr[i] + 1); arr diff --git a/testdata/std.makeArray_recursive_evalutation_order_matters.golden b/testdata/std.makeArray_recursive_evalutation_order_matters.golden new file mode 100644 index 0000000..e3fd674 --- /dev/null +++ b/testdata/std.makeArray_recursive_evalutation_order_matters.golden @@ -0,0 +1 @@ +RUNTIME ERROR: Max stack frames exceeded. diff --git a/testdata/std.makeArray_recursive_evalutation_order_matters.input b/testdata/std.makeArray_recursive_evalutation_order_matters.input new file mode 100644 index 0000000..ab466c9 --- /dev/null +++ b/testdata/std.makeArray_recursive_evalutation_order_matters.input @@ -0,0 +1 @@ +local arr = [0] + std.makeArray(2000, function(i) arr[i] + 1); arr[500] diff --git a/thunks.go b/thunks.go index 5bc9b13..b26fb21 100644 --- a/thunks.go +++ b/thunks.go @@ -75,7 +75,7 @@ type callThunk struct { } func makeCallThunk(ec evalCallable, args callArguments) potentialValue { - return &callThunk{function: ec, args: args} + return makeCachedThunk(&callThunk{function: ec, args: args}) } func (th *callThunk) getValue(i *interpreter, trace *TraceElement) (value, error) { diff --git a/value.go b/value.go index fa2d5fd..e2a0d67 100644 --- a/value.go +++ b/value.go @@ -16,6 +16,7 @@ limitations under the License. package jsonnet import ( + "errors" "fmt" "github.com/google/go-jsonnet/ast" @@ -269,6 +270,9 @@ type valueObject interface { value inheritanceSize() int index(e *evaluator, field string) (value, error) + assertionsChecked() bool + setAssertionsCheckResult(err error) + getAssertionsCheckResult() error } type selfBinding struct { @@ -276,7 +280,7 @@ type selfBinding struct { // that this is not the same as context, because we could be inside a function, // inside an object and then context would be the function, but self would still point // to the object. - self value + self valueObject // superDepth is the "super" level of self. Sometimes, we look upwards in the // inheritance tree, e.g. via an explicit use of super, or because a given field @@ -297,14 +301,43 @@ func makeUnboundSelfBinding() selfBinding { } } +// Hack - we need to distinguish not-checked-yet and no error situations +// so we have a special value for no error and nil means that we don't know yet. +var errNoErrorInObjectInvariants = errors.New("No error - assertions passed") + type valueObjectBase struct { valueBase + assertionError error } func (*valueObjectBase) typename() string { return "object" } +func (obj *valueObjectBase) assertionsChecked() bool { + // nil - not checked yet + // errNoErrorInObjectInvariants - we checked and there is no error (or checking in progress) + return obj.assertionError != nil +} + +func (obj *valueObjectBase) setAssertionsCheckResult(err error) { + if err != nil { + obj.assertionError = err + } else { + obj.assertionError = errNoErrorInObjectInvariants + } +} + +func (obj *valueObjectBase) getAssertionsCheckResult() error { + if obj.assertionError == nil { + panic("Assertions not checked yet") + } + if obj.assertionError == errNoErrorInObjectInvariants { + return nil + } + return obj.assertionError +} + // valueSimpleObject represents a flat object (no inheritance). // Note that it can be used as part of extended objects // in inheritance using operator +. @@ -317,7 +350,43 @@ type valueSimpleObject struct { valueObjectBase upValues bindingFrame fields valueSimpleObjectFieldMap - asserts []ast.Node + asserts []unboundField +} + +func checkAssertionsHelper(e *evaluator, obj valueObject, curr valueObject, superDepth int) error { + switch curr := curr.(type) { + case *valueExtendedObject: + err := checkAssertionsHelper(e, obj, curr.right, superDepth) + if err != nil { + return err + } + err = checkAssertionsHelper(e, obj, curr.left, superDepth+curr.right.inheritanceSize()) + if err != nil { + return err + } + return nil + case *valueSimpleObject: + for _, assert := range curr.asserts { + _, err := e.evaluate(assert.bindToObject(selfBinding{self: obj, superDepth: superDepth}, curr.upValues)) + if err != nil { + return err + } + } + return nil + default: + panic(fmt.Sprintf("Unknown object type %#v", obj)) + } +} + +func checkAssertions(e *evaluator, obj valueObject) error { + if !obj.assertionsChecked() { + // Assertions may refer to the object that will normally + // trigger checking of assertions, resulting in an endless recursion. + // To avoid that, while we check them, we treat them as already passed. + obj.setAssertionsCheckResult(errNoErrorInObjectInvariants) + obj.setAssertionsCheckResult(checkAssertionsHelper(e, obj, obj, 0)) + } + return obj.getAssertionsCheckResult() } func (o *valueSimpleObject) index(e *evaluator, field string) (value, error) { @@ -328,7 +397,7 @@ func (*valueSimpleObject) inheritanceSize() int { return 1 } -func makeValueSimpleObject(b bindingFrame, fields valueSimpleObjectFieldMap, asserts ast.Nodes) *valueSimpleObject { +func makeValueSimpleObject(b bindingFrame, fields valueSimpleObjectFieldMap, asserts []unboundField) *valueSimpleObject { return &valueSimpleObject{ upValues: b, fields: fields, @@ -425,6 +494,10 @@ func superIndex(e *evaluator, currentSB selfBinding, field string) (value, error } func objectIndex(e *evaluator, sb selfBinding, fieldName string) (value, error) { + err := checkAssertions(e, sb.self) + if err != nil { + return nil, err + } field, upValues, foundAt := findField(sb.self, sb.superDepth, fieldName) if field == nil { return nil, e.Error(fmt.Sprintf("Field does not exist: %s", fieldName))