mirror of
https://github.com/google/go-jsonnet.git
synced 2025-09-28 17:01:02 +02:00
Support of +:, in, in super
Also profiling
This commit is contained in:
parent
93bcf64454
commit
0c86c9e109
@ -456,6 +456,7 @@ type DesugaredObjectField struct {
|
||||
Hide ObjectFieldHide
|
||||
Name Node
|
||||
Body Node
|
||||
PlusSuper bool
|
||||
}
|
||||
type DesugaredObjectFields []DesugaredObjectField
|
||||
|
||||
|
14
builtins.go
14
builtins.go
@ -219,7 +219,7 @@ func builtinLength(e *evaluator, xp potentialValue) (value, error) {
|
||||
var num int
|
||||
switch x := x.(type) {
|
||||
case valueObject:
|
||||
num = len(objectFields(x, true))
|
||||
num = len(objectFields(x, withoutHidden))
|
||||
case *valueArray:
|
||||
num = len(x.elements)
|
||||
case *valueString:
|
||||
@ -511,7 +511,7 @@ func builtinObjectFieldsEx(e *evaluator, objp potentialValue, includeHiddenP pot
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fields := objectFields(obj, !includeHidden.value)
|
||||
fields := objectFields(obj, withHiddenFromBool(includeHidden.value))
|
||||
sort.Strings(fields)
|
||||
elems := []potentialValue{}
|
||||
for _, fieldname := range fields {
|
||||
@ -533,12 +533,9 @@ func builtinObjectHasEx(e *evaluator, objp potentialValue, fnamep potentialValue
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, fieldname := range objectFields(obj, !includeHidden.value) {
|
||||
if fieldname == string(fname.value) {
|
||||
return makeValueBoolean(true), nil
|
||||
}
|
||||
}
|
||||
return makeValueBoolean(false), nil
|
||||
h := withHiddenFromBool(includeHidden.value)
|
||||
fieldp := tryObjectIndex(objectBinding(obj), string(fname.value), h)
|
||||
return makeValueBoolean(fieldp != nil), nil
|
||||
}
|
||||
|
||||
func builtinPow(e *evaluator, basep potentialValue, expp potentialValue) (value, error) {
|
||||
@ -657,6 +654,7 @@ var desugaredBop = map[ast.BinaryOp]ast.Identifier{
|
||||
ast.BopPercent: "mod",
|
||||
ast.BopManifestEqual: "equals",
|
||||
ast.BopManifestUnequal: "notEquals", // Special case
|
||||
ast.BopIn: "objectHasAll",
|
||||
}
|
||||
|
||||
var bopBuiltins = []*BinaryBuiltin{
|
||||
|
BIN
compat/libgojsonnet.so
Normal file
BIN
compat/libgojsonnet.so
Normal file
Binary file not shown.
17
desugarer.go
17
desugarer.go
@ -191,19 +191,6 @@ func desugarFields(location ast.LocationRange, fields *ast.ObjectFields, objLeve
|
||||
}
|
||||
}
|
||||
|
||||
// Remove +:
|
||||
// TODO(dcunnin): this
|
||||
for _, field := range *fields {
|
||||
if !field.SuperSugar {
|
||||
continue
|
||||
}
|
||||
/*
|
||||
AST *super_f = alloc->make<SuperIndex>(field.expr1->location, field.expr1, nil)
|
||||
field.expr2 = alloc->make<ast.Binary>(ast->location, super_f, BOP_PLUS, field.expr2)
|
||||
field.superSugar = false
|
||||
*/
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -307,7 +294,7 @@ func buildDesugaredObject(nodeBase ast.NodeBase, fields ast.ObjectFields) *ast.D
|
||||
if field.Kind == ast.ObjectAssert {
|
||||
newAsserts = append(newAsserts, field.Expr2)
|
||||
} else if field.Kind == ast.ObjectFieldExpr {
|
||||
newFields = append(newFields, ast.DesugaredObjectField{field.Hide, field.Expr1, field.Expr2})
|
||||
newFields = append(newFields, ast.DesugaredObjectField{field.Hide, field.Expr1, field.Expr2, field.SuperSugar})
|
||||
} else {
|
||||
panic(fmt.Sprintf("INTERNAL ERROR: field should have been desugared: %s", field.Kind))
|
||||
}
|
||||
@ -400,6 +387,8 @@ func desugar(astPtr *ast.Node, objLevel int) (err error) {
|
||||
Op: ast.UopNot,
|
||||
Expr: buildStdCall(desugaredBop[ast.BopManifestEqual], node.Left, node.Right),
|
||||
}
|
||||
} else if node.Op == ast.BopIn {
|
||||
*astPtr = buildStdCall(funcname, node.Right, node.Left)
|
||||
} else {
|
||||
*astPtr = buildStdCall(funcname, node.Left, node.Right)
|
||||
}
|
||||
|
@ -324,7 +324,11 @@ func (i *interpreter) evaluate(a ast.Node, context *TraceContext) (value, error)
|
||||
if _, ok := fields[fieldName]; ok {
|
||||
return nil, e.Error(duplicateFieldNameErrMsg(fieldName))
|
||||
}
|
||||
fields[fieldName] = valueSimpleObjectField{field.Hide, &codeUnboundField{field.Body}}
|
||||
var f unboundField = &codeUnboundField{field.Body}
|
||||
if field.PlusSuper {
|
||||
f = &PlusSuperUnboundField{f}
|
||||
}
|
||||
fields[fieldName] = valueSimpleObjectField{field.Hide, f}
|
||||
}
|
||||
var asserts []unboundField
|
||||
for _, assert := range ast.Asserts {
|
||||
@ -422,7 +426,19 @@ func (i *interpreter) evaluate(a ast.Node, context *TraceContext) (value, error)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return superIndex(e, i.stack.getSelfBinding(), indexStr.getString())
|
||||
return objectIndex(e, i.stack.getSelfBinding().super(), indexStr.getString())
|
||||
|
||||
case *ast.InSuper:
|
||||
index, err := e.evalInCurrentContext(ast.Index)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
indexStr, err := e.getString(index)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
field := tryObjectIndex(i.stack.getSelfBinding().super(), indexStr.getString(), withHidden)
|
||||
return makeValueBoolean(field != nil), nil
|
||||
|
||||
case *ast.Function:
|
||||
return &valueFunction{
|
||||
@ -567,9 +583,7 @@ func (i *interpreter) manifestJSON(trace *TraceElement, v value, multiline bool,
|
||||
buf.WriteString("null")
|
||||
|
||||
case valueObject:
|
||||
// TODO(dcunnin): Run invariants (object-level assertions).
|
||||
|
||||
fieldNames := objectFields(v, true)
|
||||
fieldNames := objectFields(v, withoutHidden)
|
||||
sort.Strings(fieldNames)
|
||||
|
||||
err := checkAssertions(e, v)
|
||||
|
@ -19,7 +19,9 @@ package main
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"runtime/pprof"
|
||||
|
||||
"github.com/google/go-jsonnet"
|
||||
)
|
||||
@ -29,6 +31,17 @@ func usage() {
|
||||
}
|
||||
|
||||
func main() {
|
||||
// https://blog.golang.org/profiling-go-programs
|
||||
var cpuprofile = os.Getenv("JSONNET_CPU_PROFILE")
|
||||
if cpuprofile != "" {
|
||||
f, err := os.Create(cpuprofile)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
pprof.StartCPUProfile(f)
|
||||
defer pprof.StopCPUProfile()
|
||||
}
|
||||
|
||||
// TODO(sbarzowski) Be consistent about error codes with C++ maybe
|
||||
vm := jsonnet.MakeVM()
|
||||
if len(os.Args) != 2 {
|
||||
|
@ -76,6 +76,11 @@ func analyzeVisit(a ast.Node, inObject bool, vars ast.IdentifierSet) error {
|
||||
//nothing to do here
|
||||
case *ast.ImportStr:
|
||||
//nothing to do here
|
||||
case *ast.InSuper:
|
||||
if !inObject {
|
||||
return parser.MakeStaticError("Can't use super outside of an object.", *a.Loc())
|
||||
}
|
||||
visitNext(a.Index, inObject, vars, s)
|
||||
case *ast.SuperIndex:
|
||||
if !inObject {
|
||||
return parser.MakeStaticError("Can't use super outside of an object.", *a.Loc())
|
||||
|
1
testdata/in.golden
vendored
Normal file
1
testdata/in.golden
vendored
Normal file
@ -0,0 +1 @@
|
||||
true
|
1
testdata/in.jsonnet
vendored
Normal file
1
testdata/in.jsonnet
vendored
Normal file
@ -0,0 +1 @@
|
||||
"x" in { "x": 42 }
|
1
testdata/in2.golden
vendored
Normal file
1
testdata/in2.golden
vendored
Normal file
@ -0,0 +1 @@
|
||||
false
|
1
testdata/in2.jsonnet
vendored
Normal file
1
testdata/in2.jsonnet
vendored
Normal file
@ -0,0 +1 @@
|
||||
"x" in { }
|
1
testdata/in3.golden
vendored
Normal file
1
testdata/in3.golden
vendored
Normal file
@ -0,0 +1 @@
|
||||
true
|
1
testdata/in3.jsonnet
vendored
Normal file
1
testdata/in3.jsonnet
vendored
Normal file
@ -0,0 +1 @@
|
||||
"x" in { x: 42, y: 42 }
|
1
testdata/in4.golden
vendored
Normal file
1
testdata/in4.golden
vendored
Normal file
@ -0,0 +1 @@
|
||||
false
|
1
testdata/in4.jsonnet
vendored
Normal file
1
testdata/in4.jsonnet
vendored
Normal file
@ -0,0 +1 @@
|
||||
"x" in { assert false }
|
3
testdata/insuper.golden
vendored
Normal file
3
testdata/insuper.golden
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"x": 42
|
||||
}
|
1
testdata/insuper.jsonnet
vendored
Normal file
1
testdata/insuper.jsonnet
vendored
Normal file
@ -0,0 +1 @@
|
||||
{ x: 42 } { assert "x" in super }
|
1
testdata/insuper2.golden
vendored
Normal file
1
testdata/insuper2.golden
vendored
Normal file
@ -0,0 +1 @@
|
||||
testdata/insuper2:1:11-13 Expected token OPERATOR but got (in, "in")
|
1
testdata/insuper2.jsonnet
vendored
Normal file
1
testdata/insuper2.jsonnet
vendored
Normal file
@ -0,0 +1 @@
|
||||
{ } { "x" in super }
|
3
testdata/insuper3.golden
vendored
Normal file
3
testdata/insuper3.golden
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"false": false
|
||||
}
|
1
testdata/insuper3.jsonnet
vendored
Normal file
1
testdata/insuper3.jsonnet
vendored
Normal file
@ -0,0 +1 @@
|
||||
{ "false": "x" in super }
|
1
testdata/insuper4.golden
vendored
Normal file
1
testdata/insuper4.golden
vendored
Normal file
@ -0,0 +1 @@
|
||||
testdata/insuper4:1:2-13 Can't use super outside of an object.
|
1
testdata/insuper4.jsonnet
vendored
Normal file
1
testdata/insuper4.jsonnet
vendored
Normal file
@ -0,0 +1 @@
|
||||
"x" in super
|
6
testdata/insuper5.golden
vendored
Normal file
6
testdata/insuper5.golden
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"x": 42,
|
||||
"y": {
|
||||
"false": false
|
||||
}
|
||||
}
|
1
testdata/insuper5.jsonnet
vendored
Normal file
1
testdata/insuper5.jsonnet
vendored
Normal file
@ -0,0 +1 @@
|
||||
{ x: 42 } { y: { "false": "x" in super } }
|
1
testdata/insuper6.golden
vendored
Normal file
1
testdata/insuper6.golden
vendored
Normal file
@ -0,0 +1 @@
|
||||
testdata/insuper6:1:10-20 Unknown variable: undeclared
|
1
testdata/insuper6.jsonnet
vendored
Normal file
1
testdata/insuper6.jsonnet
vendored
Normal file
@ -0,0 +1 @@
|
||||
{ assert undeclared in super }
|
1
testdata/insuper7.golden
vendored
Normal file
1
testdata/insuper7.golden
vendored
Normal file
@ -0,0 +1 @@
|
||||
"object"
|
1
testdata/insuper7.jsonnet
vendored
Normal file
1
testdata/insuper7.jsonnet
vendored
Normal file
@ -0,0 +1 @@
|
||||
std.type({ assert false } { x: "x" in super })
|
6
testdata/supersugar.golden
vendored
Normal file
6
testdata/supersugar.golden
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"x": {
|
||||
"a": 1,
|
||||
"b": 2
|
||||
}
|
||||
}
|
1
testdata/supersugar.jsonnet
vendored
Normal file
1
testdata/supersugar.jsonnet
vendored
Normal file
@ -0,0 +1 @@
|
||||
{ x: {a: 1} } { x +: {b: 2} }
|
3
testdata/supersugar2.golden
vendored
Normal file
3
testdata/supersugar2.golden
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"x": 1
|
||||
}
|
1
testdata/supersugar2.jsonnet
vendored
Normal file
1
testdata/supersugar2.jsonnet
vendored
Normal file
@ -0,0 +1 @@
|
||||
{ x :+ 1 }
|
3
testdata/supersugar3.golden
vendored
Normal file
3
testdata/supersugar3.golden
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"x": true
|
||||
}
|
1
testdata/supersugar3.jsonnet
vendored
Normal file
1
testdata/supersugar3.jsonnet
vendored
Normal file
@ -0,0 +1 @@
|
||||
{ assert self.x } { x +: true }
|
4
testdata/supersugar4.golden
vendored
Normal file
4
testdata/supersugar4.golden
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"x": true,
|
||||
"y": 43
|
||||
}
|
1
testdata/supersugar4.jsonnet
vendored
Normal file
1
testdata/supersugar4.jsonnet
vendored
Normal file
@ -0,0 +1 @@
|
||||
{ assert self.x, y: 42 } { x: true, y +: 1 }
|
1
testdata/supersugar5.golden
vendored
Normal file
1
testdata/supersugar5.golden
vendored
Normal file
@ -0,0 +1 @@
|
||||
42
|
1
testdata/supersugar5.jsonnet
vendored
Normal file
1
testdata/supersugar5.jsonnet
vendored
Normal file
@ -0,0 +1 @@
|
||||
({ } { x +: function(x) x }).x(42)
|
3
testdata/supersugar6.golden
vendored
Normal file
3
testdata/supersugar6.golden
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"x": "hello, world"
|
||||
}
|
1
testdata/supersugar6.jsonnet
vendored
Normal file
1
testdata/supersugar6.jsonnet
vendored
Normal file
@ -0,0 +1 @@
|
||||
{ x: "hello, " } { x +: "world" }
|
10
testdata/supersugar7.golden
vendored
Normal file
10
testdata/supersugar7.golden
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"x": [
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
6
|
||||
]
|
||||
}
|
1
testdata/supersugar7.jsonnet
vendored
Normal file
1
testdata/supersugar7.jsonnet
vendored
Normal file
@ -0,0 +1 @@
|
||||
{ x: [1, 2, 3] } { x +: [4, 5, 6] }
|
1
testdata/supersugar8.golden
vendored
Normal file
1
testdata/supersugar8.golden
vendored
Normal file
@ -0,0 +1 @@
|
||||
RUNTIME ERROR: Object assertion failed.
|
1
testdata/supersugar8.jsonnet
vendored
Normal file
1
testdata/supersugar8.jsonnet
vendored
Normal file
@ -0,0 +1 @@
|
||||
{ assert self.x } { x +: false }
|
1
testdata/supersugar9.golden
vendored
Normal file
1
testdata/supersugar9.golden
vendored
Normal file
@ -0,0 +1 @@
|
||||
"object"
|
2
testdata/supersugar9.jsonnet
vendored
Normal file
2
testdata/supersugar9.jsonnet
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
local infloop() = infloop();
|
||||
std.type({ assert infloop, x: 1 } { x +: 1 })
|
25
thunks.go
25
thunks.go
@ -34,7 +34,7 @@ func (rv *readyValue) getValue(i *interpreter, t *TraceElement) (value, error) {
|
||||
return rv.content, nil
|
||||
}
|
||||
|
||||
func (rv *readyValue) bindToObject(sb selfBinding, origBinding bindingFrame) potentialValue {
|
||||
func (rv *readyValue) bindToObject(sb selfBinding, origBinding bindingFrame, fieldName string) potentialValue {
|
||||
return rv
|
||||
}
|
||||
|
||||
@ -78,6 +78,10 @@ func makeCallThunk(ec evalCallable, args callArguments) potentialValue {
|
||||
return makeCachedThunk(&callThunk{function: ec, args: args})
|
||||
}
|
||||
|
||||
func call(ec evalCallable, arguments ...potentialValue) potentialValue {
|
||||
return makeCallThunk(ec, args(arguments...))
|
||||
}
|
||||
|
||||
func (th *callThunk) getValue(i *interpreter, trace *TraceElement) (value, error) {
|
||||
evaluator := makeEvaluator(i, trace)
|
||||
err := checkArguments(evaluator, th.args, th.function.Parameters())
|
||||
@ -134,7 +138,7 @@ type codeUnboundField struct {
|
||||
body ast.Node
|
||||
}
|
||||
|
||||
func (f *codeUnboundField) bindToObject(sb selfBinding, origBindings bindingFrame) potentialValue {
|
||||
func (f *codeUnboundField) bindToObject(sb selfBinding, origBindings bindingFrame, fieldName string) potentialValue {
|
||||
// TODO(sbarzowski) better object names (perhaps include a field name too?)
|
||||
return makeThunk("object_field", makeEnvironment(origBindings, sb), f.body)
|
||||
}
|
||||
@ -146,7 +150,7 @@ type bindingsUnboundField struct {
|
||||
bindings bindingFrame
|
||||
}
|
||||
|
||||
func (f *bindingsUnboundField) bindToObject(sb selfBinding, origBindings bindingFrame) potentialValue {
|
||||
func (f *bindingsUnboundField) bindToObject(sb selfBinding, origBindings bindingFrame, fieldName string) potentialValue {
|
||||
var upValues bindingFrame
|
||||
upValues = make(bindingFrame)
|
||||
for variable, pvalue := range origBindings {
|
||||
@ -155,7 +159,20 @@ func (f *bindingsUnboundField) bindToObject(sb selfBinding, origBindings binding
|
||||
for variable, pvalue := range f.bindings {
|
||||
upValues[variable] = pvalue
|
||||
}
|
||||
return f.inner.bindToObject(sb, upValues)
|
||||
return f.inner.bindToObject(sb, upValues, fieldName)
|
||||
}
|
||||
|
||||
type PlusSuperUnboundField struct {
|
||||
inner unboundField
|
||||
}
|
||||
|
||||
func (f *PlusSuperUnboundField) bindToObject(sb selfBinding, origBinding bindingFrame, fieldName string) potentialValue {
|
||||
left := tryObjectIndex(sb.super(), fieldName, withHidden)
|
||||
right := f.inner.bindToObject(sb, origBinding, fieldName)
|
||||
if left != nil {
|
||||
return call(bopBuiltins[ast.BopPlus], left, right)
|
||||
}
|
||||
return right
|
||||
}
|
||||
|
||||
// evalCallables
|
||||
|
54
value.go
54
value.go
@ -311,6 +311,29 @@ func makeUnboundSelfBinding() selfBinding {
|
||||
}
|
||||
}
|
||||
|
||||
func objectBinding(obj valueObject) selfBinding {
|
||||
return selfBinding{self: obj, superDepth: 0}
|
||||
}
|
||||
|
||||
func (sb selfBinding) super() selfBinding {
|
||||
return selfBinding{self: sb.self, superDepth: sb.superDepth + 1}
|
||||
}
|
||||
|
||||
type Hidden int
|
||||
|
||||
const (
|
||||
withHidden Hidden = iota
|
||||
withoutHidden
|
||||
)
|
||||
|
||||
func withHiddenFromBool(with bool) Hidden {
|
||||
if with {
|
||||
return withHidden
|
||||
} else {
|
||||
return withoutHidden
|
||||
}
|
||||
}
|
||||
|
||||
// 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")
|
||||
@ -377,7 +400,7 @@ func checkAssertionsHelper(e *evaluator, obj valueObject, curr valueObject, supe
|
||||
return nil
|
||||
case *valueSimpleObject:
|
||||
for _, assert := range curr.asserts {
|
||||
_, err := e.evaluate(assert.bindToObject(selfBinding{self: obj, superDepth: superDepth}, curr.upValues))
|
||||
_, err := e.evaluate(assert.bindToObject(selfBinding{self: obj, superDepth: superDepth}, curr.upValues, ""))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -400,7 +423,7 @@ func checkAssertions(e *evaluator, obj valueObject) error {
|
||||
}
|
||||
|
||||
func (o *valueSimpleObject) index(e *evaluator, field string) (value, error) {
|
||||
return objectIndex(e, selfBinding{self: o, superDepth: 0}, field)
|
||||
return objectIndex(e, objectBinding(o), field)
|
||||
}
|
||||
|
||||
func (*valueSimpleObject) inheritanceSize() int {
|
||||
@ -426,7 +449,7 @@ type valueSimpleObjectField struct {
|
||||
|
||||
// unboundField is a field that doesn't know yet in which object it is.
|
||||
type unboundField interface {
|
||||
bindToObject(sb selfBinding, origBinding bindingFrame) potentialValue
|
||||
bindToObject(sb selfBinding, origBinding bindingFrame, fieldName string) potentialValue
|
||||
}
|
||||
|
||||
// valueExtendedObject represents an object created through inheritence (left + right).
|
||||
@ -455,7 +478,7 @@ type valueExtendedObject struct {
|
||||
}
|
||||
|
||||
func (o *valueExtendedObject) index(e *evaluator, field string) (value, error) {
|
||||
return objectIndex(e, selfBinding{self: o, superDepth: 0}, field)
|
||||
return objectIndex(e, objectBinding(o), field)
|
||||
}
|
||||
|
||||
func (o *valueExtendedObject) inheritanceSize() int {
|
||||
@ -498,23 +521,26 @@ func findField(curr value, minSuperDepth int, f string) (*valueSimpleObjectField
|
||||
}
|
||||
}
|
||||
|
||||
func superIndex(e *evaluator, currentSB selfBinding, field string) (value, error) {
|
||||
superSB := selfBinding{self: currentSB.self, superDepth: currentSB.superDepth + 1}
|
||||
return objectIndex(e, superSB, field)
|
||||
}
|
||||
|
||||
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 {
|
||||
objp := tryObjectIndex(sb, fieldName, withHidden)
|
||||
if objp == nil {
|
||||
return nil, e.Error(fmt.Sprintf("Field does not exist: %s", fieldName))
|
||||
}
|
||||
return e.evaluate(objp)
|
||||
}
|
||||
|
||||
func tryObjectIndex(sb selfBinding, fieldName string, h Hidden) potentialValue {
|
||||
field, upValues, foundAt := findField(sb.self, sb.superDepth, fieldName)
|
||||
if field == nil || (h == withoutHidden && field.hide == ast.ObjectFieldHidden) {
|
||||
return nil
|
||||
}
|
||||
fieldSelfBinding := selfBinding{self: sb.self, superDepth: foundAt}
|
||||
|
||||
return e.evaluate(field.field.bindToObject(fieldSelfBinding, upValues))
|
||||
return field.field.bindToObject(fieldSelfBinding, upValues, fieldName)
|
||||
}
|
||||
|
||||
type fieldHideMap map[string]ast.ObjectFieldHide
|
||||
@ -544,10 +570,10 @@ func objectFieldsVisibility(obj valueObject) fieldHideMap {
|
||||
return r
|
||||
}
|
||||
|
||||
func objectFields(obj valueObject, manifesting bool) []string {
|
||||
func objectFields(obj valueObject, h Hidden) []string {
|
||||
var r []string
|
||||
for fieldName, hide := range objectFieldsVisibility(obj) {
|
||||
if !manifesting || hide != ast.ObjectFieldHidden {
|
||||
if h == withHidden || hide != ast.ObjectFieldHidden {
|
||||
r = append(r, fieldName)
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user