def test_somebuiltin(): ### Operation on built-in types class MiniPickler: def __init__(self): self.data = [] def emit(self, datum): self.data.append(datum) class __extend__(pairtype(MiniPickler, int)): def write((pickler, x)): pickler.emit('I%d' % x) class __extend__(pairtype(MiniPickler, str)): def write((pickler, x)): pickler.emit('S%s' % x) class __extend__(pairtype(MiniPickler, list)): def write((pickler, x)): for item in x: pair(pickler, item).write() pickler.emit('L%d' % len(x)) p = MiniPickler() pair(p, [1, 2, ['hello', 3]]).write() assert p.data == ['I1', 'I2', 'Shello', 'I3', 'L2', 'L3']
def get_loader(type): s_obj = annotation(type, None) try: # look for a marshaller in the 'loaders' list return find_loader(s_obj) except CannotUnmarshall: # ask the annotation to produce an appropriate loader pair(_tag, s_obj).install_unmarshaller() return find_loader(s_obj)
def get_marshaller(type): """Return a marshaller function. The marshaller takes two arguments: a buffer and an object of type 'type'. The buffer is list of characters that gets extended with new data when the marshaller is called. """ s_obj = annotation(type, None) try: # look for a marshaller in the 'dumpers' list return find_dumper(s_obj) except CannotMarshal: # ask the annotation to produce an appropriate dumper pair(_tag, s_obj).install_marshaller() return find_dumper(s_obj)
def unionof(*somevalues): "The most precise SomeValue instance that contains all the values." try: s1, s2 = somevalues except ValueError: s1 = s_ImpossibleValue for s2 in somevalues: if s1 != s2: s1 = pair(s1, s2).union() else: # See comment in union() above if s1 != s2: s1 = pair(s1, s2).union() return s1
def unionof(*somevalues): "The most precise SomeValue instance that contains all the values." try: s1, s2 = somevalues except ValueError: s1 = s_ImpossibleValue for s2 in somevalues: if s1 != s2: s1 = pair(s1, s2).union() else: # this is just a performance shortcut if s1 != s2: s1 = pair(s1, s2).union() return s1
def follow_link(self, graph, link, constraints): assert not (isinstance(link.exitcase, (types.ClassType, type)) and issubclass(link.exitcase, BaseException)) ignore_link = False inputs_s = [] renaming = defaultdict(list) for v_out, v_input in zip(link.args, link.target.inputargs): renaming[v_out].append(v_input) for v_out in link.args: s_out = self.annotation(v_out) if v_out in constraints: s_constraint = constraints[v_out] s_out = pair(s_out, s_constraint).improve() # ignore links that try to pass impossible values if s_out == s_ImpossibleValue: ignore_link = True s_out = self.apply_renaming(s_out, renaming) inputs_s.append(s_out) if ignore_link: return self.links_followed[link] = True self.addpendingblock(graph, link.target, inputs_s)
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(BaseListRepr, BaseListRepr)): def rtype_is_((r_lst1, r_lst2), hop): if r_lst1.lowleveltype != r_lst2.lowleveltype: # obscure logic, the is can be true only if both are None v_lst1, v_lst2 = hop.inputargs(r_lst1, r_lst2) return hop.gendirectcall(ll_both_none, v_lst1, v_lst2) return pairtype(Repr, Repr).rtype_is_(pair(r_lst1, r_lst2), hop)
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
def convertvar(self, v, r_from, r_to): assert isinstance(v, (Variable, Constant)) if r_from != r_to: v = pair(r_from, r_to).convert_from_to(v, self) if v is NotImplemented: raise TyperError("don't know how to convert from %r to %r" % (r_from, r_to)) if v.concretetype != r_to.lowleveltype: raise TyperError("bug in conversion from %r to %r: " "returned a %r" % (r_from, r_to, v.concretetype)) return v
def get_specialization(cls, s_arg1, s_arg2, *_ignored): try: impl = getattr(pair(s_arg1, s_arg2), cls.opname) def specialized(annotator, arg1, arg2, *other_args): return impl(*[annotator.annotation(x) for x in other_args]) try: specialized.can_only_throw = impl.can_only_throw except AttributeError: pass return specialized except AttributeError: return cls._registry[type(s_arg1), type(s_arg2)]
def convertvar(self, orig_v, r_from, r_to): assert isinstance(orig_v, (Variable, Constant)) if r_from != r_to: v = pair(r_from, r_to).convert_from_to(orig_v, self) if v is NotImplemented: raise TyperError("don't know how to convert from %r to %r" % (r_from, r_to)) if v.concretetype != r_to.lowleveltype: raise TyperError("bug in conversion from %r to %r: " "returned a %r" % (r_from, r_to, v.concretetype)) else: v = orig_v return v
def contains(self, other): if self == other: return True try: TLS.no_side_effects_in_union += 1 except AttributeError: TLS.no_side_effects_in_union = 1 try: try: return pair(self, other).union() == self except UnionError: return False finally: TLS.no_side_effects_in_union -= 1
def test_binop(): ### Binary operation example class __extend__(pairtype(int, int)): def add((x, y)): return 'integer: %s+%s' % (x, y) def sub((x, y)): return 'integer: %s-%s' % (x, y) class __extend__(pairtype(bool, bool)): def add((x, y)): return 'bool: %s+%s' % (x, y) assert pair(3, 4).add() == 'integer: 3+4' assert pair(3, 4).sub() == 'integer: 3-4' assert pair(3, True).add() == 'integer: 3+True' assert pair(3, True).sub() == 'integer: 3-True' assert pair(False, 4).add() == 'integer: False+4' assert pair(False, 4).sub() == 'integer: False-4' assert pair(False, True).add() == 'bool: False+True' assert pair(False, True).sub() == 'integer: False-True'
def union(s1, s2): """The join operation in the lattice of annotations. It is the most precise SomeObject instance that contains both arguments. union() is (supposed to be) idempotent, commutative, associative and has no side-effects. """ try: TLS.no_side_effects_in_union += 1 except AttributeError: TLS.no_side_effects_in_union = 1 try: if s1 == s2: # Most pair(...).union() methods deal incorrectly with that case # when constants are involved. return s1 return pair(s1, s2).union() finally: TLS.no_side_effects_in_union -= 1
def inplace_xor((obj1, obj2)): return pair(obj1, obj2).xor() for name, func in locals().items():
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_mul((obj1, obj2)): return pair(obj1, obj2).mul() def inplace_truediv((obj1, obj2)): return pair(obj1, obj2).truediv()
def inplace_div((obj1, obj2)): return pair(obj1, obj2).div() def inplace_mod((obj1, obj2)): return pair(obj1, obj2).mod()
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 inplace_add((obj1, obj2)): return pair(obj1, obj2).add() def inplace_sub((obj1, obj2)): return pair(obj1, obj2).sub()
def inplace_lshift((obj1, obj2)): return pair(obj1, obj2).lshift()
def inplace_rshift((obj1, obj2)): return pair(obj1, obj2).rshift()
def inplace_div((obj1, obj2)): return pair(obj1, obj2).div()
def inplace_mod((obj1, obj2)): return pair(obj1, obj2).mod()
def translate_op_extend_with_char_count(self, hop): r_arg1 = hop.args_r[0] r_arg2 = hop.args_r[1] return pair(r_arg1, r_arg2).rtype_extend_with_char_count(hop)
def inplace_mul((obj1, obj2)): return pair(obj1, obj2).mul()
def inplace_sub((obj1, obj2)): return pair(obj1, obj2).sub()
def inplace_and((obj1, obj2)): return pair(obj1, obj2).and_()
def coerce((obj1, obj2)): return pair(obj1, obj2).union() # reasonable enough
def inplace_or((obj1, obj2)): return pair(obj1, obj2).or_()
def getitem_idx_key((s_c1, s_o2)): impl = pair(s_c1, s_o2).getitem return impl()
def inplace_xor((obj1, obj2)): return pair(obj1, obj2).xor()
def inplace_sub((obj1, obj2)): return pair(obj1, obj2).sub() def inplace_mul((obj1, obj2)): return pair(obj1, obj2).mul()
def divmod((obj1, obj2)): return SomeTuple([pair(obj1, obj2).div(), pair(obj1, obj2).mod()])
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 mod((s_string, s_arg)): assert not isinstance(s_arg, SomeTuple) return pair(s_string, SomeTuple([s_arg])).mod()
def inplace_rshift((obj1, obj2)): return pair(obj1, obj2).rshift() def inplace_and((obj1, obj2)): return pair(obj1, obj2).and_()
def translate_op_extend_with_str_slice(self, hop): r_arg1 = hop.args_r[0] r_arg2 = hop.args_r[3] return pair(r_arg1, r_arg2).rtype_extend_with_str_slice(hop)
def inplace_or((obj1, obj2)): return pair(obj1, obj2).or_() def inplace_xor((obj1, obj2)): return pair(obj1, obj2).xor()
def inplace_truediv((obj1, obj2)): return pair(obj1, obj2).truediv()
def inplace_add((obj1, obj2)): return pair(obj1, obj2).add()
llfn = r_str.ll.ll_stritem_nonneg_checked else: llfn = r_str.ll.ll_stritem_checked else: if hop.args_s[1].nonneg: llfn = r_str.ll.ll_stritem_nonneg else: llfn = r_str.ll.ll_stritem if checkidx: hop.exception_is_here() else: hop.exception_cannot_occur() return hop.gendirectcall(llfn, v_str, v_index) def rtype_getitem_idx((r_str, r_int), hop): return pair(r_str, r_int).rtype_getitem(hop, checkidx=True) def rtype_mul((r_str, r_int), hop): str_repr = r_str.repr v_str, v_int = hop.inputargs(str_repr, Signed) return hop.gendirectcall(r_str.ll.ll_str_mul, v_str, v_int) rtype_inplace_mul = rtype_mul class __extend__(pairtype(IntegerRepr, AbstractStringRepr)): def rtype_mul((r_int, r_str), hop): str_repr = r_str.repr v_int, v_str = hop.inputargs(Signed, str_repr) return hop.gendirectcall(r_str.ll.ll_str_mul, v_str, v_int)
def inplace_floordiv((obj1, obj2)): return pair(obj1, obj2).floordiv()