mirror of
https://github.com/google/go-jsonnet.git
synced 2025-08-08 07:17:12 +02:00
parent
9047718ad0
commit
8638a21287
31
desugarer.go
31
desugarer.go
@ -110,26 +110,23 @@ func desugarFields(location ast.LocationRange, fields *ast.ObjectFields, objLeve
|
|||||||
|
|
||||||
// Simplify asserts
|
// Simplify asserts
|
||||||
// TODO(dcunnin): this
|
// TODO(dcunnin): this
|
||||||
for _, field := range *fields {
|
for i := range *fields {
|
||||||
|
field := &(*fields)[i]
|
||||||
if field.Kind != ast.ObjectAssert {
|
if field.Kind != ast.ObjectAssert {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
/*
|
msg := field.Expr3
|
||||||
AST *msg = field.expr3
|
if msg == nil {
|
||||||
field.expr3 = nil
|
msg = buildLiteralString("Object assertion failed.")
|
||||||
if (msg == nil) {
|
}
|
||||||
auto msg_str = U"Object assertion failed."
|
field.Expr3 = nil
|
||||||
msg = alloc->make<ast.LiteralString>(field.expr2->location, msg_str,
|
onFailure := &ast.Error{Expr: msg}
|
||||||
ast.LiteralString::DOUBLE, "")
|
assertion := &ast.Conditional{
|
||||||
}
|
Cond: field.Expr2,
|
||||||
|
BranchTrue: &ast.LiteralBoolean{Value: true}, // ignored anyway
|
||||||
// if expr2 then true else error msg
|
BranchFalse: onFailure,
|
||||||
field.expr2 = alloc->make<ast.Conditional>(
|
}
|
||||||
ast->location,
|
field.Expr2 = assertion
|
||||||
field.expr2,
|
|
||||||
alloc->make<ast.LiteralBoolean>(E, true),
|
|
||||||
alloc->make<Error>(msg->location, msg))
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove methods
|
// Remove methods
|
||||||
|
@ -326,8 +326,12 @@ func (i *interpreter) evaluate(a ast.Node, context *TraceContext) (value, error)
|
|||||||
}
|
}
|
||||||
fields[fieldName] = valueSimpleObjectField{field.Hide, &codeUnboundField{field.Body}}
|
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())
|
upValues := i.capture(ast.FreeVariables())
|
||||||
return makeValueSimpleObject(upValues, fields, ast.Asserts), nil
|
return makeValueSimpleObject(upValues, fields, asserts), nil
|
||||||
|
|
||||||
case *ast.Error:
|
case *ast.Error:
|
||||||
msgVal, err := e.evalInCurrentContext(ast.Expr)
|
msgVal, err := e.evalInCurrentContext(ast.Expr)
|
||||||
@ -570,6 +574,11 @@ func (i *interpreter) manifestJSON(trace *TraceElement, v value, multiline bool,
|
|||||||
fieldNames := objectFields(v, true)
|
fieldNames := objectFields(v, true)
|
||||||
sort.Strings(fieldNames)
|
sort.Strings(fieldNames)
|
||||||
|
|
||||||
|
err := checkAssertions(e, v)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if len(fieldNames) == 0 {
|
if len(fieldNames) == 0 {
|
||||||
buf.WriteString("{ }")
|
buf.WriteString("{ }")
|
||||||
} else {
|
} else {
|
||||||
|
1
testdata/object_invariant.golden
vendored
Normal file
1
testdata/object_invariant.golden
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{ }
|
1
testdata/object_invariant.input
vendored
Normal file
1
testdata/object_invariant.input
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{ assert true }
|
1
testdata/object_invariant10.golden
vendored
Normal file
1
testdata/object_invariant10.golden
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
RUNTIME ERROR: Object assertion failed.
|
1
testdata/object_invariant10.input
vendored
Normal file
1
testdata/object_invariant10.input
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{ assert true, assert false }
|
1
testdata/object_invariant11.golden
vendored
Normal file
1
testdata/object_invariant11.golden
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
RUNTIME ERROR: Object assertion failed.
|
1
testdata/object_invariant11.input
vendored
Normal file
1
testdata/object_invariant11.input
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{ assert false }.x
|
1
testdata/object_invariant12.golden
vendored
Normal file
1
testdata/object_invariant12.golden
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{ }
|
1
testdata/object_invariant12.input
vendored
Normal file
1
testdata/object_invariant12.input
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{ assert 5 == 5 }
|
1
testdata/object_invariant13.golden
vendored
Normal file
1
testdata/object_invariant13.golden
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
RUNTIME ERROR: x
|
1
testdata/object_invariant13.input
vendored
Normal file
1
testdata/object_invariant13.input
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{ assert error "x" }
|
1
testdata/object_invariant14.golden
vendored
Normal file
1
testdata/object_invariant14.golden
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
RUNTIME ERROR: xxx
|
1
testdata/object_invariant14.input
vendored
Normal file
1
testdata/object_invariant14.input
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{ assert false: "xxx" }
|
1
testdata/object_invariant2.golden
vendored
Normal file
1
testdata/object_invariant2.golden
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
RUNTIME ERROR: Object assertion failed.
|
1
testdata/object_invariant2.input
vendored
Normal file
1
testdata/object_invariant2.input
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{ assert false }
|
1
testdata/object_invariant3.golden
vendored
Normal file
1
testdata/object_invariant3.golden
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
[ ]
|
1
testdata/object_invariant3.input
vendored
Normal file
1
testdata/object_invariant3.input
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
std.objectFields({assert false})
|
1
testdata/object_invariant4.golden
vendored
Normal file
1
testdata/object_invariant4.golden
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
false
|
1
testdata/object_invariant4.input
vendored
Normal file
1
testdata/object_invariant4.input
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
std.objectHas({assert false}, "x")
|
1
testdata/object_invariant5.golden
vendored
Normal file
1
testdata/object_invariant5.golden
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
"object"
|
1
testdata/object_invariant5.input
vendored
Normal file
1
testdata/object_invariant5.input
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
std.type({assert false})
|
3
testdata/object_invariant6.golden
vendored
Normal file
3
testdata/object_invariant6.golden
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"x": 5
|
||||||
|
}
|
1
testdata/object_invariant6.input
vendored
Normal file
1
testdata/object_invariant6.input
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{assert self.x == 5, x: 5}
|
1
testdata/object_invariant7.golden
vendored
Normal file
1
testdata/object_invariant7.golden
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
RUNTIME ERROR: Field does not exist: x
|
1
testdata/object_invariant7.input
vendored
Normal file
1
testdata/object_invariant7.input
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{ x: 5, assert super.x == 5 }
|
1
testdata/object_invariant8.golden
vendored
Normal file
1
testdata/object_invariant8.golden
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
RUNTIME ERROR: Object assertion failed.
|
1
testdata/object_invariant8.input
vendored
Normal file
1
testdata/object_invariant8.input
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{ x: 5, assert self.x == 4 }
|
1
testdata/object_invariant9.golden
vendored
Normal file
1
testdata/object_invariant9.golden
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
RUNTIME ERROR: Object assertion failed.
|
1
testdata/object_invariant9.input
vendored
Normal file
1
testdata/object_invariant9.input
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{ assert true, assert false }
|
455
testdata/object_invariant_perf.golden
vendored
Normal file
455
testdata/object_invariant_perf.golden
vendored
Normal file
@ -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
|
||||||
|
}
|
||||||
|
]
|
2
testdata/object_invariant_perf.input
vendored
Normal file
2
testdata/object_invariant_perf.input
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
local arr = [{v: -1}] + std.makeArray(150, function(x) { v: x, assert arr[x].v == self.v - 1 });
|
||||||
|
arr
|
1
testdata/object_invariant_plus.golden
vendored
Normal file
1
testdata/object_invariant_plus.golden
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
RUNTIME ERROR: Object assertion failed.
|
1
testdata/object_invariant_plus.input
vendored
Normal file
1
testdata/object_invariant_plus.input
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{assert false} + {assert true}
|
1
testdata/object_invariant_plus2.golden
vendored
Normal file
1
testdata/object_invariant_plus2.golden
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
RUNTIME ERROR: Object assertion failed.
|
1
testdata/object_invariant_plus2.input
vendored
Normal file
1
testdata/object_invariant_plus2.input
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{assert true} + {assert false}
|
1
testdata/object_invariant_plus3.golden
vendored
Normal file
1
testdata/object_invariant_plus3.golden
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{ }
|
1
testdata/object_invariant_plus3.input
vendored
Normal file
1
testdata/object_invariant_plus3.input
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{assert true} + {assert true}
|
3
testdata/object_invariant_plus4.golden
vendored
Normal file
3
testdata/object_invariant_plus4.golden
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"x": 5
|
||||||
|
}
|
1
testdata/object_invariant_plus4.input
vendored
Normal file
1
testdata/object_invariant_plus4.input
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{assert self.x == 5} { x: 5 }
|
3
testdata/object_invariant_plus5.golden
vendored
Normal file
3
testdata/object_invariant_plus5.golden
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"x": 3
|
||||||
|
}
|
1
testdata/object_invariant_plus5.input
vendored
Normal file
1
testdata/object_invariant_plus5.input
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{x: 1, assert self.x == 3} {x: 2, assert super.x == 1} {x: 3, assert super.x == 2}
|
1
testdata/object_invariant_plus6.golden
vendored
Normal file
1
testdata/object_invariant_plus6.golden
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
RUNTIME ERROR: yyy
|
1
testdata/object_invariant_plus6.input
vendored
Normal file
1
testdata/object_invariant_plus6.input
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{ assert false: "xxx" } { assert false: "yyy" }
|
3
testdata/object_invariant_plus7.golden
vendored
Normal file
3
testdata/object_invariant_plus7.golden
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"x": 4
|
||||||
|
}
|
2
testdata/object_invariant_plus7.input
vendored
Normal file
2
testdata/object_invariant_plus7.input
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
({x: 1} {x: 2, assert 1 == super.x}) +
|
||||||
|
({x: 3, assert 2 == super.x} {x: 4, assert 3 == super.x})
|
2003
testdata/std.makeArray_recursive.golden
vendored
Normal file
2003
testdata/std.makeArray_recursive.golden
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
testdata/std.makeArray_recursive.input
vendored
Normal file
1
testdata/std.makeArray_recursive.input
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
local arr = [0] + std.makeArray(2000, function(i) arr[i] + 1); arr
|
1
testdata/std.makeArray_recursive_evalutation_order_matters.golden
vendored
Normal file
1
testdata/std.makeArray_recursive_evalutation_order_matters.golden
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
RUNTIME ERROR: Max stack frames exceeded.
|
1
testdata/std.makeArray_recursive_evalutation_order_matters.input
vendored
Normal file
1
testdata/std.makeArray_recursive_evalutation_order_matters.input
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
local arr = [0] + std.makeArray(2000, function(i) arr[i] + 1); arr[500]
|
@ -75,7 +75,7 @@ type callThunk struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func makeCallThunk(ec evalCallable, args callArguments) potentialValue {
|
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) {
|
func (th *callThunk) getValue(i *interpreter, trace *TraceElement) (value, error) {
|
||||||
|
79
value.go
79
value.go
@ -16,6 +16,7 @@ limitations under the License.
|
|||||||
package jsonnet
|
package jsonnet
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/google/go-jsonnet/ast"
|
"github.com/google/go-jsonnet/ast"
|
||||||
@ -269,6 +270,9 @@ type valueObject interface {
|
|||||||
value
|
value
|
||||||
inheritanceSize() int
|
inheritanceSize() int
|
||||||
index(e *evaluator, field string) (value, error)
|
index(e *evaluator, field string) (value, error)
|
||||||
|
assertionsChecked() bool
|
||||||
|
setAssertionsCheckResult(err error)
|
||||||
|
getAssertionsCheckResult() error
|
||||||
}
|
}
|
||||||
|
|
||||||
type selfBinding struct {
|
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,
|
// 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
|
// inside an object and then context would be the function, but self would still point
|
||||||
// to the object.
|
// to the object.
|
||||||
self value
|
self valueObject
|
||||||
|
|
||||||
// superDepth is the "super" level of self. Sometimes, we look upwards in the
|
// 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
|
// 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 {
|
type valueObjectBase struct {
|
||||||
valueBase
|
valueBase
|
||||||
|
assertionError error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*valueObjectBase) typename() string {
|
func (*valueObjectBase) typename() string {
|
||||||
return "object"
|
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).
|
// valueSimpleObject represents a flat object (no inheritance).
|
||||||
// Note that it can be used as part of extended objects
|
// Note that it can be used as part of extended objects
|
||||||
// in inheritance using operator +.
|
// in inheritance using operator +.
|
||||||
@ -317,7 +350,43 @@ type valueSimpleObject struct {
|
|||||||
valueObjectBase
|
valueObjectBase
|
||||||
upValues bindingFrame
|
upValues bindingFrame
|
||||||
fields valueSimpleObjectFieldMap
|
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) {
|
func (o *valueSimpleObject) index(e *evaluator, field string) (value, error) {
|
||||||
@ -328,7 +397,7 @@ func (*valueSimpleObject) inheritanceSize() int {
|
|||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeValueSimpleObject(b bindingFrame, fields valueSimpleObjectFieldMap, asserts ast.Nodes) *valueSimpleObject {
|
func makeValueSimpleObject(b bindingFrame, fields valueSimpleObjectFieldMap, asserts []unboundField) *valueSimpleObject {
|
||||||
return &valueSimpleObject{
|
return &valueSimpleObject{
|
||||||
upValues: b,
|
upValues: b,
|
||||||
fields: fields,
|
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) {
|
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)
|
field, upValues, foundAt := findField(sb.self, sb.superDepth, fieldName)
|
||||||
if field == nil {
|
if field == nil {
|
||||||
return nil, e.Error(fmt.Sprintf("Field does not exist: %s", fieldName))
|
return nil, e.Error(fmt.Sprintf("Field does not exist: %s", fieldName))
|
||||||
|
Loading…
Reference in New Issue
Block a user