-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Composite refs #386
Composite refs #386
Conversation
577290c
to
dd04aca
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall this looks really good. Left a few comments but I'll have to come back and do another pass.
ast/check.go
Outdated
@@ -487,6 +487,9 @@ func (rc *refChecker) checkRef(curr *TypeEnv, node *typeTreeNode, ref Ref, idx i | |||
return newRefErrInvalid(ref[0].Location, ref, idx, exist, types.S, getOneOfForNode(node)) | |||
} | |||
|
|||
case Array, Object, *Set: | |||
rc.env.tree.PutOne(value, rc.env.Get(value)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should be a type error. At this point, the ref operand doesn't refer to a leaf, so the key must be a string? You'll need to think about the content of the ref error details to report here. Look at the other ref errors for examples.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yea I think you're right, this case just shouldn't exist. I'll just let it hit default
ast/check.go
Outdated
@@ -487,6 +487,9 @@ func (rc *refChecker) checkRef(curr *TypeEnv, node *typeTreeNode, ref Ref, idx i | |||
return newRefErrInvalid(ref[0].Location, ref, idx, exist, types.S, getOneOfForNode(node)) | |||
} | |||
|
|||
case Array, Object, *Set: | |||
rc.env.tree.PutOne(value, rc.env.Get(value)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, I suspect this is not being exercised by any test cases.
ast/check.go
Outdated
@@ -534,6 +538,19 @@ func (rc *refChecker) checkRefLeaf(tpe types.Type, ref Ref, idx int) *Error { | |||
} | |||
} | |||
|
|||
case Array, Object, *Set: | |||
tpe := rc.env.Get(ref[:idx]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you explain what's happening here?
checkRefLeaf
is provided with the type of the value referred to by the ref up to (but not including) the index. checkRefLeaf
should not have to lookup the type here?
ast/check.go
Outdated
return nil | ||
} | ||
|
||
unify1(rc.env, SetTerm(head), exist, false) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you consider calling unify1(rc.env, head, keys, false)
instead here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah yea that would be much better
storage/path.go
Outdated
@@ -52,6 +52,8 @@ func NewPathForRef(ref ast.Ref) (path Path, err error) { | |||
Code: NotFoundErr, | |||
Message: fmt.Sprintf("%v: does not exist", ref), | |||
} | |||
case ast.Array, ast.Object, *ast.Set: | |||
return nil, fmt.Errorf("composites may not be used as ref operands for base documents: %v", ref) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Test?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: I'd try to make this error message more concise.
topdown/topdown_test.go
Outdated
{"object", `data.test.r[{"foo": "bar"}]`, `{"foo": "bar"}`}, | ||
{"set", `data.test.r[{1, 2}]`, "[1, 2]"}, | ||
|
||
{"unify array", `data.test.r[[1, x]]`, "[1, 2]"}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm wondering if this is the best way to test refs with var operands (or non-ground composite operands). There may be more than one query result--but the test case can also assert on one of them.
topdown/topdown_test.go
Outdated
{"complete doc unify", `data.test.s[[x, y]]`, `[1, 2]`}, | ||
|
||
// These should compile, but be undefined. | ||
{"array doc", `data.test.a[[1, 2]]`, ``}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you elaborate on why this should compile? I'd expect the type checker to return an error w/ invalid ref details here.
All the issues should be fixed now. The commit IDs have changes due to resolving a merge conflict in |
fad742b
to
86d5119
Compare
This is close, but I think more testing is needed. Specifically, anywhere that was branching based on ref operand type needs to be reviewed. E.g., what happens if you write...
And then query I imagine we need to have special handling for nested refs? What about comprehensions nested inside the composites? |
Ready for another look, fixed up up some checking issues and corrected eval to handle refs nested within composite operands. Comprehensions also work inside the composites. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only two comments (which are related) on the type checking changes.
ast/check.go
Outdated
if !unifies(tpe, types.NewSet(types.A)) { | ||
return newRefErrInvalid(ref[0].Location, ref, idx, tpe, types.NewSet(types.A), nil) | ||
} | ||
unify1(rc.env, head, keys, false) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should check if the head unified w/ the keys.
if !unify1(...) { // type error }
@@ -738,6 +743,14 @@ func TestCheckRefErrInvalid(t *testing.T) { | |||
want: types.S, | |||
oneOf: []Value{String("p"), String("q")}, | |||
}, | |||
{ | |||
note: "composite ref into non-set", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about type errors with terms embedded within composite operands? This is related to the comment from above.
For example...
p = {[1],[2],[3]}
And then...p[["foo"]]
or p[{"a": b"}]
.
Comments addressed. |
topdown/topdown.go
Outdated
if err := evalRefRuleResultRec(t, e.Value, tail, path, iter); err != nil { | ||
return err | ||
} | ||
path = path[:len(path)-1] | ||
t.Unbind(undo) | ||
} | ||
return nil | ||
case ast.Array, ast.Object, *ast.Set: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This entire function can be simplified to unify the set elements with the next element in the ref. Something like...
head, tail := ref[0], ref[1:]
k := head.Value
for _, e := range *set {
undo, err := evalEqUnify(t, e.Value, k, nil, func(t *Topdown) error {
return evalRefRuleResultRec(t, e.Value, tail, path.Append(e), iter)
})
if err != nil {
return err
}
t.Unbind(undo)
}
return nil
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
0.o it's like magic
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
702e45b
to
69501e1
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Please squash your commits and then we can merge this.
69501e1
to
539afdf
Compare
Done |
Fixes #239