Andrew Godwin avatar Andrew Godwin committed b2d8292

Proper variable scoping for module variables, full conversion to class-based.

Comments (0)

Files changed (7)

kugelblitz/tests/__init__.py

     import ast
 except ImportError:
     from kugelblitz.lib import ast
-from kugelblitz.translator import translate
+from kugelblitz.translator import translate_string
 
 class SimpleTests(unittest.TestCase):
     
         Assertion that the source compiles to the output.
         Doesn't fail horribly on whitespace differences.
         """
-        compiled = translate(ast.parse(self.unindent_code(source)))
+        compiled = translate_string(self.unindent_code(source))
         self.assertEqual(
             " ".join(compiled.split()),
             " ".join(output.split()),

kugelblitz/translator/__init__.py

 from kugelblitz.translator.base import ast, BaseTranslator
 from kugelblitz.translator.exceptions import CompileError
-from kugelblitz.translator.toplevel import ModuleTranslator, FunctionTranslator, LambdaTranslator, ClassTranslator
-from kugelblitz.translator.expressions import ExprTranslator, BinOpTranslator, BoolOpTranslator, UnaryOpTranslator, CompareTranslator, SubscriptTranslator
-from kugelblitz.translator.values import NumTranslator, ListTranslator, NameTranslator, DictTranslator, StrTranslator
-from kugelblitz.translator.assignment import AssignTranslator, AugAssignTranslator
-from kugelblitz.translator.control import IfTranslator, IfExprTranslator, RaiseTranslator, ReturnTranslator, CallTranslator, ForTranslator
-
-def wrap_old_translator(func):
-    class WrappedTranslator(BaseTranslator):
-        def translate(self):
-            return func(self.node)
-    return WrappedTranslator
-
-def translate(node):
-    return get_translator(node).translate()
+from kugelblitz.translator.toplevel import (
+    ModuleTranslator,
+    FunctionTranslator,
+    LambdaTranslator,
+    ClassTranslator,
+)
+from kugelblitz.translator.expressions import (
+    ExprTranslator,
+    BinOpTranslator,
+    BoolOpTranslator,
+    UnaryOpTranslator,
+    CompareTranslator,
+    SubscriptTranslator,
+    AttributeTranslator,
+    DeleteTranslator,
+)
+from kugelblitz.translator.values import (
+    NumTranslator,
+    ListTranslator,
+    NameTranslator,
+    DictTranslator,
+    StrTranslator,
+)
+from kugelblitz.translator.assignment import (
+    AssignTranslator,
+    AugAssignTranslator,
+)
+from kugelblitz.translator.control import (
+    IfTranslator,
+    IfExprTranslator,
+    RaiseTranslator,
+    ReturnTranslator,
+    CallTranslator,
+    ForTranslator,
+)
 
 def get_translator(node, **kwargs):
     try:
             ast.ClassDef: ClassTranslator,
             ast.Return: ReturnTranslator,
             
-            ast.Delete: wrap_old_translator(translate_delete),
+            ast.Delete: DeleteTranslator,
             ast.Assign: AssignTranslator,
             ast.AugAssign: AugAssignTranslator,
             
             ast.Repr: None,
             ast.Num: NumTranslator,
             ast.Str: StrTranslator,
-            ast.Attribute: wrap_old_translator(translate_attribute),
+            ast.Attribute: AttributeTranslator,
             ast.Subscript: SubscriptTranslator,            
             ast.Name: NameTranslator,
             ast.List: ListTranslator,
     except TypeError:
         raise CompileError("No translator available for %s." % node.__class__.__name__)
 
-def translate_delete(node):
-    return ';\n'.join('delete %s' % translate(n) for n in node.targets)
-
-def translate_attribute(node):
-    return "%(left)s.%(right)s" % {
-        "left": translate(node.value),
-        "right": node.attr,
-    }
-
 def translate_string(string, module_name=None):
     return get_translator(
         node = ast.parse(string+"\n"),

kugelblitz/translator/assignment.py

 class AssignTranslator(BaseTranslator):
     
     def translate_single_assign(self, target, value):
-        context = {
+        values = {
             'target': self.sib_translate(target),
             'value': self.sib_translate(value),
             'module_name': self.module_name,
         }
         if isinstance(target, ast.Name):
             if self.module_name:
-                return "%(module_name)s.%(target)s = %(value)s" % context
+                self.context[target.id] = "%(module_name)s.%(target)s" % values
+                return "%(module_name)s.%(target)s = %(value)s" % values
             else:
-                return "var %(target)s = %(value)s" % context
+                self.context[target.id] = "%(target)s" % values
+                return "var %(target)s = %(value)s" % values
         else:
-            return "%(target)s = %(value)s" % context
+            return "%(target)s = %(value)s" % values
 
     def translate(self):
         statements = []

kugelblitz/translator/base.py

 except ImportError:
     from kugelblitz.lib import ast
 
+from kugelblitz.translator.context import Context
+
 class BaseTranslator(object):
     
     """
     
     INDENT_STRING = "    "
     
-    def __init__(self, node, indent_level=0, module_name=None):
+    def __init__(self, node, indent_level=0, module_name=None, context=None):
         self.node = node
         self.indent_level = indent_level
         self.module_name = module_name
+        self.context = context or Context()
     
     @property
     def indent(self):
             node,
             indent_level = self.indent_level + 1,
             module_name = None,
+            context = Context(self.context),
         ).translate()
     
     def sib_translate(self, node):
             node,
             indent_level = self.indent_level,
             module_name = self.module_name,
+            context = self.context,
         ).translate()

kugelblitz/translator/context.py

+
+class Context(object):
+    """
+    Represents a variable context.
+    """
+    
+    def __init__(self, parent=None):
+        self.parent = parent
+        self.items = {}
+    
+    def __getitem__(self, key):
+        if key in self.items:
+            return self.items[key]
+        elif self.parent:
+            return self.parent[key]
+        else:
+            raise KeyError("No variable %r in context." % key)
+    
+    def __setitem__(self, key, value):
+        self.items[key] = value
+    
+    def __contains__(self, key):
+        try:
+            self[key]
+        except KeyError:
+            return False
+        else:
+            return True

kugelblitz/translator/expressions.py

             
         else:
             raise CompileError("Unknown slice type %s" % type(self.node.slice))
+
+
+class AttributeTranslator(BaseTranslator):
+    """
+    Translates attribute access, e.g 'foo.bar()'.
+    """
+    
+    def translate(self):
+        return "%(left)s.%(right)s" % {
+            "left": self.sib_translate(self.node.value),
+            "right": self.node.attr,
+        }
+
+
+class DeleteTranslator(BaseTranslator):
+    """
+    Translates deletion: 'del foo' to 'delete foo;'
+    """
+    
+    def translate(self):
+        return ';\n'.join(
+            'delete %s' % self.sib_translate(n)
+            for n in self.node.targets
+        )

kugelblitz/translator/values.py

         elif self.node.id == "True":
             return "true"
         else:
-            return self.node.id
+            # See if this variable is already defined elsewhere.
+            if self.node.id in self.context:
+                return self.context[self.node.id]
+            else:
+                return self.node.id
 
 class ListTranslator(BaseTranslator):
     def translate(self):
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.