[pypy-commit] pypy default: merge
antocuni
noreply at buildbot.pypy.org
Mon Jan 21 00:32:36 CET 2013
Author: Antonio Cuni <anto.cuni at gmail.com>
Branch:
Changeset: r60260:68d5bc1decb5
Date: 2013-01-21 00:35 +0100
http://bitbucket.org/pypy/pypy/changeset/68d5bc1decb5/
Log: merge
diff too long, truncating to 2000 out of 728245 lines
diff --git a/.hgignore b/.hgignore
--- a/.hgignore
+++ b/.hgignore
@@ -85,3 +85,4 @@
^compiled
^.git/
^release/
+^rpython/_cache$
diff --git a/dotviewer/test/test_translator.py b/dotviewer/test/test_translator.py
--- a/dotviewer/test/test_translator.py
+++ b/dotviewer/test/test_translator.py
@@ -21,7 +21,7 @@
def test_annotated():
- from pypy.translator.interactive import Translation
+ from rpython.translator.interactive import Translation
t = Translation(is_prime)
t.annotate([int])
t.viewcg()
diff --git a/lib_pypy/ctypes_config_cache/autopath.py b/lib_pypy/ctypes_config_cache/autopath.py
deleted file mode 100644
--- a/lib_pypy/ctypes_config_cache/autopath.py
+++ /dev/null
@@ -1,131 +0,0 @@
-"""
-self cloning, automatic path configuration
-
-copy this into any subdirectory of pypy from which scripts need
-to be run, typically all of the test subdirs.
-The idea is that any such script simply issues
-
- import autopath
-
-and this will make sure that the parent directory containing "pypy"
-is in sys.path.
-
-If you modify the master "autopath.py" version (in pypy/tool/autopath.py)
-you can directly run it which will copy itself on all autopath.py files
-it finds under the pypy root directory.
-
-This module always provides these attributes:
-
- pypydir pypy root directory path
- this_dir directory where this autopath.py resides
-
-"""
-
-def __dirinfo(part):
- """ return (partdir, this_dir) and insert parent of partdir
- into sys.path. If the parent directories don't have the part
- an EnvironmentError is raised."""
-
- import sys, os
- try:
- head = this_dir = os.path.realpath(os.path.dirname(__file__))
- except NameError:
- head = this_dir = os.path.realpath(os.path.dirname(sys.argv[0]))
-
- error = None
- while head:
- partdir = head
- head, tail = os.path.split(head)
- if tail == part:
- checkfile = os.path.join(partdir, os.pardir, 'pypy', '__init__.py')
- if not os.path.exists(checkfile):
- error = "Cannot find %r" % (os.path.normpath(checkfile),)
- break
- else:
- error = "Cannot find the parent directory %r of the path %r" % (
- partdir, this_dir)
- if not error:
- # check for bogus end-of-line style (e.g. files checked out on
- # Windows and moved to Unix)
- f = open(__file__.replace('.pyc', '.py'), 'r')
- data = f.read()
- f.close()
- if data.endswith('\r\n') or data.endswith('\r'):
- error = ("Bad end-of-line style in the .py files. Typically "
- "caused by a zip file or a checkout done on Windows and "
- "moved to Unix or vice-versa.")
- if error:
- raise EnvironmentError("Invalid source tree - bogus checkout! " +
- error)
-
- pypy_root = os.path.join(head, '')
- try:
- sys.path.remove(head)
- except ValueError:
- pass
- sys.path.insert(0, head)
-
- munged = {}
- for name, mod in sys.modules.items():
- if '.' in name:
- continue
- fn = getattr(mod, '__file__', None)
- if not isinstance(fn, str):
- continue
- newname = os.path.splitext(os.path.basename(fn))[0]
- if not newname.startswith(part + '.'):
- continue
- path = os.path.join(os.path.dirname(os.path.realpath(fn)), '')
- if path.startswith(pypy_root) and newname != part:
- modpaths = os.path.normpath(path[len(pypy_root):]).split(os.sep)
- if newname != '__init__':
- modpaths.append(newname)
- modpath = '.'.join(modpaths)
- if modpath not in sys.modules:
- munged[modpath] = mod
-
- for name, mod in munged.iteritems():
- if name not in sys.modules:
- sys.modules[name] = mod
- if '.' in name:
- prename = name[:name.rfind('.')]
- postname = name[len(prename)+1:]
- if prename not in sys.modules:
- __import__(prename)
- if not hasattr(sys.modules[prename], postname):
- setattr(sys.modules[prename], postname, mod)
-
- return partdir, this_dir
-
-def __clone():
- """ clone master version of autopath.py into all subdirs """
- from os.path import join, walk
- if not this_dir.endswith(join('pypy','tool')):
- raise EnvironmentError("can only clone master version "
- "'%s'" % join(pypydir, 'tool',_myname))
-
-
- def sync_walker(arg, dirname, fnames):
- if _myname in fnames:
- fn = join(dirname, _myname)
- f = open(fn, 'rwb+')
- try:
- if f.read() == arg:
- print "checkok", fn
- else:
- print "syncing", fn
- f = open(fn, 'w')
- f.write(arg)
- finally:
- f.close()
- s = open(join(pypydir, 'tool', _myname), 'rb').read()
- walk(pypydir, sync_walker, s)
-
-_myname = 'autopath.py'
-
-# set guaranteed attributes
-
-pypydir, this_dir = __dirinfo('pypy')
-
-if __name__ == '__main__':
- __clone()
diff --git a/lib_pypy/ctypes_config_cache/dumpcache.py b/lib_pypy/ctypes_config_cache/dumpcache.py
--- a/lib_pypy/ctypes_config_cache/dumpcache.py
+++ b/lib_pypy/ctypes_config_cache/dumpcache.py
@@ -1,6 +1,6 @@
import os
from ctypes_configure import dumpcache
-from pypy.jit.backend import detect_cpu
+from rpython.jit.backend import detect_cpu
def dumpcache2(basename, config):
model = detect_cpu.autodetect_main_model_and_size()
@@ -14,7 +14,7 @@
try:
from __pypy__ import cpumodel
except ImportError:
- from pypy.jit.backend import detect_cpu
+ from rpython.jit.backend import detect_cpu
cpumodel = detect_cpu.autodetect_main_model_and_size()
# XXX relative import, should be removed together with
# XXX the relative imports done e.g. by lib_pypy/pypy_test/test_hashlib
diff --git a/lib_pypy/ctypes_config_cache/rebuild.py b/lib_pypy/ctypes_config_cache/rebuild.py
--- a/lib_pypy/ctypes_config_cache/rebuild.py
+++ b/lib_pypy/ctypes_config_cache/rebuild.py
@@ -1,21 +1,15 @@
#! /usr/bin/env python
# Run this script to rebuild all caches from the *.ctc.py files.
-# hack: we cannot directly import autopath, as we are outside the pypy
-# package. However, we pretend to be inside pypy/tool and manually run it, to
-# get the correct path
-import os.path
-this_dir = os.path.dirname(__file__)
-autopath_py = os.path.join(this_dir, '../../pypy/tool/autopath.py')
-autopath_py = os.path.abspath(autopath_py)
-execfile(autopath_py, dict(__name__='autopath', __file__=autopath_py))
+import os, sys
-import os, sys
+sys.path.insert(0, os.path.realpath(os.path.join(os.path.dirname(__file__), '..', '..')))
+
import py
_dirpath = os.path.dirname(__file__) or os.curdir
-from pypy.tool.ansi_print import ansi_log
+from rpython.tool.ansi_print import ansi_log
log = py.log.Producer("ctypes_config_cache")
py.log.setconsumer("ctypes_config_cache", ansi_log)
@@ -31,7 +25,7 @@
sys.path[:] = path
def try_rebuild():
- from pypy.jit.backend import detect_cpu
+ from rpython.jit.backend import detect_cpu
model = detect_cpu.autodetect_main_model_and_size()
# remove the files '_*_model_.py'
left = {}
diff --git a/lib_pypy/ctypes_config_cache/test/test_cache.py b/lib_pypy/ctypes_config_cache/test/test_cache.py
--- a/lib_pypy/ctypes_config_cache/test/test_cache.py
+++ b/lib_pypy/ctypes_config_cache/test/test_cache.py
@@ -1,6 +1,6 @@
import py
import sys, os
-from pypy.tool.udir import udir
+from rpython.tool.udir import udir
dirpath = py.path.local(__file__).dirpath().dirpath()
diff --git a/lib_pypy/pypy_test/test_dbm_extra.py b/lib_pypy/pypy_test/test_dbm_extra.py
--- a/lib_pypy/pypy_test/test_dbm_extra.py
+++ b/lib_pypy/pypy_test/test_dbm_extra.py
@@ -1,6 +1,6 @@
from __future__ import absolute_import
import py
-from pypy.tool.udir import udir
+from rpython.tool.udir import udir
try:
from lib_pypy import dbm
except ImportError, e:
diff --git a/lib_pypy/pypy_test/test_marshal_extra.py b/lib_pypy/pypy_test/test_marshal_extra.py
--- a/lib_pypy/pypy_test/test_marshal_extra.py
+++ b/lib_pypy/pypy_test/test_marshal_extra.py
@@ -4,7 +4,7 @@
import marshal as cpy_marshal
from lib_pypy import _marshal as marshal
-from pypy.tool.udir import udir
+from rpython.tool.udir import udir
hello = "he"
hello += "llo"
diff --git a/pypy/annotation/annrpython.py b/pypy/annotation/annrpython.py
deleted file mode 100644
--- a/pypy/annotation/annrpython.py
+++ /dev/null
@@ -1,676 +0,0 @@
-from __future__ import absolute_import
-
-import types
-from pypy.tool.ansi_print import ansi_log
-from pypy.tool.pairtype import pair
-from pypy.tool.error import (format_blocked_annotation_error,
- AnnotatorError, gather_error, ErrorWrapper)
-from pypy.objspace.flow.model import (Variable, Constant, FunctionGraph,
- c_last_exception, checkgraph)
-from pypy.translator import simplify, transform
-from pypy.annotation import model as annmodel, signature, unaryop, binaryop
-from pypy.annotation.bookkeeper import Bookkeeper
-import py
-log = py.log.Producer("annrpython")
-py.log.setconsumer("annrpython", ansi_log)
-
-
-FAIL = object()
-
-class RPythonAnnotator(object):
- """Block annotator for RPython.
- See description in doc/translation.txt."""
-
- def __init__(self, translator=None, policy=None, bookkeeper=None):
- import pypy.rpython.ootypesystem.ooregistry # has side effects
- import pypy.rpython.extfuncregistry # has side effects
- import pypy.rlib.nonconst # has side effects
-
- if translator is None:
- # interface for tests
- from pypy.translator.translator import TranslationContext
- translator = TranslationContext()
- translator.annotator = self
- self.translator = translator
- self.pendingblocks = {} # map {block: graph-containing-it}
- self.bindings = {} # map Variables to SomeValues
- self.annotated = {} # set of blocks already seen
- self.added_blocks = None # see processblock() below
- 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, index)}
- # --- the following information is recorded for debugging ---
- self.blocked_graphs = {} # set of graphs that have blocked blocks
- # --- end of debugging information ---
- self.frozen = False
- if policy is None:
- from pypy.annotation.policy import AnnotatorPolicy
- self.policy = AnnotatorPolicy()
- else:
- self.policy = policy
- if bookkeeper is None:
- bookkeeper = Bookkeeper(self)
- self.bookkeeper = bookkeeper
-
- def __getstate__(self):
- attrs = """translator pendingblocks bindings annotated links_followed
- notify bookkeeper frozen policy added_blocks""".split()
- ret = self.__dict__.copy()
- for key, value in ret.items():
- if key not in attrs:
- assert type(value) is dict, (
- "%r is not dict. please update %s.__getstate__" %
- (key, self.__class__.__name__))
- ret[key] = {}
- return ret
-
- #___ convenience high-level interface __________________
-
- def build_types(self, function, input_arg_types, complete_now=True,
- main_entry_point=False):
- """Recursively build annotations about the specific entry point."""
- assert isinstance(function, types.FunctionType), "fix that!"
-
- from pypy.annotation.policy import AnnotatorPolicy
- policy = AnnotatorPolicy()
- # make input arguments and set their type
- args_s = [self.typeannotation(t) for t in input_arg_types]
-
- # XXX hack
- annmodel.TLS.check_str_without_nul = (
- self.translator.config.translation.check_str_without_nul)
-
- flowgraph, inputcells = self.get_call_parameters(function, args_s, policy)
- if not isinstance(flowgraph, FunctionGraph):
- assert isinstance(flowgraph, annmodel.SomeObject)
- return flowgraph
-
- if main_entry_point:
- self.translator.entry_point_graph = flowgraph
- return self.build_graph_types(flowgraph, inputcells, complete_now=complete_now)
-
- def get_call_parameters(self, function, args_s, policy):
- desc = self.bookkeeper.getdesc(function)
- args = self.bookkeeper.build_args("simple_call", args_s[:])
- result = []
- def schedule(graph, inputcells):
- result.append((graph, inputcells))
- return annmodel.s_ImpossibleValue
-
- prevpolicy = self.policy
- self.policy = policy
- self.bookkeeper.enter(None)
- try:
- desc.pycall(schedule, args, annmodel.s_ImpossibleValue)
- finally:
- self.bookkeeper.leave()
- self.policy = prevpolicy
- [(graph, inputcells)] = result
- return graph, inputcells
-
- def annotate_helper(self, function, args_s, policy=None):
- if policy is None:
- from pypy.annotation.policy import AnnotatorPolicy
- policy = AnnotatorPolicy()
- graph, inputcells = self.get_call_parameters(function, args_s, policy)
- self.build_graph_types(graph, inputcells, complete_now=False)
- self.complete_helpers(policy)
- return graph
-
- def complete_helpers(self, policy):
- saved = self.policy, self.added_blocks
- self.policy = policy
- try:
- self.added_blocks = {}
- self.complete()
- # invoke annotation simplifications for the new blocks
- self.simplify(block_subset=self.added_blocks)
- finally:
- self.policy, self.added_blocks = saved
-
- def build_graph_types(self, flowgraph, inputcells, complete_now=True):
- checkgraph(flowgraph)
-
- nbarg = len(flowgraph.getargs())
- if len(inputcells) != nbarg:
- raise TypeError("%s expects %d args, got %d" %(
- flowgraph, nbarg, len(inputcells)))
-
- # register the entry point
- self.addpendinggraph(flowgraph, inputcells)
- # recursively proceed until no more pending block is left
- if complete_now:
- self.complete()
- return self.binding(flowgraph.getreturnvar(), None)
-
- def gettype(self, variable):
- """Return the known type of a control flow graph variable,
- defaulting to 'object'."""
- if isinstance(variable, Constant):
- return type(variable.value)
- elif isinstance(variable, Variable):
- cell = self.bindings.get(variable)
- if cell:
- return cell.knowntype
- else:
- return object
- else:
- raise TypeError, ("Variable or Constant instance expected, "
- "got %r" % (variable,))
-
- def getuserclassdefinitions(self):
- """Return a list of ClassDefs."""
- return self.bookkeeper.classdefs
-
- #___ medium-level interface ____________________________
-
- def addpendinggraph(self, flowgraph, inputcells):
- self.addpendingblock(flowgraph, flowgraph.startblock, inputcells)
-
- 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
- # a graph that has already been rtyped. Safety-check the new
- # annotations that are passed in, and don't annotate the old
- # graph -- it's already low-level operations!
- for a, s_newarg in zip(graph.getargs(), cells):
- s_oldarg = self.binding(a)
- assert annmodel.unionof(s_oldarg, s_newarg) == s_oldarg
- else:
- assert not self.frozen
- for a in cells:
- assert isinstance(a, annmodel.SomeObject)
- if block not in self.annotated:
- self.bindinputargs(graph, block, cells)
- else:
- self.mergeinputargs(graph, block, cells)
- if not self.annotated[block]:
- self.pendingblocks[block] = graph
-
- def complete(self):
- """Process pending blocks until none is left."""
- while True:
- while self.pendingblocks:
- block, graph = self.pendingblocks.popitem()
- self.processblock(graph, block)
- self.policy.no_more_blocks_to_annotate(self)
- if not self.pendingblocks:
- break # finished
- # make sure that the return variables of all graphs is annotated
- if self.added_blocks is not None:
- newgraphs = [self.annotated[block] for block in self.added_blocks]
- newgraphs = dict.fromkeys(newgraphs)
- got_blocked_blocks = False in newgraphs
- else:
- newgraphs = self.translator.graphs #all of them
- got_blocked_blocks = False in self.annotated.values()
- if got_blocked_blocks:
- for graph in self.blocked_graphs.values():
- self.blocked_graphs[graph] = True
-
- blocked_blocks = [block for block, done in self.annotated.items()
- if done is False]
- assert len(blocked_blocks) == len(self.blocked_blocks)
-
- text = format_blocked_annotation_error(self, self.blocked_blocks)
- #raise SystemExit()
- raise AnnotatorError(text)
- for graph in newgraphs:
- v = graph.getreturnvar()
- if v not in self.bindings:
- self.setbinding(v, annmodel.s_ImpossibleValue)
- # policy-dependent computation
- self.bookkeeper.compute_at_fixpoint()
-
- def binding(self, arg, default=FAIL):
- "Gives the SomeValue corresponding to the given Variable or Constant."
- if isinstance(arg, Variable):
- try:
- return self.bindings[arg]
- except KeyError:
- if default is not FAIL:
- return default
- else:
- raise
- elif isinstance(arg, Constant):
- #if arg.value is undefined_value: # undefined local variables
- # return annmodel.s_ImpossibleValue
- return self.bookkeeper.immutableconstant(arg)
- else:
- raise TypeError, 'Variable or Constant expected, got %r' % (arg,)
-
- def typeannotation(self, t):
- return signature.annotation(t, self.bookkeeper)
-
- def setbinding(self, arg, s_value):
- if arg in self.bindings:
- assert s_value.contains(self.bindings[arg])
- self.bindings[arg] = s_value
-
- def transfer_binding(self, v_target, v_source):
- assert v_source in self.bindings
- self.bindings[v_target] = self.bindings[v_source]
-
- def warning(self, msg, pos=None):
- if pos is None:
- try:
- pos = self.bookkeeper.position_key
- except AttributeError:
- pos = '?'
- if pos != '?':
- pos = self.whereami(pos)
-
- log.WARNING("%s/ %s" % (pos, msg))
-
-
- #___ interface for annotator.bookkeeper _______
-
- def recursivecall(self, graph, whence, inputcells):
- if isinstance(whence, tuple):
- parent_graph, parent_block, parent_index = whence
- tag = parent_block, parent_index
- self.translator.update_call_graph(parent_graph, graph, tag)
- # 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.
- callpositions = self.notify.setdefault(graph.returnblock, {})
- if whence is not None:
- if callable(whence):
- def callback():
- whence(self, graph)
- else:
- callback = whence
- callpositions[callback] = True
-
- # generalize the function's input arguments
- self.addpendingblock(graph, graph.startblock, inputcells)
-
- # get the (current) return value
- v = graph.getreturnvar()
- try:
- return self.bindings[v]
- except KeyError:
- # the function didn't reach any return statement so far.
- # (some functions actually never do, they always raise exceptions)
- return annmodel.s_ImpossibleValue
-
- def reflowfromposition(self, position_key):
- graph, block, index = position_key
- self.reflowpendingblock(graph, block)
-
-
- #___ simplification (should be moved elsewhere?) _______
-
- def simplify(self, block_subset=None, extra_passes=None):
- # Generic simplifications
- transform.transform_graph(self, block_subset=block_subset,
- extra_passes=extra_passes)
- if block_subset is None:
- graphs = self.translator.graphs
- else:
- graphs = {}
- for block in block_subset:
- graph = self.annotated.get(block)
- if graph:
- graphs[graph] = True
- for graph in graphs:
- simplify.eliminate_empty_blocks(graph)
-
-
- #___ flowing annotations in blocks _____________________
-
- def processblock(self, graph, block):
- # Important: this is not called recursively.
- # self.flowin() can only issue calls to self.addpendingblock().
- # The analysis of a block can be in three states:
- # * block not in self.annotated:
- # never seen the block.
- # * self.annotated[block] == False:
- # the input variables of the block are in self.bindings but we
- # still have to consider all the operations in the block.
- # * self.annotated[block] == graph-containing-block:
- # analysis done (at least until we find we must generalize the
- # input variables).
-
- #print '* processblock', block, cells
- self.annotated[block] = graph
- if block in self.blocked_blocks:
- del self.blocked_blocks[block]
- try:
- self.flowin(graph, block)
- except BlockedInference, e:
- self.annotated[block] = False # failed, hopefully temporarily
- self.blocked_blocks[block] = (graph, e.opindex)
- except Exception, e:
- # hack for debug tools only
- if not hasattr(e, '__annotator_block'):
- setattr(e, '__annotator_block', block)
- raise
-
- # The dict 'added_blocks' is used by rpython.annlowlevel to
- # detect which are the new blocks that annotating an additional
- # small helper creates.
- if self.added_blocks is not None:
- self.added_blocks[block] = True
-
- def reflowpendingblock(self, graph, block):
- assert not self.frozen
- assert graph not in self.fixed_graphs
- self.pendingblocks[block] = graph
- assert block in self.annotated
- self.annotated[block] = False # must re-flow
- self.blocked_blocks[block] = (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)
- for a, cell in zip(block.inputargs, inputcells):
- self.setbinding(a, cell)
- self.annotated[block] = False # must flowin.
- self.blocked_blocks[block] = (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]
- try:
- unions = [annmodel.unionof(c1,c2) for c1, c2 in zip(oldcells,inputcells)]
- except annmodel.UnionError, e:
- e.args = e.args + (
- ErrorWrapper(gather_error(self, graph, block, None)),)
- raise
- # if the merged cells changed, we must redo the analysis
- if unions != oldcells:
- self.bindinputargs(graph, block, unions)
-
- def whereami(self, position_key):
- graph, block, i = position_key
- blk = ""
- if block:
- at = block.at()
- if at:
- blk = " block"+at
- opid=""
- if i is not None:
- opid = " op=%d" % i
- return repr(graph) + blk + opid
-
- def flowin(self, graph, block):
- #print 'Flowing', block, [self.binding(a) for a in block.inputargs]
- try:
- for i in range(len(block.operations)):
- try:
- self.bookkeeper.enter((graph, block, i))
- self.consider_op(block, i)
- finally:
- self.bookkeeper.leave()
-
- except BlockedInference, e:
- 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
- # always raise an exception which is immediately caught by
- # an exception handler. We then only follow the exceptional
- # branches.
- exits = [link for link in block.exits
- if link.exitcase is not None]
-
- elif e.op.opname in ('simple_call', 'call_args', 'next'):
- # XXX warning, keep the name of the call operations in sync
- # with the flow object space. These are the operations for
- # which it is fine to always raise an exception. We then
- # swallow the BlockedInference and that's it.
- # About 'next': see test_annotate_iter_empty_container().
- return
-
- else:
- # other cases are problematic (but will hopefully be solved
- # later by reflowing). Throw the BlockedInference up to
- # processblock().
- raise
-
- except annmodel.HarmlesslyBlocked:
- return
-
- else:
- # dead code removal: don't follow all exits if the exitswitch
- # is known
- exits = block.exits
- if isinstance(block.exitswitch, Variable):
- s_exitswitch = self.bindings[block.exitswitch]
- if s_exitswitch.is_constant():
- exits = [link for link in exits
- if link.exitcase == s_exitswitch.const]
-
- # mapping (exitcase, variable) -> s_annotation
- # that can be attached to booleans, exitswitches
- knowntypedata = getattr(self.bindings.get(block.exitswitch),
- "knowntypedata", {})
-
- # filter out those exceptions which cannot
- # occour for this specific, typed operation.
- if block.exitswitch == c_last_exception:
- op = block.operations[-1]
- if op.opname in binaryop.BINARY_OPERATIONS:
- arg1 = self.binding(op.args[0])
- arg2 = self.binding(op.args[1])
- binop = getattr(pair(arg1, arg2), op.opname, None)
- can_only_throw = annmodel.read_can_only_throw(binop, arg1, arg2)
- elif op.opname in unaryop.UNARY_OPERATIONS:
- arg1 = self.binding(op.args[0])
- opname = op.opname
- if opname == 'contains': opname = 'op_contains'
- unop = getattr(arg1, opname, None)
- can_only_throw = annmodel.read_can_only_throw(unop, arg1)
- else:
- can_only_throw = None
-
- if can_only_throw is not None:
- candidates = can_only_throw
- candidate_exits = exits
- exits = []
- for link in candidate_exits:
- case = link.exitcase
- if case is None:
- exits.append(link)
- continue
- covered = [c for c in candidates if issubclass(c, case)]
- if covered:
- exits.append(link)
- candidates = [c for c in candidates if c not in covered]
-
- for link in exits:
- in_except_block = False
-
- last_exception_var = link.last_exception # may be None for non-exception link
- last_exc_value_var = link.last_exc_value # may be None for non-exception link
-
- if isinstance(link.exitcase, (types.ClassType, type)) \
- 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.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]
-
- if isinstance(last_exception_var, Variable):
- self.setbinding(last_exception_var, last_exception_object)
- if isinstance(last_exc_value_var, Variable):
- self.setbinding(last_exc_value_var, last_exc_value_object)
-
- last_exception_object = annmodel.SomeType()
- if isinstance(last_exception_var, Constant):
- last_exception_object.const = last_exception_var.value
- #if link.exitcase is Exception:
- # last_exc_value_object = annmodel.SomeObject()
- #else:
- last_exc_value_vars = []
- in_except_block = True
-
- ignore_link = False
- cells = []
- renaming = {}
- for a,v in zip(link.args,link.target.inputargs):
- renaming.setdefault(a, []).append(v)
- for a,v in zip(link.args,link.target.inputargs):
- if a == last_exception_var:
- assert in_except_block
- cells.append(last_exception_object)
- elif a == last_exc_value_var:
- assert in_except_block
- cells.append(last_exc_value_object)
- last_exc_value_vars.append(v)
- else:
- cell = self.binding(a)
- if (link.exitcase, a) in knowntypedata:
- knownvarvalue = knowntypedata[(link.exitcase, a)]
- cell = pair(cell, knownvarvalue).improve()
- # ignore links that try to pass impossible values
- if cell == annmodel.s_ImpossibleValue:
- ignore_link = True
-
- if hasattr(cell,'is_type_of'):
- renamed_is_type_of = []
- for v in cell.is_type_of:
- new_vs = renaming.get(v,[])
- renamed_is_type_of += new_vs
- assert cell.knowntype is type
- newcell = annmodel.SomeType()
- if cell.is_constant():
- newcell.const = cell.const
- cell = newcell
- cell.is_type_of = renamed_is_type_of
-
- if hasattr(cell, 'knowntypedata'):
- renamed_knowntypedata = {}
- for (value, v), s in cell.knowntypedata.items():
- new_vs = renaming.get(v, [])
- for new_v in new_vs:
- renamed_knowntypedata[value, new_v] = s
- assert isinstance(cell, annmodel.SomeBool)
- newcell = annmodel.SomeBool()
- if cell.is_constant():
- newcell.const = cell.const
- cell = newcell
- cell.set_knowntypedata(renamed_knowntypedata)
-
- cells.append(cell)
-
- if ignore_link:
- continue
-
- if in_except_block:
- last_exception_object.is_type_of = last_exc_value_vars
-
- self.links_followed[link] = True
- self.addpendingblock(graph, link.target, cells)
-
- if block in self.notify:
- # reflow from certain positions when this block is done
- for callback in self.notify[block]:
- if isinstance(callback, tuple):
- self.reflowfromposition(callback) # callback is a position
- else:
- callback()
-
-
- #___ creating the annotations based on operations ______
-
- 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)
- if not consider_meth:
- raise Exception,"unknown op: %r" % op
-
- # let's be careful about avoiding propagated SomeImpossibleValues
- # to enter an op; the latter can result in violations of the
- # more general results invariant: e.g. if SomeImpossibleValue enters is_
- # is_(SomeImpossibleValue, None) -> SomeBool
- # is_(SomeInstance(not None), None) -> SomeBool(const=False) ...
- # boom -- in the assert of setbinding()
- for arg in argcells:
- if isinstance(arg, annmodel.SomeImpossibleValue):
- raise BlockedInference(self, op, opindex)
- try:
- resultcell = consider_meth(*argcells)
- except Exception, e:
- graph = self.bookkeeper.position_key[0]
- 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, 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
-
- def noreturnvalue(self, op):
- return annmodel.s_ImpossibleValue # no return value (hook method)
-
- # XXX "contains" clash with SomeObject method
- def consider_op_contains(self, seq, elem):
- self.bookkeeper.count("contains", seq)
- return seq.op_contains(elem)
-
- def consider_op_newtuple(self, *args):
- return annmodel.SomeTuple(items = args)
-
- def consider_op_newlist(self, *args):
- return self.bookkeeper.newlist(*args)
-
- def consider_op_newdict(self):
- return self.bookkeeper.newdict()
-
-
- def _registeroperations(cls, unary_ops, binary_ops):
- # All unary operations
- d = {}
- for opname in unary_ops:
- fnname = 'consider_op_' + opname
- exec py.code.Source("""
-def consider_op_%s(self, arg, *args):
- return arg.%s(*args)
-""" % (opname, opname)).compile() in globals(), d
- setattr(cls, fnname, d[fnname])
- # All binary operations
- for opname in binary_ops:
- fnname = 'consider_op_' + opname
- exec py.code.Source("""
-def consider_op_%s(self, arg1, arg2, *args):
- return pair(arg1,arg2).%s(*args)
-""" % (opname, opname)).compile() in globals(), d
- setattr(cls, fnname, d[fnname])
- _registeroperations = classmethod(_registeroperations)
-
-# register simple operations handling
-RPythonAnnotator._registeroperations(unaryop.UNARY_OPERATIONS, binaryop.BINARY_OPERATIONS)
-
-
-class BlockedInference(Exception):
- """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, 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:
- break_at = "?"
- else:
- break_at = self.annotator.whereami(self.break_at)
- return "<BlockedInference break_at %s [%s]>" %(break_at, self.op)
-
- __str__ = __repr__
diff --git a/pypy/annotation/binaryop.py b/pypy/annotation/binaryop.py
deleted file mode 100644
--- a/pypy/annotation/binaryop.py
+++ /dev/null
@@ -1,1052 +0,0 @@
-"""
-Binary operations between SomeValues.
-"""
-
-import py
-import operator
-from pypy.tool.pairtype import pair, pairtype
-from pypy.annotation.model import SomeObject, SomeInteger, SomeBool, s_Bool
-from pypy.annotation.model import SomeString, SomeChar, SomeList, SomeDict
-from pypy.annotation.model import SomeUnicodeCodePoint, SomeUnicodeString
-from pypy.annotation.model import SomeTuple, SomeImpossibleValue, s_ImpossibleValue
-from pypy.annotation.model import SomeInstance, SomeBuiltin, SomeIterator
-from pypy.annotation.model import SomePBC, SomeFloat, s_None, SomeByteArray
-from pypy.annotation.model import SomeExternalObject, SomeWeakRef
-from pypy.annotation.model import SomeAddress, SomeTypedAddressAccess
-from pypy.annotation.model import SomeSingleFloat, SomeLongFloat, SomeType
-from pypy.annotation.model import unionof, UnionError, missing_operation
-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
-from pypy.annotation.bookkeeper import getbookkeeper
-from pypy.objspace.flow.model import Variable, Constant
-from pypy.rlib import rarithmetic
-from pypy.tool.error import AnnotatorError
-
-# convenience only!
-def immutablevalue(x):
- return getbookkeeper().immutablevalue(x)
-
-# XXX unify this with ObjSpace.MethodTable
-BINARY_OPERATIONS = set(['add', 'sub', 'mul', 'div', 'mod',
- 'truediv', 'floordiv', 'divmod',
- 'and_', 'or_', 'xor',
- 'lshift', 'rshift',
- 'getitem', 'setitem', 'delitem',
- 'getitem_idx', 'getitem_key', 'getitem_idx_key',
- 'inplace_add', 'inplace_sub', 'inplace_mul',
- 'inplace_truediv', 'inplace_floordiv', 'inplace_div',
- 'inplace_mod',
- 'inplace_lshift', 'inplace_rshift',
- 'inplace_and', 'inplace_or', 'inplace_xor',
- 'lt', 'le', 'eq', 'ne', 'gt', 'ge', 'is_', 'cmp',
- 'coerce',
- ]
- +[opname+'_ovf' for opname in
- """add sub mul floordiv div mod lshift
- """.split()
- ])
-
-for opname in BINARY_OPERATIONS:
- missing_operation(pairtype(SomeObject, SomeObject), opname)
-
-class __extend__(pairtype(SomeObject, SomeObject)):
-
- def union((obj1, obj2)):
- raise UnionError(obj1, obj2)
-
- # inplace_xxx ---> xxx by default
- def inplace_add((obj1, obj2)): return pair(obj1, obj2).add()
- def inplace_sub((obj1, obj2)): return pair(obj1, obj2).sub()
- def inplace_mul((obj1, obj2)): return pair(obj1, obj2).mul()
- def inplace_truediv((obj1, obj2)): return pair(obj1, obj2).truediv()
- def inplace_floordiv((obj1, obj2)): return pair(obj1, obj2).floordiv()
- def inplace_div((obj1, obj2)): return pair(obj1, obj2).div()
- def inplace_mod((obj1, obj2)): return pair(obj1, obj2).mod()
- def inplace_lshift((obj1, obj2)): return pair(obj1, obj2).lshift()
- def inplace_rshift((obj1, obj2)): return pair(obj1, obj2).rshift()
- def inplace_and((obj1, obj2)): return pair(obj1, obj2).and_()
- def inplace_or((obj1, obj2)): return pair(obj1, obj2).or_()
- def inplace_xor((obj1, obj2)): return pair(obj1, obj2).xor()
-
- for name, func in locals().items():
- if name.startswith('inplace_'):
- func.can_only_throw = []
-
- inplace_div.can_only_throw = [ZeroDivisionError]
- inplace_truediv.can_only_throw = [ZeroDivisionError]
- inplace_floordiv.can_only_throw = [ZeroDivisionError]
- inplace_mod.can_only_throw = [ZeroDivisionError]
-
- def lt((obj1, obj2)):
- if obj1.is_immutable_constant() and obj2.is_immutable_constant():
- return immutablevalue(obj1.const < obj2.const)
- else:
- getbookkeeper().count("non_int_comp", obj1, obj2)
- return s_Bool
-
- def le((obj1, obj2)):
- if obj1.is_immutable_constant() and obj2.is_immutable_constant():
- return immutablevalue(obj1.const <= obj2.const)
- else:
- getbookkeeper().count("non_int_comp", obj1, obj2)
- return s_Bool
-
- def eq((obj1, obj2)):
- if obj1.is_immutable_constant() and obj2.is_immutable_constant():
- return immutablevalue(obj1.const == obj2.const)
- else:
- getbookkeeper().count("non_int_eq", obj1, obj2)
- return s_Bool
-
- def ne((obj1, obj2)):
- if obj1.is_immutable_constant() and obj2.is_immutable_constant():
- return immutablevalue(obj1.const != obj2.const)
- else:
- getbookkeeper().count("non_int_eq", obj1, obj2)
- return s_Bool
-
- def gt((obj1, obj2)):
- if obj1.is_immutable_constant() and obj2.is_immutable_constant():
- return immutablevalue(obj1.const > obj2.const)
- else:
- getbookkeeper().count("non_int_comp", obj1, obj2)
- return s_Bool
-
- def ge((obj1, obj2)):
- if obj1.is_immutable_constant() and obj2.is_immutable_constant():
- return immutablevalue(obj1.const >= obj2.const)
- else:
- getbookkeeper().count("non_int_comp", obj1, obj2)
- return s_Bool
-
- def cmp((obj1, obj2)):
- getbookkeeper().count("cmp", obj1, obj2)
- if obj1.is_immutable_constant() and obj2.is_immutable_constant():
- return immutablevalue(cmp(obj1.const, obj2.const))
- else:
- return SomeInteger()
-
- def is_((obj1, obj2)):
- r = SomeBool()
- if obj2.is_constant():
- if obj1.is_constant():
- r.const = obj1.const is obj2.const
- if obj2.const is None and not obj1.can_be_none():
- r.const = False
- elif obj1.is_constant():
- if obj1.const is None and not obj2.can_be_none():
- r.const = False
- # XXX HACK HACK HACK
- # XXX HACK HACK HACK
- # XXX HACK HACK HACK
- bk = getbookkeeper()
- if bk is not None: # for testing
- knowntypedata = {}
- fn, block, i = bk.position_key
-
- annotator = bk.annotator
- op = block.operations[i]
- assert op.opname == "is_"
- assert len(op.args) == 2
-
- def bind(src_obj, tgt_obj, tgt_arg):
- if hasattr(tgt_obj, 'is_type_of') and src_obj.is_constant():
- add_knowntypedata(knowntypedata, True, tgt_obj.is_type_of,
- bk.valueoftype(src_obj.const))
-
- assert annotator.binding(op.args[tgt_arg]) == tgt_obj
- add_knowntypedata(knowntypedata, True, [op.args[tgt_arg]], src_obj)
-
- nonnone_obj = tgt_obj
- if src_obj.is_constant() and src_obj.const is None and tgt_obj.can_be_none():
- nonnone_obj = tgt_obj.nonnoneify()
-
- add_knowntypedata(knowntypedata, False, [op.args[tgt_arg]], nonnone_obj)
-
- bind(obj2, obj1, 0)
- bind(obj1, obj2, 1)
- r.set_knowntypedata(knowntypedata)
-
- return r
-
- def divmod((obj1, obj2)):
- getbookkeeper().count("divmod", obj1, obj2)
- return SomeTuple([pair(obj1, obj2).div(), pair(obj1, obj2).mod()])
-
- def coerce((obj1, obj2)):
- getbookkeeper().count("coerce", obj1, obj2)
- return pair(obj1, obj2).union() # reasonable enough
-
- # approximation of an annotation intersection, the result should be the annotation obj or
- # the intersection of obj and improvement
- def improve((obj, improvement)):
- if not improvement.contains(obj) and obj.contains(improvement):
- return improvement
- else:
- return obj
-
- # checked getitems
-
- def _getitem_can_only_throw(s_c1, s_o2):
- impl = pair(s_c1, s_o2).getitem
- return read_can_only_throw(impl, s_c1, s_o2)
-
- def getitem_idx_key((s_c1, s_o2)):
- impl = pair(s_c1, s_o2).getitem
- return impl()
- getitem_idx_key.can_only_throw = _getitem_can_only_throw
-
- 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):
- newfunc = type(f)(f.func_code, f.func_globals, f.func_name,
- f.func_defaults, f.func_closure)
- if can_only_throw is not None:
- newfunc.can_only_throw = can_only_throw
- return newfunc
-
-class __extend__(pairtype(SomeInteger, SomeInteger)):
- # unsignedness is considered a rare and contagious disease
-
- def union((int1, int2)):
- if int1.unsigned == int2.unsigned:
- knowntype = rarithmetic.compute_restype(int1.knowntype, int2.knowntype)
- else:
- t1 = int1.knowntype
- if t1 is bool:
- t1 = int
- t2 = int2.knowntype
- if t2 is bool:
- t2 = int
-
- if t2 is int:
- if int2.nonneg == False:
- raise UnionError, "Merging %s and a possibly negative int is not allowed" % t1
- knowntype = t1
- elif t1 is int:
- if int1.nonneg == False:
- raise UnionError, "Merging %s and a possibly negative int is not allowed" % t2
- knowntype = t2
- else:
- raise UnionError, "Merging these types (%s, %s) is not supported" % (t1, t2)
- return SomeInteger(nonneg=int1.nonneg and int2.nonneg,
- knowntype=knowntype)
-
- or_ = xor = add = mul = _clone(union, [])
- add_ovf = mul_ovf = _clone(union, [OverflowError])
- div = floordiv = mod = _clone(union, [ZeroDivisionError])
- div_ovf= floordiv_ovf = mod_ovf = _clone(union, [ZeroDivisionError, OverflowError])
-
- def truediv((int1, int2)):
- return SomeFloat()
- truediv.can_only_throw = [ZeroDivisionError]
- truediv_ovf = _clone(truediv, [ZeroDivisionError, OverflowError])
-
- inplace_div = div
- inplace_truediv = truediv
-
- def sub((int1, int2)):
- knowntype = rarithmetic.compute_restype(int1.knowntype, int2.knowntype)
- return SomeInteger(knowntype=knowntype)
- sub.can_only_throw = []
- sub_ovf = _clone(sub, [OverflowError])
-
- def and_((int1, int2)):
- knowntype = rarithmetic.compute_restype(int1.knowntype, int2.knowntype)
- return SomeInteger(nonneg=int1.nonneg or int2.nonneg,
- knowntype=knowntype)
- and_.can_only_throw = []
-
- def lshift((int1, int2)):
- if isinstance(int1, SomeBool):
- return SomeInteger()
- else:
- return SomeInteger(knowntype=int1.knowntype)
- lshift.can_only_throw = []
- lshift_ovf = _clone(lshift, [OverflowError])
-
- def rshift((int1, int2)):
- if isinstance(int1, SomeBool):
- return SomeInteger(nonneg=True)
- else:
- return SomeInteger(nonneg=int1.nonneg, knowntype=int1.knowntype)
- rshift.can_only_throw = []
-
- def _compare_helper((int1, int2), opname, operation):
- r = SomeBool()
- if int1.is_immutable_constant() and int2.is_immutable_constant():
- r.const = operation(int1.const, int2.const)
- #
- # The rest of the code propagates nonneg information between
- # the two arguments.
- #
- # Doing the right thing when int1 or int2 change from signed
- # to unsigned (r_uint) is almost impossible. See test_intcmp_bug.
- # Instead, we only deduce constrains on the operands in the
- # case where they are both signed. In other words, if y is
- # nonneg then "assert x>=y" will let the annotator know that
- # x is nonneg too, but it will not work if y is unsigned.
- #
- if not (rarithmetic.signedtype(int1.knowntype) and
- rarithmetic.signedtype(int2.knowntype)):
- return r
- knowntypedata = {}
- # XXX HACK HACK HACK
- fn, block, i = getbookkeeper().position_key
- op = block.operations[i]
- assert op.opname == opname
- assert len(op.args) == 2
- def tointtype(int0):
- if int0.knowntype is bool:
- return int
- return int0.knowntype
- if int1.nonneg and isinstance(op.args[1], Variable):
- case = opname in ('lt', 'le', 'eq')
-
- add_knowntypedata(knowntypedata, case, [op.args[1]],
- SomeInteger(nonneg=True, knowntype=tointtype(int2)))
- if int2.nonneg and isinstance(op.args[0], Variable):
- case = opname in ('gt', 'ge', 'eq')
- add_knowntypedata(knowntypedata, case, [op.args[0]],
- SomeInteger(nonneg=True, knowntype=tointtype(int1)))
- r.set_knowntypedata(knowntypedata)
- # a special case for 'x < 0' or 'x >= 0',
- # where 0 is a flow graph Constant
- # (in this case we are sure that it cannot become a r_uint later)
- if (isinstance(op.args[1], Constant) and
- type(op.args[1].value) is int and # filter out Symbolics
- op.args[1].value == 0):
- if int1.nonneg:
- if opname == 'lt':
- r.const = False
- if opname == 'ge':
- r.const = True
- return r
-
- def lt(intint): return intint._compare_helper('lt', operator.lt)
- def le(intint): return intint._compare_helper('le', operator.le)
- def eq(intint): return intint._compare_helper('eq', operator.eq)
- def ne(intint): return intint._compare_helper('ne', operator.ne)
- def gt(intint): return intint._compare_helper('gt', operator.gt)
- def ge(intint): return intint._compare_helper('ge', operator.ge)
-
-
-class __extend__(pairtype(SomeBool, SomeBool)):
-
- def union((boo1, boo2)):
- s = SomeBool()
- if getattr(boo1, 'const', -1) == getattr(boo2, 'const', -2):
- s.const = boo1.const
- if hasattr(boo1, 'knowntypedata') and \
- hasattr(boo2, 'knowntypedata'):
- ktd = merge_knowntypedata(boo1.knowntypedata, boo2.knowntypedata)
- s.set_knowntypedata(ktd)
- return s
-
- def and_((boo1, boo2)):
- s = SomeBool()
- if boo1.is_constant():
- if not boo1.const:
- s.const = False
- else:
- return boo2
- if boo2.is_constant():
- if not boo2.const:
- s.const = False
- return s
-
- def or_((boo1, boo2)):
- s = SomeBool()
- if boo1.is_constant():
- if boo1.const:
- s.const = True
- else:
- return boo2
- if boo2.is_constant():
- if boo2.const:
- s.const = True
- return s
-
- def xor((boo1, boo2)):
- s = SomeBool()
- if boo1.is_constant() and boo2.is_constant():
- s.const = boo1.const ^ boo2.const
- return s
-
-class __extend__(pairtype(SomeString, SomeString)):
-
- def union((str1, str2)):
- can_be_None = str1.can_be_None or str2.can_be_None
- no_nul = str1.no_nul and str2.no_nul
- return SomeString(can_be_None=can_be_None, no_nul=no_nul)
-
- def add((str1, str2)):
- # propagate const-ness to help getattr(obj, 'prefix' + const_name)
- result = SomeString(no_nul=str1.no_nul and str2.no_nul)
- if str1.is_immutable_constant() and str2.is_immutable_constant():
- result.const = str1.const + str2.const
- return result
-
-class __extend__(pairtype(SomeByteArray, SomeByteArray)):
- def union((b1, b2)):
- can_be_None = b1.can_be_None or b2.can_be_None
- return SomeByteArray(can_be_None=can_be_None)
-
- def add((b1, b2)):
- result = SomeByteArray()
- if b1.is_immutable_constant() and b2.is_immutable_constant():
- result.const = b1.const + b2.const
- return result
-
-class __extend__(pairtype(SomeByteArray, SomeInteger)):
- def getitem((s_b, s_i)):
- return SomeInteger()
-
- def setitem((s_b, s_i), s_i2):
- assert isinstance(s_i2, SomeInteger)
-
-class __extend__(pairtype(SomeString, SomeByteArray),
- pairtype(SomeByteArray, SomeString),
- pairtype(SomeChar, SomeByteArray),
- pairtype(SomeByteArray, SomeChar)):
- def add((b1, b2)):
- result = SomeByteArray()
- if b1.is_immutable_constant() and b2.is_immutable_constant():
- result.const = b1.const + b2.const
- return result
-
-class __extend__(pairtype(SomeChar, SomeChar)):
-
- def union((chr1, chr2)):
- return SomeChar()
-
-
-class __extend__(pairtype(SomeChar, SomeUnicodeCodePoint),
- pairtype(SomeUnicodeCodePoint, SomeChar)):
- def union((uchr1, uchr2)):
- return SomeUnicodeCodePoint()
-
-class __extend__(pairtype(SomeUnicodeCodePoint, SomeUnicodeCodePoint)):
- def union((uchr1, uchr2)):
- return SomeUnicodeCodePoint()
-
- def add((chr1, chr2)):
- return SomeUnicodeString()
-
-class __extend__(pairtype(SomeString, SomeUnicodeString),
- pairtype(SomeUnicodeString, SomeString)):
- def mod((str, unistring)):
- raise NotImplementedError(
- "string formatting mixing strings and unicode not supported")
-
-
-class __extend__(pairtype(SomeString, SomeTuple),
- pairtype(SomeUnicodeString, SomeTuple)):
- def mod((s_string, s_tuple)):
- is_string = isinstance(s_string, SomeString)
- is_unicode = isinstance(s_string, SomeUnicodeString)
- assert is_string or is_unicode
- for s_item in s_tuple.items:
- if (is_unicode and isinstance(s_item, (SomeChar, SomeString)) or
- is_string and isinstance(s_item, (SomeUnicodeCodePoint,
- SomeUnicodeString))):
- raise NotImplementedError(
- "string formatting mixing strings and unicode not supported")
- getbookkeeper().count('strformat', s_string, s_tuple)
- no_nul = s_string.no_nul
- for s_item in s_tuple.items:
- if isinstance(s_item, SomeFloat):
- pass # or s_item is a subclass, like SomeInteger
- elif (isinstance(s_item, SomeString) or
- isinstance(s_item, SomeUnicodeString)) and s_item.no_nul:
- pass
- else:
- no_nul = False
- break
- return s_string.__class__(no_nul=no_nul)
-
-
-class __extend__(pairtype(SomeString, SomeObject),
- pairtype(SomeUnicodeString, SomeObject)):
-
- def mod((s_string, args)):
- getbookkeeper().count('strformat', s_string, args)
- return s_string.__class__()
-
-class __extend__(pairtype(SomeFloat, SomeFloat)):
-
- def union((flt1, flt2)):
- return SomeFloat()
-
- add = sub = mul = union
-
- def div((flt1, flt2)):
- return SomeFloat()
- div.can_only_throw = []
- truediv = div
-
- # repeat these in order to copy the 'can_only_throw' attribute
- inplace_div = div
- inplace_truediv = truediv
-
-
-class __extend__(pairtype(SomeSingleFloat, SomeSingleFloat)):
-
- def union((flt1, flt2)):
- return SomeSingleFloat()
-
-
-class __extend__(pairtype(SomeLongFloat, SomeLongFloat)):
-
- def union((flt1, flt2)):
- return SomeLongFloat()
-
-
-class __extend__(pairtype(SomeList, SomeList)):
-
- def union((lst1, lst2)):
- return SomeList(lst1.listdef.union(lst2.listdef))
-
- def add((lst1, lst2)):
- return lst1.listdef.offspring(lst2.listdef)
-
- def eq((lst1, lst2)):
- lst1.listdef.agree(lst2.listdef)
- return s_Bool
- ne = eq
-
-
-class __extend__(pairtype(SomeList, SomeObject)):
-
- def inplace_add((lst1, obj2)):
- lst1.method_extend(obj2)
- return lst1
- inplace_add.can_only_throw = []
-
- def inplace_mul((lst1, obj2)):
- lst1.listdef.resize()
- return lst1
- inplace_mul.can_only_throw = []
-
-class __extend__(pairtype(SomeTuple, SomeTuple)):
-
- def union((tup1, tup2)):
- if len(tup1.items) != len(tup2.items):
- 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 = [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)):
-
- def union((dic1, dic2)):
- return SomeDict(dic1.dictdef.union(dic2.dictdef))
-
-
-class __extend__(pairtype(SomeDict, SomeObject)):
-
- def _can_only_throw(dic1, *ignore):
- if dic1.dictdef.dictkey.custom_eq_hash:
- return None
- return [KeyError]
-
- def getitem((dic1, obj2)):
- getbookkeeper().count("dict_getitem", dic1)
- dic1.dictdef.generalize_key(obj2)
- return dic1.dictdef.read_value()
- getitem.can_only_throw = _can_only_throw
-
- def setitem((dic1, obj2), s_value):
- getbookkeeper().count("dict_setitem", dic1)
- dic1.dictdef.generalize_key(obj2)
- dic1.dictdef.generalize_value(s_value)
- setitem.can_only_throw = _can_only_throw
-
- def delitem((dic1, obj2)):
- getbookkeeper().count("dict_delitem", dic1)
- dic1.dictdef.generalize_key(obj2)
- delitem.can_only_throw = _can_only_throw
-
-
-class __extend__(pairtype(SomeTuple, SomeInteger)):
-
- def getitem((tup1, int2)):
- if int2.is_immutable_constant():
- try:
- return tup1.items[int2.const]
- except IndexError:
- return s_ImpossibleValue
- else:
- getbookkeeper().count("tuple_random_getitem", tup1)
- return unionof(*tup1.items)
- getitem.can_only_throw = [IndexError]
-
-
-class __extend__(pairtype(SomeList, SomeInteger)):
-
- def mul((lst1, int2)):
- return lst1.listdef.offspring()
-
- def getitem((lst1, int2)):
- getbookkeeper().count("list_getitem", int2)
- return lst1.listdef.read_item()
- getitem.can_only_throw = []
-
- getitem_key = getitem
-
- def getitem_idx((lst1, int2)):
- getbookkeeper().count("list_getitem", int2)
- return lst1.listdef.read_item()
- getitem_idx.can_only_throw = [IndexError]
-
- getitem_idx_key = getitem_idx
-
- def setitem((lst1, int2), s_value):
- getbookkeeper().count("list_setitem", int2)
- lst1.listdef.mutate()
- lst1.listdef.generalize(s_value)
- setitem.can_only_throw = [IndexError]
-
- def delitem((lst1, int2)):
- getbookkeeper().count("list_delitem", int2)
- lst1.listdef.resize()
- delitem.can_only_throw = [IndexError]
-
-class __extend__(pairtype(SomeString, SomeInteger)):
-
- def getitem((str1, int2)):
- getbookkeeper().count("str_getitem", int2)
- return SomeChar()
- getitem.can_only_throw = []
-
- getitem_key = getitem
-
- def getitem_idx((str1, int2)):
- getbookkeeper().count("str_getitem", int2)
- return SomeChar()
- getitem_idx.can_only_throw = [IndexError]
-
- getitem_idx_key = getitem_idx
-
- def mul((str1, int2)): # xxx do we want to support this
- getbookkeeper().count("str_mul", str1, int2)
- return SomeString(no_nul=str1.no_nul)
-
-class __extend__(pairtype(SomeUnicodeString, SomeInteger)):
- def getitem((str1, int2)):
- getbookkeeper().count("str_getitem", int2)
- return SomeUnicodeCodePoint()
- getitem.can_only_throw = []
-
- getitem_key = getitem
-
- def getitem_idx((str1, int2)):
- getbookkeeper().count("str_getitem", int2)
- return SomeUnicodeCodePoint()
- getitem_idx.can_only_throw = [IndexError]
-
- getitem_idx_key = getitem_idx
-
- def mul((str1, int2)): # xxx do we want to support this
- getbookkeeper().count("str_mul", str1, int2)
- return SomeUnicodeString()
-
-class __extend__(pairtype(SomeInteger, SomeString),
- pairtype(SomeInteger, SomeUnicodeString)):
-
- def mul((int1, str2)): # xxx do we want to support this
- getbookkeeper().count("str_mul", str2, int1)
- return str2.basestringclass()
-
-class __extend__(pairtype(SomeUnicodeCodePoint, SomeUnicodeString),
- pairtype(SomeUnicodeString, SomeUnicodeCodePoint),
- pairtype(SomeUnicodeString, SomeUnicodeString)):
- def union((str1, str2)):
- return SomeUnicodeString(can_be_None=str1.can_be_none() or
- str2.can_be_none())
-
- def add((str1, str2)):
- # propagate const-ness to help getattr(obj, 'prefix' + const_name)
- result = SomeUnicodeString()
- if str1.is_immutable_constant() and str2.is_immutable_constant():
- result.const = str1.const + str2.const
- return result
-
-class __extend__(pairtype(SomeInteger, SomeList)):
-
- def mul((int1, lst2)):
- return lst2.listdef.offspring()
-
-
-class __extend__(pairtype(SomeInstance, SomeInstance)):
-
- def union((ins1, ins2)):
- if ins1.classdef is None or ins2.classdef is None:
- # special case only
- basedef = None
- else:
- basedef = ins1.classdef.commonbase(ins2.classdef)
- if basedef is None:
- raise UnionError(ins1, ins2)
- flags = ins1.flags
- if flags:
- flags = flags.copy()
- for key, value in flags.items():
- if key not in ins2.flags or ins2.flags[key] != value:
- del flags[key]
- return SomeInstance(basedef,
- can_be_None=ins1.can_be_None or ins2.can_be_None,
- flags=flags)
-
- def improve((ins1, ins2)):
- if ins1.classdef is None:
- resdef = ins2.classdef
- elif ins2.classdef is None:
- resdef = ins1.classdef
- else:
- basedef = ins1.classdef.commonbase(ins2.classdef)
- if basedef is ins1.classdef:
- resdef = ins2.classdef
- elif basedef is ins2.classdef:
- resdef = ins1.classdef
- else:
- if ins1.can_be_None and ins2.can_be_None:
- return s_None
- else:
- return s_ImpossibleValue
- res = SomeInstance(resdef, can_be_None=ins1.can_be_None and ins2.can_be_None)
- if ins1.contains(res) and ins2.contains(res):
- return res # fine
- else:
- # this case can occur in the presence of 'const' attributes,
- # which we should try to preserve. Fall-back...
- thistype = pairtype(SomeInstance, SomeInstance)
- return super(thistype, pair(ins1, ins2)).improve()
-
-
-class __extend__(pairtype(SomeIterator, SomeIterator)):
-
- def union((iter1, iter2)):
- 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)
-
-
-class __extend__(pairtype(SomeBuiltin, SomeBuiltin)):
-
- def union((bltn1, bltn2)):
- if (bltn1.analyser != bltn2.analyser or
- bltn1.methodname != bltn2.methodname or
- 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 = unionof(bltn1.s_self, bltn2.s_self)
- return SomeBuiltin(bltn1.analyser, s_self, methodname=bltn1.methodname)
-
-class __extend__(pairtype(SomePBC, SomePBC)):
-
- def union((pbc1, pbc2)):
- d = pbc1.descriptions.copy()
- d.update(pbc2.descriptions)
- return SomePBC(d, can_be_None = pbc1.can_be_None or pbc2.can_be_None)
-
- def is_((pbc1, pbc2)):
- thistype = pairtype(SomePBC, SomePBC)
- s = super(thistype, pair(pbc1, pbc2)).is_()
- if not s.is_constant():
- if not pbc1.can_be_None or not pbc2.can_be_None:
- for desc in pbc1.descriptions:
- if desc in pbc2.descriptions:
- break
- else:
- s.const = False # no common desc in the two sets
- return s
-
-class __extend__(pairtype(SomeGenericCallable, SomePBC)):
- def union((gencall, pbc)):
- for desc in pbc.descriptions:
- unique_key = desc
- bk = desc.bookkeeper
- s_result = bk.emulate_pbc_call(unique_key, pbc, gencall.args_s)
- s_result = unionof(s_result, gencall.s_result)
- assert gencall.s_result.contains(s_result)
- return gencall
-
-class __extend__(pairtype(SomePBC, SomeGenericCallable)):
- def union((pbc, gencall)):
- return pair(gencall, pbc).union()
-
-class __extend__(pairtype(SomeImpossibleValue, SomeObject)):
- def union((imp1, obj2)):
- return obj2
-
-class __extend__(pairtype(SomeObject, SomeImpossibleValue)):
- def union((obj1, imp2)):
- return obj1
-
-# mixing Nones with other objects
-
-def _make_none_union(classname, constructor_args='', glob=None):
- if glob is None:
- glob = globals()
- loc = locals()
- source = py.code.Source("""
- class __extend__(pairtype(%(classname)s, SomePBC)):
- def union((obj, pbc)):
- if pbc.isNone():
- return %(classname)s(%(constructor_args)s)
- else:
- return SomeObject()
-
- class __extend__(pairtype(SomePBC, %(classname)s)):
- def union((pbc, obj)):
- if pbc.isNone():
- return %(classname)s(%(constructor_args)s)
- else:
- return SomeObject()
- """ % loc)
- exec source.compile() in glob
-
-_make_none_union('SomeInstance', 'classdef=obj.classdef, can_be_None=True')
-_make_none_union('SomeString', 'no_nul=obj.no_nul, can_be_None=True')
-_make_none_union('SomeUnicodeString', 'can_be_None=True')
-_make_none_union('SomeList', 'obj.listdef')
-_make_none_union('SomeDict', 'obj.dictdef')
-_make_none_union('SomeExternalObject', 'obj.knowntype')
-_make_none_union('SomeWeakRef', 'obj.classdef')
-
-# getitem on SomePBCs, in particular None fails
-
-class __extend__(pairtype(SomePBC, SomeObject)):
- def getitem((pbc, o)):
- if not pbc.isNone():
- raise AnnotatorError("getitem on %r" % pbc)
- return s_ImpossibleValue
-
- def setitem((pbc, o), s_value):
- if not pbc.isNone():
- raise AnnotatorError("setitem on %r" % pbc)
-
-class __extend__(pairtype(SomePBC, SomeString)):
- def add((pbc, o)):
- if not pbc.isNone():
- raise AnnotatorError('add on %r' % pbc)
- return s_ImpossibleValue
-
-class __extend__(pairtype(SomeString, SomePBC)):
- def add((o, pbc)):
- if not pbc.isNone():
- raise AnnotatorError('add on %r' % pbc)
- return s_ImpossibleValue
-
-class __extend__(pairtype(SomeExternalObject, SomeExternalObject)):
- def union((ext1, ext2)):
- if ext1.knowntype == ext2.knowntype:
- return SomeExternalObject(ext1.knowntype)
- return SomeObject()
-
-# ____________________________________________________________
-# annotation of low-level types
-from pypy.annotation.model import SomePtr, SomeOOInstance, SomeOOClass
-from pypy.annotation.model import SomeOOObject
-from pypy.annotation.model import ll_to_annotation, annotation_to_lltype
-from pypy.rpython.ootypesystem import ootype
-
-_make_none_union('SomeOOInstance', 'ootype=obj.ootype, can_be_None=True')
-
-class __extend__(pairtype(SomePtr, SomePtr)):
- def union((p1, p2)):
- assert p1.ll_ptrtype == p2.ll_ptrtype,("mixing of incompatible pointer types: %r, %r" %
- (p1.ll_ptrtype, p2.ll_ptrtype))
- return SomePtr(p1.ll_ptrtype)
-
-class __extend__(pairtype(SomePtr, SomeInteger)):
-
- def getitem((p, int1)):
- example = p.ll_ptrtype._example()
- try:
- v = example[0]
- except IndexError:
- return None # impossible value, e.g. FixedSizeArray(0)
- return ll_to_annotation(v)
- getitem.can_only_throw = []
-
- def setitem((p, int1), s_value): # just doing checking
- example = p.ll_ptrtype._example()
- if example[0] is not None: # ignore Void s_value
- v_lltype = annotation_to_lltype(s_value)
- example[0] = v_lltype._defl()
- setitem.can_only_throw = []
-
-class __extend__(pairtype(SomePtr, SomeObject)):
- def union((p, obj)):
- assert False, ("mixing pointer type %r with something else %r" % (p.ll_ptrtype, obj))
-
- def getitem((p, obj)):
- assert False,"ptr %r getitem index not an int: %r" % (p.ll_ptrtype, obj)
-
- def setitem((p, obj), s_value):
- assert False,"ptr %r setitem index not an int: %r" % (p.ll_ptrtype, obj)
-
-class __extend__(pairtype(SomeObject, SomePtr)):
- def union((obj, p2)):
- return pair(p2, obj).union()
-
-
-class __extend__(pairtype(SomeOOInstance, SomeOOInstance)):
- def union((r1, r2)):
- common = ootype.commonBaseclass(r1.ootype, r2.ootype)
- assert common is not None, 'Mixing of incompatible instances %r, %r' %(r1.ootype, r2.ootype)
- return SomeOOInstance(common, can_be_None=r1.can_be_None or r2.can_be_None)
-
-class __extend__(pairtype(SomeOOClass, SomeOOClass)):
- def union((r1, r2)):
- if r1.ootype is None:
- common = r2.ootype
- elif r2.ootype is None:
- common = r1.ootype
- elif r1.ootype == r2.ootype:
- common = r1.ootype
- elif isinstance(r1.ootype, ootype.Instance) and isinstance(r2.ootype, ootype.Instance):
- common = ootype.commonBaseclass(r1.ootype, r2.ootype)
- assert common is not None, ('Mixing of incompatible classes %r, %r'
- % (r1.ootype, r2.ootype))
- else:
- common = ootype.Object
- return SomeOOClass(common)
-
-class __extend__(pairtype(SomeOOInstance, SomeObject)):
- def union((r, obj)):
- assert False, ("mixing reference type %r with something else %r" % (r.ootype, obj))
-
-class __extend__(pairtype(SomeObject, SomeOOInstance)):
- def union((obj, r2)):
- return pair(r2, obj).union()
-
-class __extend__(pairtype(SomeOOObject, SomeOOObject)):
- def union((r1, r2)):
- assert r1.ootype is ootype.Object and r2.ootype is ootype.Object
- return SomeOOObject()
-
-#_________________________________________
-# weakrefs
-
-class __extend__(pairtype(SomeWeakRef, SomeWeakRef)):
- def union((s_wrf1, s_wrf2)):
- if s_wrf1.classdef is None:
- basedef = s_wrf2.classdef # s_wrf1 is known to be dead
- elif s_wrf2.classdef is None:
- basedef = s_wrf1.classdef # s_wrf2 is known to be dead
- else:
- basedef = s_wrf1.classdef.commonbase(s_wrf2.classdef)
- if basedef is None: # no common base class! complain...
- return SomeObject()
- return SomeWeakRef(basedef)
-
-#_________________________________________
-# memory addresses
-
-class __extend__(pairtype(SomeAddress, SomeAddress)):
- def union((s_addr1, s_addr2)):
- return SomeAddress()
-
- def sub((s_addr1, s_addr2)):
- if s_addr1.is_null_address() and s_addr2.is_null_address():
- return getbookkeeper().immutablevalue(0)
- return SomeInteger()
-
- def is_((s_addr1, s_addr2)):
- assert False, "comparisons with is not supported by addresses"
-
-class __extend__(pairtype(SomeTypedAddressAccess, SomeTypedAddressAccess)):
- def union((s_taa1, s_taa2)):
- assert s_taa1.type == s_taa2.type
- return s_taa1
-
-class __extend__(pairtype(SomeTypedAddressAccess, SomeInteger)):
- def getitem((s_taa, s_int)):
- from pypy.annotation.model import lltype_to_annotation
- return lltype_to_annotation(s_taa.type)
- getitem.can_only_throw = []
-
- def setitem((s_taa, s_int), s_value):
- from pypy.annotation.model import annotation_to_lltype
- assert annotation_to_lltype(s_value) is s_taa.type
- setitem.can_only_throw = []
-
-
-class __extend__(pairtype(SomeAddress, SomeInteger)):
- def add((s_addr, s_int)):
- return SomeAddress()
-
- def sub((s_addr, s_int)):
- return SomeAddress()
-
-class __extend__(pairtype(SomeAddress, SomeImpossibleValue)):
- # need to override this specifically to hide the 'raise UnionError'
- # of pairtype(SomeAddress, SomeObject).
- def union((s_addr, s_imp)):
- return s_addr
-
-class __extend__(pairtype(SomeImpossibleValue, SomeAddress)):
- # need to override this specifically to hide the 'raise UnionError'
- # of pairtype(SomeObject, SomeAddress).
- def union((s_imp, s_addr)):
- return s_addr
-
-class __extend__(pairtype(SomeAddress, SomeObject)):
- def union((s_addr, s_obj)):
- raise UnionError, "union of address and anything else makes no sense"
-
-class __extend__(pairtype(SomeObject, SomeAddress)):
- def union((s_obj, s_addr)):
- raise UnionError, "union of address and anything else makes no sense"
diff --git a/pypy/annotation/bookkeeper.py b/pypy/annotation/bookkeeper.py
deleted file mode 100644
--- a/pypy/annotation/bookkeeper.py
+++ /dev/null
@@ -1,797 +0,0 @@
-"""
-The Bookkeeper class.
-"""
-
-from __future__ import absolute_import
-
-import sys, types, inspect, weakref
-
-from pypy.objspace.flow.model import Constant
More information about the pypy-commit
mailing list