1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/annotate.py Tue Jul 18 00:34:32 2006 +0200
1.3 @@ -0,0 +1,125 @@
1.4 +#!/usr/bin/env python
1.5 +
1.6 +"""
1.7 +Traverse and annotate simplified AST structures.
1.8 +
1.9 +Copyright (C) 2006 Paul Boddie <paul@boddie.org.uk>
1.10 +
1.11 +This software is free software; you can redistribute it and/or
1.12 +modify it under the terms of the GNU General Public License as
1.13 +published by the Free Software Foundation; either version 2 of
1.14 +the License, or (at your option) any later version.
1.15 +
1.16 +This software is distributed in the hope that it will be useful,
1.17 +but WITHOUT ANY WARRANTY; without even the implied warranty of
1.18 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.19 +GNU General Public License for more details.
1.20 +
1.21 +You should have received a copy of the GNU General Public
1.22 +License along with this library; see the file LICENCE.txt
1.23 +If not, write to the Free Software Foundation, Inc.,
1.24 +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
1.25 +"""
1.26 +
1.27 +from simplified import *
1.28 +import compiler
1.29 +
1.30 +class Namespace:
1.31 + def __init__(self, parent=None):
1.32 + self.names = {}
1.33 + self.not_local = []
1.34 + self.parent = parent
1.35 +
1.36 + def make_global(self, name):
1.37 + if name not in self.not_local:
1.38 + self.not_local.append(name)
1.39 +
1.40 + def store(self, name, types):
1.41 + if name not in self.not_local:
1.42 + self.names[name] = types
1.43 + else:
1.44 + self.parent.store(name, types)
1.45 +
1.46 + def load(self, name):
1.47 + if name in self.not_local or not self.names.has_key(name):
1.48 + return self.parent.load(name)
1.49 + else:
1.50 + return self.names[name]
1.51 +
1.52 + def merge(self, namespace):
1.53 + for name, types in namespace.names.items():
1.54 + if not self.names.has_key(name):
1.55 + self.names[name] = types
1.56 + else:
1.57 + existing = self.names[name]
1.58 + for type in types:
1.59 + if type not in existing:
1.60 + existing.append(type)
1.61 +
1.62 +class System:
1.63 + def __init__(self):
1.64 + self.count = 0
1.65 + def init(self, node):
1.66 + if not hasattr(node, "types"):
1.67 + node.types = []
1.68 + def annotate(self, node, types):
1.69 + for type in types:
1.70 + if type not in node.types:
1.71 + node.types.append(type)
1.72 + self.count += 1
1.73 +
1.74 +class Traverser(Visitor):
1.75 + def __init__(self):
1.76 + Visitor.__init__(self)
1.77 + self.system = System()
1.78 + self.types = None
1.79 + self.temp = {}
1.80 +
1.81 + def traverse(self, node):
1.82 + self.namespace = Namespace()
1.83 + compiler.walk(node, self, self)
1.84 + if hasattr(node, "structure"):
1.85 + node.structure.namespace = self.namespace
1.86 +
1.87 + def default(self, node):
1.88 + for attr in ("args", "params"):
1.89 + value = getattr(node, attr, None)
1.90 + if value is not None:
1.91 + self.dispatches(value)
1.92 + for attr in ("expr", "lvalue", "test", "handler", "star", "dstar"):
1.93 + value = getattr(node, attr, None)
1.94 + if value is not None:
1.95 + self.dispatch(value)
1.96 + for attr in ("body", "else_", "finally_", "code"):
1.97 + value = getattr(node, attr, None)
1.98 + if value is not None:
1.99 + for n in value:
1.100 + self.dispatch(n)
1.101 + print node
1.102 +
1.103 + def visitGlobal(self, global_):
1.104 + for name in global_.names:
1.105 + self.make_global(name)
1.106 +
1.107 + def visitLoadRef(self, loadref):
1.108 + self.types = [loadref.ref]
1.109 +
1.110 + def visitLoadName(self, loadname):
1.111 + self.types = self.namespace.load(loadname.name)
1.112 +
1.113 + def visitStoreName(self, storename):
1.114 + self.namespace.store(storename.name, self.types)
1.115 +
1.116 + def visitLoadTemp(self, loadtemp):
1.117 + index = getattr(loadtemp, "index", None)
1.118 + self.types = self.temp[index]
1.119 +
1.120 + def visitStoreTemp(self, storetemp):
1.121 + index = getattr(storetemp, "index", None)
1.122 + self.temp[index] = self.types
1.123 +
1.124 + def visitReleaseTemp(self, releasetemp):
1.125 + index = getattr(releasetemp, "index", None)
1.126 + del self.temp[index]
1.127 +
1.128 +# vim: tabstop=4 expandtab shiftwidth=4
2.1 --- a/simplified.py Mon Jul 17 00:10:35 2006 +0200
2.2 +++ b/simplified.py Tue Jul 18 00:34:32 2006 +0200
2.3 @@ -21,6 +21,8 @@
2.4 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
2.5 """
2.6
2.7 +from compiler.visitor import ASTVisitor
2.8 +
2.9 class Node:
2.10
2.11 """
2.12 @@ -135,4 +137,20 @@
2.13 class Raise(Node): "An exception raising node."
2.14 class Not(Node): "A negation of an expression."
2.15
2.16 +class Visitor(ASTVisitor):
2.17 + def __init__(self):
2.18 + ASTVisitor.__init__(self)
2.19 +
2.20 + def default(self, node, *args):
2.21 + raise ValueError, node.__class__
2.22 +
2.23 + def dispatch(self, node, *args):
2.24 + return ASTVisitor.dispatch(self, node, *args)
2.25 +
2.26 + def dispatches(self, nodes, *args):
2.27 + results = []
2.28 + for node in nodes:
2.29 + results.append(self.dispatch(node, *args))
2.30 + return results
2.31 +
2.32 # vim: tabstop=4 expandtab shiftwidth=4
3.1 --- a/simplify.py Mon Jul 17 00:10:35 2006 +0200
3.2 +++ b/simplify.py Tue Jul 18 00:34:32 2006 +0200
3.3 @@ -21,11 +21,10 @@
3.4 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
3.5 """
3.6
3.7 -from compiler.visitor import ASTVisitor
3.8 +from simplified import *
3.9 import compiler.ast
3.10 -from simplified import *
3.11
3.12 -class Simplifier(ASTVisitor):
3.13 +class Simplifier(Visitor):
3.14
3.15 """
3.16 A simplifying visitor for AST nodes.
3.17 @@ -44,25 +43,12 @@
3.18 """
3.19
3.20 def __init__(self):
3.21 - ASTVisitor.__init__(self)
3.22 + Visitor.__init__(self)
3.23 self.result = None # The resulting tree.
3.24 self.subprograms = [] # Subprograms outside the tree.
3.25 + self.structures = [] # Structures/classes
3.26 self.current_subprograms = [] # Current subprograms being processed.
3.27
3.28 - # Generic visitor methods.
3.29 -
3.30 - def default(self, node, *args):
3.31 - raise ValueError, node.__class__
3.32 -
3.33 - def dispatch(self, node, *args):
3.34 - return ASTVisitor.dispatch(self, node, *args)
3.35 -
3.36 - def dispatches(self, nodes, *args):
3.37 - results = []
3.38 - for node in nodes:
3.39 - results.append(self.dispatch(node, *args))
3.40 - return results
3.41 -
3.42 def dispatch_or_none(self, node, *args):
3.43 if node is not None:
3.44 return self.dispatch(node, *args)
3.45 @@ -87,26 +73,6 @@
3.46 self.result.code = self.dispatch(module.node)
3.47 return self.result
3.48
3.49 - def visitClass(self, class_):
3.50 - structure = Class(name=hex(id(class_)), bases=class_.bases)
3.51 -
3.52 - subprogram = Subprogram(name=hex(id(class_)), acquire_locals=1, structure=structure, params=[], star=None, dstar=None)
3.53 - self.current_subprograms.append(subprogram)
3.54 -
3.55 - subprogram.code = self.dispatch(class_.code)
3.56 -
3.57 - self.current_subprograms.pop()
3.58 - self.subprograms.append(subprogram)
3.59 -
3.60 - # Make a definition of the class associating it with a name.
3.61 -
3.62 - result = Assign(class_)
3.63 - init = Invoke(expr=LoadRef(ref=subprogram), args=[], star=None, dstar=None)
3.64 - load = LoadRef(ref=structure)
3.65 - store = StoreName(name=class_.name)
3.66 - result.code = [init, load, store]
3.67 - return result
3.68 -
3.69 def visitGetattr(self, getattr):
3.70 result = LoadAttr(getattr, name=getattr.attrname)
3.71 result.expr = self.dispatch(getattr.expr)
3.72 @@ -588,6 +554,26 @@
3.73
3.74 # Invocation and subprogram transformations.
3.75
3.76 + def visitClass(self, class_):
3.77 + structure = Class(name=hex(id(class_)), bases=class_.bases)
3.78 + self.structures.append(structure)
3.79 +
3.80 + subprogram = Subprogram(name=hex(id(class_)), acquire_locals=1, structure=structure, params=[], star=None, dstar=None)
3.81 + self.current_subprograms.append(subprogram)
3.82 +
3.83 + subprogram.code = self.dispatch(class_.code)
3.84 +
3.85 + self.current_subprograms.pop()
3.86 + self.subprograms.append(subprogram)
3.87 +
3.88 + # Make a definition of the class associating it with a name.
3.89 +
3.90 + result = Assign(class_)
3.91 + init = Invoke(expr=LoadRef(ref=subprogram), args=[], star=None, dstar=None)
3.92 + store = StoreName(name=class_.name, expr=LoadRef(ref=structure))
3.93 + result.code = [init, store]
3.94 + return result
3.95 +
3.96 def _visitFunction(self, function, subprogram):
3.97 if function.flags & 4 != 0: has_star = 1
3.98 else: has_star = 0
3.99 @@ -631,10 +617,7 @@
3.100
3.101 # Make a definition of the function associating it with a name.
3.102
3.103 - result = Assign(function)
3.104 - load = LoadRef(ref=subprogram)
3.105 - store = StoreName(name=function.name)
3.106 - result.code = [load, store]
3.107 + result = StoreName(name=function.name, expr=LoadRef(ref=subprogram))
3.108 return result
3.109
3.110 def visitLambda(self, lambda_):
4.1 --- a/test.py Mon Jul 17 00:10:35 2006 +0200
4.2 +++ b/test.py Tue Jul 18 00:34:32 2006 +0200
4.3 @@ -1,4 +1,11 @@
4.4 import simplify, compiler, sys
4.5 +import annotate
4.6 +
4.7 +def traverse(n):
4.8 + traverser = annotate.Traverser()
4.9 + traverser.traverse(n)
4.10 + return traverser
4.11 +
4.12 visitor = simplify.Simplifier()
4.13 m = compiler.parseFile(sys.argv[1])
4.14 v = compiler.walk(m, visitor, visitor)