[pypy-commit] pypy py3k: merge default
pjenvey
noreply at buildbot.pypy.org
Sat Oct 13 02:09:56 CEST 2012
Author: Philip Jenvey <pjenvey at underboss.org>
Branch: py3k
Changeset: r58091:4bf82358629c
Date: 2012-10-12 17:04 -0700
http://bitbucket.org/pypy/pypy/changeset/4bf82358629c/
Log: merge default
diff too long, truncating to 2000 out of 29662 lines
diff --git a/pypy/annotation/annrpython.py b/pypy/annotation/annrpython.py
--- a/pypy/annotation/annrpython.py
+++ b/pypy/annotation/annrpython.py
@@ -1,9 +1,8 @@
-import sys
import types
-from pypy.tool.ansi_print import ansi_log, raise_nicer_exception
+from pypy.tool.ansi_print import ansi_log
from pypy.tool.pairtype import pair
from pypy.tool.error import (format_blocked_annotation_error,
- format_someobject_error, AnnotatorError)
+ AnnotatorError, gather_error, ErrorWrapper)
from pypy.objspace.flow.model import (Variable, Constant, FunctionGraph,
c_last_exception, checkgraph)
from pypy.translator import simplify, transform
@@ -38,22 +37,9 @@
self.links_followed = {} # set of links that have ever been followed
self.notify = {} # {block: {positions-to-reflow-from-when-done}}
self.fixed_graphs = {} # set of graphs not to annotate again
- self.blocked_blocks = {} # set of {blocked_block: graph}
- # --- the following information is recorded for debugging only ---
- # --- and only if annotation.model.DEBUG is kept to True
- self.why_not_annotated = {} # {block: (exc_type, exc_value, traceback)}
- # records the location of BlockedInference
- # exceptions that blocked some blocks.
+ self.blocked_blocks = {} # set of {blocked_block: (graph, index)}
+ # --- the following information is recorded for debugging ---
self.blocked_graphs = {} # set of graphs that have blocked blocks
- self.bindingshistory = {}# map Variables to lists of SomeValues
- self.binding_caused_by = {} # map Variables to position_keys
- # records the caller position that caused bindings of inputargs
- # to be updated
- self.binding_cause_history = {} # map Variables to lists of positions
- # history of binding_caused_by, kept in sync with
- # bindingshistory
- self.reflowcounter = {}
- self.return_bindings = {} # map return Variables to their graphs
# --- end of debugging information ---
self.frozen = False
if policy is None:
@@ -77,10 +63,6 @@
ret[key] = {}
return ret
- def _register_returnvar(self, flowgraph):
- if annmodel.DEBUG:
- self.return_bindings[flowgraph.getreturnvar()] = flowgraph
-
#___ convenience high-level interface __________________
def build_types(self, function, input_arg_types, complete_now=True,
@@ -182,10 +164,9 @@
#___ medium-level interface ____________________________
def addpendinggraph(self, flowgraph, inputcells):
- self._register_returnvar(flowgraph)
self.addpendingblock(flowgraph, flowgraph.startblock, inputcells)
- def addpendingblock(self, graph, block, cells, called_from_graph=None):
+ def addpendingblock(self, graph, block, cells):
"""Register an entry point into block with the given input cells."""
if graph in self.fixed_graphs:
# special case for annotating/rtyping in several phases: calling
@@ -200,9 +181,9 @@
for a in cells:
assert isinstance(a, annmodel.SomeObject)
if block not in self.annotated:
- self.bindinputargs(graph, block, cells, called_from_graph)
+ self.bindinputargs(graph, block, cells)
else:
- self.mergeinputargs(graph, block, cells, called_from_graph)
+ self.mergeinputargs(graph, block, cells)
if not self.annotated[block]:
self.pendingblocks[block] = graph
@@ -211,8 +192,6 @@
while True:
while self.pendingblocks:
block, graph = self.pendingblocks.popitem()
- if annmodel.DEBUG:
- self.flowin_block = block # we need to keep track of block
self.processblock(graph, block)
self.policy.no_more_blocks_to_annotate(self)
if not self.pendingblocks:
@@ -263,60 +242,14 @@
def typeannotation(self, t):
return signature.annotation(t, self.bookkeeper)
- def ondegenerated(self, what, s_value, where=None, called_from_graph=None):
- if self.policy.allow_someobjects:
- return
- # is the function itself tagged with allow_someobjects?
- position_key = where or getattr(self.bookkeeper, 'position_key', None)
- if position_key is not None:
- graph, block, i = position_key
- try:
- if graph.func.allow_someobjects:
- return
- except AttributeError:
- pass
-
- msgstr = format_someobject_error(self, position_key, what, s_value,
- called_from_graph,
- self.bindings.get(what, "(none)"))
-
- raise AnnotatorError(msgstr)
-
- def setbinding(self, arg, s_value, called_from_graph=None, where=None):
+ def setbinding(self, arg, s_value):
if arg in self.bindings:
assert s_value.contains(self.bindings[arg])
- # for debugging purposes, record the history of bindings that
- # have been given to this variable
- if annmodel.DEBUG:
- history = self.bindingshistory.setdefault(arg, [])
- history.append(self.bindings[arg])
- cause_history = self.binding_cause_history.setdefault(arg, [])
- cause_history.append(self.binding_caused_by[arg])
-
- degenerated = annmodel.isdegenerated(s_value)
-
- if degenerated:
- self.ondegenerated(arg, s_value, where=where,
- called_from_graph=called_from_graph)
-
self.bindings[arg] = s_value
- if annmodel.DEBUG:
- if arg in self.return_bindings:
- log.event("%s -> %s" %
- (self.whereami((self.return_bindings[arg], None, None)),
- s_value))
-
- if arg in self.return_bindings and degenerated:
- self.warning("result degenerated to SomeObject",
- (self.return_bindings[arg],None, None))
-
- self.binding_caused_by[arg] = called_from_graph
def transfer_binding(self, v_target, v_source):
assert v_source in self.bindings
self.bindings[v_target] = self.bindings[v_source]
- if annmodel.DEBUG:
- self.binding_caused_by[v_target] = None
def warning(self, msg, pos=None):
if pos is None:
@@ -332,14 +265,11 @@
#___ interface for annotator.bookkeeper _______
- def recursivecall(self, graph, whence, inputcells): # whence = position_key|callback taking the annotator, graph
+ def recursivecall(self, graph, whence, inputcells):
if isinstance(whence, tuple):
- parent_graph, parent_block, parent_index = position_key = whence
+ parent_graph, parent_block, parent_index = whence
tag = parent_block, parent_index
self.translator.update_call_graph(parent_graph, graph, tag)
- else:
- position_key = None
- self._register_returnvar(graph)
# self.notify[graph.returnblock] is a dictionary of call
# points to this func which triggers a reflow whenever the
# return block of this graph has been analysed.
@@ -353,8 +283,7 @@
callpositions[callback] = True
# generalize the function's input arguments
- self.addpendingblock(graph, graph.startblock, inputcells,
- position_key)
+ self.addpendingblock(graph, graph.startblock, inputcells)
# get the (current) return value
v = graph.getreturnvar()
@@ -404,9 +333,6 @@
# input variables).
#print '* processblock', block, cells
- if annmodel.DEBUG:
- self.reflowcounter.setdefault(block, 0)
- self.reflowcounter[block] += 1
self.annotated[block] = graph
if block in self.blocked_blocks:
del self.blocked_blocks[block]
@@ -414,7 +340,7 @@
self.flowin(graph, block)
except BlockedInference, e:
self.annotated[block] = False # failed, hopefully temporarily
- self.blocked_blocks[block] = graph
+ self.blocked_blocks[block] = (graph, e.opindex)
except Exception, e:
# hack for debug tools only
if not hasattr(e, '__annotator_block'):
@@ -433,25 +359,24 @@
self.pendingblocks[block] = graph
assert block in self.annotated
self.annotated[block] = False # must re-flow
- self.blocked_blocks[block] = graph
+ self.blocked_blocks[block] = (graph, None)
- def bindinputargs(self, graph, block, inputcells, called_from_graph=None):
+ def bindinputargs(self, graph, block, inputcells):
# Create the initial bindings for the input args of a block.
assert len(block.inputargs) == len(inputcells)
- where = (graph, block, None)
for a, cell in zip(block.inputargs, inputcells):
- self.setbinding(a, cell, called_from_graph, where=where)
+ self.setbinding(a, cell)
self.annotated[block] = False # must flowin.
- self.blocked_blocks[block] = graph
+ self.blocked_blocks[block] = (graph, None)
- def mergeinputargs(self, graph, block, inputcells, called_from_graph=None):
+ def mergeinputargs(self, graph, block, inputcells):
# Merge the new 'cells' with each of the block's existing input
# variables.
oldcells = [self.binding(a) for a in block.inputargs]
unions = [annmodel.unionof(c1,c2) for c1, c2 in zip(oldcells,inputcells)]
# if the merged cells changed, we must redo the analysis
if unions != oldcells:
- self.bindinputargs(graph, block, unions, called_from_graph)
+ self.bindinputargs(graph, block, unions)
def whereami(self, position_key):
graph, block, i = position_key
@@ -471,14 +396,11 @@
for i in range(len(block.operations)):
try:
self.bookkeeper.enter((graph, block, i))
- self.consider_op(block.operations[i])
+ self.consider_op(block, i)
finally:
self.bookkeeper.leave()
except BlockedInference, e:
- if annmodel.DEBUG:
- self.why_not_annotated[block] = sys.exc_info()
-
if (e.op is block.operations[-1] and
block.exitswitch == c_last_exception):
# this is the case where the last operation of the block will
@@ -562,8 +484,7 @@
and issubclass(link.exitcase, py.builtin.BaseException):
assert last_exception_var and last_exc_value_var
last_exc_value_object = self.bookkeeper.valueoftype(link.exitcase)
- last_exception_object = annmodel.SomeObject()
- last_exception_object.knowntype = type
+ last_exception_object = annmodel.SomeType()
if isinstance(last_exception_var, Constant):
last_exception_object.const = last_exception_var.value
last_exception_object.is_type_of = [last_exc_value_var]
@@ -573,8 +494,7 @@
if isinstance(last_exc_value_var, Variable):
self.setbinding(last_exc_value_var, last_exc_value_object)
- last_exception_object = annmodel.SomeObject()
- last_exception_object.knowntype = type
+ last_exception_object = annmodel.SomeType()
if isinstance(last_exception_var, Constant):
last_exception_object.const = last_exception_var.value
#if link.exitcase is Exception:
@@ -610,9 +530,8 @@
for v in cell.is_type_of:
new_vs = renaming.get(v,[])
renamed_is_type_of += new_vs
- newcell = annmodel.SomeObject()
- if cell.knowntype == type:
- newcell.knowntype = type
+ assert cell.knowntype is type
+ newcell = annmodel.SomeType()
if cell.is_constant():
newcell.const = cell.const
cell = newcell
@@ -653,7 +572,8 @@
#___ creating the annotations based on operations ______
- def consider_op(self, op):
+ def consider_op(self, block, opindex):
+ op = block.operations[opindex]
argcells = [self.binding(a) for a in op.args]
consider_meth = getattr(self,'consider_op_'+op.opname,
None)
@@ -668,16 +588,18 @@
# boom -- in the assert of setbinding()
for arg in argcells:
if isinstance(arg, annmodel.SomeImpossibleValue):
- raise BlockedInference(self, op)
+ raise BlockedInference(self, op, opindex)
try:
resultcell = consider_meth(*argcells)
- except Exception:
+ except Exception, e:
graph = self.bookkeeper.position_key[0]
- raise_nicer_exception(op, str(graph))
+ e.args = e.args + (
+ ErrorWrapper(gather_error(self, graph, block, opindex)),)
+ raise
if resultcell is None:
resultcell = self.noreturnvalue(op)
elif resultcell == annmodel.s_ImpossibleValue:
- raise BlockedInference(self, op) # the operation cannot succeed
+ raise BlockedInference(self, op, opindex) # the operation cannot succeed
assert isinstance(resultcell, annmodel.SomeObject)
assert isinstance(op.result, Variable)
self.setbinding(op.result, resultcell) # bind resultcell to op.result
@@ -728,13 +650,14 @@
"""This exception signals the type inference engine that the situation
is currently blocked, and that it should try to progress elsewhere."""
- def __init__(self, annotator, op):
+ def __init__(self, annotator, op, opindex):
self.annotator = annotator
try:
self.break_at = annotator.bookkeeper.position_key
except AttributeError:
self.break_at = None
self.op = op
+ self.opindex = opindex
def __repr__(self):
if not self.break_at:
diff --git a/pypy/annotation/binaryop.py b/pypy/annotation/binaryop.py
--- a/pypy/annotation/binaryop.py
+++ b/pypy/annotation/binaryop.py
@@ -13,9 +13,9 @@
from pypy.annotation.model import SomePBC, SomeFloat, s_None
from pypy.annotation.model import SomeExternalObject, SomeWeakRef
from pypy.annotation.model import SomeAddress, SomeTypedAddressAccess
-from pypy.annotation.model import SomeSingleFloat, SomeLongFloat
+from pypy.annotation.model import SomeSingleFloat, SomeLongFloat, SomeType
from pypy.annotation.model import unionof, UnionError, missing_operation
-from pypy.annotation.model import isdegenerated, TLS
+from pypy.annotation.model import TLS
from pypy.annotation.model import read_can_only_throw
from pypy.annotation.model import add_knowntypedata, merge_knowntypedata
from pypy.annotation.model import SomeGenericCallable
@@ -29,15 +29,6 @@
def immutablevalue(x):
return getbookkeeper().immutablevalue(x)
-def unioncheck(*somevalues):
- s_value = unionof(*somevalues)
- if isdegenerated(s_value):
- if not getattr(TLS, 'no_side_effects_in_union', 0):
- bookkeeper = getbookkeeper()
- if bookkeeper is not None:
- bookkeeper.ondegenerated('union', s_value)
- return s_value
-
# XXX unify this with ObjSpace.MethodTable
BINARY_OPERATIONS = set(['add', 'sub', 'mul', 'div', 'mod',
'truediv', 'floordiv', 'divmod', 'pow',
@@ -64,35 +55,7 @@
class __extend__(pairtype(SomeObject, SomeObject)):
def union((obj1, obj2)):
- if obj1 == obj2:
- return obj1
- else:
- result = SomeObject()
- if obj1.knowntype == obj2.knowntype and obj1.knowntype != object:
- result.knowntype = obj1.knowntype
- is_type_of1 = getattr(obj1, 'is_type_of', None)
- is_type_of2 = getattr(obj2, 'is_type_of', None)
- if obj1.is_immutable_constant() and obj2.is_immutable_constant() and obj1.const == obj2.const:
- result.const = obj1.const
- is_type_of = {}
- if is_type_of1:
- for v in is_type_of1:
- is_type_of[v] = True
- if is_type_of2:
- for v in is_type_of2:
- is_type_of[v] = True
- if is_type_of:
- result.is_type_of = is_type_of.keys()
- else:
- if is_type_of1 and is_type_of1 == is_type_of2:
- result.is_type_of = is_type_of1
- # try to preserve the origin of SomeObjects
- if obj1 == result:
- result = obj1
- elif obj2 == result:
- result = obj2
- unioncheck(result)
- return result
+ raise UnionError(obj1, obj2)
# inplace_xxx ---> xxx by default
def inplace_add((obj1, obj2)): return pair(obj1, obj2).add()
@@ -238,7 +201,30 @@
getitem_idx = getitem_idx_key
getitem_key = getitem_idx_key
-
+
+
+class __extend__(pairtype(SomeType, SomeType)):
+
+ def union((obj1, obj2)):
+ result = SomeType()
+ is_type_of1 = getattr(obj1, 'is_type_of', None)
+ is_type_of2 = getattr(obj2, 'is_type_of', None)
+ if obj1.is_immutable_constant() and obj2.is_immutable_constant() and obj1.const == obj2.const:
+ result.const = obj1.const
+ is_type_of = {}
+ if is_type_of1:
+ for v in is_type_of1:
+ is_type_of[v] = True
+ if is_type_of2:
+ for v in is_type_of2:
+ is_type_of[v] = True
+ if is_type_of:
+ result.is_type_of = is_type_of.keys()
+ else:
+ if is_type_of1 and is_type_of1 == is_type_of2:
+ result.is_type_of = is_type_of1
+ return result
+
# cloning a function with identical code, for the can_only_throw attribute
def _clone(f, can_only_throw = None):
@@ -565,14 +551,30 @@
def union((tup1, tup2)):
if len(tup1.items) != len(tup2.items):
- return SomeObject()
+ raise UnionError("cannot take the union of a tuple of length %d "
+ "and a tuple of length %d" % (len(tup1.items),
+ len(tup2.items)))
else:
- unions = [unioncheck(x,y) for x,y in zip(tup1.items, tup2.items)]
+ unions = [unionof(x,y) for x,y in zip(tup1.items, tup2.items)]
return SomeTuple(items = unions)
def add((tup1, tup2)):
return SomeTuple(items = tup1.items + tup2.items)
+ def eq(tup1tup2):
+ tup1tup2.union()
+ return s_Bool
+ ne = eq
+
+ def lt((tup1, tup2)):
+ raise Exception("unsupported: (...) < (...)")
+ def le((tup1, tup2)):
+ raise Exception("unsupported: (...) <= (...)")
+ def gt((tup1, tup2)):
+ raise Exception("unsupported: (...) > (...)")
+ def ge((tup1, tup2)):
+ raise Exception("unsupported: (...) >= (...)")
+
class __extend__(pairtype(SomeDict, SomeDict)):
@@ -724,8 +726,7 @@
else:
basedef = ins1.classdef.commonbase(ins2.classdef)
if basedef is None:
- # print warning?
- return SomeObject()
+ raise UnionError(ins1, ins2)
flags = ins1.flags
if flags:
flags = flags.copy()
@@ -765,7 +766,7 @@
class __extend__(pairtype(SomeIterator, SomeIterator)):
def union((iter1, iter2)):
- s_cont = unioncheck(iter1.s_container, iter2.s_container)
+ s_cont = unionof(iter1.s_container, iter2.s_container)
if iter1.variant != iter2.variant:
raise UnionError("merging incompatible iterators variants")
return SomeIterator(s_cont, *iter1.variant)
@@ -779,7 +780,7 @@
bltn1.s_self is None or bltn2.s_self is None):
raise UnionError("cannot merge two different builtin functions "
"or methods:\n %r\n %r" % (bltn1, bltn2))
- s_self = unioncheck(bltn1.s_self, bltn2.s_self)
+ s_self = unionof(bltn1.s_self, bltn2.s_self)
return SomeBuiltin(bltn1.analyser, s_self, methodname=bltn1.methodname)
class __extend__(pairtype(SomePBC, SomePBC)):
@@ -807,7 +808,7 @@
unique_key = desc
bk = desc.bookkeeper
s_result = bk.emulate_pbc_call(unique_key, pbc, gencall.args_s)
- s_result = unioncheck(s_result, gencall.s_result)
+ s_result = unionof(s_result, gencall.s_result)
assert gencall.s_result.contains(s_result)
return gencall
diff --git a/pypy/annotation/bookkeeper.py b/pypy/annotation/bookkeeper.py
--- a/pypy/annotation/bookkeeper.py
+++ b/pypy/annotation/bookkeeper.py
@@ -10,7 +10,7 @@
SomeUnicodeCodePoint, SomeOOStaticMeth, s_None, s_ImpossibleValue, \
SomeLLADTMeth, SomeBool, SomeTuple, SomeOOClass, SomeImpossibleValue, \
SomeUnicodeString, SomeList, SomeObject, HarmlesslyBlocked, \
- SomeWeakRef, lltype_to_annotation
+ SomeWeakRef, lltype_to_annotation, SomeType
from pypy.annotation.classdef import InstanceSource, ClassDef
from pypy.annotation.listdef import ListDef, ListItem
from pypy.annotation.dictdef import DictDef
@@ -148,7 +148,6 @@
self.descs = {} # map Python objects to their XxxDesc wrappers
self.methoddescs = {} # map (funcdesc, classdef) to the MethodDesc
self.classdefs = [] # list of all ClassDefs
- self.pbctypes = {}
self.seen_mutable = {}
self.listdefs = {} # map position_keys to ListDefs
self.dictdefs = {} # map position_keys to DictDefs
@@ -167,9 +166,6 @@
self.stats = Stats(self)
- # used in SomeObject.__new__ for keeping debugging info
- self._isomeobject_coming_from = identity_dict()
-
delayed_imports()
def count(self, category, *args):
@@ -275,8 +271,7 @@
"""Get the ClassDef associated with the given user cls.
Avoid using this! It breaks for classes that must be specialized.
"""
- if cls is object:
- return None
+ assert cls is not object
desc = self.getdesc(cls)
return desc.getuniqueclassdef()
@@ -325,8 +320,6 @@
if hasattr(x, 'im_self') and x.im_self is None:
x = x.im_func
assert not hasattr(x, 'im_self')
- if x is sys: # special case constant sys to someobject
- return SomeObject()
tp = type(x)
if issubclass(tp, Symbolic): # symbolic constants support
result = x.annotation()
@@ -445,6 +438,12 @@
result = SomeOOInstance(ootype.typeOf(x))
elif isinstance(x, (ootype._object)):
result = SomeOOObject()
+ elif tp is type:
+ if (x is type(None) or # add cases here if needed
+ x.__module__ == 'pypy.rpython.lltypesystem.lltype'):
+ result = SomeType()
+ else:
+ result = SomePBC([self.getdesc(x)])
elif callable(x):
if hasattr(x, 'im_self') and hasattr(x, 'im_func'):
# on top of PyPy, for cases like 'l.append' where 'l' is a
@@ -455,20 +454,13 @@
# for cases like 'l.append' where 'l' is a global constant list
s_self = self.immutablevalue(x.__self__, need_const)
result = s_self.find_method(x.__name__)
- if result is None:
- result = SomeObject()
+ assert result is not None
else:
result = None
if result is None:
- if (self.annotator.policy.allow_someobjects
- and getattr(x, '__module__', None) == '__builtin__'
- # XXX note that the print support functions are __builtin__
- and tp not in (types.FunctionType, types.MethodType)):
- result = SomeObject()
- result.knowntype = tp # at least for types this needs to be correct
- else:
- result = SomePBC([self.getdesc(x)])
- elif hasattr(x, '_freeze_') and x._freeze_():
+ result = SomePBC([self.getdesc(x)])
+ elif hasattr(x, '_freeze_'):
+ assert x._freeze_() is True
# user-defined classes can define a method _freeze_(), which
# is called when a prebuilt instance is found. If the method
# returns True, the instance is considered immutable and becomes
@@ -476,16 +468,18 @@
result = SomePBC([self.getdesc(x)])
elif hasattr(x, '__class__') \
and x.__class__.__module__ != '__builtin__':
+ if hasattr(x, '_cleanup_'):
+ x._cleanup_()
self.see_mutable(x)
result = SomeInstance(self.getuniqueclassdef(x.__class__))
elif x is None:
return s_None
else:
- result = SomeObject()
+ raise Exception("Don't know how to represent %r" % (x,))
if need_const:
result.const = x
return result
-
+
def getdesc(self, pyobj):
# get the XxxDesc wrapper for the given Python object, which must be
# one of:
@@ -509,8 +503,10 @@
elif isinstance(pyobj, types.MethodType):
if pyobj.im_self is None: # unbound
return self.getdesc(pyobj.im_func)
- elif (hasattr(pyobj.im_self, '_freeze_') and
- pyobj.im_self._freeze_()): # method of frozen
+ if hasattr(pyobj.im_self, '_cleanup_'):
+ pyobj.im_self._cleanup_()
+ if hasattr(pyobj.im_self, '_freeze_'): # method of frozen
+ assert pyobj.im_self._freeze_() is True
result = description.MethodOfFrozenDesc(self,
self.getdesc(pyobj.im_func), # funcdesc
self.getdesc(pyobj.im_self)) # frozendesc
@@ -529,9 +525,9 @@
name)
else:
# must be a frozen pre-built constant, but let's check
- try:
- assert pyobj._freeze_()
- except AttributeError:
+ if hasattr(pyobj, '_freeze_'):
+ assert pyobj._freeze_() is True
+ else:
if hasattr(pyobj, '__call__'):
msg = "object with a __call__ is not RPython"
else:
@@ -551,11 +547,7 @@
return False
def getfrozen(self, pyobj):
- result = description.FrozenDesc(self, pyobj)
- cls = result.knowntype
- if cls not in self.pbctypes:
- self.pbctypes[cls] = True
- return result
+ return description.FrozenDesc(self, pyobj)
def getmethoddesc(self, funcdesc, originclassdef, selfclassdef, name,
flags={}):
diff --git a/pypy/annotation/builtin.py b/pypy/annotation/builtin.py
--- a/pypy/annotation/builtin.py
+++ b/pypy/annotation/builtin.py
@@ -150,7 +150,7 @@
def builtin_isinstance(s_obj, s_type, variables=None):
- r = SomeBool()
+ r = SomeBool()
if s_type.is_constant():
typ = s_type.const
if issubclass(typ, pypy.rlib.rarithmetic.base_int):
@@ -158,18 +158,12 @@
else:
if typ == long:
getbookkeeper().warning("isinstance(., long) is not RPython")
- if s_obj.is_constant():
- r.const = isinstance(s_obj.const, long)
- else:
- if type(s_obj) is not SomeObject: # only SomeObjects could be longs
- # type(s_obj) < SomeObject -> SomeBool(False)
- # type(s_obj) == SomeObject -> SomeBool()
- r.const = False
+ r.const = False
return r
-
+
assert not issubclass(typ, (int, long)) or typ in (bool, int, long), (
"for integers only isinstance(.,int|r_uint) are supported")
-
+
if s_obj.is_constant():
r.const = isinstance(s_obj.const, typ)
elif our_issubclass(s_obj.knowntype, typ):
@@ -195,8 +189,8 @@
for variable in variables:
assert bk.annotator.binding(variable) == s_obj
r.knowntypedata = {}
- if (not isinstance(s_type, SomeBuiltin)
- or typ.__module__ == '__builtin__'):
+
+ if not hasattr(typ, '_freeze_') and isinstance(s_type, SomePBC):
add_knowntypedata(r.knowntypedata, True, variables, bk.valueoftype(typ))
return r
diff --git a/pypy/annotation/classdef.py b/pypy/annotation/classdef.py
--- a/pypy/annotation/classdef.py
+++ b/pypy/annotation/classdef.py
@@ -2,8 +2,7 @@
Type inference for user-defined classes.
"""
from pypy.annotation.model import SomePBC, s_ImpossibleValue, unionof
-from pypy.annotation.model import SomeInteger, isdegenerated, SomeTuple,\
- SomeString
+from pypy.annotation.model import SomeInteger, SomeTuple, SomeString
from pypy.annotation import description
@@ -79,11 +78,7 @@
if source.instance_level:
# a prebuilt instance source forces readonly=False, see above
self.modified(classdef)
- s_new_value = unionof(self.s_value, s_value)
- if isdegenerated(s_new_value):
- self.bookkeeper.ondegenerated("source %r attr %s" % (source, self.name),
- s_new_value)
-
+ s_new_value = unionof(self.s_value, s_value) # XXX "source %r attr %s" % (source, self.name),
self.s_value = s_new_value
def getvalue(self):
@@ -92,11 +87,7 @@
def merge(self, other, classdef='?'):
assert self.name == other.name
- s_new_value = unionof(self.s_value, other.s_value)
- if isdegenerated(s_new_value):
- what = "%s attr %s" % (classdef, self.name)
- self.bookkeeper.ondegenerated(what, s_new_value)
-
+ s_new_value = unionof(self.s_value, other.s_value) # XXX "%s attr %s" % (classdef, self.name)
self.s_value = s_new_value
if not other.readonly:
self.modified(classdef)
diff --git a/pypy/annotation/description.py b/pypy/annotation/description.py
--- a/pypy/annotation/description.py
+++ b/pypy/annotation/description.py
@@ -247,13 +247,16 @@
defs_s = []
if graph is None:
signature = self.signature
- defaults = self.defaults
+ defaults = self.defaults
else:
signature = graph.signature
- defaults = graph.defaults
+ defaults = graph.defaults
if defaults:
for x in defaults:
- defs_s.append(self.bookkeeper.immutablevalue(x))
+ if x is NODEFAULT:
+ defs_s.append(None)
+ else:
+ defs_s.append(self.bookkeeper.immutablevalue(x))
try:
inputcells = args.match_signature(signature, defs_s)
except ArgErr, e:
diff --git a/pypy/annotation/dictdef.py b/pypy/annotation/dictdef.py
--- a/pypy/annotation/dictdef.py
+++ b/pypy/annotation/dictdef.py
@@ -119,13 +119,9 @@
self.dictvalue is other.dictvalue)
def union(self, other):
- if (self.same_as(MOST_GENERAL_DICTDEF) or
- other.same_as(MOST_GENERAL_DICTDEF)):
- return MOST_GENERAL_DICTDEF # without merging
- else:
- self.dictkey.merge(other.dictkey)
- self.dictvalue.merge(other.dictvalue)
- return self
+ self.dictkey.merge(other.dictkey)
+ self.dictvalue.merge(other.dictvalue)
+ return self
def generalize_key(self, s_key):
self.dictkey.generalize(s_key)
@@ -143,6 +139,3 @@
def __repr__(self):
return '<{%r: %r}>' % (self.dictkey.s_value, self.dictvalue.s_value)
-
-
-MOST_GENERAL_DICTDEF = DictDef(None, SomeObject(), SomeObject())
diff --git a/pypy/annotation/listdef.py b/pypy/annotation/listdef.py
--- a/pypy/annotation/listdef.py
+++ b/pypy/annotation/listdef.py
@@ -1,6 +1,6 @@
from pypy.annotation.model import SomeObject, s_ImpossibleValue
from pypy.annotation.model import SomeList, SomeString
-from pypy.annotation.model import unionof, TLS, UnionError, isdegenerated
+from pypy.annotation.model import unionof, TLS, UnionError
class TooLateForChange(Exception):
@@ -92,11 +92,6 @@
if s_new_value != s_value:
if self.dont_change_any_more:
raise TooLateForChange
- if isdegenerated(s_new_value):
- if self.bookkeeper:
- self.bookkeeper.ondegenerated(self, s_new_value)
- elif other.bookkeeper:
- other.bookkeeper.ondegenerated(other, s_new_value)
self.patch() # which should patch all refs to 'other'
if s_new_value != s_value:
self.s_value = s_new_value
@@ -114,8 +109,6 @@
def generalize(self, s_other_value):
s_new_value = unionof(self.s_value, s_other_value)
- if isdegenerated(s_new_value) and self.bookkeeper:
- self.bookkeeper.ondegenerated(self, s_new_value)
updated = s_new_value != self.s_value
if updated:
if self.dont_change_any_more:
@@ -157,12 +150,8 @@
return self.listitem is other.listitem
def union(self, other):
- if (self.same_as(MOST_GENERAL_LISTDEF) or
- other.same_as(MOST_GENERAL_LISTDEF)):
- return MOST_GENERAL_LISTDEF # without merging
- else:
- self.listitem.merge(other.listitem)
- return self
+ self.listitem.merge(other.listitem)
+ return self
def agree(self, other):
s_self_value = self.read_item()
@@ -221,7 +210,5 @@
#else: it's fine, don't set immutable=True at all (see
# test_can_merge_immutable_list_with_regular_list)
-MOST_GENERAL_LISTDEF = ListDef(None, SomeObject())
-
s_list_of_strings = SomeList(ListDef(None, SomeString(no_nul=True),
resized = True))
diff --git a/pypy/annotation/model.py b/pypy/annotation/model.py
--- a/pypy/annotation/model.py
+++ b/pypy/annotation/model.py
@@ -36,8 +36,6 @@
from pypy.rlib.rarithmetic import r_singlefloat, r_longfloat
import inspect, weakref
-DEBUG = False # set to False to disable recording of debugging information
-
class State(object):
# A global attribute :-( Patch it with 'True' to enable checking of
# the no_nul attribute...
@@ -48,8 +46,11 @@
"""The set of all objects. Each instance stands
for an arbitrary object about which nothing is known."""
__metaclass__ = extendabletype
+ immutable = False
knowntype = object
- immutable = False
+
+ def __init__(self):
+ assert type(self) is not SomeObject
def __eq__(self, other):
return (self.__class__ is other.__class__ and
@@ -105,60 +106,28 @@
return self.immutable and 'const' in self.__dict__
# delegate accesses to 'const' to accesses to 'const_box.value',
- # where const_box is a Constant. XXX the idea is to eventually
- # use systematically 'const_box' instead of 'const' for
- # non-immutable constant annotations
+ # where const_box is a Constant. This is not a property, in order
+ # to allow 'self.const = xyz' to work as well.
class ConstAccessDelegator(object):
def __get__(self, obj, cls=None):
return obj.const_box.value
const = ConstAccessDelegator()
del ConstAccessDelegator
- # for debugging, record where each instance comes from
- # this is disabled if DEBUG is set to False
- def __new__(cls, *args, **kw):
- new = super(SomeObject, cls).__new__
- if new is object.__new__:
- # Since python 2.6, object.__new__ warns
- # when parameters are passed
- self = new(cls)
- else:
- self = new(cls, *args, **kw)
- if DEBUG:
- try:
- bookkeeper = pypy.annotation.bookkeeper.getbookkeeper()
- position_key = bookkeeper.position_key
- except AttributeError:
- pass
- else:
- bookkeeper._isomeobject_coming_from[self] = position_key, None
+ def can_be_none(self):
+ return True
+
+ def nonnoneify(self):
return self
- def origin(self):
- bookkeeper = pypy.annotation.bookkeeper.getbookkeeper()
- if bookkeeper is None:
- return None
- return bookkeeper._isomeobject_coming_from.get(self, (None, None))[0]
- origin = property(origin)
- def caused_by_merge(self):
- bookkeeper = pypy.annotation.bookkeeper.getbookkeeper()
- if bookkeeper is None:
- return None
- return bookkeeper._isomeobject_coming_from.get(self, (None, None))[1]
- def set_caused_by_merge(self, nvalue):
- bookkeeper = pypy.annotation.bookkeeper.getbookkeeper()
- if bookkeeper is None:
- return
- bookkeeper._isomeobject_coming_from[self] = self.origin, nvalue
- caused_by_merge = property(caused_by_merge, set_caused_by_merge)
- del set_caused_by_merge
+class SomeType(SomeObject):
+ "Stands for a type. We might not be sure which one it is."
+ knowntype = type
+ immutable = True
def can_be_none(self):
- return True
-
- def nonnoneify(self):
- return self
+ return False
class SomeFloat(SomeObject):
"Stands for a float or an integer."
@@ -517,6 +486,7 @@
s_None = SomePBC([], can_be_None=True)
s_Bool = SomeBool()
+s_Int = SomeInteger()
s_ImpossibleValue = SomeImpossibleValue()
s_Str0 = SomeString(no_nul=True)
@@ -710,14 +680,8 @@
# this is just a performance shortcut
if s1 != s2:
s1 = pair(s1, s2).union()
- if DEBUG:
- if s1.caused_by_merge is None and len(somevalues) > 1:
- s1.caused_by_merge = somevalues
return s1
-def isdegenerated(s_value):
- return s_value.__class__ is SomeObject and s_value.knowntype is not type
-
# make knowntypedata dictionary
def add_knowntypedata(ktd, truth, vars, s_obj):
diff --git a/pypy/annotation/policy.py b/pypy/annotation/policy.py
--- a/pypy/annotation/policy.py
+++ b/pypy/annotation/policy.py
@@ -10,7 +10,6 @@
class BasicAnnotatorPolicy(object):
- allow_someobjects = True
def event(pol, bookkeeper, what, *args):
pass
@@ -80,6 +79,3 @@
def specialize__ll_and_arg(pol, *args):
from pypy.rpython.annlowlevel import LowLevelAnnotatorPolicy
return LowLevelAnnotatorPolicy.specialize__ll_and_arg(*args)
-
-class StrictAnnotatorPolicy(AnnotatorPolicy):
- allow_someobjects = False
diff --git a/pypy/annotation/signature.py b/pypy/annotation/signature.py
--- a/pypy/annotation/signature.py
+++ b/pypy/annotation/signature.py
@@ -3,9 +3,9 @@
from pypy.annotation.model import SomeBool, SomeInteger, SomeString,\
SomeFloat, SomeList, SomeDict, s_None, \
SomeObject, SomeInstance, SomeTuple, lltype_to_annotation,\
- unionof, SomeUnicodeString
-from pypy.annotation.listdef import ListDef, MOST_GENERAL_LISTDEF
-from pypy.annotation.dictdef import DictDef, MOST_GENERAL_DICTDEF
+ unionof, SomeUnicodeString, SomeType
+from pypy.annotation.listdef import ListDef
+from pypy.annotation.dictdef import DictDef
_annotation_cache = {}
@@ -78,24 +78,18 @@
return SomeString()
elif t is unicode:
return SomeUnicodeString()
- elif t is list:
- return SomeList(MOST_GENERAL_LISTDEF)
- elif t is dict:
- return SomeDict(MOST_GENERAL_DICTDEF)
- # can't do tuple
elif t is types.NoneType:
return s_None
elif bookkeeper and extregistry.is_registered_type(t, bookkeeper.policy):
entry = extregistry.lookup_type(t, bookkeeper.policy)
return entry.compute_annotation_bk(bookkeeper)
- elif bookkeeper and t.__module__ != '__builtin__' and t not in bookkeeper.pbctypes:
+ elif t is type:
+ return SomeType()
+ elif bookkeeper and not hasattr(t, '_freeze_'):
classdef = bookkeeper.getuniqueclassdef(t)
return SomeInstance(classdef)
else:
- o = SomeObject()
- if t != object:
- o.knowntype = t
- return o
+ raise AssertionError("annotationoftype(%r)" % (t,))
class Sig(object):
diff --git a/pypy/annotation/test/test_annrpython.py b/pypy/annotation/test/test_annrpython.py
--- a/pypy/annotation/test/test_annrpython.py
+++ b/pypy/annotation/test/test_annrpython.py
@@ -24,7 +24,7 @@
assert isinstance(s_list, annmodel.SomeList)
return s_list.listdef.listitem.s_value
-def somelist(s_type=annmodel.SomeObject()):
+def somelist(s_type):
return annmodel.SomeList(ListDef(None, s_type))
def dictkey(s_dict):
@@ -35,7 +35,7 @@
assert isinstance(s_dict, annmodel.SomeDict)
return s_dict.dictdef.dictvalue.s_value
-def somedict(s_key=annmodel.SomeObject(), s_value=annmodel.SomeObject()):
+def somedict(s_key, s_value):
return annmodel.SomeDict(DictDef(None, s_key, s_value))
@@ -205,15 +205,6 @@
annmodel.SomeInteger()
])
- def test_inheritance2(self):
- a = self.RPythonAnnotator()
- s = a.build_types(snippet._inheritance_nonrunnable, [])
- # result should be exactly:
- assert s == annmodel.SomeTuple([
- annmodel.SomeInteger(),
- annmodel.SomeObject()
- ])
-
def test_poor_man_range(self):
a = self.RPythonAnnotator()
s = a.build_types(snippet.poor_man_range, [int])
@@ -336,9 +327,13 @@
def test_flow_type_info(self):
a = self.RPythonAnnotator()
- s = a.build_types(snippet.flow_type_info, [object])
+ s = a.build_types(snippet.flow_type_info, [int])
a.simplify()
- #a.translator.view()
+ assert s.knowntype == int
+
+ a = self.RPythonAnnotator()
+ s = a.build_types(snippet.flow_type_info, [str])
+ a.simplify()
assert s.knowntype == int
def test_flow_type_info_2(self):
@@ -351,7 +346,7 @@
def test_flow_usertype_info(self):
a = self.RPythonAnnotator()
- s = a.build_types(snippet.flow_usertype_info, [object])
+ s = a.build_types(snippet.flow_usertype_info, [snippet.WithInit])
#a.translator.view()
assert isinstance(s, annmodel.SomeInstance)
assert s.classdef == a.bookkeeper.getuniqueclassdef(snippet.WithInit)
@@ -363,13 +358,6 @@
assert isinstance(s, annmodel.SomeInstance)
assert s.classdef == a.bookkeeper.getuniqueclassdef(snippet.WithMoreInit)
- def test_flow_identity_info(self):
- a = self.RPythonAnnotator()
- s = a.build_types(snippet.flow_identity_info, [object, object])
- a.simplify()
- #a.translator.view()
- assert s == a.bookkeeper.immutablevalue((None, None))
-
def test_mergefunctions(self):
a = self.RPythonAnnotator()
s = a.build_types(snippet.mergefunctions, [int])
@@ -431,11 +419,11 @@
# the annotator (it doesn't check that they operate property, though)
for example, methname, s_example in [
('', 'join', annmodel.SomeString()),
- ([], 'append', somelist()),
- ([], 'extend', somelist()),
- ([], 'reverse', somelist()),
- ([], 'insert', somelist()),
- ([], 'pop', somelist()),
+ ([], 'append', somelist(annmodel.s_Int)),
+ ([], 'extend', somelist(annmodel.s_Int)),
+ ([], 'reverse', somelist(annmodel.s_Int)),
+ ([], 'insert', somelist(annmodel.s_Int)),
+ ([], 'pop', somelist(annmodel.s_Int)),
]:
constmeth = getattr(example, methname)
s_constmeth = iv(constmeth)
@@ -497,12 +485,12 @@
def test_simple_slicing(self):
a = self.RPythonAnnotator()
- s = a.build_types(snippet.simple_slice, [list])
+ s = a.build_types(snippet.simple_slice, [somelist(annmodel.s_Int)])
assert isinstance(s, annmodel.SomeList)
def test_simple_iter_list(self):
a = self.RPythonAnnotator()
- s = a.build_types(snippet.simple_iter, [list])
+ s = a.build_types(snippet.simple_iter, [somelist(annmodel.s_Int)])
assert isinstance(s, annmodel.SomeIterator)
def test_simple_iter_next(self):
@@ -542,11 +530,6 @@
assert isinstance(dictkey(s), annmodel.SomeInteger)
assert isinstance(dictvalue(s), annmodel.SomeInteger)
- a = self.RPythonAnnotator()
- s = a.build_types(snippet.dict_update, [str])
- assert not isinstance(dictkey(s), annmodel.SomeString)
- assert not isinstance(dictvalue(s), annmodel.SomeString)
-
def test_dict_update_2(self):
a = self.RPythonAnnotator()
def g(n):
@@ -568,7 +551,7 @@
def test_dict_keys2(self):
a = self.RPythonAnnotator()
s = a.build_types(snippet.dict_keys2, [])
- assert not isinstance(listitem(s), annmodel.SomeString)
+ assert type(listitem(s)) is annmodel.SomeString
def test_dict_values(self):
a = self.RPythonAnnotator()
@@ -578,7 +561,7 @@
def test_dict_values2(self):
a = self.RPythonAnnotator()
s = a.build_types(snippet.dict_values2, [])
- assert not isinstance(listitem(s), annmodel.SomeString)
+ assert type(listitem(s)) is annmodel.SomeString
def test_dict_items(self):
a = self.RPythonAnnotator()
@@ -643,25 +626,6 @@
s = a.build_types(operation_always_raising, [int])
assert s == a.bookkeeper.immutablevalue(24)
- def test_bltin_code_frame_confusion(self):
- a = self.RPythonAnnotator()
- a.build_types(snippet.bltin_code_frame_confusion,[])
- f_flowgraph = graphof(a, snippet.bltin_code_frame_f)
- g_flowgraph = graphof(a, snippet.bltin_code_frame_g)
- # annotator confused by original bltin code/frame setup, we just get SomeObject here
- assert a.binding(f_flowgraph.getreturnvar()).__class__ is annmodel.SomeObject
- assert a.binding(g_flowgraph.getreturnvar()).__class__ is annmodel.SomeObject
-
- def test_bltin_code_frame_reorg(self):
- a = self.RPythonAnnotator()
- a.build_types(snippet.bltin_code_frame_reorg,[])
- f_flowgraph = graphof(a, snippet.bltin_code_frame_f)
- g_flowgraph = graphof(a, snippet.bltin_code_frame_g)
- assert isinstance(a.binding(f_flowgraph.getreturnvar()),
- annmodel.SomeInteger)
- assert isinstance(a.binding(g_flowgraph.getreturnvar()),
- annmodel.SomeString)
-
def test_propagation_of_fresh_instances_through_attrs(self):
a = self.RPythonAnnotator()
s = a.build_types(snippet.propagation_of_fresh_instances_through_attrs, [int])
@@ -748,14 +712,15 @@
assert s.classdef is a.bookkeeper.getuniqueclassdef(snippet.Exc)
def test_type_is(self):
- class C(object):
+ class B(object):
+ pass
+ class C(B):
pass
def f(x):
- if type(x) is C:
- return x
- raise Exception
- a = self.RPythonAnnotator()
- s = a.build_types(f, [object])
+ assert type(x) is C
+ return x
+ a = self.RPythonAnnotator()
+ s = a.build_types(f, [B])
assert s.classdef is a.bookkeeper.getuniqueclassdef(C)
def test_ann_assert(self):
@@ -793,24 +758,30 @@
return None
a = self.RPythonAnnotator()
- s = a.build_types(f, [list])
+ s = a.build_types(f, [somelist(annmodel.s_Int)])
assert s.classdef is a.bookkeeper.getuniqueclassdef(IndexError) # KeyError ignored because l is a list
def test_freeze_protocol(self):
class Stuff:
- def __init__(self, flag):
+ def __init__(self):
self.called = False
- self.flag = flag
def _freeze_(self):
self.called = True
- return self.flag
- myobj = Stuff(True)
+ return True
+ myobj = Stuff()
a = self.RPythonAnnotator()
s = a.build_types(lambda: myobj, [])
assert myobj.called
assert isinstance(s, annmodel.SomePBC)
assert s.const == myobj
- myobj = Stuff(False)
+
+ def test_cleanup_protocol(self):
+ class Stuff:
+ def __init__(self):
+ self.called = False
+ def _cleanup_(self):
+ self.called = True
+ myobj = Stuff()
a = self.RPythonAnnotator()
s = a.build_types(lambda: myobj, [])
assert myobj.called
@@ -854,7 +825,7 @@
def f(a,b):
return bool(a) or bool(b)
a = self.RPythonAnnotator()
- s = a.build_types(f, [int,list])
+ s = a.build_types(f, [int, somelist(annmodel.s_Int)])
assert s.knowntype == bool
def test_float(self):
@@ -1299,22 +1270,6 @@
assert isinstance(s_item, annmodel.SomeInstance)
assert s_item.classdef is a.bookkeeper.getuniqueclassdef(T)
- def test_assert_type_is_list_doesnt_lose_info(self):
- class T(object):
- pass
- def g(l):
- assert type(l) is list
- return l
- def f():
- l = [T()]
- return g(l)
- a = self.RPythonAnnotator()
- s = a.build_types(f, [])
- s_item = listitem(s)
- assert isinstance(s_item, annmodel.SomeInstance)
- assert s_item.classdef is a.bookkeeper.getuniqueclassdef(T)
-
-
def test_int_str_mul(self):
def f(x,a,b):
return a*x+x*b
@@ -1395,11 +1350,10 @@
except KeyError:
raise
a = self.RPythonAnnotator()
- a.build_types(f, [dict])
+ a.build_types(f, [somedict(annmodel.s_Int, annmodel.s_Int)])
fg = graphof(a, f)
et, ev = fg.exceptblock.inputargs
- t = annmodel.SomeObject()
- t.knowntype = type
+ t = annmodel.SomeType()
t.const = KeyError
t.is_type_of = [ev]
assert a.binding(et) == t
@@ -1412,11 +1366,10 @@
except:
raise
a = self.RPythonAnnotator()
- a.build_types(f, [dict])
+ a.build_types(f, [somedict(annmodel.s_Int, annmodel.s_Int)])
fg = graphof(a, f)
et, ev = fg.exceptblock.inputargs
- t = annmodel.SomeObject()
- t.knowntype = type
+ t = annmodel.SomeType()
t.is_type_of = [ev]
t.const = KeyError # IndexError ignored because 'dic' is a dict
assert a.binding(et) == t
@@ -1448,11 +1401,10 @@
finally:
h()
a = self.RPythonAnnotator()
- a.build_types(f, [int, list])
+ a.build_types(f, [int, somelist(annmodel.s_Int)])
fg = graphof(a, f)
et, ev = fg.exceptblock.inputargs
- t = annmodel.SomeObject()
- t.knowntype = type
+ t = annmodel.SomeType()
t.is_type_of = [ev]
assert a.binding(et) == t
assert isinstance(a.binding(ev), annmodel.SomeInstance) and a.binding(ev).classdef == a.bookkeeper.getuniqueclassdef(Exception)
@@ -1474,24 +1426,11 @@
a.build_types(f, [])
fg = graphof(a, f)
et, ev = fg.exceptblock.inputargs
- t = annmodel.SomeObject()
- t.knowntype = type
+ t = annmodel.SomeType()
t.is_type_of = [ev]
assert a.binding(et) == t
assert isinstance(a.binding(ev), annmodel.SomeInstance) and a.binding(ev).classdef == a.bookkeeper.getuniqueclassdef(Exception)
- def test_sys_attrs(self):
- def f():
- return sys.argv[0]
- a = self.RPythonAnnotator()
- try:
- oldvalue = sys.argv
- sys.argv = []
- s = a.build_types(f, [])
- finally:
- sys.argv = oldvalue
- assert s is not None
-
def test_pow(self):
def f(n):
n **= 2
@@ -1523,7 +1462,6 @@
a = self.RPythonAnnotator()
s = a.build_types(f, [int, str, a.bookkeeper.immutablevalue(1.0), a.bookkeeper.immutablevalue('d'), a.bookkeeper.immutablevalue('e')])
assert s == annmodel.SomeTuple([annmodel.SomeChar(), a.bookkeeper.immutablevalue(1.0)])
- assert not [b for b in a.bindings.itervalues() if b.__class__ == annmodel.SomeObject]
def test_is_true_coalesce2(self):
def f(a,b,a1,b1,c,d,e):
@@ -1532,9 +1470,12 @@
return d,c
return e,c
a = self.RPythonAnnotator()
- s = a.build_types(f, [int, str, float, list, a.bookkeeper.immutablevalue(1.0), a.bookkeeper.immutablevalue('d'), a.bookkeeper.immutablevalue('e')])
- assert s == annmodel.SomeTuple([annmodel.SomeChar(), a.bookkeeper.immutablevalue(1.0)])
- assert not [b for b in a.bindings.itervalues() if b.__class__ == annmodel.SomeObject]
+ s = a.build_types(f, [int, str, float, somelist(annmodel.s_Int),
+ a.bookkeeper.immutablevalue(1.0),
+ a.bookkeeper.immutablevalue('d'),
+ a.bookkeeper.immutablevalue('e')])
+ assert s == annmodel.SomeTuple([annmodel.SomeChar(),
+ a.bookkeeper.immutablevalue(1.0)])
def test_is_true_coalesce_sanity(self):
def f(a):
@@ -1954,16 +1895,7 @@
t = type(x)
return issubclass(t, A)
- def f():
- x = g(1)
- y = g(0)
- return x or y
- a = self.RPythonAnnotator()
- s = a.build_types(f, [])
- assert s.knowntype == bool
- assert not s.is_constant()
- a = self.RPythonAnnotator()
- # sanity check
+ a = self.RPythonAnnotator()
x = annmodel.SomeInteger()
x.const = 1
s = a.build_types(g, [x])
@@ -2383,8 +2315,7 @@
a = self.RPythonAnnotator()
s = a.build_types(f, [int])
- assert s.__class__ == annmodel.SomeObject
- assert s.knowntype == type
+ assert isinstance(s, annmodel.SomeType)
def test_annotate_iter_empty_container(self):
def f():
@@ -3075,7 +3006,6 @@
v = -maxint
return intmask(v * 10)
P = policy.AnnotatorPolicy()
- P.allow_someobjects = False
a = self.RPythonAnnotator(policy=P)
s = a.build_types(fun, [bool])
assert isinstance(s, annmodel.SomeInteger)
@@ -3866,6 +3796,24 @@
s = a.build_types(fn, [annmodel.SomeChar()])
assert s == annmodel.SomeChar()
+ def test_isinstance_double_const(self):
+ class X(object):
+ def _freeze_(self):
+ return True
+
+ x = X()
+
+ def f(i):
+ if i:
+ x1 = x
+ else:
+ x1 = None
+ print "hello" # this is to force the merge of blocks
+ return isinstance(x1, X)
+
+ a = self.RPythonAnnotator()
+ s = a.build_types(f, [annmodel.SomeInteger()])
+ assert isinstance(s, annmodel.SomeBool)
def g(n):
return [0,1,2,n]
diff --git a/pypy/annotation/test/test_model.py b/pypy/annotation/test/test_model.py
--- a/pypy/annotation/test/test_model.py
+++ b/pypy/annotation/test/test_model.py
@@ -2,20 +2,20 @@
import autopath
import py
from pypy.annotation.model import *
-from pypy.annotation.listdef import ListDef, MOST_GENERAL_LISTDEF
+from pypy.annotation.listdef import ListDef
from pypy.rpython.ootypesystem.ootype import ROOT
listdef1 = ListDef(None, SomeTuple([SomeInteger(nonneg=True), SomeString()]))
listdef2 = ListDef(None, SomeTuple([SomeInteger(nonneg=False), SomeString()]))
-s1 = SomeObject()
+s1 = SomeType()
s2 = SomeInteger(nonneg=True)
s3 = SomeInteger(nonneg=False)
s4 = SomeList(listdef1)
s5 = SomeList(listdef2)
s6 = SomeImpossibleValue()
-slist = [s1,s2,s3,s4,s6] # not s5 -- unionof(s4,s5) modifies s4 and s5
+slist = [s1, s2, s3, s4, s6] # not s5 -- unionof(s4,s5) modifies s4 and s5
class C(object):
@@ -42,7 +42,7 @@
def test_equality():
assert s1 != s2 != s3 != s4 != s5 != s6
- assert s1 == SomeObject()
+ assert s1 == SomeType()
assert s2 == SomeInteger(nonneg=True)
assert s3 == SomeInteger(nonneg=False)
assert s4 == SomeList(listdef1)
@@ -51,19 +51,11 @@
def test_contains():
assert ([(s,t) for s in slist for t in slist if s.contains(t)] ==
- [(s1,s1), (s1,s2), (s1,s3), (s1,s4), (s1,s6),
- (s2,s2), (s2,s6),
- (s3,s2), (s3,s3), (s3,s6),
- (s4,s4), (s4,s6),
- (s6,s6)])
-
-def test_union():
- assert ([unionof(s,t) for s in slist for t in slist] ==
- [s1, s1, s1, s1, s1,
- s1, s2, s3, s1, s2,
- s1, s3, s3, s1, s3,
- s1, s1, s1, s4, s4,
- s1, s2, s3, s4, s6])
+ [(s1, s1), (s1, s6),
+ (s2, s2), (s2, s6),
+ (s3, s2), (s3, s3), (s3, s6),
+ (s4, s4), (s4, s6),
+ (s6, s6)])
def test_commonbase_simple():
class A0:
@@ -100,9 +92,10 @@
def test_list_contains():
listdef1 = ListDef(None, SomeInteger(nonneg=True))
s1 = SomeList(listdef1)
- s2 = SomeList(MOST_GENERAL_LISTDEF)
+ listdef2 = ListDef(None, SomeInteger(nonneg=False))
+ s2 = SomeList(listdef2)
assert s1 != s2
- assert s2.contains(s1)
+ assert not s2.contains(s1)
assert s1 != s2
assert not s1.contains(s2)
assert s1 != s2
diff --git a/pypy/annotation/unaryop.py b/pypy/annotation/unaryop.py
--- a/pypy/annotation/unaryop.py
+++ b/pypy/annotation/unaryop.py
@@ -7,7 +7,7 @@
SomeObject, SomeInteger, SomeBool, SomeString, SomeChar, SomeList, \
SomeDict, SomeTuple, SomeImpossibleValue, SomeUnicodeCodePoint, \
SomeInstance, SomeBuiltin, SomeFloat, SomeIterator, SomePBC, \
- SomeExternalObject, SomeTypedAddressAccess, SomeAddress, \
+ SomeExternalObject, SomeTypedAddressAccess, SomeAddress, SomeType, \
s_ImpossibleValue, s_Bool, s_None, \
unionof, missing_operation, add_knowntypedata, HarmlesslyBlocked, \
SomeGenericCallable, SomeWeakRef, SomeUnicodeString
@@ -39,14 +39,7 @@
def type(obj, *moreargs):
if moreargs:
raise Exception, 'type() called with more than one argument'
- if obj.is_constant():
- if isinstance(obj, SomeInstance):
- r = SomePBC([obj.classdef.classdesc])
- else:
- r = immutablevalue(obj.knowntype)
- else:
- r = SomeObject()
- r.knowntype = type
+ r = SomeType()
bk = getbookkeeper()
fn, block, i = bk.position_key
annotator = bk.annotator
@@ -133,9 +126,6 @@
def float(obj):
return SomeFloat()
- def long(obj):
- return SomeObject() # XXX
-
def delattr(obj, s_attr):
if obj.__class__ != SomeObject or obj.knowntype != object:
getbookkeeper().warning(
@@ -154,18 +144,17 @@
def getattr(obj, s_attr):
# get a SomeBuiltin if the SomeObject has
# a corresponding method to handle it
- if s_attr.is_constant() and isinstance(s_attr.const, str):
- attr = s_attr.const
- s_method = obj.find_method(attr)
- if s_method is not None:
- return s_method
- # if the SomeObject is itself a constant, allow reading its attrs
- if obj.is_immutable_constant() and hasattr(obj.const, attr):
- return immutablevalue(getattr(obj.const, attr))
- else:
- getbookkeeper().warning('getattr(%r, %r) is not RPythonic enough' %
- (obj, s_attr))
- return SomeObject()
+ if not s_attr.is_constant() or not isinstance(s_attr.const, str):
+ raise AnnotatorError("getattr(%r, %r) has non-constant argument"
+ % (obj, s_attr))
+ attr = s_attr.const
+ s_method = obj.find_method(attr)
+ if s_method is not None:
+ return s_method
+ # if the SomeObject is itself a constant, allow reading its attrs
+ if obj.is_immutable_constant() and hasattr(obj.const, attr):
+ return immutablevalue(getattr(obj.const, attr))
+ raise AnnotatorError("Cannot find attribute %r on %r" % (attr, obj))
getattr.can_only_throw = []
def bind_callables_under(obj, classdef, name):
diff --git a/pypy/bin/translatorshell.py b/pypy/bin/translatorshell.py
--- a/pypy/bin/translatorshell.py
+++ b/pypy/bin/translatorshell.py
@@ -8,10 +8,10 @@
Example:
- t = Translation(func)
+ t = Translation(func, [int]) # pass the list of args types
t.view() # control flow graph
- t.annotate([int]) # pass the list of args types
+ t.annotate()
t.view() # graph + annotations under the mouse
t.rtype() # use low level operations
diff --git a/pypy/config/test/test_config.py b/pypy/config/test/test_config.py
--- a/pypy/config/test/test_config.py
+++ b/pypy/config/test/test_config.py
@@ -111,8 +111,8 @@
else:
return 'foo'
- t = Translation(f)
- t.rtype([int])
+ t = Translation(f, [int])
+ t.rtype()
block = t.context.graphs[0].startblock
assert len(block.exits[0].target.operations) == 0
diff --git a/pypy/config/translationoption.py b/pypy/config/translationoption.py
--- a/pypy/config/translationoption.py
+++ b/pypy/config/translationoption.py
@@ -129,8 +129,6 @@
# misc
BoolOption("verbose", "Print extra information", default=False),
- BoolOption("debug", "Record extra annotation information",
- cmdline="-d --debug", default=True),
BoolOption("insist", "Try hard to go on RTyping", default=False,
cmdline="--insist"),
StrOption("cc", "Specify compiler to use for compiling generated C", cmdline="--cc"),
diff --git a/pypy/conftest.py b/pypy/conftest.py
--- a/pypy/conftest.py
+++ b/pypy/conftest.py
@@ -111,15 +111,7 @@
def maketestobjspace(config=None):
if config is None:
config = make_config(option)
- try:
- space = make_objspace(config)
- except OperationError, e:
- check_keyboard_interrupt(e)
- if option.verbose:
- import traceback
- traceback.print_exc()
- py.test.fail("fatal: cannot initialize objspace: %r" %
- (config.objspace.name,))
+ space = make_objspace(config)
space.startup() # Initialize all builtin modules
space.setitem(space.builtin.w_dict, space.wrap('AssertionError'),
appsupport.build_pytest_assertion(space))
diff --git a/pypy/doc/discussion/improve-rpython.rst b/pypy/doc/discussion/improve-rpython.rst
--- a/pypy/doc/discussion/improve-rpython.rst
+++ b/pypy/doc/discussion/improve-rpython.rst
@@ -9,7 +9,7 @@
`import` statements::
from pypy.interpreter.baseobjspace import Wrappable
- from pypy.interpreter.gateway import ObjSpace, W_Root, NoneNotWrapped
+ from pypy.interpreter.gateway import ObjSpace, W_Root
from pypy.interpreter.argument import Arguments
from pypy.interpreter.typedef import TypeDef, GetSetProperty
from pypy.interpreter.typedef import interp_attrproperty, interp_attrproperty_w
diff --git a/pypy/doc/getting-started-dev.rst b/pypy/doc/getting-started-dev.rst
--- a/pypy/doc/getting-started-dev.rst
+++ b/pypy/doc/getting-started-dev.rst
@@ -27,7 +27,7 @@
``pypy/translator/test/snippet.py``, which is imported under the name
``snippet``. For example::
- >>> t = Translation(snippet.is_perfect_number)
+ >>> t = Translation(snippet.is_perfect_number, [int])
>>> t.view()
After that, the graph viewer pops up, that lets you interactively inspect the
@@ -40,7 +40,7 @@
We have a type annotator that can completely infer types for functions like
``is_perfect_number`` (as well as for much larger examples)::
- >>> t.annotate([int])
+ >>> t.annotate()
>>> t.view()
Move the mouse over variable names (in red) to see their inferred types.
@@ -74,8 +74,8 @@
>>> def myfunc(a, b): return a+b
...
- >>> t = Translation(myfunc)
- >>> t.annotate([int, int])
+ >>> t = Translation(myfunc, [int, int])
+ >>> t.annotate()
>>> f = t.compile_cli() # or compile_jvm()
>>> f(4, 5)
9
diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst
--- a/pypy/doc/whatsnew-head.rst
+++ b/pypy/doc/whatsnew-head.rst
@@ -38,7 +38,8 @@
.. branch: numpypy-complex2
Complex dtype support for numpy
-
+.. branch: kill-someobject
+major cleanups including killing some object support
.. "uninteresting" branches that we should just ignore for the whatsnew:
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -730,8 +730,15 @@
# done by a method call on w_two (and not on w_one, because of the
# expected programming style where we say "if x is None" or
# "if x is object").
+ assert w_two is not None
return w_two.is_w(self, w_one)
+ def is_none(self, w_obj):
+ """ mostly for checking inputargs that have unwrap_spec and
+ can accept both w_None and None
+ """
+ return w_obj is None or self.is_w(w_obj, self.w_None)
+
def id(self, w_obj):
w_result = w_obj.immutable_unique_id(self)
if w_result is None:
@@ -815,7 +822,7 @@
interpreter class (a subclass of Wrappable).
"""
assert RequiredClass is not None
- if can_be_None and self.is_w(w_obj, self.w_None):
+ if can_be_None and self.is_none(w_obj):
return None
obj = self.interpclass_w(w_obj)
if not isinstance(obj, RequiredClass): # or obj is None
diff --git a/pypy/interpreter/function.py b/pypy/interpreter/function.py
--- a/pypy/interpreter/function.py
+++ b/pypy/interpreter/function.py
@@ -207,11 +207,11 @@
code = space.interp_w(Code, w_code)
if not space.is_true(space.isinstance(w_globals, space.w_dict)):
raise OperationError(space.w_TypeError, space.wrap("expected dict"))
- if not space.is_w(w_name, space.w_None):
+ if not space.is_none(w_name):
name = space.str_w(w_name)
else:
name = None
- if not space.is_w(w_argdefs, space.w_None):
+ if not space.is_none(w_argdefs):
defs_w = space.fixedview(w_argdefs)
else:
defs_w = []
@@ -219,7 +219,7 @@
from pypy.interpreter.pycode import PyCode
if isinstance(code, PyCode):
nfreevars = len(code.co_freevars)
- if space.is_w(w_closure, space.w_None) and nfreevars == 0:
+ if space.is_none(w_closure) and nfreevars == 0:
closure = None
elif not space.is_w(space.type(w_closure), space.w_tuple):
raise OperationError(space.w_TypeError, space.wrap("invalid closure"))
@@ -247,7 +247,7 @@
# delicate
_all = {'': None}
- def _freeze_(self):
+ def _cleanup_(self):
from pypy.interpreter.gateway import BuiltinCode
if isinstance(self.code, BuiltinCode):
# we have been seen by other means so rtyping should not choke
@@ -346,7 +346,7 @@
def fget_func_defaults(self, space):
values_w = self.defs_w
# the `None in values_w` check here is to ensure that interp-level
- # functions with a default of NoneNotWrapped do not get their defaults
+ # functions with a default of None do not get their defaults
# exposed at applevel
if not values_w or None in values_w:
return space.w_None
@@ -459,6 +459,7 @@
def fdel_func_annotations(self, space):
self.w_ann = None
+
def descr_function_get(space, w_function, w_obj, w_cls=None):
"""functionobject.__get__(obj[, type]) -> method"""
# this is not defined as a method on Function because it's generally
@@ -476,7 +477,7 @@
def __init__(self, space, w_function, w_instance):
self.space = space
self.w_function = w_function
- self.w_instance = w_instance
+ self.w_instance = w_instance # or None
def descr_method__new__(space, w_subtype, w_function, w_instance):
if space.is_w(w_instance, space.w_None):
@@ -577,7 +578,7 @@
self.w_function = w_function
def descr_classmethod_get(self, space, w_obj, w_klass=None):
- if space.is_w(w_klass, space.w_None):
+ if space.is_none(w_klass):
w_klass = space.type(w_obj)
return space.wrap(Method(space, self.w_function, w_klass))
diff --git a/pypy/interpreter/gateway.py b/pypy/interpreter/gateway.py
--- a/pypy/interpreter/gateway.py
+++ b/pypy/interpreter/gateway.py
@@ -7,31 +7,29 @@
"""
-import types, sys, os
-from pypy.tool.compat import md5
+import sys
+import os
+import types
-NoneNotWrapped = object()
+import py
-from pypy.tool.sourcetools import func_with_new_name
+from pypy.interpreter.eval import Code
+from pypy.interpreter.argument import Arguments, Signature
+from pypy.interpreter.baseobjspace import (W_Root, ObjSpace, Wrappable,
+ SpaceCache, DescrMismatch)
from pypy.interpreter.error import OperationError
-from pypy.interpreter import eval
-from pypy.interpreter.function import Function, Method, ClassMethod
-from pypy.interpreter.function import FunctionWithFixedCode
-from pypy.interpreter.baseobjspace import W_Root, ObjSpace, Wrappable
-from pypy.interpreter.baseobjspace import Wrappable, SpaceCache, DescrMismatch
-from pypy.interpreter.argument import Arguments, Signature
-from pypy.tool.sourcetools import NiceCompile, compile2
-from pypy.rlib.rarithmetic import r_longlong, r_int, r_ulonglong, r_uint
+from pypy.interpreter.function import ClassMethod, FunctionWithFixedCode
from pypy.rlib import rstackovf
from pypy.rlib.objectmodel import we_are_translated
+from pypy.rlib.rarithmetic import r_longlong, r_int, r_ulonglong, r_uint
+from pypy.tool.sourcetools import func_with_new_name, compile2
+
# internal non-translatable parts:
-import py
-
class SignatureBuilder(object):
"NOT_RPYTHON"
def __init__(self, func=None, argnames=None, varargname=None,
- kwargname=None, name = None):
+ kwargname=None, name=None):
self.func = func
if func is not None:
self.name = func.__name__
@@ -60,10 +58,12 @@
if isinstance(el, str):
getattr(self, "visit_%s" % (el,))(el, *args)
elif isinstance(el, tuple):
- if el[0] == 'self':
+ if el[0] == 'INTERNAL:self':
self.visit_self(el[1], *args)
else:
- self.visit_function(el, *args)
+ assert False, "not supported any more, use WrappedDefault"
+ elif isinstance(el, WrappedDefault):
+ self.visit__W_Root(W_Root, *args)
elif isinstance(el, type):
for typ in self.bases_order:
if issubclass(el, typ):
@@ -81,8 +81,8 @@
for el in unwrap_spec:
dispatch(el, *extra)
+
class UnwrapSpecEmit(UnwrapSpecRecipe):
-
def __init__(self):
self.n = 0
self.miniglobals = {}
@@ -97,10 +97,11 @@
self.miniglobals[name] = obj
return name
+
#________________________________________________________________
+
class UnwrapSpec_Check(UnwrapSpecRecipe):
-
# checks for checking interp2app func argument names wrt unwrap_spec
# and synthetizing an app-level signature
@@ -108,9 +109,6 @@
self.func = original_sig.func
self.orig_arg = iter(original_sig.argnames).next
- def visit_function(self, (func, cls), app_sig):
- self.dispatch(cls, app_sig)
-
def visit_self(self, cls, app_sig):
self.visit__Wrappable(cls, app_sig)
@@ -168,8 +166,8 @@
app_sig.append(argname[2:])
def visit__Arguments(self, el, app_sig):
- argname = self.orig_arg()
- assert app_sig.varargname is None,(
+ self.orig_arg()
+ assert app_sig.varargname is None, (
"built-in function %r has conflicting rest args specs" % self.func)
app_sig.varargname = 'args'
app_sig.kwargname = 'keywords'
@@ -179,7 +177,7 @@
assert argname.endswith('_w'), (
"rest arguments arg %s of built-in function %r should end in '_w'" %
(argname, self.func))
- assert app_sig.varargname is None,(
+ assert app_sig.varargname is None, (
"built-in function %r has conflicting rest args specs" % self.func)
app_sig.varargname = argname[:-2]
@@ -188,7 +186,7 @@
assert argname.startswith('w_'), (
"rest arguments arg %s of built-in function %r should start 'w_'" %
(argname, self.func))
- assert app_sig.varargname is None,(
+ assert app_sig.varargname is None, (
"built-in function %r has conflicting rest args specs" % self.func)
app_sig.varargname = argname[2:]
@@ -208,10 +206,6 @@
def scopenext(self):
return "scope_w[%d]" % self.succ()
- def visit_function(self, (func, cls)):
- self.run_args.append("%s(%s)" % (self.use(func),
- self.scopenext()))
-
def visit_self(self, typ):
self.run_args.append("space.descr_self_interp_w(%s, %s)" %
(self.use(typ), self.scopenext()))
@@ -284,6 +278,8 @@
if isinstance(el, tuple):
parts.append(''.join([getattr(subel, '__name__', subel)
for subel in el]))
+ elif isinstance(el, WrappedDefault):
+ parts.append('W_Root')
else:
parts.append(getattr(el, '__name__', el))
label = '_'.join(parts)
@@ -320,15 +316,16 @@
def _run(self, space, scope_w):
"""Subclasses with behavior specific for an unwrap spec are generated"""
- raise TypeError, "abstract"
+ raise TypeError("abstract")
#________________________________________________________________
+
class FastFuncNotSupported(Exception):
pass
+
class UnwrapSpec_FastFunc_Unwrap(UnwrapSpecEmit):
-
def __init__(self):
UnwrapSpecEmit.__init__(self)
self.args = []
@@ -346,9 +343,6 @@
self.args.append(arg)
return arg
- def visit_function(self, (func, cls)):
- raise FastFuncNotSupported
-
def visit_self(self, typ):
self.unwrap.append("space.descr_self_interp_w(%s, %s)" %
(self.use(typ), self.nextarg()))
@@ -439,6 +433,7 @@
return narg, fastfunc
make_fastfunc = staticmethod(make_fastfunc)
+
def int_unwrapping_space_method(typ):
assert typ in (int, str, float, unicode, r_longlong, r_uint, r_ulonglong, bool)
if typ is r_int is r_longlong:
@@ -455,6 +450,7 @@
- positional arguments must be as many as the function parameters
- keywords arguments allow to change only some parameter specs
"""
+ assert spec or kwargs
def decorator(func):
if kwargs:
if spec:
@@ -466,6 +462,14 @@
return func
return decorator
+class WrappedDefault(object):
+ """ Can be used inside unwrap_spec as WrappedDefault(3) which means
+ it'll be treated as W_Root, but fed with default which will be a wrapped
+ argument to constructor.
+ """
+ def __init__(self, default_value):
+ self.default_value = default_value
+
def build_unwrap_spec(func, argnames, self_type=None):
"""build the list of parameter unwrap spec for the function.
"""
@@ -505,7 +509,8 @@
return unwrap_spec
-class BuiltinCode(eval.Code):
+
+class BuiltinCode(Code):
"The code object implementing a built-in (interpreter-level) hook."
_immutable_ = True
hidden_applevel = True
@@ -515,14 +520,11 @@
# When a BuiltinCode is stored in a Function object,
# you get the functionality of CPython's built-in function type.
- NOT_RPYTHON_ATTRIBUTES = ['_bltin', '_unwrap_spec']
-
- def __init__(self, func, unwrap_spec = None, self_type = None,
- descrmismatch=None):
More information about the pypy-commit
mailing list