Repository: hedyorg/hedy

Issue:
[CONTENT] Translation needed for cyclic var in Dutch
See: https://github.com/Felienne/hedy/blob/1ce1a2d41221f3d72d19a672b3af63f0f7ce2c71/coursedata/texts/nl.yaml#L84


Discussion:

Resolving patch:
diff --git a/app.py b/app.py
--- a/app.py
+++ b/app.py
@@ -511,6 +511,10 @@ def parse():
                 response['Location'] = ex.error_location
                 transpile_result = ex.fixed_result
                 exception = ex
+            except hedy.exceptions.UnquotedEqualityCheck as ex:
+                response['Error'] = translate_error(ex.error_code, hedy_errors, ex.arguments)
+                response['Location'] = ex.error_location
+                exception = ex
         try:
             if transpile_result.has_turtle:
                 response['Code'] = TURTLE_PREFIX_CODE + transpile_result.code
diff --git a/exceptions.py b/exceptions.py
--- a/exceptions.py
+++ b/exceptions.py
@@ -64,6 +64,12 @@ def __init__(self, level, location, found, fixed_code=None):
         #TODO (FH, 8 dec 21) many exceptions now support fixed code maybe we should move it to hedyexception?
         self.fixed_code = fixed_code
 
+class UnquotedEqualityCheck(HedyException):
+    def __init__(self, line_number):
+        super().__init__('Unquoted Equality Check',
+             line_number=line_number)
+        self.location = [line_number]
+
 class UndefinedVarException(HedyException):
     def __init__(self, name):
         super().__init__('Var Undefined',
diff --git a/hedy.py b/hedy.py
--- a/hedy.py
+++ b/hedy.py
@@ -1,5 +1,6 @@
 import textwrap
 
+import lark
 from lark import Lark
 from lark.exceptions import LarkError, UnexpectedEOF, UnexpectedCharacters, VisitError
 from lark import Tree, Transformer, visitors, v_args
@@ -951,6 +952,8 @@ def error_unsupported_number(self, args, meta):
         error = InvalidInfo('unsupported number', arguments=[str(args[0])], line=meta.line, column=meta.column)
         return False, error, meta
 
+
+
     #other rules are inherited from Filter
 
 def valid_echo(ast):
@@ -1366,8 +1369,15 @@ def ifelse(self, args):
 {ConvertToPython.indent(args[1])}
 else:
 {ConvertToPython.indent(args[2])}"""
+
     def condition(self, args):
         return ' and '.join(args)
+
+    def condition_spaces(self, args):
+        result = args[0] + " == '" + ' '.join(args[1:]) + "'"
+        return result
+
+
     def equality_check(self, args):
         arg0 = self.process_variable(args[0])
         remaining_text = ' '.join(args[1:])
@@ -2063,6 +2073,10 @@ def parse_input(input_string, level, lang):
     try:
         parse_result = parser.parse(input_string + '\n')
         return parse_result.children[0]  # getting rid of the root could also be done in the transformer would be nicer
+    except lark.UnexpectedEOF:
+        lines = input_string.split('\n')
+        last_line = len(lines)
+        raise exceptions.UnquotedEqualityCheck(line_number=last_line)
     except UnexpectedCharacters as e:
         try:
             location = e.line, e.column
@@ -2080,7 +2094,7 @@ def parse_input(input_string, level, lang):
 def is_program_valid(program_root, input_string, level, lang):
     # IsValid returns (True,) or (False, args)
     instance = IsValid()
-    instance.level = level # could be done in a constructor once we are sure we will go this way
+    instance.level = level # TODO: could be done in a constructor once we are sure we will go this way
     is_valid = instance.transform(program_root)
 
     if not is_valid[0]:


Test patch:
diff --git a/tests/test_level_05.py b/tests/test_level_05.py
--- a/tests/test_level_05.py
+++ b/tests/test_level_05.py
@@ -1,4 +1,4 @@
-import hedy
+import hedy, lark
 import textwrap
 from test_level_01 import HedyTester
 
@@ -288,11 +288,38 @@ def test_undefined_list_if_in_list(self):
 
     self.single_level_tester(code=code, exception=hedy.exceptions.UndefinedVarException)
 
-  def test_one_space_in_rhs_if(self):
+  def test_unquoted_space_rhs(self):
+    code = textwrap.dedent("""\
+    naam is James
+    if naam is James Bond print 'shaken' else print 'biertje!'""")
+
+    self.single_level_tester(
+      code=code,
+      exception=hedy.exceptions.UnquotedEqualityCheck)
+
+  def test_unquoted_space_rhs_no_else(self):
     code = textwrap.dedent("""\
     naam is James
     if naam is James Bond print 'shaken'""")
 
+    self.single_level_tester(
+      code=code,
+      exception=hedy.exceptions.UnquotedEqualityCheck)
+
+  def test_unquoted_space_rhs_assign(self):
+    code = textwrap.dedent("""\
+    naam is James
+    if naam is James Bond naam is 'Pietjansma'""")
+
+    self.single_level_tester(
+      code=code,
+      exception=hedy.exceptions.UnquotedEqualityCheck)
+
+  def test_one_space_in_rhs_if(self):
+    code = textwrap.dedent("""\
+    naam is James
+    if naam is 'James Bond' print 'shaken'""")
+
     expected = textwrap.dedent("""\
     naam = 'James'
     if naam == 'James Bond':
@@ -303,7 +330,7 @@ def test_one_space_in_rhs_if(self):
   def test_multiple_spaces_in_rhs_if(self):
     code = textwrap.dedent("""\
     naam is James
-    if naam is Bond James Bond print 'shaken'""")
+    if naam is 'Bond James Bond' print 'shaken'""")
 
     expected = textwrap.dedent("""\
     naam = 'James'
@@ -315,7 +342,7 @@ def test_multiple_spaces_in_rhs_if(self):
   def test_one_space_in_rhs_if_else(self):
     code = textwrap.dedent("""\
     naam is James
-    if naam is James Bond print 'shaken' else print 'biertje!'""")
+    if naam is 'James Bond' print 'shaken' else print 'biertje!'""")
 
     expected = textwrap.dedent("""\
     naam = 'James'
diff --git a/tests/test_level_06.py b/tests/test_level_06.py
--- a/tests/test_level_06.py
+++ b/tests/test_level_06.py
@@ -146,7 +146,24 @@ def test_if_else_with_space(self):
       code=code,
       expected=expected
     )
+  def test_print_if_else_with_is(self):
+    code = textwrap.dedent("""\
+    naam is Hedy
+    print 'ik heet' naam
+    if naam is Hedy print 'leuk' else print 'minder leuk'""")
 
+    expected = textwrap.dedent("""\
+    naam = 'Hedy'
+    print(f'ik heet{naam}')
+    if str(naam) == str('Hedy'):
+      print(f'leuk')
+    else:
+      print(f'minder leuk')""")
+
+    self.multi_level_tester(
+      code=code,
+      expected=expected,
+      max_level=7)
   def test_print_if_else_with_equals_sign(self):
     code = textwrap.dedent("""\
     naam is Hedy
@@ -317,6 +334,7 @@ def test_print_else(self):
       print(f'dat zijn dan {punten}')""")
 
       self.single_level_tester(code=code, expected=expected)
+
   def test_ifelse_should_go_before_assign(self):
     code = textwrap.dedent("""\
     kleur is geel
@@ -377,6 +395,18 @@ def test_if_calc_vars(self):
       expected=expected
     )
 
+  # So legal are:
+  #
+  # if name is Hedy print 'hello'
+  # if name is 'Hedy' print 'hello'
+  # if name is 'Hedy is het beste' print 'hello'
+  # if name is Hedy c is 5
+
+  # Illegal is:
+  #
+  # if name is Hedy is het beste print 'hello'
+  # if name is Hedy is het beste x is 5
+
   def test_equality_promotes_int_to_string(self):
     code = textwrap.dedent("""\
     a is test
@@ -397,7 +427,7 @@ def test_equality_promotes_int_to_string(self):
   def test_one_space_in_rhs_if(self):
     code = textwrap.dedent("""\
     naam is James
-    if naam is James Bond print 'shaken'""")
+    if naam is 'James Bond' print 'shaken'""")
 
     expected = textwrap.dedent("""\
     naam = 'James'
@@ -409,10 +439,27 @@ def test_one_space_in_rhs_if(self):
       expected=expected,
       max_level=7)
 
+  def test_no_space_nor_quotes_in_rhs(self):
+    code = textwrap.dedent("""\
+    warna = ask 'Apa warna favorit kamu?'
+    if warna is hijau print 'cantik!' else print 'meh!'""")
+
+    expected = textwrap.dedent("""\
+    warna = input(f'Apa warna favorit kamu?')
+    if str(warna) == str('hijau'):
+      print(f'cantik!')
+    else:
+      print(f'meh!')""")
+
+    self.multi_level_tester(
+      code=code,
+      expected=expected,
+      max_level=7)
+
   def test_one_space_in_rhs_if_else(self):
     code = textwrap.dedent("""\
     naam is James
-    if naam is James Bond print 'shaken' else print 'biertje!'""")
+    if naam is 'James Bond' print 'shaken' else print 'biertje!'""")
 
     expected = textwrap.dedent("""\
     naam = 'James'
@@ -426,10 +473,48 @@ def test_one_space_in_rhs_if_else(self):
       expected=expected,
       max_level=7)
 
+  def test_quoted_space_rhs(self):
+    code = textwrap.dedent("""\
+    naam is James
+    if naam is 'James Bond' print 'shaken' else print 'biertje!'""")
+
+    expected = textwrap.dedent("""\
+    naam = 'James'
+    if str(naam) == str('James Bond'):
+      print(f'shaken')
+    else:
+      print(f'biertje!')""")
+    self.single_level_tester(code=code, expected=expected)
+
+
+  def test_space_enter_rhs_ifelse(self):
+    code = textwrap.dedent("""\
+    naam is James
+    if naam is James Bond
+    print 'shaken' else print 'biertje!'""")
+
+    expected = textwrap.dedent("""\
+    naam = 'James'
+    if naam == 'James Bond':
+      print(f'shaken')
+    else:
+      print(f'biertje!')""")
+    self.single_level_tester(code=code, expected=expected)
+
+  def test_space_enter_rhs_if(self):
+    code = textwrap.dedent("""\
+    naam is James
+    if naam is James Bond print 'shaken'""")
+
+    self.single_level_tester(
+      code=code,
+      exception=hedy.exceptions.UnquotedEqualityCheck)
+
+
   def test_multiple_spaces_in_rhs_if(self):
     code = textwrap.dedent("""\
     naam is James
-    if naam is Bond James Bond print 'shaken'""")
+    if naam is 'Bond James Bond' print 'shaken'""")
 
     expected = textwrap.dedent("""\
     naam = 'James'
diff --git a/tests/test_level_07.py b/tests/test_level_07.py
--- a/tests/test_level_07.py
+++ b/tests/test_level_07.py
@@ -61,6 +61,7 @@ def test_repeat_basic_print(self):
 
     self.single_level_tester(code=code, expected=expected, output=output)
 
+
   def test_repeat_over_9_times(self):
 
     code = textwrap.dedent("""\
@@ -113,4 +114,21 @@ def test_repeat_with_collision(self):
         code=code,
         expected=expected,
         expected_commands=['is', 'repeat', 'print', 'print'],
-        output=output)
\ No newline at end of file
+        output=output)
+
+  def test_if_and_repeat(self):
+    code = textwrap.dedent("""\
+    naam is Hedy
+    if naam is Hedy repeat 3 times print 'Hallo Hedy!'""")
+
+    expected = textwrap.dedent("""\
+    naam = 'Hedy'
+    if str(naam) == str('Hedy'):
+      for i in range(int('3')):
+        print(f'Hallo Hedy!')
+        time.sleep(0.1)""")
+
+    self.single_level_tester(
+      code=code,
+      expected=expected)
+