Skip to content

Commit

Permalink
[BUG] Consequitive If pressed with other command in between (hedyorg#…
Browse files Browse the repository at this point in the history
…4049)

Fixes hedyorg#4042,

Makes it possible to have statements in between _if_pressed_ commands without breaking the code.
For example:
```python
als s is ingedrukt
    print 'leuk'
anders
    print 'wat ben jij stom doei'

print 'maak jij de kinderen wakker'

als a is ingedrukt
    print 'ja ik maak ze wakker'
anders
    print 'wat vervelend ben jij dan doe ik het wel.'
``` 


To-Do
- [x] Rewrite Pygame related tests
  • Loading branch information
ToniSkulj authored Mar 1, 2023
1 parent 411a9b3 commit a9e338e
Show file tree
Hide file tree
Showing 12 changed files with 566 additions and 280 deletions.
85 changes: 54 additions & 31 deletions hedy.py
Original file line number Diff line number Diff line change
Expand Up @@ -981,6 +981,28 @@ def NEGATIVE_NUMBER(self, args):


class UsesPyGame(Transformer):
command_prefix = (f"""\
pygame_end = False
while not pygame_end:
pygame.display.update()
event = pygame.event.wait()
if event.type == pygame.QUIT:
pygame_end = True
pygame.quit()
break""")

regex_string_subsequent_use = (
r"\s*# End of PyGame Event Handler"
r"\s*pygame_end = False"
r"\s*while not pygame_end:"
r"\s*pygame.display.update\(\)"
r"\s*event = pygame.event.wait\(\)"
r"\s*if event.type == pygame.QUIT:"
r"\s*pygame_end = True"
r"\s*pygame.quit\(\)"
r"\s*break"
)

def __default__(self, args, children, meta):
if len(children) == 0: # no children? you are a leaf that is not Pressed, so you are no PyGame command
return False
Expand All @@ -996,6 +1018,9 @@ def ifpressed_else(self, args):
def assign_button(self, args):
return True

def post_process_code(self, code):
return re.sub(self.regex_string_subsequent_use, '', code)


class AllCommands(Transformer):
def __init__(self, level):
Expand Down Expand Up @@ -1729,7 +1754,6 @@ def clear(self, meta, args):
class ConvertToPython_5(ConvertToPython_4):
def __init__(self, lookup, numerals_language):
super().__init__(lookup, numerals_language)
self.ifpressed_prefix_added = False

def ifs(self, meta, args):
return f"""if {args[0]}:
Expand Down Expand Up @@ -1770,46 +1794,41 @@ def assign_button(self, meta, args):
return f"""create_button({button_name})"""

def make_ifpressed_command(self, command, button=False):
command_suffix = (f"""\
while not pygame_end:
pygame.display.update()
event = pygame.event.wait()
if event.type == pygame.QUIT:
pygame_end = True
pygame.quit()
break""")

if button:
command = f"""\
if event.type == pygame.USEREVENT:
{ConvertToPython.indent(command, 4)}"""
{ConvertToPython.indent(command, 4)}
# End of PyGame Event Handler"""
else:
command = f"""\
if event.type == pygame.KEYDOWN:
{ConvertToPython.indent(command, 4)}"""
{ConvertToPython.indent(command, 4)}
# End of PyGame Event Handler"""

if self.ifpressed_prefix_added:
return command
else:
self.ifpressed_prefix_added = True
return command_suffix + "\n" + command
return UsesPyGame.command_prefix + "\n" + command

def ifpressed(self, meta, args):
button_name = self.process_variable(args[0], meta.line)
var_or_button = args[0]
# for now we assume a var is a letter, we can check this lateron by searching for a ... = button
if self.is_variable(var_or_button):
return self.make_ifpressed_command(f"""\
if event.unicode != {args[0]}:
pygame_end = True
if event.unicode == {args[0]}:
{ConvertToPython.indent(args[1])}
break""", False)
elif len(var_or_button) > 1:
return self.make_ifpressed_command(f"""\
if event.key != {button_name}:
pygame_end = True
if event.key == {button_name}:
{ConvertToPython.indent(args[1])}
break""", True)
else:
return self.make_ifpressed_command(f"""\
if event.unicode != '{args[0]}':
pygame_end = True
if event.unicode == '{args[0]}':
{ConvertToPython.indent(args[1])}
break""")
Expand All @@ -1822,25 +1841,22 @@ def ifpressed_else(self, meta, args):
{ConvertToPython.indent(args[1])}
break
else:
{ConvertToPython.indent(args[2])}
break""", False)
{ConvertToPython.indent(args[2])}""", False)
elif len(var_or_button) > 1:
button_name = self.process_variable(args[0], meta.line)
return self.make_ifpressed_command(f"""\
if event.key == {button_name}:
{ConvertToPython.indent(args[1])}
break
else:
{ConvertToPython.indent(args[2])}
break""", True)
{ConvertToPython.indent(args[2])}""", True)
else:
return self.make_ifpressed_command(f"""\
if event.unicode == '{args[0]}':
{ConvertToPython.indent(args[1])}
break
else:
{ConvertToPython.indent(args[2])}
break""")
{ConvertToPython.indent(args[2])}""")


@v_args(meta=True)
Expand Down Expand Up @@ -1960,7 +1976,6 @@ def repeat(self, meta, args):
command = args[1]
# in level 7, repeats can only have 1 line as their arguments
command = sleep_after(command, False)
self.ifpressed_prefix_added = False # add ifpressed prefix again after repeat
return f"""for {var_name} in range(int({str(times)})):
{ConvertToPython.indent(command)}"""

Expand All @@ -1985,7 +2000,6 @@ def repeat(self, meta, args):
body = "\n".join(all_lines)
body = sleep_after(body)

self.ifpressed_prefix_added = False # add ifpressed prefix again after repeat
return f"for {var_name} in range(int({times})):\n{body}"

def ifs(self, meta, args):
Expand All @@ -2001,17 +2015,23 @@ def ifpressed(self, met, args):
# if this is a variable, we assume it is a key (for now)
if self.is_variable(var_or_key):
return self.make_ifpressed_command(f"""\
if event.unicode != {args[0]}:
pygame_end = True
if event.unicode == {args[0]}:
{all_lines}
break""")
elif len(var_or_key) == 1: # one character? also a key!
return self.make_ifpressed_command(f"""\
if event.unicode != '{args[0]}':
pygame_end = True
if event.unicode == '{args[0]}':
{all_lines}
break""")
else: # otherwise we mean a button
button_name = self.process_variable(args[0], met.line)
return self.make_ifpressed_command(f"""\
if event.key != {button_name}:
pygame_end = True
if event.key == {button_name}:
{all_lines}
break""", True)
Expand Down Expand Up @@ -2044,7 +2064,6 @@ def elses(self, meta, args):

def ifpressed_elses(self, meta, args):
args = [a for a in args if a != ""] # filter out in|dedent tokens
args += [" break\n"]

all_lines = "\n".join(
[ConvertToPython.indent(x, 4) for x in args]
Expand Down Expand Up @@ -2074,7 +2093,6 @@ def for_list(self, meta, args):
body = "\n".join([ConvertToPython.indent(x) for x in args[2:]])

body = sleep_after(body, True)
self.ifpressed_prefix_added = False
return f"for {times} in {args[1]}:\n{body}"


Expand All @@ -2089,7 +2107,6 @@ def for_loop(self, meta, args):
stepvar_name = self.get_fresh_var('step')
begin = self.process_token_or_tree(args[1])
end = self.process_token_or_tree(args[2])
self.ifpressed_prefix_added = False # add ifpressed prefix again after for loop
return f"""{stepvar_name} = 1 if {begin} < {end} else -1
for {iterator} in range({begin}, {end} + {stepvar_name}, {stepvar_name}):
{body}"""
Expand Down Expand Up @@ -2274,7 +2291,6 @@ def while_loop(self, meta, args):
body = "\n".join(all_lines)
body = sleep_after(body)
exceptions = self.make_catch_exception([args[0]])
self.ifpressed_prefix_added = False # add ifpressed prefix again after while loop
return exceptions + "while " + args[0] + ":\n" + body


Expand Down Expand Up @@ -2961,8 +2977,15 @@ def transpile_inner(input_string, level, lang="en"):
convertToPython = TRANSPILER_LOOKUP[level]
python = convertToPython(lookup_table, numerals_language).transform(abstract_syntax_tree)

has_turtle = UsesTurtle().transform(abstract_syntax_tree)
has_pygame = UsesPyGame().transform(abstract_syntax_tree)
uses_turtle = UsesTurtle()
has_turtle = uses_turtle.transform(abstract_syntax_tree)

uses_pygame = UsesPyGame()
has_pygame = uses_pygame.transform(abstract_syntax_tree)

if has_pygame:
python = uses_pygame.post_process_code(python)

return ParseResult(python, has_turtle, has_pygame)
except VisitError as E:
# Exceptions raised inside visitors are wrapped inside VisitError. Unwrap it if it is a
Expand Down
Loading

0 comments on commit a9e338e

Please sign in to comment.