# HG changeset patch # User paulb@localhost.localdomain # Date 1175442200 -7200 # Node ID c8616d31e76cadc16b43c41fec94d02fccf21717 # Parent c7030168ba635de404514c1cfb6fb59d992f6ada Made the recording of return types and exceptions on function nodes annotation operations, fixing a lack of analysis on recursive functions. Changed the handling of constants so that Constant objects are not loaded as references - instead, instances are created dynamically. Changed the __atomic__ attributes in the built-in classes to use the "object" name already defined, thus avoiding issues with the initialisation order of built-in classes. Fixed a docstring in the simplified module. diff -r c7030168ba63 -r c8616d31e76c annotate.py --- a/annotate.py Sun Apr 01 01:24:50 2007 +0200 +++ b/annotate.py Sun Apr 01 17:43:20 2007 +0200 @@ -70,19 +70,19 @@ def __init__(self): self.count = 0 - def init(self, node): + def init(self, node, attr="types"): "Initialise a 'node' for annotation." - if not hasattr(node, "types"): - node.types = [] + if not hasattr(node, attr): + setattr(node, attr, []) - def annotate(self, node, types): + def annotate(self, node, types, attr="types"): "Annotate the given 'node' with the given 'types'." - self.init(node) - self.combine(node.types, types) + self.init(node, attr) + self.combine(getattr(node, attr), types) def combine(self, target, types): @@ -164,11 +164,6 @@ self.namespace = None self.module = module - # Give constants their own namespace. - - for value, constant in module.simplifier.constants.items(): - constant.namespace = Namespace() - # Process the module, supplying builtins if possible. self.builtins = builtins @@ -276,10 +271,8 @@ "Extract results from the namespace." result.namespace = self.namespace - if hasattr(result, "raises"): - combine(result.raises, self.namespace.raises) - if hasattr(result, "returns"): - combine(result.returns, self.namespace.returns) + self.system.annotate(result, self.namespace.raises, "raises") + self.system.annotate(result, self.namespace.returns, "returns") if hasattr(result, "return_locals"): combine(result.return_locals, self.namespace.return_locals) @@ -1333,37 +1326,19 @@ # NOTE: Constant not added to table. - constant = Constant( - instance=instance, - name=repr(arg), value=arg, namespace=Namespace() - ) - #constant.namespace.store("__class__", self.get_builtin_instances(invocation, constant.typename)) + constant = Constant(name=repr(arg), value=arg) code += [ StoreTemp( instance=instance, - expr=LoadRef( + expr=InvokeFunction( instance=instance, - ref=constant + expr=LoadName( + instance=instance, + name=constant.typename + ) ), index="const" ), - StoreAttr( - instance=instance, - lvalue=LoadTemp( - instance=instance, - index="const" - ), - name="__class__", - expr=LoadAttr( - instance=instance, - expr=LoadRef( - instance=instance, - ref=self.builtins - ), - name=constant.typename, - nstype="module", - ) - ), InvokeFunction( invocation.original, instance=instance, diff -r c7030168ba63 -r c8616d31e76c lib/builtins.py --- a/lib/builtins.py Sun Apr 01 01:24:50 2007 +0200 +++ b/lib/builtins.py Sun Apr 01 17:43:20 2007 +0200 @@ -31,7 +31,7 @@ return self.__add__(other) class bool: - __atomic__ = 1 + __atomic__ = object def __bool__(self): return self @@ -72,7 +72,7 @@ pass class float: - __atomic__ = 1 + __atomic__ = object def __init__(self, number_or_string=None): pass @@ -290,7 +290,7 @@ return self != 0 class int: - __atomic__ = 1 + __atomic__ = object def __init__(self, number_or_string=None): pass @@ -526,7 +526,7 @@ return bool() class long: - __atomic__ = 1 + __atomic__ = object def __init__(self, number_or_string=None): pass @@ -688,7 +688,7 @@ return self != 0 class none: - __atomic__ = 1 + __atomic__ = object def __bool__(self): return False @@ -707,7 +707,7 @@ self.step = step class str: - __atomic__ = 1 + __atomic__ = object def __init__(self, x=None): x.__str__() @@ -887,22 +887,22 @@ pass class AssertionError(Exception): - __atomic__ = 1 + __atomic__ = object class AttributeError(Exception): - __atomic__ = 1 + __atomic__ = object class IndexError(Exception): - __atomic__ = 1 + __atomic__ = object class StopIteration(Exception): - __atomic__ = 1 + __atomic__ = object class TypeError(Exception): - __atomic__ = 1 + __atomic__ = object class NotImplementedType: - __atomic__ = 1 + __atomic__ = object # General functions. diff -r c7030168ba63 -r c8616d31e76c simplified.py --- a/simplified.py Sun Apr 01 01:24:50 2007 +0200 +++ b/simplified.py Sun Apr 01 17:43:20 2007 +0200 @@ -639,7 +639,9 @@ A Python class which provides multiple instances for different versions of methods. In order to avoid unbounded instance production (since new instances cause new copies of methods which in turn would cause new - instances), + instances), a relations dictionary is maintained which attempts to map + "requesting instances" to existing instances, suggesting such instances in + preference to new ones. """ def __init__(self, *args, **kw): diff -r c7030168ba63 -r c8616d31e76c simplify.py --- a/simplify.py Sun Apr 01 01:24:50 2007 +0200 +++ b/simplify.py Sun Apr 01 17:43:20 2007 +0200 @@ -107,27 +107,7 @@ """ result = self.module = Module(module, 1, name=name) - module_code = self.dispatch(module.node) - - # NOTE: Constant initialisation necessary for annotation but perhaps - # NOTE: redundant in the program. - - init_code = [] - for value, constant in self.constants.items(): - init_code.append( - StoreAttr( - lvalue=LoadRef(ref=constant), - name="__class__", - expr=LoadName(name=constant.typename) - ) - ) - - # NOTE: Hack to ensure correct initialisation of constants. - - if self.builtins: - result.code = module_code + init_code - else: - result.code = init_code + module_code + result.code = self.dispatch(module.node) return result # Node transformations. @@ -760,7 +740,7 @@ key = "%s-%s" % (const.value.__class__.__name__, const.value) if not self.constants.has_key(key): self.constants[key] = Constant(name=repr(const.value), value=const.value) - result = LoadRef(const, 1, ref=self.constants[key]) + result = InvokeFunction(const, 1, expr=LoadName(name=self.constants[key].typename)) return result def visitContinue(self, continue_): @@ -768,10 +748,10 @@ return result def visitDict(self, dict): - result = InvokeFunction(dict, 1, expr=LoadName(name="dict"), star=None, dstar=None) + result = InvokeFunction(dict, 1, expr=LoadName(name="dict")) args = [] for key, value in dict.items: - tuple = InvokeFunction(dict, expr=LoadName(name="tuple"), star=None, dstar=None) + tuple = InvokeFunction(dict, expr=LoadName(name="tuple")) tuple.set_args([self.dispatch(key), self.dispatch(value)]) args.append(tuple) result.set_args(args) @@ -810,7 +790,7 @@ def _visitFor(self, node, body_stmt, else_=None): - subprogram = Subprogram(name=None, module=self.module, internal=1, returns_value=0, params=[], star=None, dstar=None) + subprogram = Subprogram(name=None, module=self.module, internal=1, returns_value=0, params=[]) self.current_subprograms.append(subprogram) # Always return from conditional sections/subprograms. @@ -1912,7 +1892,7 @@ return result def _visitBuiltin(self, builtin, name): - result = InvokeFunction(builtin, 1, expr=LoadName(name=name), args=self.dispatches(builtin.nodes), star=None, dstar=None) + result = InvokeFunction(builtin, 1, expr=LoadName(name=name), args=self.dispatches(builtin.nodes)) return result def _visitUnary(self, unary, name):