[pypy-dev] Objects and types in the stdobjspace

holger krekel hpk at trillke.net
Tue Jun 10 17:36:19 CEST 2003


[Armin Rigo Tue, Jun 10, 2003 at 04:30:27PM +0200]
> Hello Holger,
> 
> On Tue, Jun 10, 2003 at 04:03:00PM +0200, holger krekel wrote:
> > Though i somewhat (*) agree i also think that intermingling function definitions 
> > and function executions is ugly, too.  Does it make sense to at least move
> > the register calls to the end of the file, then? Usually the func name 
> > and the argument names make it human-understandable enough which
> > type-implementations a function is supposed to handle. 
> 
> This last point is actually another problem by itself, because we all tend to
> forget the register() stuff after we wrote the function definition. If the
> register() calls are to be moved at the end of the file it will not help.  
> Somehow I find that the closer this information is to the function definition,
> the better; even just after the body is somehow not close enough, hence the
> search for header-based alternatives.
> 
> The suggestion pointed out by Paul:
> 
> def any_list_extend(space, w_list, w_otherlist):
>     assert isinstance(w_list, W_ANY)
>     assert isinstance(w_otherlist, W_ANY)
>     return space.inplace_add(w_list, w_otherlist)
> 
> is closer to this goal, and hopefully "natural" enough to avoid type
> declaration flame war. When I wrote the example this one is based on I forgot
> that the multimethod we want to register to should be mentioned somewhere as
> well -- but where ? If that's in the function name, we are back to naming
> conventions. I'm not convinced about naming convention, but well, just for the
> comparison:
> 
> def getitem__ListObject_SliceObject(space, w_list, w_slice):
>     ...
> 
> def list_append__ListObject_object(space, w_list, w_obj):
>     ...
> 
> Why not.

nice to hear :-)

Please find attached a modified "stringobject.py" where i 
implemented this convention. I found that the naming scheme
was confused sometimes and the new "enforcement" makes this
very regular and readable (IMHO, of course).

After all it's still possible to do "explicit" registrations if
there are special cases. 

cheers,

    holger
-------------- next part --------------
from pypy.objspace.std.objspace import *
from stringtype import W_StringType
from intobject   import W_IntObject
from sliceobject import W_SliceObject
from listobject import W_ListObject
from instmethobject import W_InstMethObject
from noneobject import W_NoneObject
from tupleobject import W_TupleObject

from rarray import CharArrayFromStr, CharArraySize


applicationfile = StdObjSpace.AppFile(__name__)

class W_StringObject(W_Object):
    statictype = W_StringType

    def __init__(w_self, space, str):
        W_Object.__init__(w_self, space)
        w_self._value = CharArrayFromStr(str)

    def __repr__(w_self):
        """ representation for debugging purposes """
        return "%s(%r)" % (w_self.__class__.__name__, w_self._value.value())


registerimplementation(W_StringObject)


def _isspace(ch):
    return ord(ch) in (9, 10, 11, 12, 13, 32)  

def _isdigit(ch):
    o = ord(ch)
    return o >= 48 and o <= 57

def _isalpha(ch):
    o = ord(ch)
    return (o>=97 and o<=122) or (o>=65 and o<=90)

def _isalnum(ch):
    o = ord(ch)
    return (o>=97 and o<=122) \
        or (o>=65 and o<=90) \
        or (o>=48 and o<=57)
def _isupper(ch):
    o = ord(ch)
    return (o>=65 and o<=90)

def _islower(ch):   
    o = ord(ch)
    return (o>=97 and o<=122)


def _is_generic(w_self, fun): 
    space = w_self.space   
    v = w_self._value
    if v.len == 0:
        return space.w_False
    if v.len == 1:
        c = v.charat(0)
        return space.newbool(fun(c))
    else:
        res = 1
        for idx in range(v.len):
            if not fun(v.charat(idx)):
                return space.w_False
        return space.w_True

def str_isspace__String(space, w_self):
    return _is_generic(w_self, _isspace)

def str_isdigit__String(space, w_self):
    return _is_generic(w_self, _isdigit)

def str_isalpha__String(space, w_self):
    return _is_generic(w_self, _isalpha)

def str_isalnum__String(space, w_self):
    return _is_generic(w_self, _isalnum)

def str_isupper__String(space, w_self):
    return _is_generic(w_self, _isupper)

def str_islower__String(space, w_self):
    return _is_generic(w_self, _islower)

def str_istitle(space, w_self):
    pass

def str_split__String_None(space, w_self, w_none):
    res = []
    inword = 0
    value = w_self._value.value()
    for ch in value:
        if ch.isspace():
            if inword:
                inword = 0
        else:
            if inword:
                res[-1] += ch
            else:
                res.append(ch)
                inword = 1
    for i in range(len(res)):
        res[i] = W_StringObject(space, res[i])
    return W_ListObject(space, res)

def str_split__String_String(space, w_self, w_by):
    res = []
    start = 0
    value = w_self._value.value()
    by = w_by._value.value()
    while 1:
        next = value.find(by, start)
        if next < 0:
            res.append(value[start:])
            break
        res.append(value[start:next])
        start = next + len(by)
    for i in range(len(res)):
        res[i] = W_StringObject(w_self.space, res[i])
    return W_ListObject(w_self.space, res)


def str_join__String_ANY(space, w_self, w_list):
    list = space.unpackiterable(w_list)
    if list:
        firstelem = 1
        listlen = 0
        reslen = 0  
        for w_item in list:
            reslen = reslen + w_item._value.len
            listlen = listlen + 1

        reslen = reslen + (listlen - 1) * w_self._value.len
        res = CharArraySize(reslen)

        pos = 0
        for w_item in list:
            if firstelem:
                res.setsubstring(pos, w_item._value.value())
                pos = pos + w_item._value.len 
                firstelem = 0
            else:
                res.setsubstring(pos, w_self._value.value())
                pos = pos + w_self._value.len
                res.setsubstring(pos, w_item._value.value())
                pos = pos + w_item._value.len
        return W_StringObject(space, res.value())
    else:
        return W_StringObject(space, "")

def unwrap__String(space, w_str):
    return w_str._value.value()

def is_true__String(space, w_str):
    return w_str._value.len != 0

def hash__String(space, w_str):
    return W_IntObject(space, w_str._value.hash())


EQ = 1
LE = 2
GE = 3
GT = 4
LT = 5
NE = 6

def string_richcompare(space, w_str1, w_str2, op):
    str1 = w_str1._value
    str2 = w_str2._value

    if space.is_true(space.is_(w_str1, w_str2)):
        if op == EQ or op == LE or op == GE:
            return space.w_True
        elif op == GT or op == LT or op == NE:
            return space.w_False
    if 0:
        pass
    else:
        if op == EQ:
            if str1.len == str2.len:
                for i in range(str1.len):
                    if ord(str1.charat(i)) != ord(str2.charat(i)):
                        return space.w_False
                return space.w_True
            else:
                return space.w_False
        else:
            if str1.len > str2.len:
                min_len = str2.len
            else:
                min_len = str1.len

            c = 0
            idx = 0
            if (min_len > 0):
                while (c == 0) and (idx < min_len):
                    c = ord(str1.charat(idx)) - ord(str2.charat(idx))
                    idx = idx + 1
            else:
                c = 0

        if (c == 0):
            if str1.len < str2.len:
                c = -1
            elif str1.len > str2.len:
                c = 1
            else:
                c = 0

        if op == LT:
            return space.newbool(c < 0)
        elif op == LE:
            return space.newbool(c <= 0)
        elif op == NE:
            return space.newbool(c != 0)
        elif op == GT:
            return space.newbool(c > 0)
        elif op == GE:
            return space.newbool(c >= 0)
        else:
            raise NotImplemented

def lt__String_String(space, w_str1, w_str2):
    return string_richcompare(space, w_str1, w_str2, LT)

def le__String_String(space, w_str1, w_str2):
    return string_richcompare(space, w_str1, w_str2, LE)

def eq__String_String(space, w_str1, w_str2):
    return string_richcompare(space, w_str1, w_str2, EQ)

def ne__String_String(space, w_str1, w_str2):
    return string_richcompare(space, w_str1, w_str2, NE)

def gt__String_String(space, w_str1, w_str2):
    return string_richcompare(space, w_str1, w_str2, GT)

def ge__String_String(space, w_str1, w_str2):
    return string_richcompare(space, w_str1, w_str2, GE)

def getitem__String_Int(space, w_str, w_int):
    ival = w_int.intval
    slen = w_str._value.len
    if ival < 0:
        ival += slen
    if ival < 0 or ival >= slen:
        exc = space.call_function(space.w_IndexError,
                                  space.wrap("string index out of range"))
        raise OperationError(space.w_IndexError, exc)
    return W_StringObject(space, w_str._value.charat(ival))

def getitem__String_Slice(space, w_str, w_slice):
    return space.gethelper(applicationfile).call(
        "getitem_string_slice", [w_str, w_slice])
    w = space.wrap
    u = space.unwrap
    w_start, w_stop, w_step, w_sl = w_slice.indices(w(w_str._value.len))
    start = u(w_start)
    stop = u(w_stop)
    step = u(w_step)
    sl = u(w_sl)
    r = [None] * sl
    for i in range(sl):
        r[i] = space.getitem(w_str, w(start + i*step))
    w_r = space.newlist(r)
    w_empty = space.newstring([])
    return str_join(space, w_empty, w_r)

def add__String_String(space, w_left, w_right):
    buf = CharArraySize(w_left._value.len + w_right._value.len)
    buf.setsubstring(0, w_left._value.value())
    buf.setsubstring(w_left._value.len, w_right._value.value())
    return W_StringObject(space, buf.value())

#def mod_str_ANY(space, w_left, w_right):
#    notImplemented
 
#def mod_str_tuple(space, w_format, w_args):
#    notImplemented

def len__String(space, w_str):
    return space.wrap(w_str._value.len)

def str__String(space, w_str):
    return w_str

def repr__String(space, w_str):
    # XXX this is bogus -- mwh
    return space.wrap(repr(space.unwrap(w_str)))
    a = space.add
    q = space.wrap("'")
    return a(a(q, w_str), q)

def ord__String(space, w_str):
    return space.wrap(ord(space.unwrap(w_str)))

def mod__String_ANY(space, w_str, w_item):
    return str_mod_tuple(space, w_str, space.newtuple([w_item]))

def mod__String_Tuple(space, w_str, w_tuple):
    return space.wrap(space.unwrap(w_str)%space.unwrap(w_tuple))


# register all methods 
for name, obj in vars().items():
        try: 
            funcname, sig = name.split('__')
        except ValueError: 
            continue
        l=[]
        for i in sig.split('_'):
            i = i=='ANY' and W_ANY or vars()['W_%sObject' % i]
            l.append(i)
        try:
            getattr(StdObjSpace, funcname).register(obj, *l)
        except AttributeError:
            getattr(W_StringType, funcname).register(obj, *l)



More information about the Pypy-dev mailing list