-
-
Notifications
You must be signed in to change notification settings - Fork 314
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
Corner cases of include class as
#726
Comments
I've pushed some non-working initial code and a bunch of tests which I think are correct. (Fixes/changes welcome!) https://github.com/purpleidea/mgmt/tree/feat/include-class-scope The lexer/parser stuff is correct AFAICT. I think it's just the SetScope logic which needs fixing... Basically the Scope adding stuff works, but it's pulling from the Scope of the Class that we're including, which wasn't set yet... Hmmm... |
So I've been writing a lot of the ordering code... I seem to have fixed at least the basic ordering stuff. For this example:
The graph now looks like: And then I thought of a concern: Since we added a new "prefix:" type name (I actually named it "scoped:") is there not a worry that the ordering graph adds edges between an item that's in the wrong scope? In that vein, I also realized that what we're currently doing in git master is: (1) Running Ordering() So I thought to myself, how about instead we: (1) Run Ordering() I think this second option is more efficient, however it seems that the filtered graph now looks like: Naturally, this doesn't work because we're missing the edge. Previously it's an indirect edge that goes through So:
At this point I'm assuming there isn't a scope issue, but I don't have a test case to prove it yet. All my code is sitting at |
Yes, very wrong. Very few edges go directly from a statement to statement, most edges go from an StmtBind to an ExprVar inside another statement. So if you delete the edges which go from an StmtBind to an ExprVar, you're not going to be left with enough information to decide the ordering.
I don't understand what that means. There is only a single connected component in the first DAG, which part do you want to keep and which part do you want to delete?
I don't understand your concern, can you give an example? Are you thinking about shadowing? For example, in
I imagine that If you want a more principled way to calculate the scope without having to repeat your scoping logic in SetScope and in Ordering, I recommend using "lazy computations". A lazy computation is an object which stores a computation which needs to be done, plus some other fields. Running the computation within is called "forcing" the lazy computation. After the computation has been forced, the result is stored in one of the other fields, so that the next time the computation is forced, the result can be returned immediately without running the computation a second time. As a special case, a boolean also tracks whether the computation is currently being forced, so that if the lazy computation being forced asks to force this same lazy computation, we know that there is a loop and that the computation will never end. The idea is that we know we want to call SetScope on all the statements at some point, but we don't know in which order we should do it yet. We want to do it in dependency order, but we will only discover that order as we execute the various SetScope calls on all the statements. So:
|
So, what's the plan? Are you implementing this ticket while I switch to whatever's the next priority thing? Or am I taking over this ticket? |
I have looked at all 10 failing tests on your |
And this versions of the above counter-example passes as well, so it doesn't even seem like we'd be leaving something on the table.
|
I was a bit side-tracked tinkering with some provisioning code. Was likely going to resume here tomorrow and figure out what's left.
I thought the test we last looked at with the args coming in was not working correctly. (Our bug) but maybe with my Ordering changes it's okay now? I'll check that tomorrow and let you know! |
I am cleaning up the tests and the code... This popped out (new test)...
None of these work because they see the ordering DAG as circular! Woops. So shadowing is not working properly. So basically this means I can't use any variable in the parent scope. I think that blocking $x = $x is okay though. |
(But this is actually not trivial... should we be able to shadow this? Hmmm....) |
Secondly I have an ordering bug:
This happens some of the time. Presumably because the topo sort of the dag can be traversed two ways.
So I need to fix that, any ideas? |
I can't imagine any sane semantics in which one would be allowed but not the other. What's the difference? |
Remember, while we paired, I pointed out that the naive implementation of |
Btw the reason |
Yeah, I'm dumb for forgetting that since $x is declared (shadowed) in the child scope, that it's circular with itself there! Woops! NOT_A_BUG. ...
I see your point. What I was kind of going for, was that we're shadowing the top-level
It's really not harmful as long as it's not blocking the above example with the "important to be able to do this" comment. I've pushed these updated changes to feat/new-set-scope https://github.com/purpleidea/mgmt/tree/feat/new-set-scope In parallel (if you're curious) I wrote a neat compiler/sugar hack to automatically nest classes. None of or work should be affected by it, I just thought I'd show you for fun: https://github.com/purpleidea/mgmt/tree/feat/nested-class-sugar Cheers! |
For reference, tests that need looking into: SHADOWING: ORDERING: (run a few times to get an eventual ordering failure) |
Hmm. Are you sure you really need to support the "important to be able to do" case? The semantics where
makes sense is called "non recursive bindings", and in that world definitions must be ordered, you can have this:
but not that:
The semantic in which definitions can appear out of order is called "mutually-recursive bindings" and in that world |
Do you also want
and
or is it only variables which get the crazy semantics? |
(I edited the examples in the previous comment, make sure to look at the GitHub version, not the email version) |
I'm cleaning up the current branch as per our discussions. Since I didn't reply above, just for reference:
This looks like recursive classes, and is already handled (and forbidden) in the code. Whether it would make sense is a different discussion, but I suspect probably not.
heh, I don't see any reason why the above should be allowed or why it's necessary. The reason it's not is that if you've defined a class in a particular scope, then this is effectively overwriting that identifier. You have control over this where as for variables you might not have full control. At least I mostly see things this way for now. |
I've merged our code to git master! \o/ |
as
include class as
For future memory, related tasks here:
|
TODO: For james to fixup and merge: bug/ordering local branch. |
Simple example:
Note that the vars can be used. The defined classes can be used. And any resources always "fallthrough" into the global scope.
Note that when used without
as
, the default name would be the same as the class definition itself, so this might be confusing, and not be entirely sensible.The text was updated successfully, but these errors were encountered: