Skip to content
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

Fixes #1801 and Fixes #1784. #1811

Merged

Conversation

Dunbaratu
Copy link
Member

@Dunbaratu Dunbaratu commented Sep 9, 2016

The problem in issue #1801 was that the logic in the Compiler's IterateuserFunctions() that does a tree walk through everywhere a function statement might exist to preform function preprocessing on it, was failing to descend into the instruction_block of an anon function.

This was because the instruction_block of an anon function is a kind of expr instead of being a kind of instruction, and the case statement wasn't set up to descend into expr's.

It turns out that, as a bonus, this also fixed issue #1784 as well, for the same reason.

Fixes #1784
Fixes #1801

The problem was that the logic in the Compiler's IterateuserFunctions() that does a tree walk through everywhere a ``function`` statement might exist to preform function preprocessing on it, was failing to descend into the ``instruction_block`` of an anon function.

This was because the ``instruction_block`` of an anon function is a kind of ``expr`` instead of being a kind of ``instruction``, and the case statement wasn't set up to descend into ``expr``'s.
@hvacengi
Copy link
Member

@Dunbaratu I'm testing out this PR to merge. I noticed that you've tagged #1784 as being fixed as well but that there wasn't a function test for it. So I added the following script, and I still get the error: "The given key was not present in the dictionary."

// functest33.ks
// Testing issue 1784 - lock steering nested in anon functions.

function testNamed {
    lock steering to up.
}

set testAnon to {
    lock steering to up.
}.

testNamed().
testAnon().

Am I missing something in the testing of that error?

@Dunbaratu
Copy link
Member Author

Dunbaratu commented Sep 21, 2016

I'll give your test case a try and see what I get. I was sure I tested that case but maybe I didn't, or maybe something hidden about how I tested it caused it to avoid the problem but not in a fully fixed way.

@Dunbaratu
Copy link
Member Author

Dunbaratu commented Sep 21, 2016

Okay now I know why my test didn't catch the problem and yours did.

Although this crashes:

set testAnon to {
  lock steering to up.
}.
testAnon().

This works fine, and doesn't crash:

local testAnon is {
  lock steering to up.
}.
testAnon().

The error does not surface when using a declaration statement like local or global, and thus my tests didn't catch it.

Why it wasn't noticed before:
-----------------------------

The problem only happened when you use a SET command to
assign an anonymous function to a variable, as in

SET anon TO {lock foo to 1.}.

But if you happened to use a DECLARE command of some sort to do so,
like a LOCAL... or GLOBAL, like so:

LOCAL anon IS {lock foo to 1.}.

then it didn't exhibit the problem.  This is why I didn't
notice it before.  It turns out all my tests were doing it
that way.

The Cause:
----------

The problem had been caused by the fact that when
Compiler.IterateUserFunctions() walked the parse tree to try to
find all the user functions and lock statements, it failed
to recurse into the anon functions in some cases and thus didn't
find the locks that were inside them.  (It only pre-processes the
lock statements when this walk finds them).

It failed to recurse into some of the kinds of parse tree nodes
which could contain anon functions because it only recursed into
node types that were explicitly mentioned in a case statement list,
and it assumed anything not on the list cannot contain further
statements nested inside it.  This list was not entirely up to
date and correct, missing a few types of statement that were now
capable of containing further nested statements.  Now that anon
functions exist, almost every kind of expression could be an anon
function with statements nested inside it.

The Fix:
--------

Given that two different recent issues both were caused by failures
of this walk to recurse into some kinds of parse node, and some
other issues in the past were also caused by the very same
section of code failing to mention a new part of speech after
the grammar file changed,  I decided it was high time I flipped
the logic around. Now it operates on a blacklist instead of a
whitelist.  Now it automatically descends into every kind of
node *except* the ones explicitly mentioned that we know can't
contain any further open-ended expressions inside them.  This
way if we forget to mention a node type on that list, the failure
results in merely a bit of wasted execution time for failing
to prune the tree walk early enough, rather than a fatal error
for forgetting to mention a node like we had before.
@hvacengi hvacengi merged commit 81de368 into KSP-KOS:develop Sep 22, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Can't reference named functions inside anonymous functions Anonymous functions break with lock steering
2 participants