1.1 --- a/annotate.py Sat Aug 12 01:42:41 2006 +0200
1.2 +++ b/annotate.py Sat Aug 12 01:46:35 2006 +0200
1.3 @@ -198,7 +198,20 @@
1.4
1.5 self.visitor = self
1.6
1.7 - def process_all(self, visitor, builtins_visitor=None):
1.8 + def process(self, visitor, builtins_visitor=None):
1.9 +
1.10 + """
1.11 + Process the resources of the given 'visitor', using the optional
1.12 + 'builtins_visitor' to access built-in classes and functions.
1.13 + """
1.14 +
1.15 + self.subprograms = []
1.16 + self.current_subprograms = []
1.17 + self.current_namespaces = []
1.18 + self.current_returns = []
1.19 + self.current_return_locals = []
1.20 + self.current_temps = []
1.21 + self.current_types = []
1.22
1.23 # Give constants their own namespace.
1.24
1.25 @@ -207,12 +220,16 @@
1.26
1.27 # Process the module, supplying builtins if possible.
1.28
1.29 + self.global_namespace = Namespace()
1.30 +
1.31 if builtins_visitor is not None:
1.32 - return self.process(visitor.result, builtins=builtins_visitor.result.namespace)
1.33 + self.builtins_namespace = builtins_visitor.result.namespace
1.34 else:
1.35 - return self.process(visitor.result)
1.36 + self.builtins_namespace = self.global_namespace
1.37
1.38 - def process(self, node, locals=None, globals=None, builtins=None):
1.39 + return self.process_node(visitor.result)
1.40 +
1.41 + def process_node(self, node, locals=None):
1.42
1.43 """
1.44 Process a subprogram or module 'node', indicating any initial 'locals'.
1.45 @@ -220,12 +237,19 @@
1.46 mutate nodes in the original program.
1.47 """
1.48
1.49 - # Determine the global namespace.
1.50 - # NOTE: Improve this.
1.51 + if locals:
1.52 + self.namespace = locals
1.53 + else:
1.54 + self.namespace = self.global_namespace
1.55 +
1.56 + # Record the current subprogram and namespace.
1.57
1.58 - self.global_namespace = globals or Namespace()
1.59 - self.builtins_namespace = builtins or self.global_namespace
1.60 - self.namespace = locals or self.global_namespace
1.61 + self.current_subprograms.append(node)
1.62 + self.current_namespaces.append(self.namespace)
1.63 + self.current_returns.append([])
1.64 + self.current_return_locals.append([])
1.65 + self.current_temps.append({})
1.66 + self.current_types.append([])
1.67
1.68 # Record the namespace on the node.
1.69 # NOTE: This may eventually be a specialisation node.
1.70 @@ -234,10 +258,10 @@
1.71
1.72 # Remember return values and locals snapshots.
1.73
1.74 - self.returns = []
1.75 self.return_locals = []
1.76 - self.types = None
1.77 - self.temp = {}
1.78 + self.returns = self.current_returns[-1]
1.79 + self.temp = self.current_temps[-1]
1.80 + self.types = self.current_types[-1]
1.81
1.82 # Add namespace details to any structure involved.
1.83
1.84 @@ -256,6 +280,31 @@
1.85 # Dispatch to the code itself.
1.86
1.87 result = self.dispatch(node)
1.88 +
1.89 + # Restore the previous subprogram and namespace.
1.90 +
1.91 + self.current_namespaces.pop()
1.92 + if self.current_namespaces:
1.93 + self.namespace = self.current_namespaces[-1]
1.94 +
1.95 + self.current_types.pop()
1.96 + if self.current_types:
1.97 + self.types = self.current_types[-1]
1.98 +
1.99 + self.current_temps.pop()
1.100 + if self.current_temps:
1.101 + self.temp = self.current_temps[-1]
1.102 +
1.103 + self.last_returns = self.current_returns.pop()
1.104 + if self.current_returns:
1.105 + self.returns = self.current_returns[-1]
1.106 +
1.107 + self.returned_locals = self.current_return_locals.pop()
1.108 + if self.current_return_locals:
1.109 + self.return_locals = self.current_return_locals[-1]
1.110 +
1.111 + self.current_subprograms.pop()
1.112 +
1.113 return result
1.114
1.115 def annotate(self, node):
1.116 @@ -315,13 +364,15 @@
1.117 return storename
1.118
1.119 def visitLoadGlobal(self, loadglobal):
1.120 - try:
1.121 - self.types = self.global_namespace.load(loadglobal.name)
1.122 - except KeyError:
1.123 - self.types = self.builtins_namespace.load(loadglobal.name)
1.124 + self.types = self.global_namespace.load(loadglobal.name)
1.125 self.annotate(loadglobal)
1.126 return loadglobal
1.127
1.128 + def visitLoadBuiltin(self, loadbuiltin):
1.129 + self.types = self.builtins_namespace.load(loadbuiltin.name)
1.130 + self.annotate(loadbuiltin)
1.131 + return loadbuiltin
1.132 +
1.133 def visitStoreGlobal(self, storeglobal):
1.134 storeglobal.expr = self.dispatch(storeglobal.expr)
1.135 self.global_namespace.merge(storeglobal.name, self.types)
1.136 @@ -520,18 +571,16 @@
1.137
1.138 # Process the subprogram.
1.139
1.140 - annotator = Annotator()
1.141 - annotator.process(subprogram, namespace, self.global_namespace, self.builtins_namespace)
1.142 + self.process_node(subprogram, namespace)
1.143
1.144 - # NOTE: Annotate the node with invocation details.
1.145 - # NOTE: This should really be as part of a table of alternatives.
1.146 + # NOTE: Improve and verify this.
1.147
1.148 if getattr(subprogram, "returns_value", 0):
1.149 - self.types = annotator.returns
1.150 + self.types = self.last_returns
1.151 self.annotate(invoke)
1.152
1.153 if getattr(invoke, "same_frame", 0):
1.154 - for locals in annotator.return_locals:
1.155 + for locals in self.returned_locals:
1.156 self.namespace.merge_namespace(locals)
1.157
1.158 # Remember the state of the system.