Skip to content

Commit

Permalink
[LANGUAGE] Nested functions (hedyorg#4280)
Browse files Browse the repository at this point in the history
**Description**

**Adds** exception for nested functions
**Fixes** hedyorg#4240
  • Loading branch information
jlole authored Jun 1, 2023
1 parent 3cca9ae commit 7d6d8cb
Show file tree
Hide file tree
Showing 6 changed files with 45 additions and 1 deletion.
5 changes: 5 additions & 0 deletions exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -279,3 +279,8 @@ def __init__(self, command, level, line_number):
command=command,
level=level,
line_number=line_number)


class NestedFunctionException(HedyException):
def __init__(self):
super().__init__('Nested Function')
4 changes: 3 additions & 1 deletion grammars/level11-Additions.lark
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
command:+= for_loop | call | define
command:+= for_loop | call | error_nested_define

//new : for loop
for_loop: _FOR var _IN _RANGE (INT | var_access) _TO (INT | var_access) _EOL (_SPACE command) (_EOL _SPACE command)* _EOL? _END_BLOCK

// FUNCTIONS ======================================== =============================
// check line 1: command:+= call | define
_non_empty_program: _EOL* (define | command | error_invalid) _SPACE* (_EOL+ (define | command) _SPACE*)* _EOL* //lines may end on spaces and might be separated by many newlines
define: _DEFINE function_name _EOL (_SPACE command) (_EOL _SPACE command)* _EOL? _END_BLOCK
call: _CALL function_name
function_name: NAME -> text
error_nested_define: define
// ================================================================================
6 changes: 6 additions & 0 deletions hedy.py
Original file line number Diff line number Diff line change
Expand Up @@ -1216,6 +1216,10 @@ def error_ifpressed_missing_else(self, meta, args):
error = InvalidInfo('ifpressed missing else', arguments=[str(args[0])], line=meta.line, column=meta.column)
return False, error, meta

def error_nested_define(self, meta, args):
error = InvalidInfo('nested function', arguments=[str(args[0])], line=meta.line, column=meta.column)
return False, error, meta

# other rules are inherited from Filter


Expand Down Expand Up @@ -3018,6 +3022,8 @@ def is_program_valid(program_root, input_string, level, lang):
elif invalid_info.error_type == 'ifpressed missing else':
raise exceptions.MissingElseForPressitException(
command='ifpressed_else', level=level, line_number=invalid_info.line)
elif invalid_info.error_type == 'nested function':
raise exceptions.NestedFunctionException()
else:
invalid_command = invalid_info.command
closest = closest_command(invalid_command, get_suggestions_for_language(lang, level))
Expand Down
13 changes: 13 additions & 0 deletions tests/test_level/test_level_11.py
Original file line number Diff line number Diff line change
Expand Up @@ -389,3 +389,16 @@ def simple_function():
expected=expected,
output=output,
)

def test_nested_functions(self):
code = textwrap.dedent("""\
define simple_function
define nested_function
print 1
call simple_function""")

self.multi_level_tester(
code=code,
exception=hedy.exceptions.NestedFunctionException,
max_level=16,
)
9 changes: 9 additions & 0 deletions tests/test_level/test_level_17.py
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,15 @@ def test_pressed_elif(self):

self.single_level_tester(code=code, expected=expected)

def test_nested_functions(self):
code = textwrap.dedent("""\
define simple_function:
define nested_function:
print 1
call simple_function""")

self.single_level_tester(code=code, exception=hedy.exceptions.NestedFunctionException)

def test_source_map(self):
code = textwrap.dedent("""\
for i in range 1 to 10:
Expand Down
9 changes: 9 additions & 0 deletions tests/test_level/test_level_18.py
Original file line number Diff line number Diff line change
Expand Up @@ -334,3 +334,12 @@ def test_if_button_is_pressed_print(self):
# End of PyGame Event Handler""")

self.single_level_tester(code=code, expected=expected)

def test_nested_functions(self):
code = textwrap.dedent("""\
def simple_function():
def nested_function():
print(1)
simple_function()""")

self.single_level_tester(code=code, exception=hedy.exceptions.NestedFunctionException)

0 comments on commit 7d6d8cb

Please sign in to comment.