From ef6c131149e2177b1e5445d3bbfd22764c00d7eb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Hugo=20H=C3=B6rnquist?= <hugo@lysator.liu.se>
Date: Tue, 23 May 2023 01:24:10 +0200
Subject: [PATCH] Ensure all whitespace in outputed code is separater tokens.

---
 main.py | 151 +++++++++++++++++++++++++++-----------------------------
 1 file changed, 74 insertions(+), 77 deletions(-)

diff --git a/main.py b/main.py
index baec3d6..0999a58 100644
--- a/main.py
+++ b/main.py
@@ -99,13 +99,13 @@ def print_hash(hash: list[HashEntry],
                 items += [
                     ind(indent),
                     parse(key, indent, context),
-                    ' ⇒ ',
+                    ' ', '⇒', ' ',
                     parse(value, indent, context),
                 ]
             case ['splat-hash', value]:
                 items += [
                     ind(indent),
-                    '* ⇒ ',
+                    '*', ' ', '⇒', ' ',
                     parse(value, indent, context),
                 ]
             case _:
@@ -131,16 +131,6 @@ def ops_namelen(ops: list[HashEntry]) -> int:
     return namelen
 
 
-def print_array(arr: list[Any], indent: int, context: list[str]) -> None:
-    """Print a puppet array literal."""
-    print('[')
-    for item in arr:
-        print(' '*(indent+1)*2, end='')
-        parse(item, indent, context)
-        print(',')
-    print(' '*indent*2 + ']', end='')
-
-
 def print_var(x: str, dollar: bool = True) -> Tag:
     """
     Print the given variable.
@@ -196,8 +186,10 @@ def handle_case_body(forms: list[dict[str, Any]],
         ret += [ind(indent+1)]
         # cases = []
 
-        ret += list(intersperse(', ', list(parse(item, indent+1, context)
-                                           for item in when)))
+        for sublist in intersperse([',', ' '],
+                                   [[parse(item, indent+1, context)]
+                                    for item in when]):
+            ret += sublist
 
         ret += [':', ' ', '{', '\n']
 
@@ -231,13 +223,14 @@ def parse(form: Any, indent: int, context: list[str]) -> Tag:
 
         case ['access', how, *args]:
             # TODO newlines?
-            t = [parse(arg, indent, context) for arg in args]
-            return tag([
-                parse(how, indent, context),
-                '[',
-                *intersperse(', ', t),
-                ']',
-            ], 'access')
+            items = []
+            items += [parse(how, indent, context), '[']
+            for sublist in intersperse([',', ' '],
+                                       [[parse(arg, indent, context)]
+                                        for arg in args]):
+                items += sublist
+            items += [']']
+            return tag(items, 'access')
 
         case ['and', a, b]:
             return tag([
@@ -263,26 +256,25 @@ def parse(form: Any, indent: int, context: list[str]) -> Tag:
 
         case ['call', {'functor': func,
                        'args': args}]:
-            return tag([
-                parse(func, indent, context),
-                '(',
-                *intersperse(', ', [parse(arg, indent, context)
-                                    for arg in args]),
-                ')',
-            ], 'call')
+            items = []
+            items += [parse(func, indent, context), '(']
+            for sublist in intersperse([',', ' '],
+                                       [[parse(arg, indent, context)]
+                                        for arg in args]):
+                items += sublist
+            items += [')']
+            return tag(items, 'call')
 
         case ['call-method', func]:
-            items = [
-                parse(func['functor'], indent, context)
-            ]
+            items = [parse(func['functor'], indent, context)]
 
             if not ('block' in func and func['args'] == []):
-                items += [
-                    '(',
-                    *intersperse(', ', [parse(x, indent, context)
-                                        for x in func['args']]),
-                    ')',
-                ]
+                items += ['(']
+                for sublist in intersperse([',', ' '],
+                                           [[parse(x, indent, context)]
+                                            for x in func['args']]):
+                    items += sublist
+                items += [')']
 
             if 'block' in func:
                 items += [parse(func['block'], indent+1, context)]
@@ -326,7 +318,7 @@ def parse(form: Any, indent: int, context: list[str]) -> Tag:
                     items += [tag(f'${name}', 'var')]
                     if 'value' in data:
                         items += [
-                            ' = ',
+                            ' ', '=', ' ',
                             parse(data.get('value'), indent, context),
                         ]
                     items += [',', '\n']
@@ -427,13 +419,13 @@ def parse(form: Any, indent: int, context: list[str]) -> Tag:
                     items += [f'${name}']
                     if 'value' in attributes:
                         items += [
-                            ' = ',
+                            ' ', '=', ' ',
                             parse(attributes['value'], indent, context),
                         ]
                     items += [',', '\n']
             items += [')']
             if 'returns' in rest:
-                items += [' >> ',
+                items += [' ', '>>', ' ',
                           parse(rest['returns'], indent, context)]
             items += [' ', '{', '\n']
             for item in body:
@@ -528,14 +520,12 @@ def parse(form: Any, indent: int, context: list[str]) -> Tag:
             if len(args) == 1:
                 items += [parse(args[0], indent+1, context)]
             else:
-                items += [
-                    args,
-                    '\n',
-                    '(',
-                    *intersperse(', ', [parse(arg, indent+1, context)
-                                        for arg in args]),
-                    ')',
-                ]
+                items += [args, '\n', '(']
+                for sublist in intersperse([',', ' '],
+                                           [[parse(arg, indent+1, context)]
+                                            for arg in args]):
+                    items += sublist
+                items += [')']
             return tag(items, 'invoke')
 
         case ['nop']:
@@ -544,8 +534,13 @@ def parse(form: Any, indent: int, context: list[str]) -> Tag:
         case ['lambda', {'params': params,
                          'body': body}]:
             items = []
-            args = [', '.join(f'${x}' for x in params.keys())]
-            items += [f' |{args}| {{', '\n']
+            args = [f'${x}' for x in params.keys()]
+            if args:
+                first, *rest = args
+                items += [first]
+                for arg in rest:
+                    items += [',', ' ', arg]
+            items += [' ', f'|{args}|', ' ', '{', '\n']
             for entry in body:
                 items += [
                     ind(indent),
@@ -607,7 +602,7 @@ def parse(form: Any, indent: int, context: list[str]) -> Tag:
                         items += [
                             ind(indent+1),
                             tag(key, 'parameter'),
-                            ' '*pad, ' ⇒ ',
+                            ' '*pad, ' ', '⇒', ' ',
                             parse(value, indent+1, context),
                             ',', '\n',
                         ]
@@ -617,7 +612,7 @@ def parse(form: Any, indent: int, context: list[str]) -> Tag:
                                 ind(indent+1),
                                 tag('*', 'parameter', 'splat'),
                                 ' '*(namelen-1),
-                                ' ⇒ ',
+                                ' ', '⇒', ' ',
                                 parse(value, indent+1, context),
                                 ',', '\n',
                         ]
@@ -694,7 +689,7 @@ def parse(form: Any, indent: int, context: list[str]) -> Tag:
                             ind(indent+1),
                             tag(key, 'parameter'),
                             ' '*pad,
-                            ' ⇒ ',
+                            ' ', '⇒', ' ',
                             parse(value, indent+3, context),
                             ',', '\n',
                         ]
@@ -706,7 +701,7 @@ def parse(form: Any, indent: int, context: list[str]) -> Tag:
                             tag('*', 'parameter', 'splat'),
                             ' '*pad,
                             ' '*(namelen-1),
-                            ' ⇒ ',
+                            ' ', '⇒', ' ',
                             parse(value, indent+2, context),
                             ',', '\n',
                         ]
@@ -725,6 +720,7 @@ def parse(form: Any, indent: int, context: list[str]) -> Tag:
                 parse(resources, indent, context),
                 ' ', '{', '\n',
             ]
+
             namelen = ops_namelen(ops)
             for op in ops:
                 match op:
@@ -734,7 +730,7 @@ def parse(form: Any, indent: int, context: list[str]) -> Tag:
                             ind(indent+1),
                             tag(key, 'parameter'),
                             ' '*pad,
-                            ' ⇒ ',
+                            ' ', '⇒', ' ',
                             parse(value, indent+3, context),
                             ',', '\n',
                         ]
@@ -745,7 +741,7 @@ def parse(form: Any, indent: int, context: list[str]) -> Tag:
                             ind(indent+2),
                             tag(key, 'parameter'),
                             ' '*pad,
-                            ' +> ',
+                            ' ', '+>', ' ',
                             parse(value, indent+2, context),
                             ',', '\n',
                         ]
@@ -757,7 +753,7 @@ def parse(form: Any, indent: int, context: list[str]) -> Tag:
                             tag('*', 'parameter', 'splat'),
                             ' '*pad,
                             ' '*(namelen-1),
-                            ' ⇒ ',
+                            ' ', '⇒', ' ',
                             parse(value, indent+2, context),
                             ',', '\n',
                         ]
@@ -819,83 +815,83 @@ def parse(form: Any, indent: int, context: list[str]) -> Tag:
         case ['!=', a, b]:
             return tag([
                 parse(a, indent, context),
-                ' ≠ ',
+                ' ', '≠', ' ',
                 parse(b, indent, context),
             ])
 
         case ['+', a, b]:
             return tag([
                 parse(a, indent, context),
-                ' + ',
+                ' ', '+', ' ',
                 parse(b, indent, context),
             ])
 
         case ['-', a, b]:
             return tag([
                 parse(a, indent, context),
-                ' - ',
+                ' ', '-', ' ',
                 parse(b, indent, context),
             ])
 
         case ['-', a]:
             return tag([
-                '- ',
+                '-', ' ',
                 parse(a),
             ])
 
         case ['*', a, b]:
             return tag([
                 parse(a, indent, context),
-                ' × ',
+                ' ', '×', ' ',
                 parse(b, indent, context),
             ])
 
         case ['%', a, b]:
             return tag([
                 parse(a, indent, context),
-                ' % ',
+                ' ', '%', ' ',
                 parse(b, indent, context),
             ])
 
         case ['<<', a, b]:
             return tag([
                 parse(a, indent, context),
-                '  << ',
+                ' ', '<<', ' ',
                 parse(b, indent, context),
             ])
 
         case ['>>', a, b]:
             return tag([
                 parse(a, indent, context),
-                ' >> ',
+                ' ', '>>', ' ',
                 parse(b, indent, context),
             ])
 
         case ['>=', a, b]:
             return tag([
                 parse(a, indent, context),
-                ' ≥ ',
+                ' ', '≥', ' ',
                 parse(b, indent, context),
             ])
 
         case ['<=', a, b]:
             return tag([
                 parse(a, indent, context),
-                ' ≤ ',
+                ' ', '≤', ' ',
                 parse(b, indent, context),
             ])
 
         case ['>', a, b]:
             return tag([
                 parse(a, indent, context),
-                ' > ',
+                ' ', '>', ' ',
                 parse(b, indent, context),
             ])
 
         case ['<', a, b]:
             return tag([
                 parse(a, indent, context),
-                ' < ',
+                ' ', '<', ' ',
                 parse(b, indent, context),
             ])
 
@@ -913,7 +909,7 @@ def parse(form: Any, indent: int, context: list[str]) -> Tag:
                 parse(left, indent, context),
                 '\n',
                 ind(indent),
-                '→ ',
+                '→', ' ',
                 parse(right, indent, context),
             ])
 
@@ -929,43 +925,42 @@ def parse(form: Any, indent: int, context: list[str]) -> Tag:
         case ['/', a, b]:
             return tag([
                 parse(a, indent, context),
-                ' / ',
+                ' ', '/', ' ',
                 parse(b, indent, context),
             ])
 
         case ['=', field, value]:
             return tag([
                 parse(field, indent, context),
-                ' = ',
+                ' ', '=', ' ',
                 parse(value, indent, context),
             ])
 
         case ['==', a, b]:
             return tag([
                 parse(a, indent, context),
-                ' ≡ ',
+                ' ', '≡', ' ',
                 parse(b, indent, context),
             ])
 
         case ['=~', a, b]:
             return tag([
                 parse(a, indent, context),
-                ' =~ ',
+                ' ', '=~', ' ',
                 parse(b, indent, context),
             ])
 
         case ['!~', a, b]:
             return tag([
                 parse(a, indent, context),
-                ' ≁ ',
+                ' ', '≁', ' ',
                 parse(b, indent, context),
             ])
 
         case ['?', condition, cases]:
             return tag([
                 parse(condition, indent, context),
-                ' ? {',
-                '\n',
+                ' ', '?', ' ', '{', '\n',
                 print_hash(cases, indent+1, context),
                 ind(indent),
                 '}',
@@ -986,7 +981,9 @@ def parse(form: Any, indent: int, context: list[str]) -> Tag:
                         items += [ind(indent), line, '\n']
 
                     return tag(items, 'literal', 'string')
+
                 else:
+                    # TODO further escaping?
                     s = form.replace('\n', r'\n')
                     s = f"'{s}'"
                     return tag(s, 'literal', 'string')
-- 
GitLab