[pypy-svn] rev 2489 - in pypy/trunk/src/pypy: annotation annotation/testtranslator translator/test
arigo at codespeak.net
arigo at codespeak.net
Thu Dec 18 13:16:54 CET 2003
Author: arigo
Date: Thu Dec 18 13:16:53 2003
New Revision: 2489
Removed:
pypy/trunk/src/pypy/translator/annheap.py
pypy/trunk/src/pypy/translator/annotation.py
pypy/trunk/src/pypy/translator/test/test_annheap.py
pypy/trunk/src/pypy/translator/test/test_annotation.py
Modified:
pypy/trunk/src/pypy/annotation/annset.py
pypy/trunk/src/pypy/annotation/model.py
pypy/trunk/src/pypy/annotation/test/test_annset.py
pypy/trunk/src/pypy/translator/annrpython.py
pypy/trunk/src/pypy/translator/translator.py
Log:
Started to port translator to the new annotations.
Currently only translator.py can be imported, not gencl nor genpyrex.
Modified: pypy/trunk/src/pypy/annotation/annset.py
==============================================================================
--- pypy/trunk/src/pypy/annotation/annset.py (original)
+++ pypy/trunk/src/pypy/annotation/annset.py Thu Dec 18 13:16:53 2003
@@ -6,6 +6,10 @@
QUERYARG = QueryArgument()
+class IDontKnow(Exception):
+ pass
+
+
class AnnotationSet:
"""An annotation set is a (large) family of Annotations."""
@@ -109,15 +113,6 @@
""" list all matching annotations."""
return list(self._annmatches(checkann))
- def queryconstant(self, cell):
- "Return the list of all 'x' such that ANN.constant(x)[cell] is set."
- cell = self.normalized(cell)
- result = []
- for ann in self.annlist:
- if isinstance(ann.predicate, ConstPredicate) and ann.args[0] is cell:
- result.append(ann.predicate.value)
- return result
-
def record(self, recfunc, *args):
""" invoke the given 'recording' function by passing it a new
Recorder instance and letting it use its modification API. This API will
@@ -232,6 +227,28 @@
else:
return None
+ def get_del(self, *querylist):
+ """Like get() but kills the matching annotation."""
+ resultlist = list(self.match(*querylist))
+ assert len(resultlist) <= 1, "Confusing annotations..."
+ if resultlist:
+ matchanns, matchvalue = resultlist[0]
+ self.kill(*matchanns)
+ return matchvalue
+ else:
+ return None
+
+ def getconstant(self, cell):
+ """If cell is a constant, return its value; otherwise, raise IDontKnow.
+ Also accepts a None for convenience."""
+ if not cell:
+ raise IDontKnow
+ cell = self.normalized(cell)
+ for ann in self.annlist:
+ if isinstance(ann.predicate, ConstPredicate) and ann.args[0] is cell:
+ return ann.predicate.value
+ raise IDontKnow, cell
+
def set(self, ann):
"""Insert the annotation into the AnnotationSet."""
self.normalizeann(ann)
@@ -260,6 +277,12 @@
if knowntype in immutable_types:
self.set(ANN.immutable[someval])
+ def copytype(self, oldcell, newcell):
+ for typecell in self.query(ANN.type[oldcell, QUERYARG]):
+ self.set(ANN.type[newcell, typecell])
+ if self.findfirst(ANN.immutable[oldcell]):
+ self.set(ANN.immutable[newcell])
+
def newconstant(self, value):
cell = SomeValue()
self.set(ANN.constant(value)[cell])
Modified: pypy/trunk/src/pypy/annotation/model.py
==============================================================================
--- pypy/trunk/src/pypy/annotation/model.py (original)
+++ pypy/trunk/src/pypy/annotation/model.py Thu Dec 18 13:16:53 2003
@@ -30,6 +30,8 @@
class ANN:
add = Predicate('add', 3)
+ len = Predicate('len', 2)
+ getitem = Predicate('getitem', 3)
neg = Predicate('neg', 2)
constant = ConstPredicate
type = Predicate('type', 2)
@@ -85,6 +87,7 @@
tuple: 'tuple',
str: 'str',
bool: 'bool',
+ slice: 'slice',
types.FunctionType: 'function',
}
Modified: pypy/trunk/src/pypy/annotation/test/test_annset.py
==============================================================================
--- pypy/trunk/src/pypy/annotation/test/test_annset.py (original)
+++ pypy/trunk/src/pypy/annotation/test/test_annset.py Thu Dec 18 13:16:53 2003
@@ -3,7 +3,7 @@
from pypy.tool import test
from pypy.annotation.model import ANN, SomeValue, blackholevalue
-from pypy.annotation.annset import AnnotationSet, QUERYARG
+from pypy.annotation.annset import AnnotationSet, QUERYARG, IDontKnow
c1,c2,c3,c4 = SomeValue(), SomeValue(), SomeValue(), SomeValue()
@@ -89,15 +89,13 @@
c = a.newconstant(42)
self.assertSameSet(a, [ANN.constant(42)[c]])
- def test_queryconstant(self):
+ def test_getconstant(self):
lst = [
ANN.constant(42)[c1],
]
a = AnnotationSet(lst)
- vlist = a.queryconstant(c1)
- self.assertEquals(vlist, [42])
- vlist = a.queryconstant(c2)
- self.assertEquals(vlist, [])
+ self.assertEquals(a.getconstant(c1), 42)
+ self.assertRaises(IDontKnow, a.getconstant, c2)
def test_query_blackholevalue(self):
lst = [
@@ -301,6 +299,17 @@
a.delete(ANN.add[c1, c3, ...])
self.assertSameSet(a, lst[1:])
+ def test_get_del(self):
+ lst = [
+ ANN.add[c1, c3, c2],
+ ANN.type[c1, c4],
+ ANN.constant(int)[c4],
+ ]
+ a = AnnotationSet(lst)
+ c = a.get_del(ANN.add[c1, c3, QUERYARG])
+ self.assertSameCells(a, c, c2)
+ self.assertSameSet(a, lst[1:])
+
if __name__ == '__main__':
test.main()
Deleted: /pypy/trunk/src/pypy/translator/annheap.py
==============================================================================
--- /pypy/trunk/src/pypy/translator/annheap.py Thu Dec 18 13:16:53 2003
+++ (empty file)
@@ -1,212 +0,0 @@
-from __future__ import generators
-import types
-from annotation import Annotation, XCell, XConstant, nothingyet
-
-
-class AnnotationHeap:
- """An annotation heap is a (large) family of Annotations."""
-
- # XXX STORED AS A PLAIN LIST, THE COMPLEXITY IS PLAINLY WRONG
-
- def __init__(self, annlist=[]):
- self.annlist = list(annlist) # List of annotations
-
- def dump(self): # debugging
- for ann in self.enumerate():
- print ann
-
- def enumerate(self):
- """Enumerates all annotations in the heap."""
- return iter(self.annlist)
-
- __iter__ = enumerate
-
- def simplify(self, kill=[]):
- """Kill annotations in the list, and recursively all the annotations
- that depend on them, and simplify the resulting heap to remove
- duplicates."""
- # temporarykey() returns a tuple with all the information about
- # the annotation; equal temporarykey() means equal annotations.
- # Such keys are temporary because making new XCells shared can
- # change the temporarykey(), but this doesn't occur during
- # one call to simplify().
-
- allkeys = {} # map temporarykeys to Annotation instances
- for ann in self.annlist:
- key = ann.temporarykey()
- if key in allkeys: # duplicate?
- previous = allkeys[key]
- previous.forward_deps += ann.forward_deps # merge
- else:
- allkeys[key] = ann
-
- killkeys = {} # set of temporarykeys of annotations to remove
- for ann in kill:
- killkeys[ann.temporarykey()] = True
-
- pending = killkeys.keys()
- for key in pending:
- if key in allkeys:
- ann = allkeys[key]
- del allkeys[key] # remove annotations from the dict
- for dep in ann.forward_deps: # propagate dependencies
- depkey = dep.temporarykey()
- if depkey not in killkeys:
- killkeys[depkey] = True
- pending.append(depkey)
-
- self.annlist = allkeys.values()
-
- def merge(self, oldcell, newcell):
- """Update the heap to account for the merging of oldcell and newcell.
- Return the merged cell."""
- if newcell is nothingyet or newcell == oldcell:
- return oldcell
- elif oldcell is nothingyet:
- return newcell
- else:
- # any annotation or "constantness" about oldcell that must be killed?
- deleting = isinstance(oldcell, XConstant)
- # find the annotations common to oldcell and newcell
- common = []
- for ann in self.annlist:
- if oldcell in ann.args or oldcell == ann.result:
- test1 = rename(ann, oldcell, newcell)
- test2 = rename(ann, newcell, oldcell) # may equal 'ann'
- if test1 in self.annlist and test2 in self.annlist:
- common.append(test1)
- else:
- deleting = True
- # the involved objects are immutable if we have both
- # 'immutable() -> oldcell' and 'immutable() -> newcell'
- if Annotation('immutable', [], newcell) in common:
- # for immutable objects we can create a new cell if necessary
- if not deleting:
- return oldcell # nothing must be removed from oldcell
- else:
- resultcell = XCell() # invent a new cell
- for ann in common:
- self.annlist.append(rename(ann, newcell, resultcell))
- return resultcell
- else:
- if Annotation('immutable', [], oldcell) in self.annlist:
- pass # old was immutable, don't touch it
- elif Annotation('immutable', [], newcell) in self.annlist:
- # new is immutable, old was not, inverse the roles
- oldcell, newcell = newcell, oldcell
- else:
- # two mutable objects: we identify oldcell and newcell
- newcell.share(oldcell)
- # only keep the common annotations by listing all annotations
- # to remove, which are the ones that talk about newcell but
- # are not in 'common'.
- deleting = []
- for ann in self.annlist:
- if newcell in ann.args or newcell == ann.result:
- if ann not in common:
- deleting.append(ann)
- # apply changes
- self.simplify(kill=deleting)
- return newcell
-
-
-def rename(ann, oldcell, newcell):
- "Make a copy of 'ann' in which 'oldcell' has been replaced by 'newcell'."
- args = []
- for a in ann.args:
- if a == oldcell:
- a = newcell
- args.append(a)
- a = ann.result
- if a == oldcell:
- a = newcell
- return Annotation(ann.opname, args, a)
-
-
-class Transaction:
- """A transaction contains methods to look for annotations in the
- AnnotationHeap and create new annotations accordingly. Each
- Transaction instance records which Annotations were needed, which
- allows dependencies to be tracked."""
-
- def __init__(self, heap):
- self.heap = heap
- self.using_annotations = [] # annotations that we have used
-
- def _list_annotations(self, opname, args):
- # patch(arglist) -> arglist with None plugged where
- # there is a None in the input 'args'
- def patch(arglist):
- return arglist
- for i in range(len(args)):
- if args[i] is None:
- def patch(arglist, prevpatch=patch, i=i):
- arglist = prevpatch(arglist)[:]
- arglist[i] = None
- return arglist
-
- matchann = []
- for ann in self.heap.annlist:
- if ann.opname == opname and patch(ann.args) == args:
- matchann.append(ann)
- return matchann
-
- def get(self, opname, args):
- """Return the Cell with the annotation 'opname(args) -> Cell',
- or None if there is no such annotation or several different ones.
- Hack to generalize: a None in the args matches anything."""
- matchann = self._list_annotations(opname, args)
- if not matchann:
- return None
- else:
- result = matchann[0].result
- for ann in matchann[1:]:
- if result != ann.result:
- return None # conflicting results
- for ann in matchann:
- self.using(ann)
- return result
-
- def delete(self, opname, args):
- """Kill the annotations 'opname(args) -> *'."""
- matchann = self._list_annotations(opname, args)
- self.heap.simplify(kill=matchann)
-
- def set(self, opname, args, result):
- """Put a new annotation into the AnnotationHeap."""
- ann = Annotation(opname, args, result)
- for prev in self.using_annotations:
- prev.forward_deps.append(ann)
- self.heap.annlist.append(ann)
-
- def get_type(self, cell):
- """Get the type of 'cell', as specified by the annotations, or None.
- Returns None if cell is None."""
- if cell is None:
- return None
- assert isinstance(cell, XCell)
- c = self.get('type', [cell])
- if isinstance(c, XConstant):
- return c.value
- else:
- return None
-
- def set_type(self, cell, type):
- """Register an annotation describing the type of the object 'cell'."""
- self.set('type', [cell], XConstant(type))
- if type in immutable_types:
- self.set('immutable', [], cell)
-
- def using(self, ann):
- """Mark 'ann' as used in this transaction."""
- self.using_annotations.append(ann)
-
-
-immutable_types = {
- int: True,
- long: True,
- tuple: True,
- str: True,
- bool: True,
- types.FunctionType: True,
- }
Deleted: /pypy/trunk/src/pypy/translator/annotation.py
==============================================================================
--- /pypy/trunk/src/pypy/translator/annotation.py Thu Dec 18 13:16:53 2003
+++ (empty file)
@@ -1,137 +0,0 @@
-import weakref
-
-
-class Annotation:
- """An Annotation asserts something about heap objects represented
- by XCell instances."""
-
- # Note that this is very much like a SpaceOperation, but we keep
- # them separate because they have different purposes.
-
- # Attention, handle Annotations with care! Two Annotations that
- # were initially different could become equal when XCells become
- # shared. This is the reason why Annotations are not hashable.
-
- def __init__(self, opname, args, result):
- self.opname = opname # operation name
- self.args = list(args) # list of XCells
- self.result = result # an XCell
- self.forward_deps = [] # annotations that depend on this one
- # catch bugs involving confusion between Variables/Constants
- # and XCells/XConstants
- for cell in args + [result]:
- assert isinstance(cell, XCell)
-
- def __eq__(self, other):
- return (self.__class__ is other.__class__ and
- self.opname == other.opname and
- self.args == other.args and
- self.result == other.result)
-
- def __ne__(self, other):
- return not (self == other)
-
- def __repr__(self):
- return "%s(%s) -> %s" % (self.opname, ", ".join(map(repr, self.args)),
- self.result)
-
- def temporarykey(self):
- lst = [self.opname, self.result.temporarykey()]
- lst += [arg.temporarykey() for arg in self.args]
- return tuple(lst)
-
-def debugname(xcell, name=None, _seen = {}):
- """ return a simple name for an xcell. """
- try:
- return _seen[id(xcell)]
- except KeyError:
- if name is None:
- name = "X%d" % len(_seen)
- _seen[id(xcell)] = name
- return name
-
-class XCell:
- """A placeholder for a heap object contained in an AnnotationHeap.
- It represents an object that will actually appear at run-time in the heap.
- XCells are the arguments and return value of Annotations."""
-
- # Multiple XCells can be "shared"; a group of shared cells
- # act essentially like a single cell (they become all equal).
-
- def __init__(self):
- self.shared = [] # list of weakrefs to XCells
- # defining a group of shared cells.
-
- def __repr__(self):
- names = [debugname(cell) for cell in self.cellsingroup()]
- names.sort()
- return '=='.join(names)
-
- def __eq__(self, other):
- "Two sharing cells are equal."
- return isinstance(other, XCell) and self.is_shared(other)
-
- def __ne__(self, other):
- return not (self == other)
-
- def temporarykey(self):
- ids = [id(cell) for cell in self.cellsingroup()]
- return min(ids)
-
- def cellsingroup(self):
- if self.shared:
- l = [s() for s in self.shared]
- assert self in l
- return [c for c in l if c is not None]
- else:
- return [self]
-
- def getsharelist(self):
- if not self.shared:
- self.shared = [weakref.ref(self)]
- return self.shared
-
- def is_shared(self, other):
- "Test if two cells are shared."
- return self.shared is other.shared
-
- def share(self, other):
- "Make two cells shared."
- if not self.is_shared(other):
- lst1 = self.getsharelist()
- lst2 = other.getsharelist()
- for s in lst2:
- c = s()
- if c is not None:
- c.shared = lst1
- lst1.append(s)
-
-class XConstant(XCell):
- """A fully determined XCell. For immutable constants."""
-
- def __init__(self, value):
- XCell.__init__(self)
- self.value = value
-
- def __eq__(self, other):
- "Two constants with the same value are equal."
- return (isinstance(other, XConstant) and self.value == other.value
- or XCell.__eq__(self, other))
-
- def __repr__(self):
- if self.shared:
- return 'UNEXPECTEDLY SHARED %r' % XCell.__repr__(self)
- else:
- return 'XConstant %r' % self.value
-
-
-# The more annotations about an XCell, the least general
-# it is. Extreme case: *all* possible annotations stand for an
-# object that cannot exist (e.g. the return value of a function
-# that never returns or we didn't see return so far).
-# This is specified by using nothingyet instead of a real XCell().
-# Conversely, *no* annotation stands for any object.
-
-nothingyet = XCell()
-debugname(nothingyet, 'nothingyet')
-
Modified: pypy/trunk/src/pypy/translator/annrpython.py
==============================================================================
--- pypy/trunk/src/pypy/translator/annrpython.py (original)
+++ pypy/trunk/src/pypy/translator/annrpython.py Thu Dec 18 13:16:53 2003
@@ -1,9 +1,9 @@
from __future__ import generators
from types import FunctionType
-from pypy.translator.annheap import AnnotationHeap, Transaction
-from pypy.translator.annotation import XCell, XConstant, nothingyet
-from pypy.translator.annotation import Annotation
+from pypy.annotation.model import SomeValue, ANN, blackholevalue
+from pypy.annotation.model import intvalue, boolvalue, slicevalue
+from pypy.annotation.annset import AnnotationSet, QUERYARG, IDontKnow
from pypy.objspace.flow.model import Variable, Constant, UndefinedConstant
from pypy.objspace.flow.model import SpaceOperation
@@ -17,18 +17,13 @@
See description in doc/transation/annotation.txt."""
def __init__(self, translator=None):
- self.heap = AnnotationHeap()
- self.pendingblocks = [] # list of (block, list-of-XCells)
+ self.heap = AnnotationSet()
+ self.pendingblocks = [] # list of (block, list-of-SomeValues-args)
self.delayedblocks = [] # list of blocked blocks
- self.bindings = {} # map Variables/Constants to XCells/XConstants
+ self.bindings = self.heap.getbindings() # map Variables/Constants
+ # to SomeValues
self.annotated = {} # set of blocks already seen
self.translator = translator
- # build default annotations
- t = self.transaction()
- self.any_immutable = XCell()
- t.set('immutable', [], self.any_immutable)
- self.any_int = XCell()
- t.set_type(self.any_int, int)
#___ convenience high-level interface __________________
@@ -36,10 +31,10 @@
def build_types(self, flowgraph, input_arg_types):
"""Recursively build annotations about the specific entry point."""
# make input arguments and set their type
- inputcells = [XCell() for arg in flowgraph.getargs()]
- t = self.transaction()
+ inputcells = [SomeValue() for arg in flowgraph.getargs()]
for cell, arg_type in zip(inputcells, input_arg_types):
- t.set_type(cell, arg_type)
+ self.heap.settype(cell, arg_type)
+
# register the entry point
self.addpendingblock(flowgraph.startblock, inputcells)
# recursively proceed until no more pending block is left
@@ -52,11 +47,6 @@
"""Register an entry point into block with the given input cells."""
self.pendingblocks.append((block, cells))
- def transaction(self):
- """Start a Transaction. Each new Annotation is marked as depending
- on the Annotations queried for during the same Transation."""
- return Transaction(self.heap)
-
def complete(self):
"""Process pending blocks until none is left."""
while self.pendingblocks:
@@ -70,28 +60,21 @@
len(delayed))
def binding(self, arg):
- "XCell or XConstant corresponding to the given Variable or Constant."
+ "Gives the SomeValue corresponding to the given Variable or Constant."
try:
return self.bindings[arg]
except KeyError:
if not isinstance(arg, Constant):
raise # propagate missing bindings for Variables
if isinstance(arg, UndefinedConstant):
- result = nothingyet # undefined local variables
+ result = blackholevalue # undefined local variables
else:
- result = XConstant(arg.value)
- self.consider_const(result, arg)
+ result = self.consider_const(arg.value)
self.bindings[arg] = result
return result
- def bindnew(self, arg):
- "Force the creation of a new binding for the given Variable."
- assert isinstance(arg, Variable)
- self.bindings[arg] = result = XCell()
- return result
-
def constant(self, value):
- "Turn a value into an XConstant with the proper annotations."
+ "Turn a value into a SomeValue with the proper annotations."
return self.binding(Constant(value))
@@ -104,20 +87,22 @@
def reverse_binding(self, known_variables, cell):
"""This is a hack."""
# In simplify_calls, when we are trying to create the new
- # SpaceOperation, all we have are XCells. But SpaceOperations take
- # Variables, not XCells. Trouble is, we don't always have a Variable
- # that just happens to be bound to the given XCells. A typical
- # example would be if the tuple of arguments was created from another
- # basic block or even another function. Well I guess there is no
- # clean solution.
- if isinstance(cell, XConstant):
- return Constant(cell.value)
+ # SpaceOperation, all we have are SomeValues. But SpaceOperations take
+ # Variables, not SomeValues. Trouble is, we don't always have a
+ # Variable that just happens to be bound to the given SomeValue.
+ # A typical example would be if the tuple of arguments was created
+ # from another basic block or even another function. Well I guess
+ # there is no clean solution.
+ vlist = self.heap.queryconstant(cell)
+ if len(vlist) == 1:
+ return Constant(vlist[0])
else:
+ cell = self.heap.normalized(cell)
for v in known_variables:
if self.bindings[v] == cell:
return v
else:
- raise CannotSimplify
+ raise IDontKnow, cell
def simplify(self):
# Generic simpliciations
@@ -161,7 +146,7 @@
def bindinputargs(self, block, inputcells):
# Create the initial bindings for the input args of a block.
for a, cell in zip(block.inputargs, inputcells):
- self.bindings[a] = cell
+ self.bindings[a] = self.heap.normalized(cell)
self.annotated[block] = False # must flowin.
def mergeinputargs(self, block, inputcells):
@@ -173,9 +158,11 @@
cell1 = self.bindings[a] # old binding
oldcells.append(cell1)
newcells.append(self.heap.merge(cell1, cell2))
+ # if the merged cells changed, we must redo the analysis
+ oldcells = [self.heap.normalized(c) for c in oldcells]
+ newcells = [self.heap.normalized(c) for c in newcells]
#print '** oldcells = ', oldcells
#print '** newcells = ', newcells
- # if the merged cells changed, we must redo the analysis
if newcells != oldcells:
self.bindinputargs(block, newcells)
@@ -191,71 +178,80 @@
def consider_op(self,op):
argcells = [self.binding(a) for a in op.args]
- resultcell = self.bindnew(op.result)
- consider_meth = getattr(self,'consider_op_'+op.opname,None)
- if consider_meth is not None:
- consider_meth(argcells, resultcell, self.transaction())
-
- def consider_op_add(self, (arg1,arg2), result, t):
- type1 = t.get_type(arg1)
- type2 = t.get_type(arg2)
- if type1 is int and type2 is int:
- t.set_type(result, int)
- elif type1 in (int, long) and type2 in (int, long):
- t.set_type(result, long)
- if type1 is str and type2 is str:
- t.set_type(result, str)
- if type1 is list and type2 is list:
- t.set_type(result, list)
+ consider_meth = getattr(self,'consider_op_'+op.opname,
+ self.default_consider_op)
+ try:
+ resultcell = consider_meth(*argcells)
+ except IDontKnow:
+ resultcell = SomeValue()
+ if resultcell is blackholevalue:
+ raise DelayAnnotation # the operation cannot succeed
+ assert isinstance(resultcell, SomeValue)
+ assert isinstance(op.result, Variable)
+ self.bindings[op.result] = resultcell # bind resultcell to op.result
+
+ def default_consider_op(self, *args):
+ return SomeValue()
+
+ def consider_op_add(self, arg1, arg2):
+ result = SomeValue()
+ tp = self.heap.checktype
+ if tp(arg1, int) and tp(arg2, int):
+ self.heap.settype(result, int)
+ elif tp(arg1, (int, long)) and tp(arg2, (int, long)):
+ self.heap.settype(result, long)
+ if tp(arg1, str) and tp(arg2, str):
+ self.heap.settype(result, str)
+ if tp(arg1, list) and tp(arg2, list):
+ self.heap.settype(result, list)
# XXX propagate information about the type of the elements
+ return result
+
+ def consider_op_mul(self, arg1, arg2):
+ result = SomeValue()
+ tp = self.heap.checktype
+ if tp(arg1, int) and tp(arg2, int):
+ self.heap.settype(result, int)
+ elif tp(arg1, (int, long)) and tp(arg2, (int, long)):
+ self.heap.settype(result, long)
+ return result
- def consider_op_mul(self, (arg1,arg2), result, t):
- type1 = t.get_type(arg1)
- type2 = t.get_type(arg2)
- if type1 is int and type2 is int:
- t.set_type(result, int)
- elif type1 in (int, long) and type2 in (int, long):
- t.set_type(result, long)
-
- def consider_op_inplace_add(self, (arg1,arg2), result, t):
- type1 = t.get_type(arg1)
- type2 = t.get_type(arg1)
- if type1 is list and type2 is list:
+ def consider_op_inplace_add(self, arg1, arg2):
+ tp = self.heap.checktype
+ if tp(arg1, list) and tp(arg2, list):
# Annotations about the items of arg2 are merged with the ones about
# the items of arg1. arg2 is not modified during this operation.
# result is arg1.
- result.share(arg1)
- t.delete('len', [arg1])
- item1 = t.get('getitem', [arg1, None])
- if item1 is not None:
- item2 = t.get('getitem', [arg2, None])
- if item2 is None:
- item2 = XCell() # anything at all
+ self.heap.delete(ANN.len[arg1, ...])
+ item1 = self.heap.get_del(ANN.getitem[arg1, intvalue, QUERYARG])
+ if item1:
+ item2 = self.heap.get(ANN.getitem[arg2, intvalue, QUERYARG])
+ item2 = item2 or SomeValue() # defaults to "can be anything"
item3 = self.heap.merge(item1, item2)
- if item3 != item1:
- t.delete('getitem', [arg1, None])
- t.set('getitem', [arg1, self.any_int], item3)
+ self.heap.set(ANN.getitem[arg1, intvalue, item3])
+ return arg1
else:
- self.consider_op_add((arg1,arg2), result, t)
+ return self.consider_op_add(arg1, arg2)
- def consider_op_sub(self, (arg1,arg2), result, t):
- type1 = t.get_type(arg1)
- type2 = t.get_type(arg2)
- if type1 is int and type2 is int:
- t.set_type(result, int)
- elif type1 in (int, long) and type2 in (int, long):
- t.set_type(result, long)
+ def consider_op_sub(self, arg1, arg2):
+ result = SomeValue()
+ tp = self.heap.checktype
+ if tp(arg1, int) and tp(arg2, int):
+ self.heap.settype(result, int)
+ elif tp(arg1, (int, long)) and tp(arg2, (int, long)):
+ self.heap.settype(result, long)
+ return result
consider_op_and_ = consider_op_sub # trailing underline
consider_op_inplace_lshift = consider_op_sub
- def consider_op_is_true(self, (arg,), result, t):
- t.set_type(result, bool)
+ def consider_op_is_true(self, arg):
+ return boolvalue
consider_op_not_ = consider_op_is_true
- def consider_op_lt(self, (arg1,arg2), result, t):
- t.set_type(result, bool)
+ def consider_op_lt(self, arg1, arg2):
+ return boolvalue
consider_op_le = consider_op_lt
consider_op_eq = consider_op_lt
@@ -263,90 +259,88 @@
consider_op_gt = consider_op_lt
consider_op_ge = consider_op_lt
- def consider_op_newtuple(self, args, result, t):
- t.set_type(result,tuple)
- t.set("len", [result], self.constant(len(args)))
+ def consider_op_newtuple(self, *args):
+ result = SomeValue()
+ self.heap.settype(result, tuple)
+ self.heap.set(ANN.len[result, self.constant(len(args))])
for i in range(len(args)):
- t.set("getitem", [result, self.constant(i)], args[i])
+ self.heap.set(ANN.getitem[result, self.constant(i), args[i]])
+ return result
- def consider_op_newlist(self, args, result, t):
- t.set_type(result, list)
- t.set("len", [result], self.constant(len(args)))
- item_cell = nothingyet
+ def consider_op_newlist(self, *args):
+ result = SomeValue()
+ self.heap.settype(result, list)
+ self.heap.set(ANN.len[result, self.constant(len(args))])
+ item_cell = blackholevalue
for a in args:
item_cell = self.heap.merge(item_cell, a)
- t.set("getitem", [result, self.any_int], item_cell)
+ self.heap.set(ANN.getitem[result, intvalue, item_cell])
+ return result
- def consider_op_newslice(self, args, result, t):
- t.set_type(result, slice)
+ def consider_op_newslice(self, *args):
+ return slicevalue
- def consider_op_newdict(self, args, result, t):
- t.set_type(result, dict)
+ def consider_op_newdict(self, *args):
+ result = SomeValue()
+ self.heap.settype(result, dict)
if not args:
- t.set("len", [result], self.constant(0))
+ self.heap.set(ANN.len[result, self.constant(0)])
+ return result
+
+ def consider_op_getitem(self, arg1, arg2):
+ tp = self.heap.checktype
+ result = self.heap.get(ANN.getitem[arg1, arg2, QUERYARG])
+ if result:
+ return result
+ if tp(arg2, int): # not too nice, but needed for lists
+ result = self.heap.get(ANN.getitem[arg1, intvalue, QUERYARG])
+ if result:
+ return result
+ result = SomeValue()
+ if tp(arg2, slice):
+ self.heap.copytype(arg1, result)
+ return result
- def consider_op_getitem(self, (arg1,arg2), result, t):
- type1 = t.get_type(arg1)
- type2 = t.get_type(arg2)
- if type1 in (list, tuple) and type2 is slice:
- t.set_type(result, type1)
-
- def decode_simple_call(self, varargs_cell, varkwds_cell, t):
- len_cell = t.get('len', [varargs_cell])
- if not isinstance(len_cell, XConstant):
- return None
- nbargs = len_cell.value
- arg_cells = [t.get('getitem', [varargs_cell, self.constant(j)])
+ def decode_simple_call(self, varargs_cell, varkwds_cell):
+ len_cell = self.heap.get(ANN.len[varargs_cell, QUERYARG])
+ nbargs = self.heap.getconstant(len_cell)
+ arg_cells = [self.heap.get(ANN.getitem[varargs_cell,
+ self.constant(j), QUERYARG])
for j in range(nbargs)]
if None in arg_cells:
- return None
- len_cell = t.get('len', [varkwds_cell])
- if not isinstance(len_cell, XConstant):
- return None
- nbkwds = len_cell.value
+ raise IDontKnow
+ len_cell = self.heap.get(ANN.len[varkwds_cell, QUERYARG])
+ nbkwds = self.heap.getconstant(len_cell)
if nbkwds != 0:
- return None
+ raise IDontKnow
return arg_cells
- def consider_op_call(self, (func,varargs,kwargs), result, t):
- if not isinstance(func, XConstant):
- return
- func = func.value
+ def consider_op_call(self, func, varargs, kwargs):
+ func = self.heap.getconstant(func)
if isinstance(func, FunctionType) and self.translator:
- args = self.decode_simple_call(varargs, kwargs, t)
- if args is not None:
- result_cell = self.translator.consider_call(self, func, args)
- if result_cell is nothingyet:
- raise DelayAnnotation
- # 'result' is made shared with 'result_cell'. This has the
- # effect that even if result_cell is actually an XConstant,
- # result stays an XCell, but the annotations about the constant
- # are also appliable to result. This is bad because it means
- # functions returning constants won't propagate the constant
- # but only e.g. its type. This is needed at this point because
- # XConstants are not too well supported in the forward_deps
- # lists: forward_deps cannot downgrade XConstant to XCell.
- result.share(result_cell)
+ args = self.decode_simple_call(varargs, kwargs)
+ return self.translator.consider_call(self, func, args)
# XXX: generalize this later
+ tp = self.heap.checktype
+ result = SomeValue()
if func is range:
- t.set_type(result, list)
+ self.heap.settype(result, list)
if func is pow:
- tp1 = t.get_type(t.get('getitem', [varargs, self.constant(0)]))
- tp2 = t.get_type(t.get('getitem', [varargs, self.constant(1)]))
- if tp1 is int and tp2 is int:
- t.set_type(result, int)
-
- def consider_const(self,to_var,const):
- t = self.transaction()
- t.set('immutable', [], to_var)
- t.set_type(to_var,type(const.value))
- if isinstance(const.value, tuple):
- pass # XXX say something about the elements
+ args = self.decode_simple_call(varargs, kwargs)
+ if len(args) == 2:
+ if tp(args[0], int) and tp(args[1], int):
+ self.heap.settype(result, int)
+ return result
+ def consider_const(self, constvalue):
+ result = self.heap.newconstant(constvalue)
+ self.heap.set(ANN.immutable[result])
+ self.heap.settype(result, type(constvalue))
+ if isinstance(constvalue, tuple):
+ pass # XXX say something about the elements
+ return result
-class CannotSimplify(Exception):
- pass
class DelayAnnotation(Exception):
pass
Deleted: /pypy/trunk/src/pypy/translator/test/test_annheap.py
==============================================================================
--- /pypy/trunk/src/pypy/translator/test/test_annheap.py Thu Dec 18 13:16:53 2003
+++ (empty file)
@@ -1,250 +0,0 @@
-
-import autopath
-from pypy.tool import test
-
-from pypy.translator.annotation import XCell, XConstant, nothingyet, Annotation
-from pypy.translator.annheap import AnnotationHeap, Transaction
-
-
-class TestAnnotationHeap(test.IntTestCase):
-
- def setUp(self):
- self.c1 = XCell()
- self.c2 = XCell()
- self.c3 = XConstant(-2)
-
- def assertSameSet(self, a, b):
- a = list(a)
- b = list(b)
- # try to reorder a to match b, without failing if the lists
- # are different -- this will be checked by assertEquals()
- for i in range(len(b)):
- try:
- j = i + a[i:].index(b[i])
- except ValueError:
- pass
- else:
- a[i], a[j] = a[j], a[i]
- self.assertEquals(a, b)
-
- def test_enumerate(self):
- lst = [Annotation('add', [self.c1, self.c3], self.c2)]
- a = AnnotationHeap(lst)
- self.assertSameSet(a.enumerate(), lst)
-
- def test_simplify(self):
- lst = [Annotation('add', [self.c1, self.c3], self.c2),
- Annotation('add', [self.c1, self.c2], self.c2),
- Annotation('neg', [self.c2], self.c3)]
- a = AnnotationHeap(lst)
- a.simplify()
- self.assertSameSet(a, lst)
-
- self.c2.share(self.c3)
- a.simplify()
- self.assertSameSet(a, lst[1:])
-
- def test_simplify_kill(self):
- ann1 = Annotation('add', [self.c1, self.c3], self.c2)
- lst = [ann1,
- Annotation('add', [self.c1, self.c2], self.c2),
- Annotation('neg', [self.c2], self.c3)]
- a = AnnotationHeap(lst)
- a.simplify(kill=[ann1])
- self.assertSameSet(a, lst[1:])
-
- def test_simplify_kill_deps(self):
- ann1 = Annotation('add', [self.c1, self.c3], self.c2)
- ann2 = Annotation('add', [self.c1, self.c2], self.c2)
- ann3 = Annotation('add', [self.c1, self.c1], self.c2)
- ann1.forward_deps.append(ann2)
- ann2.forward_deps.append(ann3)
- lst = [ann1, ann2, ann3,
- Annotation('neg', [self.c2], self.c3)]
- a = AnnotationHeap(lst)
- a.simplify(kill=[ann1])
- self.assertSameSet(a, lst[3:])
-
- def test_merge_nothingyet(self):
- lst = [Annotation('add', [self.c1, self.c3], self.c2),
- Annotation('neg', [self.c2], self.c3)]
- a = AnnotationHeap(lst)
- # (c3) inter (all annotations) == (c3)
- c = a.merge(self.c3, nothingyet)
- self.assertEquals(c, self.c3)
- self.failIfEqual(c, nothingyet)
- self.assertSameSet(a, lst)
-
- def test_merge_mutable1(self):
- lst = [Annotation('type', [self.c1], self.c3),
- Annotation('type', [self.c2], self.c3),
- Annotation('somethingelse', [self.c2, self.c3], self.c3)]
- a = AnnotationHeap(lst)
- # (c1) inter (c2) == (c1 shared with c2)
- c = a.merge(self.c1, self.c2)
- self.assertEquals(c, self.c1)
- self.assertEquals(c, self.c2)
- self.assertEquals(self.c1, self.c2)
- self.assertSameSet(a, [Annotation('type', [c], self.c3)])
-
- def test_merge_mutable2(self):
- lst = [Annotation('type', [self.c1], self.c3),
- Annotation('type', [self.c2], self.c3),
- Annotation('somethingelse', [self.c1, self.c3], self.c3)]
- a = AnnotationHeap(lst)
- # (c1) inter (c2) == (c1 shared with c2)
- c = a.merge(self.c1, self.c2)
- self.assertEquals(c, self.c1)
- self.assertEquals(c, self.c2)
- self.assertEquals(self.c1, self.c2)
- self.assertSameSet(a, [Annotation('type', [c], self.c3)])
-
- def test_merge_immutable(self):
- lst = [Annotation('type', [self.c1], self.c3),
- Annotation('type', [self.c2], self.c3),
- Annotation('immutable', [], self.c1),
- Annotation('immutable', [], self.c2),
- Annotation('somethingelse', [self.c2, self.c3], self.c3)]
- a = AnnotationHeap(lst)
- # (c1) inter (c2) == (some new c4)
- c = a.merge(self.c1, self.c2)
- self.failIfEqual(self.c1, self.c2)
- # c could be equal to c1 here, but we don't require that
- for op in [Annotation('type', [c], self.c3),
- Annotation('immutable', [], c)]:
- if op not in lst:
- lst.append(op)
- self.assertSameSet(a, lst)
-
- def test_merge_mutable_ex(self):
- lst = [Annotation('add', [self.c1, self.c2], self.c2),
- Annotation('neg', [self.c2], self.c1),
- Annotation('add', [self.c3, self.c2], self.c2),
- Annotation('immutable', [], self.c2)]
- a = AnnotationHeap(lst)
- # (c1) inter (c3) == (c1 shared with c3)
- c = a.merge(self.c1, self.c3)
- self.assertEquals(c, self.c1)
- self.assertEquals(c, self.c3)
- self.assertEquals(self.c1, self.c3)
- self.assertSameSet(a, [lst[0], lst[3]])
- self.assertSameSet(a, [lst[2], lst[3]])
-
- def test_merge_immutable_ex(self):
- lst = [Annotation('add', [self.c1, self.c2], self.c2),
- Annotation('neg', [self.c2], self.c1),
- Annotation('add', [self.c3, self.c2], self.c2),
- Annotation('immutable', [], self.c1),
- Annotation('immutable', [], self.c2),
- Annotation('immutable', [], self.c3)]
- a = AnnotationHeap(lst)
- # (c1) inter (c3) == (some new c4)
- c = a.merge(self.c1, self.c3)
- self.failIfEqual(c, self.c1)
- self.failIfEqual(c, self.c3)
- lst += [Annotation('add', [c, self.c2], self.c2),
- Annotation('immutable', [], c)]
- self.assertSameSet(a, lst)
-
- def dont_test_merge_mutable_ex(self):
- # This test is expected to fail at this point because the algorithms
- # are not 100% theoretically correct, but probably quite good and
- # clear enough right now. In theory in the intersection below
- # 'add' should be kept. In practice the extra 'c3' messes things
- # up. I can only think about much-more-obscure algos to fix that.
- lst = [Annotation('add', [self.c1, self.c3], self.c2),
- Annotation('neg', [self.c2], self.c1),
- Annotation('add', [self.c3, self.c3], self.c2),
- Annotation('immutable', [], self.c2)]
- a = AnnotationHeap(lst)
- # (c1) inter (c3) == (c1 shared with c3)
- c = a.merge(self.c1, self.c3)
- self.assertEquals(c, self.c1)
- self.assertEquals(c, self.c3)
- self.assertEquals(self.c1, self.c3)
- self.assertSameSet(a, [lst[0], lst[3]])
- self.assertSameSet(a, [lst[2], lst[3]])
-
- def dont_test_merge_immutable_ex(self):
- # Disabled -- same as above.
- lst = [Annotation('add', [self.c1, self.c3], self.c2),
- Annotation('neg', [self.c2], self.c1),
- Annotation('add', [self.c3, self.c3], self.c2),
- Annotation('immutable', [], self.c1),
- Annotation('immutable', [], self.c2),
- Annotation('immutable', [], self.c3)]
- a = AnnotationHeap(lst)
- # (c1) inter (c3) == (some new c4)
- c = a.merge(self.c1, self.c3)
- self.failIfEqual(c, self.c1)
- self.failIfEqual(c, self.c3)
- lst += [Annotation('add', [c, self.c3], self.c2),
- Annotation('immutable', [], c)]
- self.assertSameSet(a, lst)
-
-
-class TestTransaction(test.IntTestCase):
-
- def setUp(self):
- self.c1 = XCell()
- self.c2 = XCell()
- self.c3 = XConstant(-2)
- self.lst = [Annotation('add', [self.c1, self.c3], self.c2),
- Annotation('neg', [self.c2], self.c1),
- Annotation('add', [self.c3, self.c3], self.c2),
- Annotation('immutable', [], self.c1),
- Annotation('type', [self.c1], self.c3),
- Annotation('type', [self.c3], self.c2)]
- self.a = AnnotationHeap(self.lst)
-
- def test_get(self):
- t = Transaction(self.a)
- self.assertEquals(t.get('add', [self.c1, self.c3]), self.c2)
- self.assertEquals(t.get('add', [self.c1, self.c2]), None)
- self.assertEquals(t.get('sub', [self.c1, self.c3]), None)
-
- def test_get_None(self):
- t = Transaction(self.a)
- self.assertEquals(t.get('add', [self.c1, None]), self.c2)
- self.assertEquals(t.get('add', [None, self.c3]), self.c2)
- self.assertEquals(t.get('add', [self.c2, None]), None)
- self.assertEquals(t.get('type', [None]), None)
-
- def test_get_type(self):
- t = Transaction(self.a)
- self.assertEquals(t.get_type(self.c1), -2)
- self.assertEquals(t.get_type(self.c2), None)
- self.assertEquals(t.get_type(self.c3), None)
-
- def test_set(self):
- t = Transaction(self.a)
- t.set('dummy', [self.c2], self.c1)
- self.assertEquals(t.get('dummy', [self.c2]), self.c1)
-
- def test_set_type(self):
- t = Transaction(self.a)
- t.set_type(self.c2, int)
- self.assertEquals(t.get('type', [self.c2]), XConstant(int))
-
- def test_dep_set(self):
- t = Transaction(self.a)
- t.get('add', [self.c1, self.c3])
- t.get_type(self.c1)
- t.set('dummy', [self.c2], self.c1)
- new_ann = Annotation('dummy', [self.c2], self.c1)
- self.cases = []
- for ann in self.a.enumerate():
- if ann == Annotation('add', [self.c1, self.c3], self.c2):
- self.cases.append(0)
- self.assertEquals(ann.forward_deps, [new_ann])
- elif ann == Annotation('type', [self.c1], self.c3):
- self.cases.append(1)
- self.assertEquals(ann.forward_deps, [new_ann])
- else:
- self.assertEquals(ann.forward_deps, [])
- self.cases.sort()
- self.assertEquals(self.cases, [0, 1])
-
-
-if __name__ == '__main__':
- test.main()
Deleted: /pypy/trunk/src/pypy/translator/test/test_annotation.py
==============================================================================
--- /pypy/trunk/src/pypy/translator/test/test_annotation.py Thu Dec 18 13:16:53 2003
+++ (empty file)
@@ -1,46 +0,0 @@
-
-import autopath
-from pypy.tool import test
-
-from pypy.translator.annotation import XCell, XConstant, nothingyet, Annotation
-
-
-class TestAnnotation(test.IntTestCase):
-
- def test_is_shared(self):
- c1 = XCell()
- c2 = XCell()
- c3 = XCell()
- c4 = XCell()
- for a in (c1,c2,c3,c4):
- for b in (c1,c2,c3,c4):
- if a is not b:
- self.failIfEqual(a, b)
- c1.share(c2)
- c4.share(c2)
- c1.share(c3)
- for a in (c1,c2,c3,c4):
- for b in (c1,c2,c3,c4):
- self.assert_(a.is_shared(b))
- self.assertEquals(a, b)
-
- def test_constant(self):
- self.assertEquals(XConstant(5), XConstant(5))
- self.failIfEqual(XConstant(5), XConstant(6))
- self.failIfEqual(XConstant(5), XCell())
-
- def test_annotation(self):
- c1 = XCell()
- c2 = XCell()
- c3 = XCell()
- a1 = Annotation('hello', [c1], c2)
- a2 = Annotation('hello', [c1], c3)
-
- self.assertEquals(a1, a1)
- self.failIfEqual (a1, a2)
- c2.share(c3)
- self.assertEquals(a1, a2)
-
-
-if __name__ == '__main__':
- test.main()
Modified: pypy/trunk/src/pypy/translator/translator.py
==============================================================================
--- pypy/trunk/src/pypy/translator/translator.py (original)
+++ pypy/trunk/src/pypy/translator/translator.py Thu Dec 18 13:16:53 2003
@@ -31,11 +31,12 @@
import test.autopath
from pypy.objspace.flow.model import *
-from pypy.translator.annotation import *
+from pypy.annotation.model import *
+from pypy.annotation.annset import *
from pypy.translator.annrpython import RPythonAnnotator
from pypy.translator.simplify import simplify_graph
-from pypy.translator.genpyrex import GenPyrex
-from pypy.translator.gencl import GenCL
+#from pypy.translator.genpyrex import GenPyrex
+#from pypy.translator.gencl import GenCL
from pypy.translator.tool.buildpyxmodule import make_module_from_pyxstring
from pypy.objspace.flow import FlowObjSpace
More information about the Pypy-commit
mailing list