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

While loops with complex conditions #37

Open
TelosTelos opened this issue Jan 22, 2021 · 0 comments
Open

While loops with complex conditions #37

TelosTelos opened this issue Jan 22, 2021 · 0 comments

Comments

@TelosTelos
Copy link
Collaborator

Consider the following while loop:

y = 0
while (y+3)<10:  y+=1

In Python, this would exit the loop once y reaches 7. However, our handling of complex expressions currently compiles this to be equivalent to the following:

y = 0
dummy = y+3
while dummy < 10: y+=1

This loop continues infinitely, since nothing within the loop changes the value of dummy. To get the intuitive expected behavior, we would need to recompute dummy within the loop.

Currently while loops are implemented with a negated test at the beginning (if the condition isn't met skip the loop entirely) and a positive test at the end (if the condition is met, loop back up). In cases where the condition is simple, this double-test versions works correctly and is generally optimal (barring some truly heroic optimizations that would require a lot more code-inspection than we're prepared to do), both in speed and brevity. Problems arise only in the case of complex conditions.

If we continue with a double-test version, to get correct behavior for complex conditions, we'll need to recompute things like dummy in both instances of the test, which quickly stops being optimally short (as soon as setting up the test requires two or more dummy computations, repeating them increases length), though it would still be optimally fast. Alternatively we could go back to a single-test version for complex conditions, which would trade away a bit of speed (adding a single jump-always instruction to each iteration to jump to our single instance of the test) in order to gain brevity (you only need one copy of the code that sets up the test).

As in other speed-vs-brevity tradeoffs, the only case where brevity matters is the case where a program exceeds the 1000-instruction limit and becomes uncompilable. But it'll be quite rare for this to be the straw that breaks the camel's back. So on balance it'd almost always be better to favor speed over brevity, even if doing so requires duplicating the code to set up a complex test. So I guess that's what we should do?

The same problem doesn't afflict if (uses only a single negated test), nor our current quite limited implementation of for (uses a double-test, but the exit condition is always simple), though we might someday consider more sophisticated for loops with more sophisticated exit conditions, in which case the same tradeoff could arise there too.

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

No branches or pull requests

1 participant