コード例 #1
0
class W_Parameterization(W_Object):
    _immutable_fields_ = ["root", "map"]
    _attrs_ = ["root", "map"]
    errorname = "parameterization"

    def __init__(self, root, map):
        self.root = root
        self.map = map

    @jit.look_inside_iff(lambda self, params, vals: \
            jit.loop_unrolling_heuristic(params, len(params), values.UNROLLING_CUTOFF) and
            jit.loop_unrolling_heuristic(vals, len(vals), values.UNROLLING_CUTOFF))
    def extend(self, params, vals):
        assert len(params) == len(vals)
        map = self.map
        for i, param in enumerate(params):
            cell = values.W_ThreadCell(vals[i], True)
            map = map.assoc(param.get_key(), cell)
        return W_Parameterization(self.root, map)

    @jit.elidable
    def get(self, param):
        key = param.key
        result = self.map.val_at(key, None)
        if result is not None:
            return result
        result = self.root.table[key]
        assert result is not None
        return result

    def tostring(self):
        return "#<parameterization>"
コード例 #2
0
ファイル: values_string.py プロジェクト: pycket/pycket
def _is_ascii(s):
    if not jit.loop_unrolling_heuristic(s, len(s)):
        return _is_ascii_elidable(s)
    for c in s:
        if ord(c) >= 128:
            return False
    return True
コード例 #3
0
def _is_ascii(s):
    if not jit.loop_unrolling_heuristic(s, len(s)):
        return _is_ascii_elidable(s)
    for c in s:
        if ord(c) >= 128:
            return False
    return True
コード例 #4
0
ファイル: vector.py プロジェクト: shiplift/PycketOnAShip
class UnwrappedVectorStrategyMixin(object):
    # the concrete class needs to implement:
    # erase, unerase, is_correct_type, wrap, unwrap

    def _copy_storage(self, w_vector, immutable=False):
        strategy = self if not immutable else self.immutable_variant()
        l = self.unerase(w_vector.get_storage())[:]
        return W_Vector(strategy, self.erase(l), w_vector.len)

    def _storage(self, w_vector):
        l = self.unerase(w_vector.get_storage())
        debug.make_sure_not_resized(l)
        return l

    def _ref(self, w_vector, i):
        assert i >= 0
        return self.wrap(self._storage(w_vector)[i])

    def _set(self, w_vector, i, w_val):
        assert i >= 0
        self._storage(w_vector)[i] = self.unwrap(w_val)

    @jit.look_inside_iff(lambda strategy, w_vector: jit.isconstant(
        w_vector.length()) and w_vector.length() < UNROLLING_CUTOFF)
    def ref_all(self, w_vector):
        unwrapped = self._storage(w_vector)
        return [self.wrap(i) for i in unwrapped]

    def create_storage_for_element(self, element, times):
        e = self.unwrap(element)
        return self.erase([e] * times)

    @jit.look_inside_iff(lambda self, elements_w: jit.loop_unrolling_heuristic(
        elements_w, len(elements_w), UNROLLING_CUTOFF))
    def create_storage_for_elements(self, elements_w):
        if not elements_w:
            return self.erase([])
        l = [self.unwrap(e) for e in elements_w]
        return self.erase(l)

    def wrap(self, obj):
        return obj

    def unwrap(self, w_obj):
        return w_obj

    def unrolling_heuristic(self, w_vector):
        storage = self._storage(w_vector)
        return jit.loop_unrolling_heuristic(storage, w_vector.len,
                                            UNROLLING_CUTOFF)
コード例 #5
0
ファイル: general.py プロジェクト: vishesh/pycket
def ormap_cont(f, ls, env, cont, vals):
    # XXX this is currently not properly jitted
    from pycket.interpreter import return_value, check_one_val
    val = check_one_val(vals)
    if val is values.w_true:
        return return_value(val, env, cont)
    for l in ls:
        if l is values.w_null:
            return return_value(values.w_false, env, cont)
    cars = [l.car() for l in ls]
    cdrs = [l.cdr() for l in ls]
    return f.call(cars, env, ormap_cont(f, cdrs, env, cont))

@expose("append", arity=Arity.geq(0))
@jit.look_inside_iff(
    lambda l: jit.loop_unrolling_heuristic(l, len(l), values.UNROLLING_CUTOFF))
def append(lists):
    if not lists:
        return values.w_null
    lists, acc = lists[:-1], lists[-1]
    while lists:
        vals = values.from_list(lists.pop())
        acc  = values.to_improper(vals, acc)
    return acc

@expose("reverse", [values.W_List])
def reverse(w_l):
    acc = values.w_null
    while isinstance(w_l, values.W_Cons):
        val, w_l = w_l.car(), w_l.cdr()
        acc = values.W_Cons.make(val, acc)
コード例 #6
0
def min_max(space, args, implementation_of):
    if not jit.we_are_jitted() or len(args.arguments_w) != 1 and \
            jit.loop_unrolling_heuristic(args.arguments_w, len(args.arguments_w)):
        return min_max_unroll(space, args, implementation_of)
    else:
        return min_max_normal(space, args, implementation_of)
コード例 #7
0
class CPyListStrategy(ListStrategy):
    erase, unerase = rerased.new_erasing_pair("empty")
    erase = staticmethod(erase)
    unerase = staticmethod(unerase)

    def _check_index(self, index, length):
        if index < 0:
            index = length + index
        if index < 0 or index >= length:
            raise IndexError
        return index

    def getitem(self, w_list, index):
        storage = self.unerase(w_list.lstorage)
        index = self._check_index(index, storage._length)
        return from_ref(w_list.space, storage._elems[index])

    def setitem(self, w_list, index, w_obj):
        storage = self.unerase(w_list.lstorage)
        index = self._check_index(index, storage._length)
        py_old = storage._elems[index]
        storage._elems[index] = make_ref(w_list.space, w_obj)
        decref(w_list.space, py_old)

    def length(self, w_list):
        storage = self.unerase(w_list.lstorage)
        return storage._length

    def get_raw_items(self, w_list):
        storage = self.unerase(w_list.lstorage)
        return storage._elems

    def getslice(self, w_list, start, stop, step, length):
        w_list.switch_to_object_strategy()
        return w_list.strategy.getslice(w_list, start, stop, step, length)

    def getitems(self, w_list):
        # called when switching list strategy, so convert storage
        storage = self.unerase(w_list.lstorage)
        retval = [None] * storage._length
        for i in range(storage._length):
            retval[i] = from_ref(w_list.space, storage._elems[i])
        return retval

    @jit.unroll_safe
    def getitems_unroll(self, w_list):
        storage = self.unerase(w_list.lstorage)
        retval = [None] * storage._length
        for i in range(storage._length):
            retval[i] = from_ref(w_list.space, storage._elems[i])
        return retval

    @jit.look_inside_iff(lambda self, w_list:
            jit.loop_unrolling_heuristic(w_list, w_list.length(),
                                         UNROLL_CUTOFF))
    def getitems_fixedsize(self, w_list):
        return self.getitems_unroll(w_list)

    def copy_into(self, w_list, w_other):
        w_other.strategy = self
        w_other.lstorage = self.getstorage_copy(w_list)

    def clone(self, w_list):
        storage = self.getstorage_copy(w_list)
        w_clone = W_ListObject.from_storage_and_strategy(self.space, storage,
                                                         self)
        return w_clone

    def getitems_copy(self, w_list):
        return self.getitems(w_list) # getitems copies anyway

    def getstorage_copy(self, w_list):
        lst = self.getitems(w_list)
        return self.erase(CPyListStorage(w_list.space, lst))

    #------------------------------------------
    # all these methods fail or switch strategy and then call ListObjectStrategy's method

    def setslice(self, w_list, start, stop, step, length):
        w_list.switch_to_object_strategy()
        w_list.strategy.setslice(w_list, start, stop, step, length)

    def init_from_list_w(self, w_list, list_w):
        raise NotImplementedError

    def _resize_hint(self, w_list, hint):
        pass

    def find(self, w_list, w_item, start, stop):
        w_list.switch_to_object_strategy()
        return w_list.strategy.find(w_list, w_item, start, stop)

    def append(self, w_list, w_item):
        w_list.switch_to_object_strategy()
        w_list.strategy.append(w_list, w_item)

    def inplace_mul(self, w_list, times):
        w_list.switch_to_object_strategy()
        w_list.strategy.inplace_mul(w_list, times)

    def deleteslice(self, w_list, start, step, slicelength):
        w_list.switch_to_object_strategy()
        w_list.strategy.deleteslice(w_list, start, step, slicelength)

    def pop(self, w_list, index):
        w_list.switch_to_object_strategy()
        return w_list.strategy.pop(w_list, index)

    def pop_end(self, w_list):
        w_list.switch_to_object_strategy()
        return w_list.strategy.pop_end(w_list)

    def insert(self, w_list, index, w_item):
        w_list.switch_to_object_strategy()
        w_list.strategy.insert(w_list, index, w_item)

    def extend(self, w_list, w_any):
        w_list.switch_to_object_strategy()
        w_list.strategy.extend(w_list, w_any)

    def _extend_from_list(self, w_list, w_other):
        w_list.switch_to_object_strategy()
        w_list.strategy._extend_from_list(w_list, w_other)

    def _extend_from_iterable(self, w_list, w_iterable):
        w_list.switch_to_object_strategy()
        w_list.strategy._extend_from_iterable(w_list, w_iterable)

    def reverse(self, w_list):
        w_list.switch_to_object_strategy()
        w_list.strategy.reverse(w_list)

    def sort(self, w_list, reverse):
        w_list.switch_to_object_strategy()
        w_list.descr_sort(w_list.space, reverse=reverse)

    def is_empty_strategy(self):
        return False
コード例 #8
0
        return self.call_with_extra_info(args, env, cont, None)

    def call_with_extra_info(self, args, env, cont, extra_call_info):
        jit.promote(self)
        return self.code(args, env, cont, extra_call_info)

    def tostring(self):
        return "#<procedure:%s>" % self.name


def to_list(l):
    return to_improper(l, w_null)


@jit.look_inside_iff(
    lambda l, curr: jit.loop_unrolling_heuristic(l, len(l), UNROLLING_CUTOFF))
def to_improper(l, curr):
    for i in range(len(l) - 1, -1, -1):
        curr = W_Cons.make(l[i], curr)
    return curr


def to_mlist(l):
    return to_mimproper(l, w_null)


@jit.look_inside_iff(
    lambda l, curr: jit.loop_unrolling_heuristic(l, len(l), UNROLLING_CUTOFF))
def to_mimproper(l, curr):
    for i in range(len(l) - 1, -1, -1):
        curr = W_MCons(l[i], curr)
コード例 #9
0
ファイル: equal.py プロジェクト: yws/pycket-1
        index = i.value
        if index >= self.length(w_dict) - 1:
            return values.w_false
        return values.wrap(index + 1)

    def hash_iterate_first(self, w_dict):
        return 0

    def length(self, w_dict):
        raise NotImplementedError("abstract base class")

    def create_storage(self, keys, vals):
        raise NotImplementedError("abstract base class")


@jit.look_inside_iff(lambda keys: jit.loop_unrolling_heuristic(
    keys, len(keys), values.UNROLLING_CUTOFF))
def _find_strategy_class(keys):
    if not config.strategies:
        return ObjectHashmapStrategy.singleton
    if len(keys) == 0:
        return EmptyHashmapStrategy.singleton
        # An empty vector stays empty forever. Don't implement special EmptyVectorStrategy.
    single_class = type(keys[0])
    for elem in keys:
        if not isinstance(elem, single_class):
            return ObjectHashmapStrategy.singleton
    if single_class is values.W_Fixnum:
        return FixnumHashmapStrategy.singleton
    if single_class is values.W_Symbol:
        return SymbolHashmapStrategy.singleton
    if single_class is values_string.W_String:
コード例 #10
0
ファイル: tupleobject.py プロジェクト: Qointum/pypy
def _unroll_condition(self):
    return jit.loop_unrolling_heuristic(self, self.length(), UNROLL_CUTOFF)
コード例 #11
0
ファイル: vector.py プロジェクト: pycket/pycket
from rpython.rlib import debug, jit, objectmodel, rerased
from rpython.rlib.longlong2float import (
    can_encode_int32,
    decode_int32_from_longlong_nan,
    encode_int32_into_longlong_nan,
    float2longlong,
    is_int32_from_longlong_nan,
    longlong2float
)
from rpython.rlib.objectmodel import import_from_mixin, specialize, we_are_translated
from rpython.rlib.rarithmetic import intmask


@jit.look_inside_iff(lambda elements, immutable:
        jit.loop_unrolling_heuristic(
                elements, len(elements), UNROLLING_CUTOFF))
def _find_strategy_class(elements, immutable):
    if not config.strategies or len(elements) == 0:
        # An empty vector stays empty forever. Don't implement special EmptyVectorStrategy.
        if immutable:
            return ObjectImmutableVectorStrategy.singleton
        return ObjectVectorStrategy.singleton
    single_class = type(elements[0])
    for elem in elements:
        if not isinstance(elem, single_class):
            if immutable:
                return ObjectImmutableVectorStrategy.singleton
            return ObjectVectorStrategy.singleton
    if single_class is W_Fixnum:
        if immutable:
            return FixnumImmutableVectorStrategy.singleton
コード例 #12
0
ファイル: stringobject.py プロジェクト: sota/pypy-old
    size = len(list_w)

    if size == 0:
        return W_StringObject.EMPTY

    if size == 1:
        w_s = list_w[0]
        # only one item,  return it if it's not a subclass of str
        if (space.is_w(space.type(w_s), space.w_str) or
            space.is_w(space.type(w_s), space.w_unicode)):
            return w_s

    return _str_join_many_items(space, w_self, list_w, size)

@jit.look_inside_iff(lambda space, w_self, list_w, size:
                     jit.loop_unrolling_heuristic(list_w, size))
def _str_join_many_items(space, w_self, list_w, size):
    self = w_self._value
    reslen = len(self) * (size - 1)
    for i in range(size):
        w_s = list_w[i]
        if not space.isinstance_w(w_s, space.w_str):
            if space.isinstance_w(w_s, space.w_unicode):
                # we need to rebuild w_list here, because the original
                # w_list might be an iterable which we already consumed
                w_list = space.newlist(list_w)
                w_u = space.call_function(space.w_unicode, w_self)
                return space.call_method(w_u, "join", w_list)
            msg = "sequence item %d: expected string, %T found"
            raise operationerrfmt(space.w_TypeError, msg, i, w_s)
        reslen += len(space.str_w(w_s))
コード例 #13
0
ファイル: values.py プロジェクト: rjnw/pycket
    def get_result_arity(self):
        return self.result_arity

    def call_with_extra_info(self, args, env, cont, extra_call_info):
        jit.promote(self)
        return self.code(args, env, cont, extra_call_info)

    def tostring(self):
        return "#<procedure:%s>" % self.name.variable_name()


def to_list(l):
    return to_improper(l, w_null)


@jit.look_inside_iff(lambda l, curr: jit.loop_unrolling_heuristic(l, len(l), UNROLLING_CUTOFF))
def to_improper(l, curr):
    for i in range(len(l) - 1, -1, -1):
        curr = W_Cons.make(l[i], curr)
    return curr


@jit.look_inside_iff(lambda v, curr: v.unrolling_heuristic())
def vector_to_improper(v, curr):
    for i in range(v.len - 1, -1, -1):
        curr = W_Cons.make(v.ref(i), curr)
    return curr


def to_mlist(l):
    return to_mimproper(l, w_null)
コード例 #14
0
class StringMethods(object):
    def _sliced(self, space, s, start, stop, orig_obj):
        assert start >= 0
        assert stop >= 0
        #if start == 0 and stop == len(s) and space.is_w(space.type(orig_obj),
        #                                                space.w_bytes):
        #    return orig_obj
        return self._new(s[start:stop])

    def _convert_idx_params(self, space, w_start, w_end):
        value = self._val(space)
        lenself = len(value)
        start, end = unwrap_start_stop(space, lenself, w_start, w_end)
        # the None means "no offset"; see bytearrayobject.py
        return (value, start, end, None)

    @staticmethod
    def descr_maketrans(space, w_type, w_from, w_to):
        """B.maketrans(frm, to) -> translation table

        Return a translation table (a bytes object of length 256) suitable
        for use in the bytes or bytearray translate method where each byte
        in frm is mapped to the byte at the same position in to.
        The bytes objects frm and to must be of the same length.
        """
        from pypy.objspace.std.bytesobject import makebytesdata_w

        base_table = [chr(i) for i in range(256)]
        list_from = makebytesdata_w(space, w_from)
        list_to = makebytesdata_w(space, w_to)

        if len(list_from) != len(list_to):
            raise oefmt(space.w_ValueError,
                        "maketrans arguments must have same length")

        for i in range(len(list_from)):
            pos_from = ord(list_from[i])
            char_to = list_to[i]
            base_table[pos_from] = char_to

        return space.newbytes(''.join(base_table))

    def _multi_chr(self, c):
        return c

    @staticmethod
    def _single_char(space, w_sub):
        try:
            char = space.int_w(w_sub)
        except OperationError as e:
            if e.match(space, space.w_OverflowError):
                char = 256 # arbitrary value which will trigger the ValueError
                # condition below
            else:
                raise
        if not 0 <= char < 256:
            raise oefmt(space.w_ValueError,
                        "byte must be in range(0, 256)")
        return chr(char)

    def descr_len(self, space):
        return space.newint(self._len())

    def descr_iter(self, space):
        from pypy.objspace.std.iterobject import W_StringIterObject
        return W_StringIterObject(self, self._iter_getitem_result)

    def descr_contains(self, space, w_sub):
        value, start, end, _ = self._convert_idx_params(space, None, None)
        other = self._op_val(space, w_sub, allow_char=True)
        if self._use_rstr_ops(space, w_sub):
            res = value.find(other, start, end)
        else:
            res = find(value, other, start, end)
        return space.newbool(res >= 0)

    def descr_add(self, space, w_other):
        if self._use_rstr_ops(space, w_other):
            try:
                other = self._op_val(space, w_other)
            except OperationError as e:
                if e.match(space, space.w_TypeError):
                    return space.w_NotImplemented
                raise
            return self._new(self._val(space) + other)

        # Bytearray overrides this method, CPython doesn't support contacting
        # buffers and strs, and unicodes are always handled above
        return space.w_NotImplemented

    def descr_mul(self, space, w_times):
        try:
            times = space.getindex_w(w_times, space.w_OverflowError)
        except OperationError as e:
            if e.match(space, space.w_TypeError):
                return space.w_NotImplemented
            raise
        if times <= 0:
            return self._empty()
        if self._len() == 1:
            return self._new(self._multi_chr(self._val(space)[0]) * times)
        return self._new(self._val(space) * times)

    descr_rmul = descr_mul

    _KIND1 = "string"
    _KIND2 = "string"

    def descr_getitem(self, space, w_index):
        if isinstance(w_index, W_SliceObject):
            selfvalue = self._val(space)
            length = len(selfvalue)
            start, stop, step, sl = w_index.indices4(space, length)
            if sl == 0:
                return self._empty()
            elif step == 1:
                assert start >= 0 and stop >= 0
                return self._sliced(space, selfvalue, start, stop, self)
            else:
                ret = _descr_getslice_slowpath(selfvalue, start, step, sl)
                return self._new_from_list(ret)

        index = space.getindex_w(w_index, space.w_IndexError, self._KIND1)
        return self._getitem_result(space, index)

    def _getitem_result(self, space, index):
        # Returns the result of 'self[index]', where index is an unwrapped int.
        # Used by descr_getitem() and by descr_iter().
        selfvalue = self._val(space)
        try:
            character = selfvalue[index]
        except IndexError:
            raise oefmt(space.w_IndexError, self._KIND1 + " index out of range")
        from pypy.objspace.std.bytesobject import W_BytesObject
        if isinstance(self, W_BytesObject):
            return space.newint(ord(character))
        return self._new(character)

    def descr_capitalize(self, space):
        value = self._val(space)
        if len(value) == 0:
            return self._empty()

        builder = self._builder(len(value))
        builder.append(self._upper(value[0]))
        for i in range(1, len(value)):
            builder.append(self._lower_in_str(value, i))
        return self._new(builder.build())

    @unwrap_spec(width=int, w_fillchar=WrappedDefault(' '))
    def descr_center(self, space, width, w_fillchar):
        value = self._val(space)
        fillchar = self._op_val(space, w_fillchar)
        if len(fillchar) != 1:
            raise oefmt(space.w_TypeError,
                        "center() argument 2 must be a single character")

        d = width - len(value)
        if d > 0:
            offset = d//2 + (d & width & 1)
            fillchar = self._multi_chr(fillchar[0])
            centered = offset * fillchar + value + (d - offset) * fillchar
        else:
            centered = value

        return self._new(centered)

    def descr_count(self, space, w_sub, w_start=None, w_end=None):
        value, start, end, _ = self._convert_idx_params(space, w_start, w_end)

        sub = self._op_val(space, w_sub, allow_char=True)
        if self._use_rstr_ops(space, w_sub):
            return space.newint(value.count(sub, start, end))
        else:
            res = count(value, sub, start, end)
            assert res >= 0
        return space.newint(res)

    def descr_decode(self, space, w_encoding=None, w_errors=None):
        from pypy.objspace.std.unicodeobject import (
            get_encoding_and_errors, decode_object)
        encoding, errors = get_encoding_and_errors(space, w_encoding, w_errors)
        if encoding is None:
            encoding = 'utf8'
        if encoding == 'utf8' or encoding == 'utf-8':
            # fast path - do not call into app-level codecs.py
            from pypy.module._codecs.interp_codecs import CodecState
            state = space.fromcache(CodecState)
            eh = state.decode_error_handler
            s = space.charbuf_w(self)
            ret, lgt, pos = str_decode_utf8(s, errors, True, eh)
            return space.newtext(ret, lgt)
        return decode_object(space, self, encoding, errors)

    @unwrap_spec(tabsize=int)
    def descr_expandtabs(self, space, tabsize=8):
        value = self._val(space)
        if not value:
            return self._empty()

        if self._use_rstr_ops(space, self):
            splitted = value.split(self._chr('\t'))
        else:
            splitted = split(value, self._chr('\t'))

        try:
            if tabsize > 0:
                ovfcheck(len(splitted) * tabsize)
        except OverflowError:
            raise oefmt(space.w_OverflowError, "new string is too long")
        expanded = oldtoken = splitted.pop(0)

        for token in splitted:
            expanded += self._multi_chr(self._chr(' ')) * self._tabindent(oldtoken,
                                                         tabsize) + token
            oldtoken = token

        return self._new(expanded)

    def _tabindent(self, token, tabsize):
        """calculates distance behind the token to the next tabstop"""

        if tabsize <= 0:
            return 0
        distance = tabsize
        if token:
            distance = 0
            offset = len(token)

            while 1:
                if token[offset-1] == "\n" or token[offset-1] == "\r":
                    break
                distance += 1
                offset -= 1
                if offset == 0:
                    break

            # the same like distance = len(token) - (offset + 1)
            distance = (tabsize - distance) % tabsize
            if distance == 0:
                distance = tabsize

        return distance

    def descr_find(self, space, w_sub, w_start=None, w_end=None):
        value, start, end, ofs = self._convert_idx_params(space, w_start, w_end)

        sub = self._op_val(space, w_sub, allow_char=True)
        if self._use_rstr_ops(space, w_sub):
            res = value.find(sub, start, end)
        else:
            res = find(value, sub, start, end)
        if ofs is not None and res >= 0:
            res -= ofs
        return space.newint(res)

    def descr_rfind(self, space, w_sub, w_start=None, w_end=None):
        value, start, end, ofs = self._convert_idx_params(space, w_start, w_end)

        sub = self._op_val(space, w_sub, allow_char=True)
        if self._use_rstr_ops(space, w_sub):
            res = value.rfind(sub, start, end)
        else:
            res = rfind(value, sub, start, end)
        if ofs is not None and res >= 0:
            res -= ofs
        return space.newint(res)

    def descr_index(self, space, w_sub, w_start=None, w_end=None):
        value, start, end, ofs = self._convert_idx_params(space, w_start, w_end)

        sub = self._op_val(space, w_sub, allow_char=True)
        if self._use_rstr_ops(space, w_sub):
            res = value.find(sub, start, end)
        else:
            res = find(value, sub, start, end)

        if res < 0:
            raise oefmt(space.w_ValueError,
                        "substring not found in " + self._KIND2 + ".index")
        if ofs is not None:
            res -= ofs
        return space.newint(res)

    def descr_rindex(self, space, w_sub, w_start=None, w_end=None):
        value, start, end, ofs = self._convert_idx_params(space, w_start, w_end)

        sub = self._op_val(space, w_sub, allow_char=True)
        if self._use_rstr_ops(space, w_sub):
            res = value.rfind(sub, start, end)
        else:
            res = rfind(value, sub, start, end)

        if res < 0:
            raise oefmt(space.w_ValueError,
                        "substring not found in " + self._KIND2 + ".rindex")
        if ofs is not None:
            res -= ofs
        return space.newint(res)

    @specialize.arg(2)
    def _is_generic(self, space, func_name):
        func = getattr(self, func_name)
        v = self._val(space)
        if len(v) == 0:
            return space.w_False
        if len(v) == 1:
            c = v[0]
            return space.newbool(func(c))
        else:
            return self._is_generic_loop(space, v, func_name)

    @specialize.arg(3)
    def _is_generic_loop(self, space, v, func_name):
        func = getattr(self, func_name)
        for idx in range(len(v)):
            if not func(v[idx]):
                return space.w_False
        return space.w_True

    def descr_isalnum(self, space):
        return self._is_generic(space, '_isalnum')

    def descr_isalpha(self, space):
        return self._is_generic(space, '_isalpha')

    def descr_isdigit(self, space):
        return self._is_generic(space, '_isdigit')

    # this is only for bytes and bytesarray: unicodeobject overrides it
    def _descr_islower_slowpath(self, space, v):
        cased = False
        for idx in range(len(v)):
            if self._isupper(v[idx]):
                return False
            elif not cased and self._islower(v[idx]):
                cased = True
        return cased

    def descr_islower(self, space):
        v = self._val(space)
        if len(v) == 1:
            c = v[0]
            return space.newbool(self._islower(c))
        cased = self._descr_islower_slowpath(space, v)
        return space.newbool(cased)

    def descr_isspace(self, space):
        return self._is_generic(space, '_isspace')

    def descr_istitle(self, space):
        input = self._val(space)
        cased = False
        previous_is_cased = False

        for pos in range(0, len(input)):
            ch = input[pos]
            if self._istitle(ch):
                if previous_is_cased:
                    return space.w_False
                previous_is_cased = True
                cased = True
            elif self._islower(ch):
                if not previous_is_cased:
                    return space.w_False
                cased = True
            else:
                previous_is_cased = False

        return space.newbool(cased)

    # this is only for bytes and bytesarray: unicodeobject overrides it
    def _descr_isupper_slowpath(self, space, v):
        cased = False
        for idx in range(len(v)):
            if self._islower(v[idx]):
                return False
            elif not cased and self._isupper(v[idx]):
                cased = True
        return cased

    def descr_isupper(self, space):
        v = self._val(space)
        if len(v) == 1:
            c = v[0]
            return space.newbool(self._isupper(c))
        cased = self._descr_isupper_slowpath(space, v)
        return space.newbool(cased)

    def descr_join(self, space, w_list):
        list_w = space.listview(w_list)
        size = len(list_w)

        if size == 0:
            return self._empty()

        if size == 1:
            w_s = list_w[0]
            # only one item, return it if it's not a subclass of str
            if self._join_return_one(space, w_s):
                return w_s

        return self._str_join_many_items(space, list_w, size)

    @jit.look_inside_iff(lambda self, space, list_w, size:
                         jit.loop_unrolling_heuristic(list_w, size))
    def _str_join_many_items(self, space, list_w, size):
        value = self._val(space)

        prealloc_size = len(value) * (size - 1)
        unwrapped = newlist_hint(size)
        for i in range(size):
            w_s = list_w[i]
            try:
                next_string = self._op_val(space, w_s)
            except OperationError as e:
                if not e.match(space, space.w_TypeError):
                    raise
                raise oefmt(space.w_TypeError,
                            "sequence item %d: expected %s, %T found",
                            i, self._generic_name(), w_s)
            # XXX Maybe the extra copy here is okay? It was basically going to
            #     happen anyway, what with being placed into the builder
            unwrapped.append(next_string)
            prealloc_size += len(unwrapped[i])

        sb = self._builder(prealloc_size)
        for i in range(size):
            if value and i != 0:
                sb.append(value)
            sb.append(unwrapped[i])
        return self._new(sb.build())

    @unwrap_spec(width=int, w_fillchar=WrappedDefault(' '))
    def descr_ljust(self, space, width, w_fillchar):
        value = self._val(space)
        fillchar = self._op_val(space, w_fillchar)
        if len(fillchar) != 1:
            raise oefmt(space.w_TypeError,
                        "ljust() argument 2 must be a single character")
        d = width - len(value)
        if d > 0:
            fillchar = self._multi_chr(fillchar[0])
            value = value + fillchar * d

        return self._new(value)

    @unwrap_spec(width=int, w_fillchar=WrappedDefault(' '))
    def descr_rjust(self, space, width, w_fillchar):
        value = self._val(space)
        fillchar = self._op_val(space, w_fillchar)
        if len(fillchar) != 1:
            raise oefmt(space.w_TypeError,
                        "rjust() argument 2 must be a single character")
        d = width - len(value)
        if d > 0:
            fillchar = self._multi_chr(fillchar[0])
            value = d * fillchar + value

        return self._new(value)

    def descr_lower(self, space):
        value = self._val(space)
        builder = self._builder(len(value))
        for i in range(len(value)):
            builder.append(self._lower_in_str(value, i))
        return self._new(builder.build())

    def _lower_in_str(self, value, i):
        # overridden in unicodeobject.py
        return self._lower(value[i])

    # This is not used for W_UnicodeObject.
    def descr_partition(self, space, w_sub):
        from pypy.objspace.std.bytearrayobject import W_BytearrayObject
        value = self._val(space)

        if self._use_rstr_ops(space, w_sub):
            sub = self._op_val(space, w_sub)
            sublen = len(sub)
            if sublen == 0:
                raise oefmt(space.w_ValueError, "empty separator")

            pos = value.find(sub)
        else:
            sub = space.readbuf_w(w_sub)
            sublen = sub.getlength()
            if sublen == 0:
                raise oefmt(space.w_ValueError, "empty separator")

            pos = find(value, sub, 0, len(value))
            if pos != -1 and isinstance(self, W_BytearrayObject):
                w_sub = self._new_from_buffer(sub)

        if pos == -1:
            if isinstance(self, W_BytearrayObject):
                self = self._new(value)
            return space.newtuple([self, self._empty(), self._empty()])
        else:
            return space.newtuple(
                [self._sliced(space, value, 0, pos, self), w_sub,
                 self._sliced(space, value, pos + sublen, len(value), self)])

    def descr_rpartition(self, space, w_sub):
        from pypy.objspace.std.bytearrayobject import W_BytearrayObject
        value = self._val(space)

        if self._use_rstr_ops(space, w_sub):
            sub = self._op_val(space, w_sub)
            sublen = len(sub)
            if sublen == 0:
                raise oefmt(space.w_ValueError, "empty separator")

            pos = value.rfind(sub)
        else:
            sub = space.readbuf_w(w_sub)
            sublen = sub.getlength()
            if sublen == 0:
                raise oefmt(space.w_ValueError, "empty separator")

            pos = rfind(value, sub, 0, len(value))
            if pos != -1 and isinstance(self, W_BytearrayObject):
                w_sub = self._new_from_buffer(sub)

        if pos == -1:
            if isinstance(self, W_BytearrayObject):
                self = self._new(value)
            return space.newtuple([self._empty(), self._empty(), self])
        else:
            return space.newtuple(
                [self._sliced(space, value, 0, pos, self), w_sub,
                 self._sliced(space, value, pos + sublen, len(value), self)])

    @unwrap_spec(count=int)
    def descr_replace(self, space, w_old, w_new, count=-1):
        input = self._val(space)

        sub = self._op_val(space, w_old)
        by = self._op_val(space, w_new)
        # the following two lines are for being bug-to-bug compatible
        # with CPython: see issue #2448
        if count >= 0 and len(input) == 0:
            return self._empty()
        try:
            res = replace(input, sub, by, count)
        except OverflowError:
            raise oefmt(space.w_OverflowError, "replace string is too long")

        return self._new(res)

    @unwrap_spec(maxsplit=int)
    def descr_split(self, space, w_sep=None, maxsplit=-1):
        res = []
        value = self._val(space)
        if space.is_none(w_sep):
            res = split(value, maxsplit=maxsplit)
            return self._newlist_unwrapped(space, res)

        by = self._op_val(space, w_sep)
        if len(by) == 0:
            raise oefmt(space.w_ValueError, "empty separator")
        res = split(value, by, maxsplit)

        return self._newlist_unwrapped(space, res)

    @unwrap_spec(maxsplit=int)
    def descr_rsplit(self, space, w_sep=None, maxsplit=-1):
        res = []
        value = self._val(space)
        if space.is_none(w_sep):
            res = rsplit(value, maxsplit=maxsplit)
            return self._newlist_unwrapped(space, res)

        by = self._op_val(space, w_sep)
        if len(by) == 0:
            raise oefmt(space.w_ValueError, "empty separator")
        res = rsplit(value, by, maxsplit)

        return self._newlist_unwrapped(space, res)

    @unwrap_spec(keepends=int)
    def descr_splitlines(self, space, keepends=False):
        value = self._val(space)
        length = len(value)
        strs = []
        pos = 0
        while pos < length:
            sol = pos
            while pos < length and not self._islinebreak(value[pos]):
                pos += 1
            eol = pos
            pos += 1
            # read CRLF as one line break
            if pos < length and value[eol] == '\r' and value[pos] == '\n':
                pos += 1
            if keepends:
                eol = pos
            strs.append(value[sol:eol])
        if pos < length:
            # XXX is this code reachable?
            strs.append(value[pos:length])
        return self._newlist_unwrapped(space, strs)

    def _generic_name(self):
        return "bytes"

    # This is overridden in unicodeobject, _startswith_tuple is not.
    def descr_startswith(self, space, w_prefix, w_start=None, w_end=None):
        value, start, end, _ = self._convert_idx_params(space, w_start, w_end)
        if space.isinstance_w(w_prefix, space.w_tuple):
            return self._startswith_tuple(space, value, w_prefix, start, end)
        try:
            res = self._startswith(space, value, w_prefix, start, end)
        except OperationError as e:
            if not e.match(space, space.w_TypeError):
                raise
            wanted = self._generic_name()
            raise oefmt(space.w_TypeError,
                        "startswith first arg must be %s or a tuple of %s, "
                        "not %T", wanted, wanted, w_prefix)
        return space.newbool(res)

    def _startswith_tuple(self, space, value, w_prefix, start, end):
        for w_prefix in space.fixedview(w_prefix):
            if self._startswith(space, value, w_prefix, start, end):
                return space.w_True
        return space.w_False

    # This is overridden in unicodeobject, _startswith_tuple is not.
    def _startswith(self, space, value, w_prefix, start, end):
        prefix = self._op_val(space, w_prefix)
        if start > len(value):
            return False
        return startswith(value, prefix, start, end)

    # This is overridden in unicodeobject, _endswith_tuple is not.
    def descr_endswith(self, space, w_suffix, w_start=None, w_end=None):
        value, start, end, _ = self._convert_idx_params(space, w_start, w_end)
        if space.isinstance_w(w_suffix, space.w_tuple):
            return self._endswith_tuple(space, value, w_suffix, start, end)
        try:
            res = self._endswith(space, value, w_suffix, start, end)
        except OperationError as e:
            if not e.match(space, space.w_TypeError):
                raise
            wanted = self._generic_name()
            raise oefmt(space.w_TypeError,
                        "endswith first arg must be %s or a tuple of %s, not "
                        "%T", wanted, wanted, w_suffix)
        return space.newbool(res)

    def _endswith_tuple(self, space, value, w_suffix, start, end):
        for w_suffix in space.fixedview(w_suffix):
            if self._endswith(space, value, w_suffix, start, end):
                return space.w_True
        return space.w_False

    # This is overridden in unicodeobject, but _endswith_tuple is not.
    def _endswith(self, space, value, w_prefix, start, end):
        prefix = self._op_val(space, w_prefix)
        if start > len(value):
            return False
        return endswith(value, prefix, start, end)

    def _strip(self, space, w_chars, left, right, name='strip'):
        "internal function called by str_xstrip methods"
        value = self._val(space)
        chars = self._op_val(space, w_chars)

        lpos = 0
        rpos = len(value)

        if left:
            while lpos < rpos and value[lpos] in chars:
                lpos += 1

        if right:
            while rpos > lpos and value[rpos - 1] in chars:
                rpos -= 1

        assert rpos >= lpos    # annotator hint, don't remove
        return self._sliced(space, value, lpos, rpos, self)

    def _strip_none(self, space, left, right):
        "internal function called by str_xstrip methods"
        value = self._val(space)

        lpos = 0
        rpos = len(value)

        if left:
            while lpos < rpos and self._isspace(value[lpos]):
                lpos += 1

        if right:
            while rpos > lpos and self._isspace(value[rpos - 1]):
                rpos -= 1

        assert rpos >= lpos    # annotator hint, don't remove
        return self._sliced(space, value, lpos, rpos, self)

    def descr_strip(self, space, w_chars=None):
        if space.is_none(w_chars):
            return self._strip_none(space, left=1, right=1)
        return self._strip(space, w_chars, left=1, right=1, name='strip')

    def descr_lstrip(self, space, w_chars=None):
        if space.is_none(w_chars):
            return self._strip_none(space, left=1, right=0)
        return self._strip(space, w_chars, left=1, right=0, name='lstrip')

    def descr_rstrip(self, space, w_chars=None):
        if space.is_none(w_chars):
            return self._strip_none(space, left=0, right=1)
        return self._strip(space, w_chars, left=0, right=1, name='rstrip')

    def descr_swapcase(self, space):
        selfvalue = self._val(space)
        builder = self._builder(len(selfvalue))
        for i in range(len(selfvalue)):
            ch = selfvalue[i]
            if self._isupper(ch):
                builder.append(self._lower_in_str(selfvalue, i))
            elif self._islower(ch):
                builder.append(self._upper(ch))
            else:
                builder.append(ch)
        return self._new(builder.build())

    def descr_title(self, space):
        selfval = self._val(space)
        if len(selfval) == 0:
            return self
        return self._new(self.title(selfval))

    @jit.elidable
    def title(self, value):
        builder = self._builder(len(value))
        previous_is_cased = False
        for i in range(len(value)):
            ch = value[i]
            if not previous_is_cased:
                builder.append(self._title(ch))
            else:
                builder.append(self._lower_in_str(value, i))
            previous_is_cased = self._iscased(ch)
        return builder.build()

    DEFAULT_NOOP_TABLE = ''.join([chr(i) for i in range(256)])

    # for bytes and bytearray, overridden by unicode
    @unwrap_spec(w_delete=WrappedDefault(''))
    def descr_translate(self, space, w_table, w_delete):
        if space.is_w(w_table, space.w_None):
            table = self.DEFAULT_NOOP_TABLE
        else:
            table = self._op_val(space, w_table)
            if len(table) != 256:
                raise oefmt(space.w_ValueError,
                            "translation table must be 256 characters long")

        string = self._val(space)
        deletechars = self._op_val(space, w_delete)
        if len(deletechars) == 0:
            buf = self._builder(len(string))
            for char in string:
                buf.append(table[ord(char)])
        else:
            # XXX Why not preallocate here too?
            buf = self._builder()
            deletion_table = [False] * 256
            for i in range(len(deletechars)):
                deletion_table[ord(deletechars[i])] = True
            for char in string:
                if not deletion_table[ord(char)]:
                    buf.append(table[ord(char)])
        return self._new(buf.build())

    def descr_upper(self, space):
        value = self._val(space)
        builder = self._builder(len(value))
        for i in range(len(value)):
            builder.append(self._upper(value[i]))
        return self._new(builder.build())

    @unwrap_spec(width=int)
    def descr_zfill(self, space, width):
        selfval = self._val(space)
        if len(selfval) == 0:
            return self._new(self._multi_chr(self._chr('0')) * width)
        num_zeros = width - len(selfval)
        if num_zeros <= 0:
            # cannot return self, in case it is a subclass of str
            return self._new(selfval)

        builder = self._builder(width)
        if len(selfval) > 0 and (selfval[0] == '+' or selfval[0] == '-'):
            # copy sign to first position
            builder.append(selfval[0])
            start = 1
        else:
            start = 0
        builder.append_multiple_char(self._chr('0'), num_zeros)
        builder.append_slice(selfval, start, len(selfval))
        return self._new(builder.build())

    def descr_getnewargs(self, space):
        return space.newtuple([self._new(self._val(space))])
コード例 #15
0
ファイル: stringmethods.py プロジェクト: zielmicha/pypy
class StringMethods(object):
    def _sliced(self, space, s, start, stop, orig_obj):
        assert start >= 0
        assert stop >= 0
        #if start == 0 and stop == len(s) and space.is_w(space.type(orig_obj),
        #                                                space.w_str):
        #    return orig_obj
        return self._new(s[start:stop])

    @specialize.arg(4)
    def _convert_idx_params(self, space, w_start, w_end, upper_bound=False):
        value = self._val(space)
        lenself = len(value)
        start, end = unwrap_start_stop(space, lenself, w_start, w_end,
                                       upper_bound=upper_bound)
        return (value, start, end)

    def _multi_chr(self, c):
        return c

    def descr_len(self, space):
        return space.wrap(self._len())

    #def descr_iter(self, space):
    #    pass

    def descr_contains(self, space, w_sub):
        value = self._val(space)
        if self._use_rstr_ops(space, w_sub):
            other = self._op_val(space, w_sub)
            return space.newbool(value.find(other) >= 0)

        from pypy.objspace.std.bytesobject import W_BytesObject
        if isinstance(w_sub, W_BytesObject):
            other = self._op_val(space, w_sub)
            res = find(value, other, 0, len(value))
        else:
            buffer = _get_buffer(space, w_sub)
            res = find(value, buffer, 0, len(value))

        return space.newbool(res >= 0)

    def descr_add(self, space, w_other):
        if self._use_rstr_ops(space, w_other):
            try:
                other = self._op_val(space, w_other)
            except OperationError as e:
                if e.match(space, space.w_TypeError):
                    return space.w_NotImplemented
                raise
            return self._new(self._val(space) + other)

        # Bytearray overrides this method, CPython doesn't support contacting
        # buffers and strs, and unicodes are always handled above
        return space.w_NotImplemented

    def descr_mul(self, space, w_times):
        try:
            times = space.getindex_w(w_times, space.w_OverflowError)
        except OperationError as e:
            if e.match(space, space.w_TypeError):
                return space.w_NotImplemented
            raise
        if times <= 0:
            return self._empty()
        if self._len() == 1:
            return self._new(self._multi_chr(self._val(space)[0]) * times)
        return self._new(self._val(space) * times)

    descr_rmul = descr_mul

    def descr_getitem(self, space, w_index):
        if isinstance(w_index, W_SliceObject):
            selfvalue = self._val(space)
            length = len(selfvalue)
            start, stop, step, sl = w_index.indices4(space, length)
            if sl == 0:
                return self._empty()
            elif step == 1:
                assert start >= 0 and stop >= 0
                return self._sliced(space, selfvalue, start, stop, self)
            else:
                ret = _descr_getslice_slowpath(selfvalue, start, step, sl)
                return self._new_from_list(ret)

        index = space.getindex_w(w_index, space.w_IndexError, "string index")
        return self._getitem_result(space, index)

    def _getitem_result(self, space, index):
        selfvalue = self._val(space)
        try:
            character = selfvalue[index]
        except IndexError:
            raise oefmt(space.w_IndexError, "string index out of range")
        return self._new(character)

    def descr_getslice(self, space, w_start, w_stop):
        selfvalue = self._val(space)
        start, stop = normalize_simple_slice(space, len(selfvalue), w_start,
                                             w_stop)
        if start == stop:
            return self._empty()
        else:
            return self._sliced(space, selfvalue, start, stop, self)

    def descr_capitalize(self, space):
        value = self._val(space)
        if len(value) == 0:
            return self._empty()

        builder = self._builder(len(value))
        builder.append(self._upper(value[0]))
        for i in range(1, len(value)):
            builder.append(self._lower(value[i]))
        return self._new(builder.build())

    @unwrap_spec(width=int, w_fillchar=WrappedDefault(' '))
    def descr_center(self, space, width, w_fillchar):
        value = self._val(space)
        fillchar = self._op_val(space, w_fillchar)
        if len(fillchar) != 1:
            raise oefmt(space.w_TypeError,
                        "center() argument 2 must be a single character")

        d = width - len(value)
        if d > 0:
            offset = d//2 + (d & width & 1)
            fillchar = self._multi_chr(fillchar[0])
            centered = offset * fillchar + value + (d - offset) * fillchar
        else:
            centered = value

        return self._new(centered)

    def descr_count(self, space, w_sub, w_start=None, w_end=None):
        value, start, end = self._convert_idx_params(space, w_start, w_end)

        if self._use_rstr_ops(space, w_sub):
            return space.newint(value.count(self._op_val(space, w_sub), start,
                                            end))

        from pypy.objspace.std.bytearrayobject import W_BytearrayObject
        from pypy.objspace.std.bytesobject import W_BytesObject
        if isinstance(w_sub, W_BytearrayObject):
            res = count(value, w_sub.data, start, end)
        elif isinstance(w_sub, W_BytesObject):
            res = count(value, w_sub._value, start, end)
        else:
            buffer = _get_buffer(space, w_sub)
            res = count(value, buffer, start, end)

        return space.wrap(max(res, 0))

    def descr_decode(self, space, w_encoding=None, w_errors=None):
        from pypy.objspace.std.unicodeobject import (
            _get_encoding_and_errors, decode_object, unicode_from_string)
        encoding, errors = _get_encoding_and_errors(space, w_encoding,
                                                    w_errors)

        from pypy.objspace.std.bytearrayobject import W_BytearrayObject
        if (encoding is None and errors is None and
            not isinstance(self, W_BytearrayObject)):
            return unicode_from_string(space, self)
        return decode_object(space, self, encoding, errors)

    def descr_encode(self, space, w_encoding=None, w_errors=None):
        from pypy.objspace.std.unicodeobject import (
            _get_encoding_and_errors, encode_object)
        encoding, errors = _get_encoding_and_errors(space, w_encoding,
                                                    w_errors)
        return encode_object(space, self, encoding, errors)

    @unwrap_spec(tabsize=int)
    def descr_expandtabs(self, space, tabsize=8):
        value = self._val(space)
        if not value:
            return self._empty()

        if self._use_rstr_ops(space, self):
            splitted = value.split(self._chr('\t'))
        else:
            splitted = split(value, self._chr('\t'))

        try:
            ovfcheck(len(splitted) * tabsize)
        except OverflowError:
            raise oefmt(space.w_OverflowError, "new string is too long")
        expanded = oldtoken = splitted.pop(0)

        for token in splitted:
            expanded += self._multi_chr(self._chr(' ')) * self._tabindent(oldtoken,
                                                         tabsize) + token
            oldtoken = token

        return self._new(expanded)

    def _tabindent(self, token, tabsize):
        """calculates distance behind the token to the next tabstop"""

        distance = tabsize
        if token:
            distance = 0
            offset = len(token)

            while 1:
                if token[offset-1] == "\n" or token[offset-1] == "\r":
                    break
                distance += 1
                offset -= 1
                if offset == 0:
                    break

            # the same like distance = len(token) - (offset + 1)
            distance = (tabsize - distance) % tabsize
            if distance == 0:
                distance = tabsize

        return distance

    def descr_find(self, space, w_sub, w_start=None, w_end=None):
        (value, start, end) = self._convert_idx_params(space, w_start, w_end)

        if self._use_rstr_ops(space, w_sub):
            res = value.find(self._op_val(space, w_sub), start, end)
            return space.wrap(res)

        from pypy.objspace.std.bytearrayobject import W_BytearrayObject
        from pypy.objspace.std.bytesobject import W_BytesObject
        if isinstance(w_sub, W_BytearrayObject):
            res = find(value, w_sub.data, start, end)
        elif isinstance(w_sub, W_BytesObject):
            res = find(value, w_sub._value, start, end)
        else:
            buffer = _get_buffer(space, w_sub)
            res = find(value, buffer, start, end)

        return space.wrap(res)

    def descr_rfind(self, space, w_sub, w_start=None, w_end=None):
        (value, start, end) = self._convert_idx_params(space, w_start, w_end)

        if self._use_rstr_ops(space, w_sub):
            res = value.rfind(self._op_val(space, w_sub), start, end)
            return space.wrap(res)

        from pypy.objspace.std.bytearrayobject import W_BytearrayObject
        from pypy.objspace.std.bytesobject import W_BytesObject
        if isinstance(w_sub, W_BytearrayObject):
            res = rfind(value, w_sub.data, start, end)
        elif isinstance(w_sub, W_BytesObject):
            res = rfind(value, w_sub._value, start, end)
        else:
            buffer = _get_buffer(space, w_sub)
            res = rfind(value, buffer, start, end)

        return space.wrap(res)

    def descr_index(self, space, w_sub, w_start=None, w_end=None):
        (value, start, end) = self._convert_idx_params(space, w_start, w_end)

        from pypy.objspace.std.bytearrayobject import W_BytearrayObject
        from pypy.objspace.std.bytesobject import W_BytesObject
        if self._use_rstr_ops(space, w_sub):
            res = value.find(self._op_val(space, w_sub), start, end)
        elif isinstance(w_sub, W_BytearrayObject):
            res = find(value, w_sub.data, start, end)
        elif isinstance(w_sub, W_BytesObject):
            res = find(value, w_sub._value, start, end)
        else:
            buffer = _get_buffer(space, w_sub)
            res = find(value, buffer, start, end)

        if res < 0:
            raise oefmt(space.w_ValueError,
                        "substring not found in string.index")
        return space.wrap(res)

    def descr_rindex(self, space, w_sub, w_start=None, w_end=None):
        (value, start, end) = self._convert_idx_params(space, w_start, w_end)

        from pypy.objspace.std.bytearrayobject import W_BytearrayObject
        from pypy.objspace.std.bytesobject import W_BytesObject
        if self._use_rstr_ops(space, w_sub):
            res = value.rfind(self._op_val(space, w_sub), start, end)
        elif isinstance(w_sub, W_BytearrayObject):
            res = rfind(value, w_sub.data, start, end)
        elif isinstance(w_sub, W_BytesObject):
            res = rfind(value, w_sub._value, start, end)
        else:
            buffer = _get_buffer(space, w_sub)
            res = rfind(value, buffer, start, end)

        if res < 0:
            raise oefmt(space.w_ValueError,
                        "substring not found in string.rindex")
        return space.wrap(res)

    @specialize.arg(2)
    def _is_generic(self, space, func_name):
        func = getattr(self, func_name)
        v = self._val(space)
        if len(v) == 0:
            return space.w_False
        if len(v) == 1:
            c = v[0]
            return space.newbool(func(c))
        else:
            return self._is_generic_loop(space, v, func_name)

    @specialize.arg(3)
    def _is_generic_loop(self, space, v, func_name):
        func = getattr(self, func_name)
        for idx in range(len(v)):
            if not func(v[idx]):
                return space.w_False
        return space.w_True

    def descr_isalnum(self, space):
        return self._is_generic(space, '_isalnum')

    def descr_isalpha(self, space):
        return self._is_generic(space, '_isalpha')

    def descr_isdigit(self, space):
        return self._is_generic(space, '_isdigit')

    # this is only for bytes and bytesarray: unicodeobject overrides it
    def _descr_islower_slowpath(self, space, v):
        cased = False
        for idx in range(len(v)):
            if self._isupper(v[idx]):
                return False
            elif not cased and self._islower(v[idx]):
                cased = True
        return cased

    def descr_islower(self, space):
        v = self._val(space)
        if len(v) == 1:
            c = v[0]
            return space.newbool(self._islower(c))
        cased = self._descr_islower_slowpath(space, v)
        return space.newbool(cased)

    def descr_isspace(self, space):
        return self._is_generic(space, '_isspace')

    def descr_istitle(self, space):
        input = self._val(space)
        cased = False
        previous_is_cased = False

        for pos in range(0, len(input)):
            ch = input[pos]
            if self._istitle(ch):
                if previous_is_cased:
                    return space.w_False
                previous_is_cased = True
                cased = True
            elif self._islower(ch):
                if not previous_is_cased:
                    return space.w_False
                cased = True
            else:
                previous_is_cased = False

        return space.newbool(cased)

    # this is only for bytes and bytesarray: unicodeobject overrides it
    def _descr_isupper_slowpath(self, space, v):
        cased = False
        for idx in range(len(v)):
            if self._islower(v[idx]):
                return False
            elif not cased and self._isupper(v[idx]):
                cased = True
        return cased

    def descr_isupper(self, space):
        v = self._val(space)
        if len(v) == 1:
            c = v[0]
            return space.newbool(self._isupper(c))
        cased = self._descr_isupper_slowpath(space, v)
        return space.newbool(cased)

    def descr_join(self, space, w_list):
        list_w = space.listview(w_list)
        size = len(list_w)

        if size == 0:
            return self._empty()

        if size == 1:
            w_s = list_w[0]
            # only one item, return it if it's not a subclass of str
            if self._join_return_one(space, w_s):
                return w_s

        return self._str_join_many_items(space, list_w, size)

    @jit.look_inside_iff(lambda self, space, list_w, size:
                         jit.loop_unrolling_heuristic(list_w, size))
    def _str_join_many_items(self, space, list_w, size):
        value = self._val(space)

        prealloc_size = len(value) * (size - 1)
        unwrapped = newlist_hint(size)
        for i in range(size):
            w_s = list_w[i]
            check_item = self._join_check_item(space, w_s)
            if check_item == 1:
                raise oefmt(space.w_TypeError,
                            "sequence item %d: expected string, %T found",
                            i, w_s)
            elif check_item == 2:
                return self._join_autoconvert(space, list_w)
            # XXX Maybe the extra copy here is okay? It was basically going to
            #     happen anyway, what with being placed into the builder
            unwrapped.append(self._op_val(space, w_s))
            prealloc_size += len(unwrapped[i])

        sb = self._builder(prealloc_size)
        for i in range(size):
            if value and i != 0:
                sb.append(value)
            sb.append(unwrapped[i])
        return self._new(sb.build())

    def _join_autoconvert(self, space, list_w):
        assert False, 'unreachable'

    @unwrap_spec(width=int, w_fillchar=WrappedDefault(' '))
    def descr_ljust(self, space, width, w_fillchar):
        value = self._val(space)
        fillchar = self._op_val(space, w_fillchar)
        if len(fillchar) != 1:
            raise oefmt(space.w_TypeError,
                        "ljust() argument 2 must be a single character")
        d = width - len(value)
        if d > 0:
            fillchar = self._multi_chr(fillchar[0])
            value = value + fillchar * d

        return self._new(value)

    @unwrap_spec(width=int, w_fillchar=WrappedDefault(' '))
    def descr_rjust(self, space, width, w_fillchar):
        value = self._val(space)
        fillchar = self._op_val(space, w_fillchar)
        if len(fillchar) != 1:
            raise oefmt(space.w_TypeError,
                        "rjust() argument 2 must be a single character")
        d = width - len(value)
        if d > 0:
            fillchar = self._multi_chr(fillchar[0])
            value = d * fillchar + value

        return self._new(value)

    def descr_lower(self, space):
        value = self._val(space)
        builder = self._builder(len(value))
        for i in range(len(value)):
            builder.append(self._lower(value[i]))
        return self._new(builder.build())

    def descr_partition(self, space, w_sub):
        from pypy.objspace.std.bytearrayobject import W_BytearrayObject
        value = self._val(space)

        if self._use_rstr_ops(space, w_sub):
            sub = self._op_val(space, w_sub)
            sublen = len(sub)
            if sublen == 0:
                raise oefmt(space.w_ValueError, "empty separator")

            pos = value.find(sub)
        else:
            sub = _get_buffer(space, w_sub)
            sublen = sub.getlength()
            if sublen == 0:
                raise oefmt(space.w_ValueError, "empty separator")

            pos = find(value, sub, 0, len(value))
            if pos != -1 and isinstance(self, W_BytearrayObject):
                w_sub = self._new_from_buffer(sub)

        if pos == -1:
            if isinstance(self, W_BytearrayObject):
                self = self._new(value)
            return space.newtuple([self, self._empty(), self._empty()])
        else:
            return space.newtuple(
                [self._sliced(space, value, 0, pos, self), w_sub,
                 self._sliced(space, value, pos + sublen, len(value), self)])

    def descr_rpartition(self, space, w_sub):
        from pypy.objspace.std.bytearrayobject import W_BytearrayObject
        value = self._val(space)

        if self._use_rstr_ops(space, w_sub):
            sub = self._op_val(space, w_sub)
            sublen = len(sub)
            if sublen == 0:
                raise oefmt(space.w_ValueError, "empty separator")

            pos = value.rfind(sub)
        else:
            sub = _get_buffer(space, w_sub)
            sublen = sub.getlength()
            if sublen == 0:
                raise oefmt(space.w_ValueError, "empty separator")

            pos = rfind(value, sub, 0, len(value))
            if pos != -1 and isinstance(self, W_BytearrayObject):
                w_sub = self._new_from_buffer(sub)

        if pos == -1:
            if isinstance(self, W_BytearrayObject):
                self = self._new(value)
            return space.newtuple([self._empty(), self._empty(), self])
        else:
            return space.newtuple(
                [self._sliced(space, value, 0, pos, self), w_sub,
                 self._sliced(space, value, pos + sublen, len(value), self)])

    @unwrap_spec(count=int)
    def descr_replace(self, space, w_old, w_new, count=-1):
        input = self._val(space)

        sub = self._op_val(space, w_old)
        by = self._op_val(space, w_new)
        try:
            res = replace(input, sub, by, count)
        except OverflowError:
            raise oefmt(space.w_OverflowError, "replace string is too long")

        return self._new(res)

    @unwrap_spec(maxsplit=int)
    def descr_split(self, space, w_sep=None, maxsplit=-1):
        res = []
        value = self._val(space)
        if space.is_none(w_sep):
            res = split(value, maxsplit=maxsplit)
            return self._newlist_unwrapped(space, res)

        by = self._op_val(space, w_sep)
        if len(by) == 0:
            raise oefmt(space.w_ValueError, "empty separator")
        res = split(value, by, maxsplit)

        return self._newlist_unwrapped(space, res)

    @unwrap_spec(maxsplit=int)
    def descr_rsplit(self, space, w_sep=None, maxsplit=-1):
        res = []
        value = self._val(space)
        if space.is_none(w_sep):
            res = rsplit(value, maxsplit=maxsplit)
            return self._newlist_unwrapped(space, res)

        by = self._op_val(space, w_sep)
        if len(by) == 0:
            raise oefmt(space.w_ValueError, "empty separator")
        res = rsplit(value, by, maxsplit)

        return self._newlist_unwrapped(space, res)

    @unwrap_spec(keepends=bool)
    def descr_splitlines(self, space, keepends=False):
        value = self._val(space)
        length = len(value)
        strs = []
        pos = 0
        while pos < length:
            sol = pos
            while pos < length and not self._islinebreak(value[pos]):
                pos += 1
            eol = pos
            pos += 1
            # read CRLF as one line break
            if pos < length and value[eol] == '\r' and value[pos] == '\n':
                pos += 1
            if keepends:
                eol = pos
            strs.append(value[sol:eol])
        if pos < length:
            strs.append(value[pos:length])
        return self._newlist_unwrapped(space, strs)

    def descr_startswith(self, space, w_prefix, w_start=None, w_end=None):
        (value, start, end) = self._convert_idx_params(space, w_start, w_end,
                                                       True)
        if space.isinstance_w(w_prefix, space.w_tuple):
            for w_prefix in space.fixedview(w_prefix):
                if self._startswith(space, value, w_prefix, start, end):
                    return space.w_True
            return space.w_False
        return space.newbool(self._startswith(space, value, w_prefix, start,
                                              end))

    def _startswith(self, space, value, w_prefix, start, end):
        return startswith(value, self._op_val(space, w_prefix), start, end)

    def descr_endswith(self, space, w_suffix, w_start=None, w_end=None):
        (value, start, end) = self._convert_idx_params(space, w_start, w_end,
                                                       True)
        if space.isinstance_w(w_suffix, space.w_tuple):
            for w_suffix in space.fixedview(w_suffix):
                if self._endswith(space, value, w_suffix, start, end):
                    return space.w_True
            return space.w_False
        return space.newbool(self._endswith(space, value, w_suffix, start,
                                            end))

    def _endswith(self, space, value, w_prefix, start, end):
        return endswith(value, self._op_val(space, w_prefix), start, end)

    def _strip(self, space, w_chars, left, right):
        "internal function called by str_xstrip methods"
        value = self._val(space)
        chars = self._op_val(space, w_chars)

        lpos = 0
        rpos = len(value)

        if left:
            while lpos < rpos and value[lpos] in chars:
                lpos += 1

        if right:
            while rpos > lpos and value[rpos - 1] in chars:
                rpos -= 1

        assert rpos >= lpos    # annotator hint, don't remove
        return self._sliced(space, value, lpos, rpos, self)

    def _strip_none(self, space, left, right):
        "internal function called by str_xstrip methods"
        value = self._val(space)

        lpos = 0
        rpos = len(value)

        if left:
            while lpos < rpos and self._isspace(value[lpos]):
                lpos += 1

        if right:
            while rpos > lpos and self._isspace(value[rpos - 1]):
                rpos -= 1

        assert rpos >= lpos    # annotator hint, don't remove
        return self._sliced(space, value, lpos, rpos, self)

    def descr_strip(self, space, w_chars=None):
        if space.is_none(w_chars):
            return self._strip_none(space, left=1, right=1)
        return self._strip(space, w_chars, left=1, right=1)

    def descr_lstrip(self, space, w_chars=None):
        if space.is_none(w_chars):
            return self._strip_none(space, left=1, right=0)
        return self._strip(space, w_chars, left=1, right=0)

    def descr_rstrip(self, space, w_chars=None):
        if space.is_none(w_chars):
            return self._strip_none(space, left=0, right=1)
        return self._strip(space, w_chars, left=0, right=1)

    def descr_swapcase(self, space):
        selfvalue = self._val(space)
        builder = self._builder(len(selfvalue))
        for i in range(len(selfvalue)):
            ch = selfvalue[i]
            if self._isupper(ch):
                builder.append(self._lower(ch))
            elif self._islower(ch):
                builder.append(self._upper(ch))
            else:
                builder.append(ch)
        return self._new(builder.build())

    def descr_title(self, space):
        selfval = self._val(space)
        if len(selfval) == 0:
            return self
        return self._new(self.title(selfval))

    @jit.elidable
    def title(self, value):
        builder = self._builder(len(value))
        previous_is_cased = False
        for ch in value:
            if not previous_is_cased:
                builder.append(self._title(ch))
            else:
                builder.append(self._lower(ch))
            previous_is_cased = self._iscased(ch)
        return builder.build()

    DEFAULT_NOOP_TABLE = ''.join([chr(i) for i in range(256)])

    # for bytes and bytearray, overridden by unicode
    @unwrap_spec(w_deletechars=WrappedDefault(''))
    def descr_translate(self, space, w_table, w_deletechars):
        if space.is_w(w_table, space.w_None):
            table = self.DEFAULT_NOOP_TABLE
        else:
            table = self._op_val(space, w_table)
            if len(table) != 256:
                raise oefmt(space.w_ValueError,
                            "translation table must be 256 characters long")

        string = self._val(space)
        deletechars = self._op_val(space, w_deletechars)
        if len(deletechars) == 0:
            buf = self._builder(len(string))
            for char in string:
                buf.append(table[ord(char)])
        else:
            # XXX Why not preallocate here too?
            buf = self._builder()
            deletion_table = [False] * 256
            for i in range(len(deletechars)):
                deletion_table[ord(deletechars[i])] = True
            for char in string:
                if not deletion_table[ord(char)]:
                    buf.append(table[ord(char)])
        return self._new(buf.build())

    def descr_upper(self, space):
        value = self._val(space)
        builder = self._builder(len(value))
        for i in range(len(value)):
            builder.append(self._upper(value[i]))
        return self._new(builder.build())

    @unwrap_spec(width=int)
    def descr_zfill(self, space, width):
        selfval = self._val(space)
        if len(selfval) == 0:
            return self._new(self._multi_chr(self._chr('0')) * width)
        num_zeros = width - len(selfval)
        if num_zeros <= 0:
            # cannot return self, in case it is a subclass of str
            return self._new(selfval)

        builder = self._builder(width)
        if len(selfval) > 0 and (selfval[0] == '+' or selfval[0] == '-'):
            # copy sign to first position
            builder.append(selfval[0])
            start = 1
        else:
            start = 0
        builder.append_multiple_char(self._chr('0'), num_zeros)
        builder.append_slice(selfval, start, len(selfval))
        return self._new(builder.build())

    def descr_getnewargs(self, space):
        return space.newtuple([self._new(self._val(space))])
コード例 #16
0
ファイル: vector.py プロジェクト: shiplift/PycketOnAShip
 def unrolling_heuristic(self, w_vector):
     storage = self._storage(w_vector)
     return jit.loop_unrolling_heuristic(storage, w_vector.len,
                                         UNROLLING_CUTOFF)
コード例 #17
0
ファイル: vector.py プロジェクト: shiplift/PycketOnAShip
from pycket.values import W_MVector, W_VectorSuper, W_Fixnum, W_Flonum, W_Character, UNROLLING_CUTOFF, wrap
from pycket.base import W_Object, SingletonMeta, UnhashableType
from pycket import config

from rpython.rlib import debug, jit, objectmodel, rerased
from rpython.rlib.longlong2float import (can_encode_int32,
                                         decode_int32_from_longlong_nan,
                                         encode_int32_into_longlong_nan,
                                         float2longlong,
                                         is_int32_from_longlong_nan,
                                         longlong2float)
from rpython.rlib.objectmodel import import_from_mixin, specialize, we_are_translated
from rpython.rlib.rarithmetic import intmask


@jit.look_inside_iff(lambda elements, immutable: jit.loop_unrolling_heuristic(
    elements, len(elements), UNROLLING_CUTOFF))
def _find_strategy_class(elements, immutable):
    if not config.strategies or len(elements) == 0:
        # An empty vector stays empty forever. Don't implement special EmptyVectorStrategy.
        if immutable:
            return ObjectImmutableVectorStrategy.singleton
        return ObjectVectorStrategy.singleton
    single_class = type(elements[0])
    for elem in elements:
        if not isinstance(elem, single_class):
            if immutable:
                return ObjectImmutableVectorStrategy.singleton
            return ObjectVectorStrategy.singleton
    if single_class is W_Fixnum:
        if immutable:
            return FixnumImmutableVectorStrategy.singleton
コード例 #18
0
def _unroll_condition(self):
    return jit.loop_unrolling_heuristic(self, self.length(), UNROLL_CUTOFF)
コード例 #19
0
ファイル: vector.py プロジェクト: krono/pycket
from pycket.values import W_MVector, W_VectorSuper, W_Fixnum, W_Flonum, W_Character, UNROLLING_CUTOFF
from pycket.base import W_Object, SingletonMeta
from pycket import config

from rpython.rlib import rerased
from rpython.rlib.objectmodel import newlist_hint, import_from_mixin
from rpython.rlib import debug, jit


@jit.look_inside_iff(
    lambda elements, immutable: jit.loop_unrolling_heuristic(elements, len(elements), UNROLLING_CUTOFF)
)
def _find_strategy_class(elements, immutable):
    if not config.strategies or len(elements) == 0:
        # An empty vector stays empty forever. Don't implement special EmptyVectorStrategy.
        return ObjectVectorStrategy.singleton
    single_class = type(elements[0])
    for elem in elements:
        if not isinstance(elem, single_class):
            if immutable:
                return ObjectImmutableVectorStrategy.singleton
            return ObjectVectorStrategy.singleton
    if single_class is W_Fixnum:
        if immutable:
            return FixnumImmutableVectorStrategy.singleton
        return FixnumVectorStrategy.singleton
    if single_class is W_Flonum:
        if immutable:
            return FlonumImmutableVectorStrategy.singleton
        return FlonumVectorStrategy.singleton
    if single_class is W_Character:
コード例 #20
0
def _unroll_condition_cmp(self, space, other):
    return (jit.loop_unrolling_heuristic(self, self.length(), UNROLL_CUTOFF) or
            jit.loop_unrolling_heuristic(other, other.length(), UNROLL_CUTOFF))
コード例 #21
0
ファイル: values.py プロジェクト: uternet/pycket
        return self.arity

    def call(self, args, env, cont):
        return self.call_with_extra_info(args, env, cont, None)

    def call_with_extra_info(self, args, env, cont, extra_call_info):
        jit.promote(self)
        return self.code(args, env, cont, extra_call_info)

    def tostring(self):
        return "#<procedure:%s>" % self.name.variable_name()

def to_list(l): return to_improper(l, w_null)

@jit.look_inside_iff(
    lambda l, curr: jit.loop_unrolling_heuristic(l, len(l), UNROLLING_CUTOFF))
def to_improper(l, curr):
    for i in range(len(l) - 1, -1, -1):
        curr = W_Cons.make(l[i], curr)
    return curr

@jit.look_inside_iff(
    lambda v, curr: jit.loop_unrolling_heuristic(v, v.len, UNROLLING_CUTOFF))
def vector_to_improper(v, curr):
    for i in range(v.len - 1, -1, -1):
        curr = W_Cons.make(v.ref(i), curr)
    return curr

def to_mlist(l): return to_mimproper(l, w_null)

@jit.look_inside_iff(
コード例 #22
0
ファイル: vector.py プロジェクト: pycket/pycket
 def unrolling_heuristic(self, w_vector):
     storage = self._storage(w_vector)
     return jit.loop_unrolling_heuristic(storage, w_vector.len, UNROLLING_CUTOFF)
コード例 #23
0
ファイル: equal.py プロジェクト: magnusmorton/pycket
        index = i.value
        if index >= self.length(w_dict) - 1:
            return values.w_false
        return values.wrap(index + 1)

    def hash_iterate_first(self, w_dict):
        return 0

    def length(self, w_dict):
        raise NotImplementedError("abstract base class")

    def create_storage(self, keys, vals):
        raise NotImplementedError("abstract base class")

@jit.look_inside_iff(lambda keys:
        jit.loop_unrolling_heuristic(
                keys, len(keys), values.UNROLLING_CUTOFF))
def _find_strategy_class(keys):
    if not config.strategies:
        return ObjectHashmapStrategy.singleton
    if len(keys) == 0:
        return EmptyHashmapStrategy.singleton
        # An empty vector stays empty forever. Don't implement special EmptyVectorStrategy.
    single_class = type(keys[0])
    for elem in keys:
        if not isinstance(elem, single_class):
            return ObjectHashmapStrategy.singleton
    if single_class is values.W_Fixnum:
        return FixnumHashmapStrategy.singleton
    if single_class is values.W_Symbol:
        return SymbolHashmapStrategy.singleton
    if single_class is values_string.W_String:
コード例 #24
0
ファイル: tupleobject.py プロジェクト: Qointum/pypy
def _unroll_condition_cmp(self, space, other):
    return (jit.loop_unrolling_heuristic(self, self.length(), UNROLL_CUTOFF) or
            jit.loop_unrolling_heuristic(other, other.length(), UNROLL_CUTOFF))
コード例 #25
0
ファイル: stringobject.py プロジェクト: charred/pypy
    size = len(list_w)

    if size == 0:
        return W_StringObject.EMPTY

    if size == 1:
        w_s = list_w[0]
        # only one item,  return it if it's not a subclass of str
        if (space.is_w(space.type(w_s), space.w_str) or
            space.is_w(space.type(w_s), space.w_unicode)):
            return w_s

    return _str_join_many_items(space, w_self, list_w, size)

@jit.look_inside_iff(lambda space, w_self, list_w, size:
                     jit.loop_unrolling_heuristic(list_w, size))
def _str_join_many_items(space, w_self, list_w, size):
    self = w_self._value
    reslen = len(self) * (size - 1)
    for i in range(size):
        w_s = list_w[i]
        if not space.isinstance_w(w_s, space.w_str):
            if space.isinstance_w(w_s, space.w_unicode):
                # we need to rebuild w_list here, because the original
                # w_list might be an iterable which we already consumed
                w_list = space.newlist(list_w)
                w_u = space.call_function(space.w_unicode, w_self)
                return space.call_method(w_u, "join", w_list)
            msg = "sequence item %d: expected string, %T found"
            raise operationerrfmt(space.w_TypeError, msg, i, w_s)
        reslen += len(space.str_w(w_s))
コード例 #26
0
class LLHelpers(AbstractLLHelpers):
    from rpython.rtyper.annlowlevel import llstr, llunicode

    @staticmethod
    @jit.elidable
    def ll_str_mul(s, times):
        if times < 0:
            times = 0
        try:
            size = ovfcheck(len(s.chars) * times)
        except OverflowError:
            raise MemoryError
        newstr = s.malloc(size)
        i = 0
        if i < size:
            s.copy_contents(s, newstr, 0, 0, len(s.chars))
            i += len(s.chars)
        while i < size:
            if i <= size - i:
                j = i
            else:
                j = size - i
            s.copy_contents(newstr, newstr, 0, i, j)
            i += j
        return newstr

    @staticmethod
    @jit.elidable
    def ll_char_mul(ch, times):
        if typeOf(ch) is Char:
            malloc = mallocstr
        else:
            malloc = mallocunicode
        if times < 0:
            times = 0
        newstr = malloc(times)
        j = 0
        # XXX we can use memset here, not sure how useful this is
        while j < times:
            newstr.chars[j] = ch
            j += 1
        return newstr

    @staticmethod
    def ll_strlen(s):
        return len(s.chars)

    @staticmethod
    @signature(types.any(), types.int(), returns=types.any())
    def ll_stritem_nonneg(s, i):
        chars = s.chars
        ll_assert(i >= 0, "negative str getitem index")
        ll_assert(i < len(chars), "str getitem index out of bound")
        return chars[i]

    @staticmethod
    def ll_chr2str(ch):
        if typeOf(ch) is Char:
            malloc = mallocstr
        else:
            malloc = mallocunicode
        s = malloc(1)
        s.chars[0] = ch
        return s

    # @jit.look_inside_iff(lambda str: jit.isconstant(len(str.chars)) and len(str.chars) == 1)
    @staticmethod
    @jit.oopspec("str.str2unicode(str)")
    def ll_str2unicode(str):
        lgt = len(str.chars)
        s = mallocunicode(lgt)
        for i in range(lgt):
            if ord(str.chars[i]) > 127:
                raise UnicodeDecodeError
            s.chars[i] = cast_primitive(UniChar, str.chars[i])
        return s

    @staticmethod
    def ll_str2bytearray(str):
        from rpython.rtyper.lltypesystem.rbytearray import BYTEARRAY

        lgt = len(str.chars)
        b = malloc(BYTEARRAY, lgt)
        for i in range(lgt):
            b.chars[i] = str.chars[i]
        return b

    @staticmethod
    def ll_strhash(s):
        if s:
            return jit.conditional_call_elidable(s.hash, LLHelpers._ll_strhash,
                                                 s)
        else:
            return 0

    @staticmethod
    @dont_inline
    @jit.dont_look_inside
    def _ll_strhash(s):
        # unlike CPython, there is no reason to avoid to return -1
        # but our malloc initializes the memory to zero, so we use zero as the
        # special non-computed-yet value.  Also, jit.conditional_call_elidable
        # always checks for zero, for now.
        x = ll_hash_string(s)
        if x == 0:
            x = 29872897
        s.hash = x
        return x

    @staticmethod
    def ll_length(s):
        return len(s.chars)

    @staticmethod
    def ll_strfasthash(s):
        ll_assert(s.hash != 0, "ll_strfasthash: hash==0")
        return s.hash  # assumes that the hash is already computed

    @staticmethod
    @jit.elidable
    @jit.oopspec('stroruni.concat(s1, s2)')
    def ll_strconcat(s1, s2):
        len1 = s1.length()
        len2 = s2.length()
        # a single '+' like this is allowed to overflow: it gets
        # a negative result, and the gc will complain
        # the typechecks below are if TP == BYTEARRAY
        if typeOf(s1) == Ptr(STR):
            newstr = s2.malloc(len1 + len2)
            newstr.copy_contents_from_str(s1, newstr, 0, 0, len1)
        else:
            newstr = s1.malloc(len1 + len2)
            newstr.copy_contents(s1, newstr, 0, 0, len1)
        if typeOf(s2) == Ptr(STR):
            newstr.copy_contents_from_str(s2, newstr, 0, len1, len2)
        else:
            newstr.copy_contents(s2, newstr, 0, len1, len2)
        return newstr

    @staticmethod
    @jit.elidable
    def ll_strip(s, ch, left, right):
        s_len = len(s.chars)
        if s_len == 0:
            return s.empty()
        lpos = 0
        rpos = s_len - 1
        if left:
            while lpos < rpos and s.chars[lpos] == ch:
                lpos += 1
        if right:
            while lpos < rpos + 1 and s.chars[rpos] == ch:
                rpos -= 1
        if rpos < lpos:
            return s.empty()
        r_len = rpos - lpos + 1
        result = s.malloc(r_len)
        s.copy_contents(s, result, lpos, 0, r_len)
        return result

    @staticmethod
    @jit.elidable
    def ll_strip_default(s, left, right):
        s_len = len(s.chars)
        if s_len == 0:
            return s.empty()
        lpos = 0
        rpos = s_len - 1
        if left:
            while lpos < rpos and s.chars[lpos].isspace():
                lpos += 1
        if right:
            while lpos < rpos + 1 and s.chars[rpos].isspace():
                rpos -= 1
        if rpos < lpos:
            return s.empty()
        r_len = rpos - lpos + 1
        result = s.malloc(r_len)
        s.copy_contents(s, result, lpos, 0, r_len)
        return result

    @staticmethod
    @jit.elidable
    def ll_strip_multiple(s, s2, left, right):
        s_len = len(s.chars)
        if s_len == 0:
            return s.empty()
        lpos = 0
        rpos = s_len - 1
        if left:
            while lpos < rpos and LLHelpers.ll_contains(s2, s.chars[lpos]):
                lpos += 1
        if right:
            while lpos < rpos + 1 and LLHelpers.ll_contains(s2, s.chars[rpos]):
                rpos -= 1
        if rpos < lpos:
            return s.empty()
        r_len = rpos - lpos + 1
        result = s.malloc(r_len)
        s.copy_contents(s, result, lpos, 0, r_len)
        return result

    @staticmethod
    @jit.elidable
    def ll_upper(s):
        s_chars = s.chars
        s_len = len(s_chars)
        if s_len == 0:
            return s.empty()
        i = 0
        result = mallocstr(s_len)
        #        ^^^^^^^^^ specifically to explode on unicode
        while i < s_len:
            result.chars[i] = LLHelpers.ll_upper_char(s_chars[i])
            i += 1
        return result

    @staticmethod
    @jit.elidable
    def ll_lower(s):
        s_chars = s.chars
        s_len = len(s_chars)
        if s_len == 0:
            return s.empty()
        i = 0
        result = mallocstr(s_len)
        #        ^^^^^^^^^ specifically to explode on unicode
        while i < s_len:
            result.chars[i] = LLHelpers.ll_lower_char(s_chars[i])
            i += 1
        return result

    @staticmethod
    def ll_join(s, length, items):
        s_chars = s.chars
        s_len = len(s_chars)
        num_items = length
        if num_items == 0:
            return s.empty()
        itemslen = 0
        i = 0
        while i < num_items:
            try:
                itemslen = ovfcheck(itemslen + len(items[i].chars))
            except OverflowError:
                raise MemoryError
            i += 1
        try:
            seplen = ovfcheck(s_len * (num_items - 1))
        except OverflowError:
            raise MemoryError
        # a single '+' at the end is allowed to overflow: it gets
        # a negative result, and the gc will complain
        result = s.malloc(itemslen + seplen)
        res_index = len(items[0].chars)
        s.copy_contents(items[0], result, 0, 0, res_index)
        i = 1
        while i < num_items:
            s.copy_contents(s, result, 0, res_index, s_len)
            res_index += s_len
            lgt = len(items[i].chars)
            s.copy_contents(items[i], result, 0, res_index, lgt)
            res_index += lgt
            i += 1
        return result

    @staticmethod
    @jit.elidable
    @jit.oopspec('stroruni.cmp(s1, s2)')
    def ll_strcmp(s1, s2):
        if not s1 and not s2:
            return True
        if not s1 or not s2:
            return False
        chars1 = s1.chars
        chars2 = s2.chars
        len1 = len(chars1)
        len2 = len(chars2)

        if len1 < len2:
            cmplen = len1
        else:
            cmplen = len2
        i = 0
        while i < cmplen:
            diff = ord(chars1[i]) - ord(chars2[i])
            if diff != 0:
                return diff
            i += 1
        return len1 - len2

    @staticmethod
    @jit.elidable
    @jit.oopspec('stroruni.equal(s1, s2)')
    def ll_streq(s1, s2):
        if s1 == s2:  # also if both are NULLs
            return True
        if not s1 or not s2:
            return False
        len1 = len(s1.chars)
        len2 = len(s2.chars)
        if len1 != len2:
            return False
        j = 0
        chars1 = s1.chars
        chars2 = s2.chars
        while j < len1:
            if chars1[j] != chars2[j]:
                return False
            j += 1
        return True

    @staticmethod
    @jit.elidable
    def ll_startswith(s1, s2):
        len1 = len(s1.chars)
        len2 = len(s2.chars)
        if len1 < len2:
            return False
        j = 0
        chars1 = s1.chars
        chars2 = s2.chars
        while j < len2:
            if chars1[j] != chars2[j]:
                return False
            j += 1

        return True

    @staticmethod
    def ll_startswith_char(s, ch):
        if not len(s.chars):
            return False
        return s.chars[0] == ch

    @staticmethod
    @jit.elidable
    def ll_endswith(s1, s2):
        len1 = len(s1.chars)
        len2 = len(s2.chars)
        if len1 < len2:
            return False
        j = 0
        chars1 = s1.chars
        chars2 = s2.chars
        offset = len1 - len2
        while j < len2:
            if chars1[offset + j] != chars2[j]:
                return False
            j += 1

        return True

    @staticmethod
    def ll_endswith_char(s, ch):
        if not len(s.chars):
            return False
        return s.chars[len(s.chars) - 1] == ch

    @staticmethod
    @jit.elidable
    @signature(types.any(),
               types.any(),
               types.int(),
               types.int(),
               returns=types.int())
    def ll_find_char(s, ch, start, end):
        i = start
        if end > len(s.chars):
            end = len(s.chars)
        while i < end:
            if s.chars[i] == ch:
                return i
            i += 1
        return -1

    @staticmethod
    @jit.elidable
    @signature(types.any(),
               types.any(),
               types.int(),
               types.int(),
               returns=types.int())
    def ll_rfind_char(s, ch, start, end):
        if end > len(s.chars):
            end = len(s.chars)
        i = end
        while i > start:
            i -= 1
            if s.chars[i] == ch:
                return i
        return -1

    @staticmethod
    @jit.elidable
    def ll_count_char(s, ch, start, end):
        count = 0
        i = start
        if end > len(s.chars):
            end = len(s.chars)
        while i < end:
            if s.chars[i] == ch:
                count += 1
            i += 1
        return count

    @staticmethod
    @signature(types.any(),
               types.any(),
               types.int(),
               types.int(),
               returns=types.int())
    def ll_find(s1, s2, start, end):
        if start < 0:
            start = 0
        if end > len(s1.chars):
            end = len(s1.chars)
        if end - start < 0:
            return -1

        m = len(s2.chars)
        if m == 1:
            return LLHelpers.ll_find_char(s1, s2.chars[0], start, end)

        return LLHelpers.ll_search(s1, s2, start, end, FAST_FIND)

    @staticmethod
    @signature(types.any(),
               types.any(),
               types.int(),
               types.int(),
               returns=types.int())
    def ll_rfind(s1, s2, start, end):
        if start < 0:
            start = 0
        if end > len(s1.chars):
            end = len(s1.chars)
        if end - start < 0:
            return -1

        m = len(s2.chars)
        if m == 1:
            return LLHelpers.ll_rfind_char(s1, s2.chars[0], start, end)

        return LLHelpers.ll_search(s1, s2, start, end, FAST_RFIND)

    @classmethod
    def ll_count(cls, s1, s2, start, end):
        if start < 0:
            start = 0
        if end > len(s1.chars):
            end = len(s1.chars)
        if end - start < 0:
            return 0

        m = len(s2.chars)
        if m == 1:
            return cls.ll_count_char(s1, s2.chars[0], start, end)

        res = cls.ll_search(s1, s2, start, end, FAST_COUNT)
        assert res >= 0
        return res

    @staticmethod
    @jit.elidable
    def ll_search(s1, s2, start, end, mode):
        count = 0
        n = end - start
        m = len(s2.chars)

        if m == 0:
            if mode == FAST_COUNT:
                return end - start + 1
            elif mode == FAST_RFIND:
                return end
            else:
                return start

        w = n - m

        if w < 0:
            if mode == FAST_COUNT:
                return 0
            return -1

        mlast = m - 1
        skip = mlast - 1
        mask = 0

        if mode != FAST_RFIND:
            for i in range(mlast):
                mask = bloom_add(mask, s2.chars[i])
                if s2.chars[i] == s2.chars[mlast]:
                    skip = mlast - i - 1
            mask = bloom_add(mask, s2.chars[mlast])

            i = start - 1
            while i + 1 <= start + w:
                i += 1
                if s1.chars[i + m - 1] == s2.chars[m - 1]:
                    for j in range(mlast):
                        if s1.chars[i + j] != s2.chars[j]:
                            break
                    else:
                        if mode != FAST_COUNT:
                            return i
                        count += 1
                        i += mlast
                        continue

                    if i + m < len(s1.chars):
                        c = s1.chars[i + m]
                    else:
                        c = '\0'
                    if not bloom(mask, c):
                        i += m
                    else:
                        i += skip
                else:
                    if i + m < len(s1.chars):
                        c = s1.chars[i + m]
                    else:
                        c = '\0'
                    if not bloom(mask, c):
                        i += m
        else:
            mask = bloom_add(mask, s2.chars[0])
            for i in range(mlast, 0, -1):
                mask = bloom_add(mask, s2.chars[i])
                if s2.chars[i] == s2.chars[0]:
                    skip = i - 1

            i = start + w + 1
            while i - 1 >= start:
                i -= 1
                if s1.chars[i] == s2.chars[0]:
                    for j in xrange(mlast, 0, -1):
                        if s1.chars[i + j] != s2.chars[j]:
                            break
                    else:
                        return i
                    if i - 1 >= 0 and not bloom(mask, s1.chars[i - 1]):
                        i -= m
                    else:
                        i -= skip
                else:
                    if i - 1 >= 0 and not bloom(mask, s1.chars[i - 1]):
                        i -= m

        if mode != FAST_COUNT:
            return -1
        return count

    @staticmethod
    @signature(types.int(), types.any(), returns=types.any())
    @jit.look_inside_iff(
        lambda length, items: jit.loop_unrolling_heuristic(items, length))
    def ll_join_strs(length, items):
        # Special case for length 1 items, helps both the JIT and other code
        if length == 1:
            return items[0]

        num_items = length
        itemslen = 0
        i = 0
        while i < num_items:
            try:
                itemslen = ovfcheck(itemslen + len(items[i].chars))
            except OverflowError:
                raise MemoryError
            i += 1
        if typeOf(items).TO.OF.TO == STR:
            malloc = mallocstr
            copy_contents = copy_string_contents
        else:
            malloc = mallocunicode
            copy_contents = copy_unicode_contents
        result = malloc(itemslen)
        res_index = 0
        i = 0
        while i < num_items:
            item_chars = items[i].chars
            item_len = len(item_chars)
            copy_contents(items[i], result, 0, res_index, item_len)
            res_index += item_len
            i += 1
        return result

    @staticmethod
    @jit.look_inside_iff(lambda length, chars, RES: jit.isconstant(length) and
                         jit.isvirtual(chars))
    def ll_join_chars(length, chars, RES):
        # no need to optimize this, will be replaced by string builder
        # at some point soon
        num_chars = length
        if RES is StringRepr.lowleveltype:
            target = Char
            malloc = mallocstr
        else:
            target = UniChar
            malloc = mallocunicode
        result = malloc(num_chars)
        res_chars = result.chars
        i = 0
        while i < num_chars:
            res_chars[i] = cast_primitive(target, chars[i])
            i += 1
        return result

    @staticmethod
    @jit.oopspec('stroruni.slice(s1, start, stop)')
    @signature(types.any(), types.int(), types.int(), returns=types.any())
    @jit.elidable
    def _ll_stringslice(s1, start, stop):
        lgt = stop - start
        assert start >= 0
        # If start > stop, return a empty string. This can happen if the start
        # is greater than the length of the string. Use < instead of <= to avoid
        # creating another path for the JIT when start == stop.
        if lgt < 0:
            return s1.empty()
        newstr = s1.malloc(lgt)
        s1.copy_contents(s1, newstr, start, 0, lgt)
        return newstr

    @staticmethod
    def ll_stringslice_startonly(s1, start):
        return LLHelpers._ll_stringslice(s1, start, len(s1.chars))

    @staticmethod
    @signature(types.any(), types.int(), types.int(), returns=types.any())
    def ll_stringslice_startstop(s1, start, stop):
        if jit.we_are_jitted():
            if stop > len(s1.chars):
                stop = len(s1.chars)
        else:
            if stop >= len(s1.chars):
                if start == 0:
                    return s1
                stop = len(s1.chars)
        return LLHelpers._ll_stringslice(s1, start, stop)

    @staticmethod
    def ll_stringslice_minusone(s1):
        newlen = len(s1.chars) - 1
        return LLHelpers._ll_stringslice(s1, 0, newlen)

    @staticmethod
    def ll_split_chr(LIST, s, c, max):
        chars = s.chars
        strlen = len(chars)
        count = 1
        i = 0
        if max == 0:
            i = strlen
        while i < strlen:
            if chars[i] == c:
                count += 1
                if max >= 0 and count > max:
                    break
            i += 1
        res = LIST.ll_newlist(count)
        items = res.ll_items()
        i = 0
        j = 0
        resindex = 0
        if max == 0:
            j = strlen
        while j < strlen:
            if chars[j] == c:
                item = items[resindex] = s.malloc(j - i)
                item.copy_contents(s, item, i, 0, j - i)
                resindex += 1
                i = j + 1
                if max >= 0 and resindex >= max:
                    j = strlen
                    break
            j += 1
        item = items[resindex] = s.malloc(j - i)
        item.copy_contents(s, item, i, 0, j - i)
        return res

    @staticmethod
    def ll_split(LIST, s, c, max):
        count = 1
        if max == -1:
            max = len(s.chars)
        pos = 0
        last = len(s.chars)
        markerlen = len(c.chars)
        pos = s.find(c, 0, last)
        while pos >= 0 and count <= max:
            pos = s.find(c, pos + markerlen, last)
            count += 1
        res = LIST.ll_newlist(count)
        items = res.ll_items()
        pos = 0
        count = 0
        pos = s.find(c, 0, last)
        prev_pos = 0
        if pos < 0:
            items[0] = s
            return res
        while pos >= 0 and count < max:
            item = items[count] = s.malloc(pos - prev_pos)
            item.copy_contents(s, item, prev_pos, 0, pos - prev_pos)
            count += 1
            prev_pos = pos + markerlen
            pos = s.find(c, pos + markerlen, last)
        item = items[count] = s.malloc(last - prev_pos)
        item.copy_contents(s, item, prev_pos, 0, last - prev_pos)
        return res

    @staticmethod
    def ll_rsplit_chr(LIST, s, c, max):
        chars = s.chars
        strlen = len(chars)
        count = 1
        i = 0
        if max == 0:
            i = strlen
        while i < strlen:
            if chars[i] == c:
                count += 1
                if max >= 0 and count > max:
                    break
            i += 1
        res = LIST.ll_newlist(count)
        items = res.ll_items()
        i = strlen
        j = strlen
        resindex = count - 1
        assert resindex >= 0
        if max == 0:
            j = 0
        while j > 0:
            j -= 1
            if chars[j] == c:
                item = items[resindex] = s.malloc(i - j - 1)
                item.copy_contents(s, item, j + 1, 0, i - j - 1)
                resindex -= 1
                i = j
                if resindex == 0:
                    j = 0
                    break
        item = items[resindex] = s.malloc(i - j)
        item.copy_contents(s, item, j, 0, i - j)
        return res

    @staticmethod
    def ll_rsplit(LIST, s, c, max):
        count = 1
        if max == -1:
            max = len(s.chars)
        pos = len(s.chars)
        markerlen = len(c.chars)
        pos = s.rfind(c, 0, pos)
        while pos >= 0 and count <= max:
            pos = s.rfind(c, 0, pos - markerlen)
            count += 1
        res = LIST.ll_newlist(count)
        items = res.ll_items()
        pos = 0
        pos = len(s.chars)
        prev_pos = pos
        pos = s.rfind(c, 0, pos)
        if pos < 0:
            items[0] = s
            return res
        count -= 1
        while pos >= 0 and count > 0:
            item = items[count] = s.malloc(prev_pos - pos - markerlen)
            item.copy_contents(s, item, pos + markerlen, 0,
                               prev_pos - pos - markerlen)
            count -= 1
            prev_pos = pos
            pos = s.rfind(c, 0, pos)
        item = items[count] = s.malloc(prev_pos)
        item.copy_contents(s, item, 0, 0, prev_pos)
        return res

    @staticmethod
    @jit.elidable
    def ll_replace_chr_chr(s, c1, c2):
        length = len(s.chars)
        newstr = s.malloc(length)
        src = s.chars
        dst = newstr.chars
        j = 0
        while j < length:
            c = src[j]
            if c == c1:
                c = c2
            dst[j] = c
            j += 1
        return newstr

    @staticmethod
    @jit.elidable
    def ll_contains(s, c):
        chars = s.chars
        strlen = len(chars)
        i = 0
        while i < strlen:
            if chars[i] == c:
                return True
            i += 1
        return False

    @staticmethod
    @jit.elidable
    def ll_int(s, base):
        if not 2 <= base <= 36:
            raise ValueError
        chars = s.chars
        strlen = len(chars)
        i = 0
        #XXX: only space is allowed as white space for now
        while i < strlen and chars[i] == ' ':
            i += 1
        if not i < strlen:
            raise ValueError
        #check sign
        sign = 1
        if chars[i] == '-':
            sign = -1
            i += 1
        elif chars[i] == '+':
            i += 1
        # skip whitespaces between sign and digits
        while i < strlen and chars[i] == ' ':
            i += 1
        #now get digits
        val = 0
        oldpos = i
        while i < strlen:
            c = ord(chars[i])
            if ord('a') <= c <= ord('z'):
                digit = c - ord('a') + 10
            elif ord('A') <= c <= ord('Z'):
                digit = c - ord('A') + 10
            elif ord('0') <= c <= ord('9'):
                digit = c - ord('0')
            else:
                break
            if digit >= base:
                break
            val = val * base + digit
            i += 1
        if i == oldpos:
            raise ValueError  # catch strings like '+' and '+  '
        #skip trailing whitespace
        while i < strlen and chars[i] == ' ':
            i += 1
        if not i == strlen:
            raise ValueError
        return sign * val

    # interface to build strings:
    #   x = ll_build_start(n)
    #   ll_build_push(x, next_string, 0)
    #   ll_build_push(x, next_string, 1)
    #   ...
    #   ll_build_push(x, next_string, n-1)
    #   s = ll_build_finish(x)

    @staticmethod
    def ll_build_start(parts_count):
        return malloc(TEMP, parts_count)

    @staticmethod
    def ll_build_push(builder, next_string, index):
        builder[index] = next_string

    @staticmethod
    def ll_build_finish(builder):
        return LLHelpers.ll_join_strs(len(builder), builder)

    @staticmethod
    @specialize.memo()
    def ll_constant(s):
        return string_repr.convert_const(s)

    @staticmethod
    @specialize.memo()
    def ll_constant_unicode(s):
        return unicode_repr.convert_const(s)

    @classmethod
    def do_stringformat(cls, hop, sourcevarsrepr):
        s_str = hop.args_s[0]
        assert s_str.is_constant()
        is_unicode = isinstance(s_str, annmodel.SomeUnicodeString)
        if is_unicode:
            TEMPBUF = TEMP_UNICODE
        else:
            TEMPBUF = TEMP
        s = s_str.const
        things = cls.parse_fmt_string(s)
        size = inputconst(Signed, len(things))  # could be unsigned?
        cTEMP = inputconst(Void, TEMPBUF)
        cflags = inputconst(Void, {'flavor': 'gc'})
        vtemp = hop.genop("malloc_varsize", [cTEMP, cflags, size],
                          resulttype=Ptr(TEMPBUF))

        argsiter = iter(sourcevarsrepr)

        from rpython.rtyper.rclass import InstanceRepr
        for i, thing in enumerate(things):
            if isinstance(thing, tuple):
                code = thing[0]
                vitem, r_arg = argsiter.next()
                if not hasattr(r_arg, 'll_str'):
                    raise TyperError("ll_str unsupported for: %r" % r_arg)
                if code == 's':
                    if is_unicode:
                        # only UniCharRepr and UnicodeRepr has it so far
                        vchunk = hop.gendirectcall(r_arg.ll_unicode, vitem)
                    else:
                        vchunk = hop.gendirectcall(r_arg.ll_str, vitem)
                elif code == 'r' and isinstance(r_arg, InstanceRepr):
                    vchunk = hop.gendirectcall(r_arg.ll_str, vitem)
                elif code == 'd':
                    assert isinstance(r_arg, IntegerRepr)
                    #vchunk = hop.gendirectcall(r_arg.ll_str, vitem)
                    vchunk = hop.gendirectcall(ll_str.ll_int2dec, vitem)
                elif code == 'f':
                    #assert isinstance(r_arg, FloatRepr)
                    vchunk = hop.gendirectcall(r_arg.ll_str, vitem)
                elif code == 'x':
                    assert isinstance(r_arg, IntegerRepr)
                    vchunk = hop.gendirectcall(ll_str.ll_int2hex, vitem,
                                               inputconst(Bool, False))
                elif code == 'o':
                    assert isinstance(r_arg, IntegerRepr)
                    vchunk = hop.gendirectcall(ll_str.ll_int2oct, vitem,
                                               inputconst(Bool, False))
                else:
                    raise TyperError("%%%s is not RPython" % (code, ))
            else:
                if is_unicode:
                    vchunk = inputconst(unicode_repr, thing)
                else:
                    vchunk = inputconst(string_repr, thing)
            i = inputconst(Signed, i)
            if is_unicode and vchunk.concretetype != Ptr(UNICODE):
                # if we are here, one of the ll_str.* functions returned some
                # STR, so we convert it to unicode. It's a bit suboptimal
                # because we do one extra copy.
                vchunk = hop.gendirectcall(cls.ll_str2unicode, vchunk)
            hop.genop('setarrayitem', [vtemp, i, vchunk])

        hop.exception_cannot_occur()  # to ignore the ZeroDivisionError of '%'
        return hop.gendirectcall(cls.ll_join_strs, size, vtemp)

    @staticmethod
    @jit.dont_look_inside
    def ll_string2list(RESLIST, src):
        length = len(src.chars)
        lst = RESLIST.ll_newlist(length)
        dst = lst.ll_items()
        SRC = typeOf(src).TO  # STR or UNICODE
        DST = typeOf(dst).TO  # GcArray
        assert DST.OF is SRC.chars.OF
        # from here, no GC operations can happen
        asrc = llmemory.cast_ptr_to_adr(src) + (llmemory.offsetof(
            SRC, 'chars') + llmemory.itemoffsetof(SRC.chars, 0))
        adst = llmemory.cast_ptr_to_adr(dst) + llmemory.itemoffsetof(DST, 0)
        llmemory.raw_memcopy(asrc, adst, llmemory.sizeof(DST.OF) * length)
        # end of "no GC" section
        keepalive_until_here(src)
        keepalive_until_here(dst)
        return lst
コード例 #27
0
ファイル: casting.py プロジェクト: abhinavthomas/pypy
    arrays_w = []
    dtypes_w = []
    for w_arg in args_w:
        if isinstance(w_arg, W_NDimArray):
            arrays_w.append(w_arg)
        elif is_scalar_w(space, w_arg):
            w_scalar = as_scalar(space, w_arg)
            w_arr = W_NDimArray.from_scalar(space, w_scalar)
            arrays_w.append(w_arr)
        else:
            dtype = as_dtype(space, w_arg)
            dtypes_w.append(dtype)
    return find_result_type(space, arrays_w, dtypes_w)

@jit.look_inside_iff(lambda space, arrays_w, dtypes_w:
    jit.loop_unrolling_heuristic(arrays_w, len(arrays_w)) and
    jit.loop_unrolling_heuristic(dtypes_w, len(dtypes_w)))
def find_result_type(space, arrays_w, dtypes_w):
    # equivalent to PyArray_ResultType
    if len(arrays_w) == 1 and not dtypes_w:
        return arrays_w[0].get_dtype()
    elif not arrays_w and len(dtypes_w) == 1:
        return dtypes_w[0]
    result = None
    if not _use_min_scalar(arrays_w, dtypes_w):
        for w_array in arrays_w:
            if result is None:
                result = w_array.get_dtype()
            else:
                result = promote_types(space, result, w_array.get_dtype())
        for dtype in dtypes_w:
コード例 #28
0
ファイル: equal.py プロジェクト: cderici/pycket
        index = i.value
        if index >= self.length(w_dict) - 1:
            return values.w_false
        return values.wrap(index + 1)

    def hash_iterate_first(self, w_dict):
        return 0

    def length(self, w_dict):
        raise NotImplementedError("abstract base class")

    def create_storage(self, keys, vals):
        raise NotImplementedError("abstract base class")

@jit.look_inside_iff(lambda keys:
        jit.loop_unrolling_heuristic(
                keys, len(keys), values.UNROLLING_CUTOFF))
def _find_strategy_class(keys):
    if not config.strategies:
        return ObjectHashmapStrategy.singleton
    if len(keys) == 0:
        return EmptyHashmapStrategy.singleton
        # An empty vector stays empty forever. Don't implement special EmptyVectorStrategy.
    single_class = type(keys[0])
    for elem in keys:
        if not isinstance(elem, single_class):
            return ObjectHashmapStrategy.singleton
    if single_class is values.W_Fixnum:
        return FixnumHashmapStrategy.singleton
    if single_class is values.W_Symbol:
        return SymbolHashmapStrategy.singleton
    if single_class is values_string.W_String:
コード例 #29
0
        if has_key:
            w_compare_with = space.call_function(w_key, w_item)
        else:
            w_compare_with = w_item
        if (not has_item or
                space.is_true(compare(w_compare_with, w_max_val))):
            has_item = True
            w_max_item = w_item
            w_max_val = w_compare_with
    if w_max_item is None:
        raise oefmt(space.w_ValueError, "arg is an empty sequence")
    return w_max_item

@specialize.arg(3)
@jit.look_inside_iff(lambda space, args_w, w_key, implementation_of:
        jit.loop_unrolling_heuristic(args_w, len(args_w), 3))
def min_max_multiple_args(space, args_w, w_key, implementation_of):
    # case of multiple arguments (at least two).  We unroll it if there
    # are 2 or 3 arguments.
    if implementation_of == "max":
        compare = space.gt
    else:
        compare = space.lt
    w_max_item = args_w[0]
    if w_key is not None:
        w_max_val = space.call_function(w_key, w_max_item)
    else:
        w_max_val = w_max_item
    for i in range(1, len(args_w)):
        w_item = args_w[i]
        if w_key is not None: