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

🖊️ Allow if_pressed to work with functions #5933

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

boryanagoncharenko
Copy link
Collaborator

@boryanagoncharenko boryanagoncharenko commented Nov 12, 2024

This PR allows the if-pressed feature to be used with functions. Specifically, it introduces the following set of changes:

  • If a program does not contain an if-pressed statement, its transpilation remains unchanged
  • If a program contains an if-pressed statement it will use scopes:
    • a global scope dictionary is added to the start of the program
    • a local scope dictionary is added to the start of every function. If the function has any arguments, the are added to the local scope.
    • when a variable is assigned (appears on the lhs of an assignment), instead of creating a new variable, we add a key to the current scope. If the assignment is in the global scope, we use the global scope. If it is in a function, we use the specific local scope.
    • when for-list and for-loops are used, the iterator variable (for a in animals) is not added no any scope (since it must be accessible only in the scope of the loop).
    • when a variable is retrieved (e.g. appears on the rhs of an assignment or in a print statement), we try to fetch it from the local scope, then from the global scope, and then directly as a variable. The last case is required to support the variables defined in for-loops (for a in animals).

Fixes #5749

How to test
All scenarios I could think of are covered with automated tests. However, they are far from exhaustive. Please use the following scenarios as starting points to explore different combinations, i.e. just try to break it:

  • if-pressed correctly should reassign a variable from outer scope:
# level 12
x is 'a'
if x is pressed
  x is 'great'
else
  x is 'not great'
print x
  • if-pressed should expose a variable created within it to the outer scope:
# level 12
x is 'a'
if x is pressed
  m is 'great'
else
  m is 'not great'
print m
  • if-pressed should work within a function:
# level 12
define make_turn
    if x is pressed
        print 'good'
    else
        print 'bad'
call make_turn
  • if-pressed should work within a function with an argument:
# level 12
define make_turn with x
    if x is pressed
        print 'good'
    else
        print 'bad'
call make_turn with 'm'
  • if-pressed should work outside of a function:
# level 17
define go_left with last_direction:
    if last_direction = 'right':
        turn 180

define go_right with last_direction:
    if last_direction = 'left':
        turn 180

move = True
last_direction = 'left'

while move = True:
    if a is pressed:
        call go_left with last_direction
        last_direction = 'left'
    elif d is pressed:
        call go_right with last_direction
        last_direction = 'right'
    else:
        move = False
    if move is True:
        forward 25
  • If-pressed should work within for-loops:
# level 12
animals is 'cat', 'dog', 'platypus'
if a is pressed
    for animal in animals
        print animal
else
    print 'no animals'

@Felienne
Copy link
Member

Owwwww so excited about this!!

@jpelay jpelay self-requested a review November 13, 2024 20:14
Copy link
Member

@jpelay jpelay left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work! Glad that you figured it out. I tried braking the feature and couldn't really find a way to do it! Kudos. Although there is a comment in the tester that Im not too sure was meant to be commited? If you can fix that I will approve.

return already_successful
except UnicodeEncodeError: # some tests (generated by Hypothesis) can't be hashed
return False
# try:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was this an unintended change?

variables = sorted(list(set(variables)))
global_vars = f"global {', '.join(variables)}"
lines.insert(0, global_vars)
# variables = [e.name for e in self.lookup.get_only_vars()]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess we can remove it?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: In Progress
Development

Successfully merging this pull request may close these issues.

🪲 If-pressed assignment does not work in functions
3 participants