Repository: hedyorg/hedy

Issue:
Feedback for missing quotes sometimes does not work? 
Weirdly, the issue seems to lie in 1 period: `print Hello welcome to Hedy.` versus `print Hello welcome to Hedy`



![image](https://user-images.githubusercontent.com/1003685/131550997-07c46d2b-0023-4e3e-b9b0-1ab51cdb15bd.png)

![image](https://user-images.githubusercontent.com/1003685/131551116-6c22cbb6-33a8-443a-ac63-3e9013a37966.png)



Discussion:

Resolving patch:
diff --git a/hedy.py b/hedy.py
--- a/hedy.py
+++ b/hedy.py
@@ -173,7 +173,7 @@ def assign_list(self, args):
     # list access is accessing a variable, so must be escaped
     # for example we print(dieren[1]) not print('dieren[1]')
     def list_access(self, args):
-        listname = args[0][0]
+        listname = args[0]
         if args[1] == 'random':
             return 'random.choice(' + listname + ')'
         else:
@@ -183,8 +183,7 @@ def list_access(self, args):
     # additions Laura, to be checked for higher levels:
     def list_access_var(self, args):
         return args[0]
-    def var_access(self,args):
-        return args[0]
+
     def change_list_item(self, args):
         return args[0]
 
@@ -192,8 +191,15 @@ def text(self, args):
         #text never contains a variable
         return None
 
+    def var_access(self, args):
+        # just accessing (printing) a variable does not count toward the lookup table
+        return None
+
     def var(self, args):
-        return args
+        # the var itself (when in an assignment) should be added
+        # if it happens to be a keyword in Python, prefix with _
+        name = args[0]
+        return "_" + name if name in reserved_words else name
 
     def punctuation(self, args):
         #is never a variable (but should be removed from the tree or it will be seen as one!)
@@ -429,17 +435,33 @@ def list_access(self, args):
         else:
             return args[0] + '[' + args[1] + ']'
 
+def quoted(s):
+    return s[0] == "'" and s[-1] == "'"
 
-
-#TODO: lookuptable and punctuation chars not be needed for level2 and up anymore, could be removed
+#TODO: punctuation chars not be needed for level2 and up anymore, could be removed
 class ConvertToPython_3(ConvertToPython_2):
+
+    def var_access(self, args):
+        name = ''.join(args)
+        return "_" + name if name in reserved_words else name
+
     def text(self, args):
         return ''.join([str(c) for c in args])
+
     def print(self, args):
-        #opzoeken is nu niet meer nodig
-        return "print(" + '+'.join(args) + ')'
+        unquoted_args = [a for a in args if not quoted(a)]
+        unquoted_in_lookup = [a in self.lookup for a in unquoted_args]
+        #we can print if all arguments are quoted OR they are all variables
+        if unquoted_in_lookup == [] or all(unquoted_in_lookup):
+            return "print(" + '+'.join(args) + ')'
+        else:
+            # I would like to raise normally but that is caught by the tranformer :(
+            return f"HedyException:{args[0]}"
+            #raise HedyException('Var Undefined', name=args[0])
+
     def print_nq(self, args):
         return ConvertToPython_2.print(self, args)
+
     def ask(self, args):
         args_new = []
         var = args[0]
@@ -584,15 +606,8 @@ def assign(self, args):  # TODO: needs to be merged with 6, when 6 is improved t
     def var_access(self, args):
         if len(args) == 1: #accessing a var
             return wrap_non_var_in_quotes(args[0], self.lookup)
-            # this was used to produce better error messages, but needs more work
-            # (because plain text strings are now also var_access and not textwithoutspaces
-            # since we no longer have priority rules
-            # if args[0] in self.lookup:
-            #     return args[0]
-            # else:
-            #     raise HedyException('VarUndefined', level=7, name=args[0])
         else:
-        # dit was list_access
+        # this is list_access
             return args[0] + "[" + str(args[1]) + "]" if type(args[1]) is not Tree else "random.choice(" + str(args[0]) + ")"
 
 class ConvertToPython_8(ConvertToPython_7):
@@ -1164,6 +1179,9 @@ def transpile_inner(input_string, level, sub=0):
         raise Exception('Levels over 22 are not implemented yet')
 
     has_turtle = UsesTurtle().transform(program_root)
+    if 'HedyException' in python:
+        var = python.split(':')
+        raise HedyException('Var Undefined', name=var[1])
 
     return ParseResult(python, has_turtle)
 


Test patch:
diff --git a/tests/tests_level_03.py b/tests/tests_level_03.py
--- a/tests/tests_level_03.py
+++ b/tests/tests_level_03.py
@@ -30,21 +30,22 @@ def test_name(self):
 
   def test_transpile_other(self):
     with self.assertRaises(Exception) as context:
-      result = hedy.transpile("abc felienne 123", 3)
+      result = hedy.transpile("abc felienne 123", self.level)
     self.assertEqual(str(context.exception), 'Invalid')
 
   def test_transpile_print_level_2(self):
     with self.assertRaises(Exception) as context:
-      result = hedy.transpile("print felienne 123", 3)
+      result = hedy.transpile("print felienne 123", self.level)
 
     self.assertEqual('Unquoted Text', context.exception.args[0])  # hier moet nog we een andere foutmelding komen!
 
+
   def test_print(self):
 
     code = textwrap.dedent("""\
     print 'hallo wereld!'""")
 
-    result = hedy.transpile(code, 3)
+    result = hedy.transpile(code, self.level)
 
     expected = textwrap.dedent("""\
     print('hallo wereld!')""")
@@ -54,7 +55,7 @@ def test_print(self):
 
 
   def test_transpile_turtle_basic(self):
-    result = hedy.transpile("forward 50\nturn\nforward 100", 3)
+    result = hedy.transpile("forward 50\nturn\nforward 100", self.level)
     expected = textwrap.dedent("""\
     t.forward(50)
     t.right(90)
@@ -66,7 +67,7 @@ def test_transpile_turtle_with_ask(self):
     code = textwrap.dedent("""\
     afstand is ask 'hoe ver dan?'
     forward afstand""")
-    result = hedy.transpile(code, 3)
+    result = hedy.transpile(code, self.level)
     expected = textwrap.dedent("""\
     afstand = input('hoe ver dan?')
     t.forward(afstand)""")
@@ -78,7 +79,7 @@ def test_print_with_comma(self):
     naam is Hedy
     print 'ik heet ,'""")
 
-    result = hedy.transpile(code, 3)
+    result = hedy.transpile(code, self.level)
 
     expected = textwrap.dedent("""\
     naam = 'Hedy'
@@ -93,7 +94,7 @@ def test_print_with_single_quote(self):
     naam is Hedy
     print 'ik heet \\''""")
 
-    result = hedy.transpile(code, 3)
+    result = hedy.transpile(code, self.level)
 
     expected = textwrap.dedent("""\
     naam = 'Hedy'
@@ -107,7 +108,7 @@ def test_name_with_underscore(self):
     voor_naam is Hedy
     print 'ik heet '""")
 
-    result = hedy.transpile(code, 3)
+    result = hedy.transpile(code, self.level)
 
     expected = textwrap.dedent("""\
     voor_naam = 'Hedy'
@@ -121,7 +122,7 @@ def test_name_that_is_keyword(self):
     for is Hedy
     print 'ik heet ' for """)
 
-    result = hedy.transpile(code, 3)
+    result = hedy.transpile(code, self.level)
 
     expected = textwrap.dedent("""\
     _for = 'Hedy'
@@ -135,7 +136,7 @@ def test_print_Spanish(self):
     code = textwrap.dedent("""\
     print 'Cuál es tu color favorito?'""")
 
-    result = hedy.transpile(code, 3)
+    result = hedy.transpile(code, self.level)
 
     expected = textwrap.dedent("""\
     print('Cuál es tu color favorito?')""")
@@ -149,7 +150,7 @@ def test_print_with_list_var(self):
     dieren is Hond, Kat, Kangoeroe
     print dieren at 1""")
 
-    result = hedy.transpile(code, 3)
+    result = hedy.transpile(code, self.level)
 
     expected = textwrap.dedent("""\
     dieren = ['Hond', 'Kat', 'Kangoeroe']
@@ -166,7 +167,7 @@ def test_print_with_list_var_random(self):
     dieren is Hond, Kat, Kangoeroe
     print dieren at random""")
 
-    result = hedy.transpile(code, 3)
+    result = hedy.transpile(code, self.level)
 
     expected = textwrap.dedent("""\
     dieren = ['Hond', 'Kat', 'Kangoeroe']
@@ -180,7 +181,7 @@ def test_transpile_ask_Spanish(self):
     code = textwrap.dedent("""\
     color is ask 'Cuál es tu color favorito?'""")
 
-    result = hedy.transpile(code, 3)
+    result = hedy.transpile(code, self.level)
 
     expected = textwrap.dedent("""\
     color = input('Cuál es tu color favorito?')""")
@@ -193,7 +194,7 @@ def test_print_2(self):
     code = textwrap.dedent("""\
     print 'ik heet henk'""")
 
-    result = hedy.transpile(code, 3)
+    result = hedy.transpile(code, self.level)
 
     expected = textwrap.dedent("""\
     print('ik heet henk')""")
@@ -207,7 +208,7 @@ def test_print_with_var(self):
     naam is Hedy
     print 'ik heet' naam""")
 
-    result = hedy.transpile(code, 3)
+    result = hedy.transpile(code, self.level)
 
     expected = textwrap.dedent("""\
     naam = 'Hedy'
@@ -222,7 +223,7 @@ def test_transpile_ask_with_print(self):
     kleur is ask 'wat is je lievelingskleur?'
     print 'jouw lievelingskleur is dus' kleur '!'""")
 
-    result = hedy.transpile(code, 3)
+    result = hedy.transpile(code, self.level)
 
     expected = textwrap.dedent("""\
     kleur = input('wat is je lievelingskleur?')
@@ -238,7 +239,7 @@ def test_transpile_ask_with_var(self):
     kleur is ask 'Wat is je lievelings' ding
     print 'Jouw favoriet is dus ' kleur""")
 
-    result = hedy.transpile(code, 3)
+    result = hedy.transpile(code, self.level)
 
     expected = textwrap.dedent("""\
     ding = 'kleur'
@@ -255,20 +256,38 @@ def test_transpile_ask_no_quotes(self):
     print 'Jouw favoriet is dus ' kleur""")
 
     with self.assertRaises(Exception) as context:
-      result = hedy.transpile(code, 3)
+      result = hedy.transpile(code, self.level)
 
     self.assertEqual('Unquoted Text', context.exception.args[0])  # hier moet nog we een andere foutmelding komen!
 
 
 
   def test_transpile_missing_opening_quote(self):
-    code = textwrap.dedent("""
+    code = textwrap.dedent("""\
       print hallo wereld'""")
 
     with self.assertRaises(Exception) as context:
-      result = hedy.transpile(code, 3)
+      result = hedy.transpile(code, self.level)
+
+    self.assertEqual('Unquoted Text', context.exception.args[0])
+
+
+  def test_transpile_missing_all_quotes(self):
+    max_level = 5
+
+    code = textwrap.dedent("""\
+      print hallo wereld""")
+    
+    for level in range(self.level, max_level+1):
+
+      with self.assertRaises(Exception) as context:
+        result = hedy.transpile(code, level)
+
+      self.assertEqual('Var Undefined', context.exception.args[0])
+
+      print(f'{self.test_name()} level {level}')
+
 
-    self.assertEqual('Unquoted Text', context.exception.args[0])  # hier moet nog we een andere foutmelding komen!
 
   def test_transpile_issue_375(self):
     code = textwrap.dedent("""
@@ -276,9 +295,9 @@ def test_transpile_issue_375(self):
       print welcome""")
 
     with self.assertRaises(Exception) as context:
-      result = hedy.transpile(code, 3)
+      result = hedy.transpile(code, self.level)
 
-    self.assertEqual('Parse', context.exception.args[0])  # hier moet nog we een andere foutmelding komen!
+    self.assertEqual('Parse', context.exception.args[0])
 
   def test_two_spaces_after_print(self):
 
diff --git a/tests/tests_level_04.py b/tests/tests_level_04.py
--- a/tests/tests_level_04.py
+++ b/tests/tests_level_04.py
@@ -335,7 +335,7 @@ def test_ifelse_should_go_before_assign(self):
     code = textwrap.dedent("""\
     kleur is geel
     if kleur is groen antwoord is ok else antwoord is stom
-    print ans""")
+    print antwoord""")
 
     for level in range(self.level, maxlevel+1):
       result = hedy.transpile(code, level)
@@ -346,7 +346,7 @@ def test_ifelse_should_go_before_assign(self):
         antwoord = 'ok'
       else:
         antwoord = 'stom'
-      print(ans)""")
+      print(antwoord)""")
 
       self.assertEqual(expected, result.code)
       self.assertEqual(False, result.has_turtle)
diff --git a/tests/tests_level_06.py b/tests/tests_level_06.py
--- a/tests/tests_level_06.py
+++ b/tests/tests_level_06.py
@@ -103,6 +103,19 @@ def test_simple_calculation(self):
     self.assertEqual(expected, result.code)
     self.assertEqual(False, result.has_turtle)
 
+  def test_addition_var(self):
+    code = textwrap.dedent("""\
+    var is 5
+    print var + 5""")
+
+    result = hedy.transpile(code, self.level)
+
+    expected = textwrap.dedent("""\
+    var = '5'
+    print(str(int(var) + int(5)))""")
+
+    self.assertEqual(expected, result.code)
+
   def test_simple_calculation_without_space(self):
     code = "nummer is 4+5"
     result = hedy.transpile(code, self.level)