-
Notifications
You must be signed in to change notification settings - Fork 284
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
🪲 Fix Key Pressed adventure in level 9 #5725
Conversation
…d in if_pressed command #5679
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.
With respect to your last comment, I think I found a way to sort of break the global scope, but I think this is true in general in Hedy. If you declare a variable in the script and then use pressed
in a function, the program will complain and say that the variable was not defined:
define turn
if x is pressed
print 'good'
else
print 'bad'
print 'Lets play a game of Twister!'
for i in range 1 to 10
call turn
x is 2
print x
If you declare the variable within the function and then use pressed, it does work:
define turn
x is 1
print 'Lets play a game of Twister!'
for i in range 1 to 10
call turn
if x is pressed
print 'good'
else
print 'bad'
A last problem that I found is that if the command does not work at all within a function:
define turn
if x is pressed
print 'good'
else
print 'bad'
print 'Lets play a game of Twister!'
for i in range 1 to 10
call turn
@@ -33,7 +33,15 @@ var $builtinmodule = function (name) { | |||
// If mapped key is a variable (not char), we retrieve variable value and use that | |||
// otherwise if char, use that. | |||
const charOrVar = value[0].v; | |||
let mapLetterKey = Object.hasOwn(Sk.globals, charOrVar) ? Sk.globals[charOrVar].v : charOrVar; | |||
|
|||
let mapLetterKey = charOrVar; |
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 solution is great and works, my only question would be if someone assigns a multileter string, and not a single letter, and then uses it in the key press. Like this:
x is asdf
if x is pressed
print 'great'
else
print 'not great'
Then it will always be 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.
You are right. We allow the left-hand-side of the if-pressed command to be a variable. And this variable could be assigned anything: x is 21 + 1
or x is hello world
. At the same time we do not allow for multiple keys to be pressed at the same time.
What do you think is the best thing to do here? We could either silently take the first letter of the string which might be confusing. Alternatively, we could issue a warning at runtime (not sure if we have the mechanism for that?) that lets the user know that it is a multi-letter string so it will not work.
Since this issue was not introduced by the PR, I created a separate issue to discuss and track the matter: #5727
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 the best way would be show an alert or an error warning the user that probably they don't want to be using a multicharacter string in a keypress! It can probably be done by checking the value of the variable and then calling the modal.alert
function I think.
Thanks for all the tests! The undefined variable problem is not specific to the if-pressed command. The issue is 2-layered. First, we make the assumption that if is-pressed is using a variable which happens to be defined after its usage, then we should give an error because it is likely a mistake:
Is this a correct assumption here? I am not sure but it feels safer to give an error and ask the user to change the x variable name if needed. Second, the check mentioned above does not take into account that functions use a different scope. It just uses the line number for the access-before-definition error. This is definitely a bug on its own and I logged it here: #5728. About the second issue you discovered, I fixed the transpiler, so that some if-pressed statements could be executed from a function. However, not all scenarios are covered. Consider the following snippet:
You might expect that printing x would yield either |
Yes I think so!
Thanks!
Can we somehow pass the variables used inside the if_pressed as parameters in the functions instead of using global? Although I think that wouldn't work because it wouldn't modify the variable anyway. I don't think allowing functions to use global scope would be advisable because it would break assumptions.
By this you mean forbidding the use of if_pressed inside functions? |
Another option would be that assignments in the if_pressed are treated as return statements:
Do you think this could work? |
I was also thinking of a way to pass the variables to the functions as parameters but then the issue is that the changes inside the function remain in the current scope only. This is a plain python function:
It yields the following outcome:
This is a perspective I have not considered. This approach definitely works for the example at hand. However, I cannot think of a way to generalize the solution to other programs. For example, if there are multiple assignments done in the if-body, this means the function should return multiple values. And if there is a print statement in between the assignments, the complexity would become crazy.
I meant that before the refactoring, the if-pressed commands used pygame, so the transpiled code for the program above looked like this:
If you look at the PR that switched from pygame to a custom implementation with functions #5117 (or the issue that this PR was closing #3966) I am not sure why this was done. Perhaps there was an issue that was just not mentioned. If not, however, we could consider just rolling back that change altogether. @Felienne may be you know why the pygame was removed? |
Thank you for contributing! Your pull request is now going on the merge train (choo choo! Do not click update from main anymore, and be sure to allow changes to be pushed to your fork). |
Thank you for contributing! Your pull request is now going on the merge train (choo choo! Do not click update from main anymore, and be sure to allow changes to be pushed to your fork). |
Fixes #5679
There are 2 separate issues resolved with this PR:
It gets transpiled to:
With this PR, the problem is resolved via adding a
global points
line in the function body:Note that no matter what keys you press (x or a you will always get the output
not great
. This bug was caused with the latest changes for localization.How to test
global
in the if_pressed body, think of a way to break this. While it makes the current examples work, could there be a situation in which theglobal
keyword makes things worse?