1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/fixnames.py Fri Jul 28 00:20:57 2006 +0200
1.3 @@ -0,0 +1,136 @@
1.4 +#!/usr/bin/env python
1.5 +
1.6 +"""
1.7 +Fix name-related operations. The code in this module operates upon nodes which
1.8 +are produced when simplifying AST node trees originating from the compiler
1.9 +module.
1.10 +
1.11 +Copyright (C) 2006 Paul Boddie <paul@boddie.org.uk>
1.12 +
1.13 +This software is free software; you can redistribute it and/or
1.14 +modify it under the terms of the GNU General Public License as
1.15 +published by the Free Software Foundation; either version 2 of
1.16 +the License, or (at your option) any later version.
1.17 +
1.18 +This software is distributed in the hope that it will be useful,
1.19 +but WITHOUT ANY WARRANTY; without even the implied warranty of
1.20 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.21 +GNU General Public License for more details.
1.22 +
1.23 +You should have received a copy of the GNU General Public
1.24 +License along with this library; see the file LICENCE.txt
1.25 +If not, write to the Free Software Foundation, Inc.,
1.26 +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
1.27 +"""
1.28 +
1.29 +from simplified import *
1.30 +import compiler
1.31 +
1.32 +# Fixing of name-related operations.
1.33 +
1.34 +class Fixer(Visitor):
1.35 +
1.36 + """
1.37 + The name fixer which traverses the program nodes, typically depth-first,
1.38 + and maintains a record of name usage in the different namespaces. As a
1.39 + consequence of various observations, some parts of the program node tree are
1.40 + modified with different operations employed to those originally defined.
1.41 + """
1.42 +
1.43 + def __init__(self):
1.44 + Visitor.__init__(self)
1.45 +
1.46 + # Satisfy visitor issues.
1.47 +
1.48 + self.visitor = self
1.49 +
1.50 + def process_all(self, visitor):
1.51 + subprograms = []
1.52 + for subprogram in visitor.subprograms:
1.53 + subprograms.append(self.process(subprogram))
1.54 + visitor.subprograms = subprograms
1.55 + visitor.result = self.process(visitor.result)
1.56 + return visitor
1.57 +
1.58 + def process(self, node):
1.59 +
1.60 + """
1.61 + Process a subprogram or module 'node', indicating any initial 'locals'
1.62 + and 'globals' if either are defined. Return an annotated subprogram or
1.63 + module. Note that this method may mutate nodes in the original program.
1.64 + """
1.65 +
1.66 + # Obtain a namespace either based on locals or on a structure.
1.67 +
1.68 + self.namespace = Namespace(structure=getattr(node, "structure", None))
1.69 +
1.70 + # Add namespace details to any structure involved.
1.71 +
1.72 + if hasattr(node, "structure") and node.structure is not None:
1.73 +
1.74 + # Initialise bases where appropriate.
1.75 +
1.76 + if hasattr(node.structure, "bases"):
1.77 + bases = []
1.78 + for base in node.structure.bases:
1.79 + bases.append(self.dispatch(base))
1.80 + node.structure.bases = bases
1.81 +
1.82 + # Dispatch to the code itself.
1.83 +
1.84 + result = self.dispatch(node)
1.85 + return result
1.86 +
1.87 + # Visitor methods.
1.88 +
1.89 + def default(self, node):
1.90 +
1.91 + """
1.92 + Process the given 'node', given that it does not have a specific
1.93 + handler.
1.94 + """
1.95 +
1.96 + for attr in ("args",):
1.97 + value = getattr(node, attr, None)
1.98 + if value is not None:
1.99 + setattr(node, attr, self.dispatches(value))
1.100 + for attr in ("expr", "lvalue", "test", "handler", "star", "dstar"):
1.101 + value = getattr(node, attr, None)
1.102 + if value is not None:
1.103 + setattr(node, attr, self.dispatch(value))
1.104 + for attr in ("body", "else_", "finally_", "code"):
1.105 + value = getattr(node, attr, None)
1.106 + if value is not None:
1.107 + setattr(node, attr, self.dispatches(value))
1.108 + return node
1.109 +
1.110 + def dispatch(self, node, *args):
1.111 + return Visitor.dispatch(self, node, *args)
1.112 +
1.113 + def visitGlobal(self, global_):
1.114 + for name in global_.names:
1.115 + self.namespace.make_global(name)
1.116 + return global_
1.117 +
1.118 + def visitLoadName(self, loadname):
1.119 + scope = self.namespace.find_for_load(loadname.name)
1.120 + if scope == "structure":
1.121 + result = self.dispatch(LoadAttr(expr=LoadRef(ref=self.namespace.structure), name=loadname.name))
1.122 + elif scope == "global":
1.123 + result = self.dispatch(LoadGlobal(name=loadname.name))
1.124 + else:
1.125 + result = loadname
1.126 + return result
1.127 +
1.128 + def visitStoreName(self, storename):
1.129 + scope = self.namespace.find_for_store(storename.name)
1.130 + if scope == "structure":
1.131 + return self.dispatch(StoreAttr(lvalue=LoadRef(ref=self.namespace.structure), name=storename.name, expr=storename.expr))
1.132 + elif scope == "global":
1.133 + return self.dispatch(StoreGlobal(name=storename.name, expr=storename.expr))
1.134 + else:
1.135 + storename.expr = self.dispatch(storename.expr)
1.136 + self.namespace.store(storename.name)
1.137 + return storename
1.138 +
1.139 +# vim: tabstop=4 expandtab shiftwidth=4