Ejemplo n.º 1
0
class W_DomainError(W_StandardError):
    classdef = ClassDef("Math::DomainError", W_StandardError.classdef)
    method_allocate = new_exception_allocate(classdef)
Ejemplo n.º 2
0
class W_ProcObject(W_Object):
    classdef = ClassDef("Proc", W_Object.classdef)
    _immutable_fields_ = [
        "bytecode", "w_self", "lexical_scope", "cells[*]", "block",
        "parent_interp", "top_parent_interp", "regexp_match_cell", "is_lambda"
    ]

    def __init__(self, space, bytecode, w_self, lexical_scope, cells, block,
                 parent_interp, top_parent_interp, regexp_match_cell,
                 is_lambda):
        W_Object.__init__(self, space)
        self.bytecode = bytecode
        self.w_self = w_self
        self.lexical_scope = lexical_scope
        self.cells = cells
        self.block = block
        self.parent_interp = parent_interp
        self.top_parent_interp = top_parent_interp
        self.regexp_match_cell = regexp_match_cell
        self.is_lambda = is_lambda

    def copy(self, space, w_self=None, lexical_scope=None, is_lambda=False):
        return W_ProcObject(space, self.bytecode, w_self or self.w_self,
                            lexical_scope or self.lexical_scope, self.cells,
                            self.block, self.parent_interp,
                            self.top_parent_interp, self.regexp_match_cell,
                            is_lambda or self.is_lambda)

    @classdef.singleton_method("new")
    def method_new(self, space, block):
        if block is None:
            block = space.getexecutioncontext().gettoprubyframe().block
        if block is None:
            raise space.error(space.w_ArgumentError,
                              "tried to create Proc object without a block")
        return block.copy(space)

    method_allocate = classdef.undefine_allocator()

    @classdef.method("yield")
    @classdef.method("===")
    @classdef.method("[]")
    @classdef.method("call")
    def method_call(self, space, args_w, block):
        from topaz.interpreter import RaiseReturn, RaiseBreak

        try:
            return space.invoke_block(self, args_w, block_arg=block)
        except RaiseReturn as e:
            if self.is_lambda:
                return e.w_value
            else:
                raise
        except RaiseBreak as e:
            if self.is_lambda:
                return e.w_value
            else:
                raise space.error(space.w_LocalJumpError,
                                  "break from proc-closure")

    @classdef.method("lambda?")
    def method_lambda(self, space):
        return space.newbool(self.is_lambda)

    @classdef.method("arity")
    def method_arity(self, space):
        return space.newint(
            self.bytecode.arity(negative_defaults=self.is_lambda))

    @classdef.method("binding")
    def method_binding(self, space):
        return space.newbinding_fromblock(self)

    @classdef.method("source_location")
    def method_source_location(self, space):
        return space.newarray([
            space.newstr_fromstr(self.bytecode.filepath),
            space.newint(self.bytecode.lineno)
        ])
Ejemplo n.º 3
0
class W_IOObject(W_Object):
    classdef = ClassDef("IO", W_Object.classdef)

    def __init__(self, space):
        W_Object.__init__(self, space)
        self.fd = -1

    def __del__(self):
        # Do not close standard file streams
        if self.fd > 3:
            os.close(self.fd)

    def __deepcopy__(self, memo):
        obj = super(W_IOObject, self).__deepcopy__(memo)
        obj.fd = self.fd
        return obj

    def ensure_not_closed(self, space):
        if self.fd < 0:
            raise space.error(space.w_IOError, "closed stream")

    def getfd(self):
        return self.fd

    @classdef.setup_class
    def setup_class(cls, space, w_cls):
        w_stdin = space.send(w_cls, "new", [space.newint(0)])
        space.globals.set(space, "$stdin", w_stdin)
        space.set_const(space.w_object, "STDIN", w_stdin)

        w_stdout = space.send(w_cls, "new", [space.newint(1)])
        space.globals.set(space, "$stdout", w_stdout)
        space.globals.set(space, "$>", w_stdout)
        space.globals.set(space, "$/", space.newstr_fromstr("\n"))
        space.set_const(space.w_object, "STDOUT", w_stdout)

        w_stderr = space.send(w_cls, "new", [space.newint(2)])
        space.globals.set(space, "$stderr", w_stderr)
        space.set_const(space.w_object, "STDERR", w_stderr)

        space.set_const(w_cls, "SEEK_CUR", space.newint(os.SEEK_CUR))
        space.set_const(w_cls, "SEEK_END", space.newint(os.SEEK_END))
        space.set_const(w_cls, "SEEK_SET", space.newint(os.SEEK_SET))

    @classdef.singleton_method("allocate")
    def method_allocate(self, space, args_w):
        return W_IOObject(space)

    @classdef.singleton_method("sysopen")
    def method_sysopen(self,
                       space,
                       w_path,
                       w_mode_str_or_int=None,
                       w_perm=None):
        perm = 0666
        mode = os.O_RDONLY
        if w_mode_str_or_int is not None:
            mode = map_filemode(space, w_mode_str_or_int)
        if w_perm is not None and w_perm is not space.w_nil:
            perm = space.int_w(w_perm)
        path = Coerce.path(space, w_path)
        try:
            fd = os.open(path, mode, perm)
        except OSError as e:
            raise error_for_oserror(space, e)
        else:
            return space.newint(fd)

    @classdef.method("initialize")
    def method_initialize(self,
                          space,
                          w_fd_or_io,
                          w_mode_str_or_int=None,
                          w_opts=None):
        if isinstance(w_fd_or_io, W_IOObject):
            fd = w_fd_or_io.fd
        else:
            fd = Coerce.int(space, w_fd_or_io)
        if isinstance(w_mode_str_or_int, W_StringObject):
            mode = space.str_w(w_mode_str_or_int)
            if ":" in mode:
                raise space.error(space.w_NotImplementedError,
                                  "encoding for IO.new")
        elif w_mode_str_or_int is None:
            mode = None
        else:
            raise space.error(space.w_NotImplementedError,
                              "int mode for IO.new")
        if w_opts is not None:
            raise space.error(space.w_NotImplementedError,
                              "options hash for IO.new")
        if mode is None:
            mode = "r"
        self.fd = fd
        return self

    @classdef.method("read")
    def method_read(self, space, w_length=None, w_str=None):
        self.ensure_not_closed(space)
        if w_length:
            length = space.int_w(w_length)
            if length < 0:
                raise space.error(space.w_ArgumentError,
                                  "negative length %d given" % length)
        else:
            length = -1
        read_bytes = 0
        read_chunks = []
        while length < 0 or read_bytes < length:
            if length > 0:
                max_read = int(length - read_bytes)
            else:
                max_read = 8192
            current_read = os.read(self.fd, max_read)
            if len(current_read) == 0:
                break
            read_bytes += len(current_read)
            read_chunks += current_read
        # Return nil on EOF if length is given
        if read_bytes == 0:
            return space.w_nil
        w_read_str = space.newstr_fromchars(read_chunks)
        if w_str is not None:
            w_str.clear(space)
            w_str.extend(space, w_read_str)
            return w_str
        else:
            return w_read_str

    @classdef.method("write")
    def method_write(self, space, w_str):
        self.ensure_not_closed(space)
        string = space.str_w(space.send(w_str, "to_s"))
        bytes_written = os.write(self.fd, string)
        return space.newint(bytes_written)

    @classdef.method("flush")
    def method_flush(self, space):
        # We have no internal buffers to flush!
        self.ensure_not_closed(space)
        return self

    @classdef.method("seek", amount="int", whence="int")
    def method_seek(self, space, amount, whence=os.SEEK_SET):
        self.ensure_not_closed(space)
        os.lseek(self.fd, amount, whence)
        return space.newint(0)

    @classdef.method("pos")
    @classdef.method("tell")
    def method_pos(self, space):
        self.ensure_not_closed(space)
        # TODO: this currently truncates large values, switch this to use a
        # Bignum in those cases
        return space.newint(int(os.lseek(self.fd, 0, os.SEEK_CUR)))

    @classdef.method("rewind")
    def method_rewind(self, space):
        self.ensure_not_closed(space)
        os.lseek(self.fd, 0, os.SEEK_SET)
        return space.newint(0)

    @classdef.method("print")
    def method_print(self, space, args_w):
        self.ensure_not_closed(space)
        if not args_w:
            w_last = space.globals.get(space, "$_")
            if w_last is not None:
                args_w.append(w_last)
        w_sep = space.globals.get(space, "$,")
        if w_sep:
            sep = space.str_w(space.send(w_sep, "to_s"))
        else:
            sep = ""
        w_end = space.globals.get(space, "$\\")
        if w_end:
            end = space.str_w(space.send(w_end, "to_s"))
        else:
            end = ""
        strings = [space.str_w(space.send(w_arg, "to_s")) for w_arg in args_w]
        os.write(self.fd, sep.join(strings))
        os.write(self.fd, end)
        return space.w_nil

    @classdef.method("getc")
    def method_getc(self, space):
        self.ensure_not_closed(space)
        c = os.read(self.fd, 1)
        if not c:
            return space.w_nil
        return space.newstr_fromstr(c)

    @classdef.singleton_method("pipe")
    def method_pipe(self, space, block=None):
        r, w = os.pipe()
        pipes_w = [
            space.send(self, "new", [space.newint(r)]),
            space.send(self, "new", [space.newint(w)])
        ]
        if block is not None:
            try:
                return space.invoke_block(block, pipes_w)
            finally:
                for pipe_w in pipes_w:
                    if not space.is_true(space.send(pipe_w, "closed?")):
                        space.send(pipe_w, "close")
        else:
            return space.newarray(pipes_w)

    @classdef.method("reopen")
    def method_reopen(self, space, w_arg, w_mode=None):
        self.ensure_not_closed(space)
        w_io = space.convert_type(w_arg,
                                  space.w_io,
                                  "to_io",
                                  raise_error=False)
        if w_io is space.w_nil:
            from topaz.objects.fileobject import W_FileObject
            args = [w_arg] if w_mode is None else [w_arg, w_mode]
            w_io = space.send(space.getclassfor(W_FileObject), "new", args)
        assert isinstance(w_io, W_IOObject)
        w_io.ensure_not_closed(space)
        os.close(self.fd)
        os.dup2(w_io.getfd(), self.fd)
        return self

    @classdef.method("to_io")
    def method_to_io(self):
        return self

    @classdef.method("fileno")
    @classdef.method("to_i")
    def method_to_i(self, space):
        self.ensure_not_closed(space)
        return space.newint(self.fd)

    @classdef.method("close")
    def method_close(self, space):
        self.ensure_not_closed(space)
        os.close(self.fd)
        self.fd = -1
        return self

    @classdef.method("closed?")
    def method_closedp(self, space):
        return space.newbool(self.fd == -1)

    @classdef.method("stat")
    def method_stat(self, space):
        from topaz.objects.fileobject import W_FileStatObject
        try:
            stat_val = os.fstat(self.fd)
        except OSError as e:
            raise error_for_oserror(space, e)
        stat_obj = W_FileStatObject(space)
        stat_obj.set_stat(stat_val)
        return stat_obj

    @classdef.method("isatty")
    @classdef.method("tty?")
    def method_isatty(self, space):
        self.ensure_not_closed(space)
        return space.newbool(os.isatty(self.fd))
Ejemplo n.º 4
0
class W_ArrayObject(W_Object):
    classdef = ClassDef("Array", W_Object.classdef, filepath=__file__)
    classdef.include_module(Enumerable)

    def __init__(self, space, items_w, klass=None):
        W_Object.__init__(self, space, klass)
        self.items_w = items_w

    def __deepcopy__(self, memo):
        obj = super(W_ArrayObject, self).__deepcopy__(memo)
        obj.items_w = copy.deepcopy(self.items_w, memo)
        return obj

    def listview(self, space):
        return self.items_w

    @classdef.singleton_method("allocate")
    def singleton_method_allocate(self, space, args_w):
        return W_ArrayObject(space, [], self)

    @classdef.method("initialize_copy", other_w="array")
    @classdef.method("replace", other_w="array")
    @check_frozen()
    def method_replace(self, space, other_w):
        del self.items_w[:]
        self.items_w.extend(other_w)
        return self

    @classdef.method("[]")
    @classdef.method("slice")
    def method_subscript(self, space, w_idx, w_count=None):
        start, end, as_range, nil = space.subscript_access(len(self.items_w),
                                                           w_idx,
                                                           w_count=w_count)
        if nil:
            return space.w_nil
        elif as_range:
            assert start >= 0
            assert end >= 0
            return space.newarray(self.items_w[start:end])
        else:
            return self.items_w[start]

    @classdef.method("[]=")
    @check_frozen()
    def method_subscript_assign(self,
                                space,
                                w_idx,
                                w_count_or_obj,
                                w_obj=None):
        w_count = None
        if w_obj:
            w_count = w_count_or_obj
        else:
            w_obj = w_count_or_obj
        start, end, as_range, nil = space.subscript_access(len(self.items_w),
                                                           w_idx,
                                                           w_count=w_count)

        if w_count and end < start:
            raise space.error(space.w_IndexError,
                              "negative length (%d)" % (end - start))
        elif start < 0:
            raise space.error(
                space.w_IndexError,
                "index %d too small for array; minimum: %d" %
                (start - len(self.items_w), -len(self.items_w)))
        elif start >= len(self.items_w):
            self.items_w += [space.w_nil] * (start - len(self.items_w) + 1)
            self.items_w[start] = w_obj
        elif as_range:
            assert end >= 0
            w_converted = space.convert_type(w_obj,
                                             space.w_array,
                                             "to_ary",
                                             raise_error=False)
            if w_converted is space.w_nil:
                rep_w = [w_obj]
            else:
                rep_w = space.listview(w_converted)
            delta = (end - start) - len(rep_w)
            if delta < 0:
                self.items_w += [None] * -delta
                lim = start + len(rep_w)
                i = len(self.items_w) - 1
                while i >= lim:
                    self.items_w[i] = self.items_w[i + delta]
                    i -= 1
            elif delta > 0:
                del self.items_w[start:start + delta]
            self.items_w[start:start + len(rep_w)] = rep_w
        else:
            self.items_w[start] = w_obj
        return w_obj

    @classdef.method("slice!")
    @check_frozen()
    def method_slice_i(self, space, w_idx, w_count=None):
        start, end, as_range, nil = space.subscript_access(len(self.items_w),
                                                           w_idx,
                                                           w_count=w_count)

        if nil:
            return space.w_nil
        elif as_range:
            start = min(max(start, 0), len(self.items_w))
            end = min(max(end, 0), len(self.items_w))
            delta = (end - start)
            assert delta >= 0
            w_items = self.items_w[start:start + delta]
            del self.items_w[start:start + delta]
            return space.newarray(w_items)
        else:
            w_item = self.items_w[start]
            del self.items_w[start]
            return w_item

    @classdef.method("size")
    @classdef.method("length")
    def method_length(self, space):
        return space.newint(len(self.items_w))

    @classdef.method("empty?")
    def method_emptyp(self, space):
        return space.newbool(len(self.items_w) == 0)

    @classdef.method("+", other="array")
    def method_add(self, space, other):
        return space.newarray(self.items_w + other)

    @classdef.method("<<")
    @check_frozen()
    def method_lshift(self, space, w_obj):
        self.items_w.append(w_obj)
        return self

    @classdef.method("concat", other="array")
    @check_frozen()
    def method_concat(self, space, other):
        self.items_w += other
        return self

    @classdef.method("push")
    @check_frozen()
    def method_push(self, space, args_w):
        self.items_w.extend(args_w)
        return self

    @classdef.method("shift")
    @check_frozen()
    def method_shift(self, space, w_n=None):
        if w_n is None:
            if self.items_w:
                return self.items_w.pop(0)
            else:
                return space.w_nil
        n = space.int_w(space.convert_type(w_n, space.w_fixnum, "to_int"))
        if n < 0:
            raise space.error(space.w_ArgumentError, "negative array size")
        items_w = self.items_w[:n]
        del self.items_w[:n]
        return space.newarray(items_w)

    @classdef.method("unshift")
    @check_frozen()
    def method_unshift(self, space, args_w):
        for i in xrange(len(args_w) - 1, -1, -1):
            w_obj = args_w[i]
            self.items_w.insert(0, w_obj)
        return self

    @classdef.method("join")
    def method_join(self, space, w_sep=None):
        if not self.items_w:
            return space.newstr_fromstr("")
        if w_sep is None:
            separator = ""
        elif space.respond_to(w_sep, space.newsymbol("to_str")):
            separator = space.str_w(
                space.send(w_sep, space.newsymbol("to_str")))
        else:
            raise space.error(
                space.w_TypeError,
                "can't convert %s into String" % space.getclass(w_sep).name)
        return space.newstr_fromstr(
            separator.join([
                space.str_w(space.send(w_o, space.newsymbol("to_s")))
                for w_o in self.items_w
            ]))

    @classdef.singleton_method("try_convert")
    def method_try_convert(self, space, w_obj):
        if not space.is_kind_of(w_obj, space.w_array):
            w_obj = space.convert_type(w_obj,
                                       space.w_array,
                                       "to_ary",
                                       raise_error=False)
        return w_obj

    @classdef.method("pop")
    @check_frozen()
    def method_pop(self, space, w_num=None):
        if w_num is None:
            if self.items_w:
                return self.items_w.pop()
            else:
                return space.w_nil
        else:
            num = space.int_w(
                space.convert_type(w_num, space.w_fixnum, "to_int"))
            if num < 0:
                raise space.error(space.w_ArgumentError, "negative array size")
            else:
                pop_size = max(0, len(self.items_w) - num)
                res_w = self.items_w[pop_size:]
                del self.items_w[pop_size:]
                return space.newarray(res_w)

    @classdef.method("delete_at", idx="int")
    @check_frozen()
    def method_delete_at(self, space, idx):
        if idx < 0:
            idx += len(self.items_w)
        if idx < 0 or idx >= len(self.items_w):
            return space.w_nil
        else:
            return self.items_w.pop(idx)

    @classdef.method("last")
    def method_last(self, space, w_count=None):
        if w_count is not None:
            count = Coerce.int(space, w_count)
            if count < 0:
                raise space.error(space.w_ArgumentError, "negative array size")
            start = len(self.items_w) - count
            if start < 0:
                start = 0
            return space.newarray(self.items_w[start:])

        if len(self.items_w) == 0:
            return space.w_nil
        else:
            return self.items_w[len(self.items_w) - 1]

    @classdef.method("pack")
    def method_pack(self, space, w_template):
        template = Coerce.str(space, w_template)
        result = RPacker(template, space.listview(self)).operate(space)
        w_result = space.newstr_fromchars(result)
        if space.is_true(space.send(w_template, space.newsymbol("tainted?"))):
            space.send(w_result, space.newsymbol("taint"))
        return w_result

    @classdef.method("to_ary")
    def method_to_ary(self, space):
        return self

    @classdef.method("clear")
    @check_frozen()
    def method_clear(self, space):
        del self.items_w[:]
        return self

    @classdef.method("sort!")
    @check_frozen()
    def method_sort_i(self, space, block):
        RubySorter(space, self.items_w, sortblock=block).sort()
        return self

    @classdef.method("sort_by!")
    @check_frozen()
    def method_sort_by_i(self, space, block):
        if block is None:
            return space.send(self, space.newsymbol("enum_for"),
                              [space.newsymbol("sort_by!")])
        RubySortBy(space, self.items_w, sortblock=block).sort()
        return self

    @classdef.method("reverse!")
    @check_frozen()
    def method_reverse_i(self, space):
        self.items_w.reverse()
        return self

    @classdef.method("rotate!", n="int")
    @check_frozen()
    def method_rotate_i(self, space, n=1):
        length = len(self.items_w)
        if length == 0:
            return self
        if abs(n) >= length:
            n %= length
        if n < 0:
            n += length
        if n == 0:
            return self
        assert n >= 0
        self.items_w.extend(self.items_w[:n])
        del self.items_w[:n]
        return self
Ejemplo n.º 5
0
class W_CodeObject(W_BaseObject):
    _immutable_fields_ = [
        "code",
        "consts_w[*]",
        "max_stackdepth",
        "cellvars[*]",
        "freevars[*]",
        "arg_pos[*]",
        "defaults[*]",
        "block_arg_pos",
        "splat_arg_pos",
    ]

    classdef = ClassDef("Code", W_BaseObject.classdef, filepath=__file__)

    def __init__(self, name, filepath, code, max_stackdepth, consts, args,
                 splat_arg, block_arg, defaults, cellvars, freevars,
                 lineno_table):

        self.name = name
        self.filepath = filepath
        self.code = code
        self.max_stackdepth = max_stackdepth
        self.consts_w = consts
        self.defaults = defaults
        self.cellvars = cellvars
        self.freevars = freevars
        self.lineno_table = lineno_table

        n_args = len(args)
        arg_pos = [-1] * n_args
        for idx, arg in enumerate(args):
            arg_pos[idx] = cellvars.index(arg)
        self.arg_pos = arg_pos

        block_arg_pos = -1
        if block_arg is not None:
            block_arg_pos = cellvars.index(block_arg)
        self.block_arg_pos = block_arg_pos

        splat_arg_pos = -1
        if splat_arg is not None:
            splat_arg_pos = cellvars.index(splat_arg)
        self.splat_arg_pos = splat_arg_pos

    def __deepcopy__(self, memo):
        obj = super(W_CodeObject, self).__deepcopy__(memo)
        obj.name = self.name
        obj.filepath = self.filepath
        obj.code = self.code
        obj.max_stackdepth = self.max_stackdepth
        obj.consts_w = copy.deepcopy(self.consts_w, memo)
        obj.defaults = copy.deepcopy(self.defaults, memo)
        obj.cellvars = self.cellvars
        obj.freevars = self.freevars
        obj.lineno_table = self.lineno_table
        obj.arg_pos = self.arg_pos
        obj.block_arg_pos = self.block_arg_pos
        obj.splat_arg_pos = self.splat_arg_pos
        return obj

    @classdef.method("filepath")
    def method_filepath(self, space):
        return space.newstr_fromstr(self.filepath)
Ejemplo n.º 6
0
class W_LoadError(W_ScriptError):
    classdef = ClassDef("LoadError", W_ScriptError.classdef, filepath=__file__)
    method_allocate = new_exception_allocate(classdef)
Ejemplo n.º 7
0
class W_SymbolObject(W_Object):
    _immutable_fields_ = ["symbol"]
    classdef = ClassDef("Symbol", W_Object.classdef)
    classdef.include_module(Comparable)

    def __init__(self, space, symbol):
        W_Object.__init__(self, space)
        self.symbol = symbol

    def __deepcopy__(self, memo):
        obj = super(W_SymbolObject, self).__deepcopy__(memo)
        obj.symbol = self.symbol
        return obj

    def symbol_w(self, space):
        return self.symbol

    def str_w(self, space):
        return self.symbol

    @classdef.singleton_method("all_symbols")
    def singleton_method_all_symbols(self, space):
        return space.newarray(space.symbol_cache.values())

    @classdef.method("extend")
    @classdef.method("singleton_class")
    def method_singleton_class(self, space):
        raise space.error(space.w_TypeError, "can't define singleton")

    @classdef.method("to_s")
    def method_to_s(self, space):
        return space.newstr_fromstr(self.symbol)

    @classdef.method("inspect")
    def method_inspect(self, space):
        string_format = (not self.symbol or not self.symbol[0].isalpha()
                         or not self.symbol.isalnum())
        if string_format:
            result = [":", '"']
            for c in self.symbol:
                if c == '"':
                    result.append("\\")
                result.append(c)
            result.append('"')
            return space.newstr_fromchars(result)
        else:
            return space.newstr_fromstr(":%s" % self.symbol)

    @classdef.method("length")
    @classdef.method("size")
    def method_size(self, space):
        return space.newint(len(self.symbol))

    @classdef.method("empty?")
    def method_emptyp(self, space):
        return space.newbool(not self.symbol)

    @classdef.method("<=>")
    def method_comparator(self, space, w_other):
        if not space.is_kind_of(w_other, space.w_symbol):
            return space.w_nil
        s1 = self.symbol
        s2 = space.symbol_w(w_other)
        if s1 < s2:
            return space.newint(-1)
        elif s1 == s2:
            return space.newint(0)
        elif s1 > s2:
            return space.newint(1)

    @classdef.method("downcase")
    def method_downcase(self, space):
        return space.newsymbol(self.symbol.lower())

    @classdef.method("upcase")
    def method_upcase(self, space):
        return space.newsymbol(self.symbol.upper())
Ejemplo n.º 8
0
class W_RandomObject(W_Object):
    classdef = ClassDef("Random", W_Object.classdef, filepath=__file__)

    def __init__(self, space, seed=0, klass=None):
        W_Object.__init__(self, space, klass)
        self.w_seed = None
        self.random = Random(abs(seed))

    @classdef.setup_class
    def setup_class(cls, space, w_cls):
        default = space.send(w_cls, space.newsymbol("new"))
        space.set_const(w_cls, "DEFAULT", default)

    @classdef.singleton_method("allocate", seed="int")
    def method_allocate(self, space, seed=0):
        return W_RandomObject(space, seed, self)

    @classdef.method("initialize")
    def method_initialize(self, space, w_seed=None):
        self.srand(space, w_seed)

    @classdef.method("seed")
    def method_seed(self, space):
        return self.w_seed

    def srand(self, space, seed=None):
        previous_seed = self.w_seed
        if seed is None:
            seed = self._generate_seed()
        else:
            seed = Coerce.int(space, seed)
        self.w_seed = space.newint(seed)
        if previous_seed is None:
            value = space.newfloat(self.random.random())
        else:
            value = previous_seed
        self.random = Random(abs(seed))
        return value

    @classdef.method("rand")
    def method_rand(self, space, w_max=None):
        if w_max is None:
            return space.newfloat(self.random.random())
        elif space.is_kind_of(w_max, space.w_float):
            return self._rand_float(space, w_max)
        elif space.is_kind_of(w_max, space.getclassfor(W_RangeObject)):
            return self._rand_range(space, w_max)
        else:
            return self._rand_int(space, w_max)

    @classdef.singleton_method("rand")
    def method_singleton_rand(self, space, args_w):
        default = space.find_const(self, "DEFAULT")
        return space.send(default, space.newsymbol("rand"), args_w)

    def _rand_range(self, space, range):
        random = self.random.random()
        first = space.send(range, space.newsymbol("first"))
        last = space.send(range, space.newsymbol("last"))
        if space.is_true(space.send(range, space.newsymbol("include?"),
                                    [last])):
            last = space.send(last, space.newsymbol("+"), [space.newint(1)])
        diff = space.send(last, space.newsymbol("-"), [first])
        offset = space.send(diff, space.newsymbol("*"),
                            [space.newfloat(random)])
        choice = space.send(offset, space.newsymbol("+"), [first])
        if (not space.is_kind_of(first, space.w_float)
                and not space.is_kind_of(last, space.w_float)):
            choice = space.send(choice, space.newsymbol("to_i"))
        return choice

    def _rand_float(self, space, float):
        random = self.random.random()
        max = Coerce.float(space, float)
        if max <= 0:
            raise space.error(space.w_ArgumentError, "invalid argument")
        return space.newfloat(random * max)

    def _rand_int(self, space, integer):
        random = self.random.random()
        max = Coerce.int(space, integer)
        if max <= 0:
            raise space.error(space.w_ArgumentError, "invalid argument")
        else:
            return space.newint(int(random * max))

    def _generate_seed(self):
        seed = 0
        if os.access('/dev/urandom', os.R_OK):
            file = os.open('/dev/urandom', os.R_OK, 0644)
            bytes = os.read(file, 4)
            os.close(file)
            for b in bytes:
                seed = seed * 0xff + ord(b)
        return seed + int(time.time()) + os.getpid()
Ejemplo n.º 9
0
class W_HashObject(W_Object):
    classdef = ClassDef("Hash", W_Object.classdef, filepath=__file__)
    classdef.include_module(Enumerable)

    def __init__(self, space, klass=None):
        W_Object.__init__(self, space, klass)
        self.contents = OrderedDict(space.eq_w, space.hash_w)
        self.w_default = space.w_nil
        self.default_proc = None

    @classdef.singleton_method("allocate")
    def method_allocate(self, space, args_w):
        return W_HashObject(space, self)

    @classdef.singleton_method("try_convert")
    def method_try_convert(self, space, w_obj):
        if not space.is_kind_of(w_obj, space.w_hash):
            w_obj = space.convert_type(w_obj,
                                       space.w_hash,
                                       "to_hash",
                                       raise_error=False)
        return w_obj

    @classdef.method("initialize")
    def method_initialize(self, space, w_default=None, block=None):
        if w_default is not None:
            self.w_default = w_default
        if block is not None:
            self.default_proc = block

    @classdef.method("default")
    def method_default(self, space, w_key=None):
        if self.default_proc is not None and w_key is not None:
            return space.invoke_block(self.default_proc, [self, w_key])
        else:
            return self.w_default

    @classdef.method("default=")
    @check_frozen()
    def method_set_default(self, space, w_defl):
        self.default_proc = None
        self.w_default = w_defl

    @classdef.method("default_proc")
    def method_default_proc(self, space):
        if self.default_proc is None:
            return space.w_nil
        return space.newproc(self.default_proc)

    @classdef.method("[]")
    def method_subscript(self, space, w_key):
        try:
            return self.contents[w_key]
        except KeyError:
            return space.send(self, space.newsymbol("default"), [w_key])

    @classdef.method("fetch")
    def method_fetch(self, space, w_key, w_value=None, block=None):
        try:
            return self.contents[w_key]
        except KeyError:
            if w_value is not None:
                return w_value
            elif block is not None:
                return space.invoke_block(block, [w_key])
            else:
                raise space.error(
                    space.w_KeyError, "key not found: %s" %
                    space.send(w_key, space.newsymbol("inspect")))

    @classdef.method("store")
    @classdef.method("[]=")
    @check_frozen()
    def method_subscript_assign(self, space, w_key, w_value):
        if (space.is_kind_of(w_key, space.w_string) and not space.is_true(
                space.send(w_key, space.newsymbol("frozen?")))):

            w_key = space.send(w_key, space.newsymbol("dup"))
            w_key = space.send(w_key, space.newsymbol("freeze"))
        self.contents[w_key] = w_value
        return w_value

    @classdef.method("length")
    @classdef.method("size")
    def method_size(self, space):
        return space.newint(len(self.contents))

    @classdef.method("empty?")
    def method_emptyp(self, space):
        return space.newbool(not bool(self.contents))

    @classdef.method("delete")
    @check_frozen()
    def method_delete(self, space, w_key, block):
        w_res = self.contents.pop(w_key, None)
        if w_res is None:
            if block:
                return space.invoke_block(block, [w_key])
            w_res = space.w_nil
        return w_res

    @classdef.method("clear")
    @check_frozen()
    def method_clear(self, space):
        self.contents.clear()
        return self

    @classdef.method("shift")
    @check_frozen()
    def method_shift(self, space):
        if not self.contents:
            return space.send(self, space.newsymbol("default"), [space.w_nil])
        w_key, w_value = self.contents.popitem()
        return space.newarray([w_key, w_value])

    @classdef.method("initialize_copy")
    @classdef.method("replace")
    @check_frozen()
    def method_replace(self, space, w_hash):
        assert isinstance(w_hash, W_HashObject)
        self.contents.clear()
        self.contents.update(w_hash.contents)
        return self

    @classdef.method("keys")
    def method_keys(self, space):
        return space.newarray(self.contents.keys())

    @classdef.method("values")
    def method_values(self, space):
        return space.newarray(self.contents.values())

    @classdef.method("to_hash")
    def method_to_hash(self, space):
        return self

    @classdef.method("key?")
    @classdef.method("has_key?")
    @classdef.method("member?")
    @classdef.method("include?")
    def method_includep(self, space, w_key):
        return space.newbool(w_key in self.contents)
Ejemplo n.º 10
0
class W_RootObject(W_BaseObject):
    _attrs_ = []

    classdef = ClassDef("Object", W_BaseObject.classdef, filepath=__file__)

    @classdef.setup_class
    def setup_class(cls, space, w_cls):
        space.w_top_self = W_Object(space, w_cls)

    @classdef.method("object_id")
    def method_object_id(self, space):
        return space.send(self, space.newsymbol("__id__"))

    @classdef.method("singleton_class")
    def method_singleton_class(self, space):
        return space.getsingletonclass(self)

    @classdef.method("extend")
    def method_extend(self, space, w_mod):
        if not space.is_kind_of(w_mod, space.w_module) or space.is_kind_of(
                w_mod, space.w_class):
            if space.is_kind_of(w_mod, space.w_class):
                name = "Class"
            else:
                name = space.obj_to_s(space.getclass(w_mod))
            raise space.error(
                space.w_TypeError,
                "wrong argument type %s (expected Module)" % name)
        self.getsingletonclass(space).extend_object(space, self, w_mod)

    @classdef.method("inspect")
    def method_inspect(self, space):
        return space.send(self, space.newsymbol("to_s"))

    @classdef.method("to_s")
    def method_to_s(self, space):
        return space.newstr_fromstr(space.any_to_s(self))

    @classdef.method("===")
    def method_eqeqeq(self, space, w_other):
        if self is w_other:
            return space.w_true
        return space.send(self, space.newsymbol("=="), [w_other])

    @classdef.method("send")
    def method_send(self, space, args_w, block):
        return space.send(self, space.newsymbol("__send__"), args_w, block)

    @classdef.method("nil?")
    def method_nilp(self, space):
        return space.w_false

    @classdef.method("hash")
    def method_hash(self, space):
        return space.newint(compute_identity_hash(self))

    @classdef.method("instance_variable_get", name="str")
    def method_instance_variable_get(self, space, name):
        return space.find_instance_var(self, name)

    @classdef.method("instance_variable_set", name="str")
    def method_instance_variable_set(self, space, name, w_value):
        space.set_instance_var(self, name, w_value)
        return w_value

    @classdef.method("method")
    def method_method(self, space, w_sym):
        return space.send(
            space.send(space.getclass(self),
                       space.newsymbol("instance_method"), [w_sym]),
            space.newsymbol("bind"), [self])

    @classdef.method("tap")
    def method_tap(self, space, block):
        if block is not None:
            space.invoke_block(block, [self])
        else:
            raise space.error(space.w_LocalJumpError, "no block given")
        return self
Ejemplo n.º 11
0
class W_BaseObject(W_Root):
    _attrs_ = []

    classdef = ClassDef("BasicObject", filepath=__file__)

    def getclass(self, space):
        return space.getclassobject(self.classdef)

    def is_kind_of(self, space, w_cls):
        return w_cls.is_ancestor_of(self.getclass(space))

    def attach_method(self, space, name, func):
        w_cls = space.getsingletonclass(self)
        w_cls.define_method(space, name, func)

    def is_true(self, space):
        return True

    def find_const(self, space, name):
        raise space.error(
            space.w_TypeError, "%s is not a class/module" %
            space.str_w(space.send(self, space.newsymbol("inspect"))))

    find_included_const = find_local_const = find_const

    @classdef.method("initialize")
    def method_initialize(self):
        return self

    @classdef.method("__id__")
    def method___id__(self, space):
        return space.newint(compute_unique_id(self))

    @classdef.method("method_missing")
    def method_method_missing(self, space, w_name, args_w):
        name = space.symbol_w(w_name)
        class_name = space.str_w(
            space.send(self.getclass(space), space.newsymbol("to_s")))
        raise space.error(space.w_NoMethodError,
                          "undefined method `%s' for %s" % (name, class_name))

    @classdef.method("==")
    @classdef.method("equal?")
    def method_eq(self, space, w_other):
        return space.newbool(self is w_other)

    @classdef.method("!")
    def method_not(self, space):
        return space.newbool(not space.is_true(self))

    @classdef.method("!=")
    def method_ne(self, space, w_other):
        return space.newbool(not space.is_true(
            space.send(self, space.newsymbol("=="), [w_other])))

    @classdef.method("__send__", method="str")
    def method_send(self, space, method, args_w, block):
        return space.send(self, space.newsymbol(method), args_w, block)

    @classdef.method("instance_eval", string="str", filename="str")
    def method_instance_eval(self,
                             space,
                             string=None,
                             filename=None,
                             w_lineno=None,
                             block=None):
        if string is not None:
            if filename is None:
                filename = "instance_eval"
            if w_lineno is not None:
                lineno = space.int_w(w_lineno)
            else:
                lineno = 1
            return space.execute(string, self,
                                 StaticScope(space.getclass(self), None),
                                 filename, lineno)
        else:
            return space.invoke_block(block.copy(w_self=self), [])
Ejemplo n.º 12
0
class W_EncodingObject(W_Object):
    classdef = ClassDef("Encoding", W_Object.classdef, filepath=__file__)
Ejemplo n.º 13
0
class W_ProcObject(W_Object):
    classdef = ClassDef("Proc", W_Object.classdef)

    def __init__(self, space, bytecode, w_self, lexical_scope, cells, block,
                 parent_interp, regexp_match_cell, is_lambda):
        W_Object.__init__(self, space)
        self.bytecode = bytecode
        self.w_self = w_self
        self.lexical_scope = lexical_scope
        self.cells = cells
        self.block = block
        self.parent_interp = parent_interp
        self.regexp_match_cell = regexp_match_cell
        self.is_lambda = is_lambda

    def copy(self, space, w_self=None, lexical_scope=None, is_lambda=False):
        return W_ProcObject(space, self.bytecode, w_self or self.w_self,
                            lexical_scope or self.lexical_scope, self.cells,
                            self.block, self.parent_interp,
                            self.regexp_match_cell, is_lambda
                            or self.is_lambda)

    @classdef.singleton_method("new")
    def method_new(self, space, block):
        if block is None:
            raise space.error(space.w_ArgumentError,
                              "tried to create Proc object without a block")
        return block.copy(space)

    method_allocate = classdef.undefine_allocator()

    @classdef.method("yield")
    @classdef.method("===")
    @classdef.method("[]")
    @classdef.method("call")
    def method_call(self, space, args_w, block):
        from topaz.interpreter import RaiseReturn, RaiseBreak

        try:
            return space.invoke_block(self, args_w, block_arg=block)
        except RaiseReturn as e:
            if self.is_lambda:
                return e.w_value
            else:
                raise
        except RaiseBreak as e:
            if self.is_lambda:
                return e.w_value
            else:
                raise space.error(space.w_LocalJumpError,
                                  "break from proc-closure")

    @classdef.method("lambda?")
    def method_lambda(self, space):
        return space.newbool(self.is_lambda)

    @classdef.method("arity")
    def method_arity(self, space):
        return space.newint(self.bytecode.arity())

    @classdef.method("binding")
    def method_binding(self, space):
        return space.newbinding_fromblock(self)
Ejemplo n.º 14
0
class W_FixnumObject(W_RootObject):
    _immutable_fields_ = ["intvalue"]

    classdef = ClassDef("Fixnum", W_IntegerObject.classdef)

    def __init__(self, space, intvalue):
        check_regular_int(intvalue)
        self.intvalue = intvalue

    def __deepcopy__(self, memo):
        obj = super(W_FixnumObject, self).__deepcopy__(memo)
        obj.intvalue = self.intvalue
        return obj

    def int_w(self, space):
        return self.intvalue

    def bigint_w(self, space):
        return rbigint.fromint(self.intvalue)

    def float_w(self, space):
        return float(self.intvalue)

    def intmask_w(self, space):
        return self.intvalue

    def uintmask_w(self, space):
        return r_uint(self.intvalue)

    def longlongmask_w(self, space):
        return r_longlong(self.intvalue)

    def ulonglongmask_w(self, space):
        return r_ulonglong(self.intvalue)

    def find_instance_var(self, space, name):
        storage = space.fromcache(FixnumStorage).get_or_create(
            space, self.intvalue)
        return storage.find_instance_var(space, name)

    def set_instance_var(self, space, name, w_value):
        storage = space.fromcache(FixnumStorage).get_or_create(
            space, self.intvalue)
        storage.set_instance_var(space, name, w_value)

    def set_flag(self, space, name):
        storage = space.fromcache(FixnumStorage).get_or_create(
            space, self.intvalue)
        storage.set_flag(space, name)

    def unset_flag(self, space, name):
        storage = space.fromcache(FixnumStorage).get_or_create(
            space, self.intvalue)
        storage.unset_flag(space, name)

    def get_flag(self, space, name):
        storage = space.fromcache(FixnumStorage).get_or_create(
            space, self.intvalue)
        return storage.get_flag(space, name)

    @classdef.method("extend")
    @classdef.method("singleton_class")
    def method_singleton_class(self, space):
        raise space.error(space.w_TypeError, "can't define singleton")

    @classdef.method("inspect")
    @classdef.method("to_s")
    def method_to_s(self, space):
        return space.newstr_fromstr(str(self.intvalue))

    @classdef.method("to_f")
    def method_to_f(self, space):
        return space.newfloat(float(self.intvalue))

    @classdef.method("to_i")
    @classdef.method("to_int")
    def method_to_i(self, space):
        return self

    def new_binop(classdef, name, func):
        @classdef.method(name)
        def method(self, space, w_other):
            if space.is_kind_of(w_other, space.w_fixnum):
                other = space.int_w(w_other)
                try:
                    value = ovfcheck(func(self.intvalue, other))
                except OverflowError:
                    return space.send(space.newbigint_fromint(self.intvalue),
                                      name, [w_other])
                else:
                    return space.newint(value)
            elif space.is_kind_of(w_other, space.w_bignum):
                return space.send(space.newbigint_fromint(self.intvalue), name,
                                  [w_other])
            elif space.is_kind_of(w_other, space.w_float):
                return space.newfloat(
                    func(self.intvalue, space.float_w(w_other)))
            else:
                return W_NumericObject.retry_binop_coercing(
                    space, self, w_other, name)

        method.__name__ = "method_%s" % func.__name__
        return method

    method_add = new_binop(classdef, "+", operator.add)
    method_sub = new_binop(classdef, "-", operator.sub)
    method_mul = new_binop(classdef, "*", operator.mul)

    def raise_zero_division_error(self, space):
        raise space.error(space.w_ZeroDivisionError, "divided by 0")

    def divide(self, space, w_other):
        if space.is_kind_of(w_other, space.w_fixnum):
            other = space.int_w(w_other)
            try:
                return space.newint(self.intvalue / other)
            except ZeroDivisionError:
                self.raise_zero_division_error(space)
        elif space.is_kind_of(w_other, space.w_bignum):
            return space.send(space.newbigint_fromint(self.intvalue), "/",
                              [w_other])
        elif space.is_kind_of(w_other, space.w_float):
            return space.send(space.newfloat(space.float_w(self)), "/",
                              [w_other])
        else:
            return W_NumericObject.retry_binop_coercing(
                space, self, w_other, "/")

    @classdef.method("/")
    def method_divide(self, space, w_other):
        return self.divide(space, w_other)

    @classdef.method("div")
    def method_div(self, space, w_other):
        if space.is_kind_of(w_other, space.w_float):
            if space.float_w(w_other) == 0.0:
                self.raise_zero_division_error(space)
            else:
                w_float = space.send(space.newfloat(space.float_w(self)), "/",
                                     [w_other])
                w_float = space.newfloat(
                    math.floor(Coerce.float(space, w_float)))
                return space.send(w_float, "to_i")
        else:
            return self.divide(space, w_other)

    @classdef.method("fdiv")
    def method_fdiv(self, space, w_other):
        if space.is_kind_of(w_other, space.w_fixnum):
            other = space.int_w(w_other)
            try:
                res = float(self.intvalue) / float(other)
            except ZeroDivisionError:
                return space.newfloat(
                    rfloat.copysign(rfloat.INFINITY, float(self.intvalue)))
            else:
                return space.newfloat(res)
        elif space.is_kind_of(w_other, space.w_bignum):
            return space.send(space.newbigint_fromint(self.intvalue), "fdiv",
                              [w_other])
        elif space.is_kind_of(w_other, space.w_float):
            other = space.float_w(w_other)
            try:
                res = float(self.intvalue) / other
            except ZeroDivisionError:
                return space.newfloat(
                    rfloat.copysign(rfloat.INFINITY, float(self.intvalue)))
            else:
                return space.newfloat(res)
        else:
            return W_NumericObject.retry_binop_coercing(
                space, self, w_other, "fdiv")

    @classdef.method("**")
    def method_pow(self, space, w_other):
        if space.is_kind_of(w_other, space.w_fixnum):
            return self.method_pow_int_impl(space, w_other)
        elif space.getclass(w_other) is space.w_float:
            return space.send(space.newfloat(float(self.intvalue)), "**",
                              [w_other])
        elif space.getclass(w_other) is space.w_bignum:
            return space.send(space.newbigint_fromint(self.intvalue), "**",
                              [w_other])
        else:
            raise space.error(
                space.w_TypeError, "%s can't be coerced into Fixnum" %
                space.obj_to_s(space.getclass(w_other)))

    def method_pow_int_impl(self, space, w_other):
        exp = space.int_w(w_other)
        temp = self.intvalue
        if exp > 0:
            ix = 1
            try:
                while exp > 0:
                    if exp & 1:
                        ix = ovfcheck(ix * temp)
                    exp >>= 1
                    if exp == 0:
                        break
                    temp = ovfcheck(temp * temp)
            except OverflowError:
                return space.send(space.newbigint_fromint(self.intvalue), "**",
                                  [w_other])
            return space.newint(ix)
        else:
            return space.send(space.newfloat(float(temp)), "**", [w_other])

    @classdef.method("divmod")
    def method_divmod(self, space, w_other):
        if space.is_kind_of(w_other, space.w_float):
            return space.send(self.method_to_f(space), "divmod", [w_other])
        elif space.is_kind_of(w_other, space.w_bignum):
            return space.send(space.newbigint_fromint(self.intvalue), "divmod",
                              [w_other])
        elif space.is_kind_of(w_other, space.w_fixnum):
            y = space.int_w(w_other)
            if y == 0:
                raise space.error(space.w_ZeroDivisionError, "divided by 0")
            mod = space.int_w(self.method_mod_int_impl(space, y))
            div = (self.intvalue - mod) / y
            return space.newarray(
                [space.newint(int(round_away(div))),
                 space.newfloat(mod)])
        else:
            raise space.error(
                space.w_TypeError, "%s can't be coerced into Fixnum" %
                (space.obj_to_s(space.getclass(w_other))))

    @classdef.method("%")
    @classdef.method("modulo")
    def method_mod(self, space, w_other):
        if space.is_kind_of(w_other, space.w_fixnum):
            return self.method_mod_int_impl(space, space.int_w(w_other))
        elif space.is_kind_of(w_other, space.w_float):
            return space.send(self.method_to_f(space), "%", [w_other])
        elif space.is_kind_of(w_other, space.w_bignum):
            return space.send(space.newbigint_fromint(self.intvalue), "%",
                              [w_other])
        else:
            raise space.error(
                space.w_TypeError, "%s can't be coerced into Fixnum" %
                (space.obj_to_s(space.getclass(w_other))))

    def method_mod_int_impl(self, space, other):
        if other == 0:
            raise space.error(space.w_ZeroDivisionError, "divided by 0")
        return space.newint(self.intvalue % other)

    @classdef.method("<<", other="int")
    def method_left_shift(self, space, other):
        if other < 0:
            return space.newint(self.intvalue >> -other)
        elif other >= LONG_BIT:
            return space.send(space.newbigint_fromint(self.intvalue), "<<",
                              [space.newint(other)])
        else:
            try:
                value = ovfcheck(self.intvalue << other)
            except OverflowError:
                return space.send(space.newbigint_fromint(self.intvalue), "<<",
                                  [space.newint(other)])
            else:
                return space.newint(value)

    @classdef.method(">>", other="int")
    def method_right_shift(self, space, other):
        if other < 0:
            return space.newint(self.intvalue << -other)
        else:
            return space.newint(self.intvalue >> other)

    def new_bitwise_op(classdef, name, func):
        @classdef.method(name)
        def method(self, space, w_other):
            w_other = space.convert_type(w_other, space.w_integer, "to_int")
            if space.is_kind_of(w_other, space.w_fixnum):
                other = space.int_w(w_other)
                return space.newint(func(self.intvalue, other))
            elif space.is_kind_of(w_other, space.w_bignum):
                return space.send(space.newbigint_fromint(self.intvalue), name,
                                  [w_other])
            else:
                return W_NumericObject.retry_binop_coercing(
                    space, self, w_other, name)

        method.__name__ = "method_%s" % func.__name__
        return method

    method_and = new_bitwise_op(classdef, "&", operator.and_)
    method_or = new_bitwise_op(classdef, "|", operator.or_)
    method_xor = new_bitwise_op(classdef, "^", operator.xor)

    @classdef.method("~")
    def method_invert(self, space):
        return space.newint(~self.intvalue)

    @classdef.method("==")
    @classdef.method("equal?")
    def method_eq(self, space, w_other):
        if isinstance(w_other, W_FixnumObject):
            return space.newbool(
                self.comparator(space, space.int_w(w_other)) == 0)
        elif isinstance(w_other, W_FloatObject):
            return space.newbool(
                self.comparator(space, space.float_w(w_other)) == 0)
        else:
            return space.send(w_other, "==", [self])

    @classdef.method("!=")
    def method_ne(self, space, w_other):
        return space.newbool(
            space.send(self, "==", [w_other]) is space.w_false)

    def new_bool_op(classdef, name, func):
        @classdef.method(name)
        def method(self, space, w_other):
            if space.is_kind_of(w_other, space.w_float):
                return space.newbool(
                    func(self.intvalue, space.float_w(w_other)))
            elif space.is_kind_of(w_other, space.w_fixnum):
                return space.newbool(func(self.intvalue, space.int_w(w_other)))
            else:
                return W_NumericObject.retry_binop_coercing(space,
                                                            self,
                                                            w_other,
                                                            name,
                                                            raise_error=True)

        method.__name__ = "method_%s" % func.__name__
        return method

    method_lt = new_bool_op(classdef, "<", operator.lt)
    method_lte = new_bool_op(classdef, "<=", operator.le)
    method_gt = new_bool_op(classdef, ">", operator.gt)
    method_gte = new_bool_op(classdef, ">=", operator.ge)

    @classdef.method("<=>")
    def method_comparator(self, space, w_other):
        if isinstance(w_other, W_FixnumObject):
            return space.newint(self.comparator(space, space.int_w(w_other)))
        elif isinstance(w_other, W_FloatObject):
            return space.newint(self.comparator(space, space.float_w(w_other)))
        else:
            return space.w_nil

    @specialize.argtype(2)
    def comparator(self, space, other):
        if self.intvalue < other:
            return -1
        elif self.intvalue == other:
            return 0
        elif self.intvalue > other:
            return 1
        return 1

    @classdef.method("hash")
    def method_hash(self, space):
        return self

    if IS_WINDOWS:

        @classdef.method("size")
        def method_size(self, space):
            # RPython translation is always 32bit on Windows
            return space.newint(4)
    else:

        @classdef.method("size")
        def method_size(self, space):
            return space.newint(rffi.sizeof(lltype.typeOf(self.intvalue)))

    @classdef.method("coerce")
    def method_coerce(self, space, w_other):
        if space.getclass(w_other) is space.getclass(self):
            return space.newarray([w_other, self])
        else:
            return space.newarray([space.send(self, "Float", [w_other]), self])

    @classdef.method("chr")
    def method_chr(self, space):
        if self.intvalue > 255 or self.intvalue < 0:
            raise space.error(space.w_RangeError,
                              "%d out of char range" % self.intvalue)
        else:
            return space.newstr_fromstr(chr(self.intvalue))

    @classdef.method("[]", idx="int")
    def method_subscript(self, space, idx):
        if not 0 <= idx < LONG_BIT:
            return space.newint(0)
        return space.newint(int(bool(self.intvalue & (1 << idx))))
Ejemplo n.º 15
0
class W_EOFError(W_IOError):
    classdef = ClassDef("EOFError", W_IOError.classdef, filepath=__file__)
    method_allocate = new_exception_allocate(classdef)
Ejemplo n.º 16
0
class W_BignumObject(W_IntegerObject):
    classdef = ClassDef("Bignum", W_IntegerObject.classdef, filepath=__file__)

    def __init__(self, space, bigint):
        W_IntegerObject.__init__(self, space)
        self.bigint = bigint

    @staticmethod
    def newbigint_fromint(space, intvalue):
        return W_BignumObject(space, rbigint.fromint(intvalue))

    @staticmethod
    def newbigint_fromfloat(space, floatvalue):
        return W_BignumObject(space, rbigint.fromfloat(floatvalue))

    @staticmethod
    def newbigint_fromrbigint(space, bigint):
        return W_BignumObject(space, bigint)

    def int_w(self, space):
        return self.bigint.toint()

    def bigint_w(self, space):
        return self.bigint

    def float_w(self, space):
        return self.bigint.tofloat()

    @classdef.method("to_s")
    def method_to_s(self, space):
        return space.newstr_fromstr(self.bigint.str())

    @classdef.method("to_f")
    def method_to_f(self, space):
        return space.newfloat(self.bigint.tofloat())

    @classdef.method("+", other="bigint")
    def method_plus(self, space, other):
        return space.newbigint_fromrbigint(self.bigint.add(other))

    @classdef.method("-", other="bigint")
    def method_sub(self, space, other):
        return space.newbigint_fromrbigint(self.bigint.sub(other))

    @classdef.method("*", other="bigint")
    def method_times(self, space, other):
        return space.newbigint_fromrbigint(self.bigint.mul(other))

    def floordiv(self, space, other):
        try:
            result = self.bigint.div(other)
        except ZeroDivisionError:
            raise space.error(space.w_ZeroDivisionError, "divided by 0")
        try:
            return space.newint(result.toint())
        except OverflowError:
            return space.newbigint_fromrbigint(result)

    @classdef.method("/")
    def method_divide(self, space, w_other):
        if space.is_kind_of(w_other, space.w_fixnum):
            return self.floordiv(space, rbigint.fromint(space.int_w(w_other)))
        elif space.is_kind_of(w_other, space.w_bignum):
            return self.floordiv(space, space.bigint_w(w_other))
        elif space.is_kind_of(w_other, space.w_float):
            return space.send(space.newfloat(space.float_w(self)),
                              space.newsymbol("/"), [w_other])
        else:
            return W_NumericObject.retry_binop_coercing(
                space, self, w_other, "/")

    @classdef.method("<<", other="int")
    def method_left_shift(self, space, other):
        return space.newbigint_fromrbigint(self.bigint.lshift(other))

    @classdef.method("&", other="bigint")
    def method_and(self, space, other):
        return space.newbigint_fromrbigint(self.bigint.and_(other))

    @classdef.method("|", other="bigint")
    def method_or(self, space, other):
        return space.newbigint_fromrbigint(self.bigint.or_(other))

    @classdef.method("^", other="bigint")
    def method_xor(self, space, other):
        return space.newbigint_fromrbigint(self.bigint.xor(other))

    @classdef.method("==", other="bigint")
    def method_eq(self, space, other):
        return space.newbool(self.bigint.eq(other))

    @classdef.method("<=>", other="bigint")
    def method_comparator(self, space, other):
        if self.bigint.gt(other):
            return space.newint(1)
        elif self.bigint.eq(other):
            return space.newint(0)
        elif self.bigint.lt(other):
            return space.newint(-1)

    @classdef.method("hash")
    def method_hash(self, space):
        return space.newint(self.bigint.hash())

    @classdef.method("coerce")
    def method_coerce(self, space, w_other):
        if isinstance(w_other, W_BignumObject):
            return space.newarray([w_other, self])
        elif space.getclass(w_other) is space.w_fixnum:
            return space.newarray([
                space.newbigint_fromint(space.int_w(w_other)),
                self,
            ])
        else:
            raise space.error(
                space.w_TypeError, "can't coerce %s to Bignum" %
                space.obj_to_s(space.getclass(w_other)))

    @classdef.method("**")
    def method_pow(self, space, w_other):
        if space.getclass(w_other) is space.w_fixnum or space.getclass(
                w_other) is space.w_bignum:
            exp = space.bigint_w(w_other)
            negative_exponent = False
            if exp.sign < 0:
                negative_exponent = True
                exp = exp.abs()
            result = self.bigint.pow(exp, None)
            if negative_exponent:
                return space.newfloat(1.0 / result.tofloat())
            else:
                return space.newbigint_fromrbigint(result)
        elif space.getclass(w_other) is space.w_float:
            try:
                float_value = space.float_w(self)
            except OverflowError:
                return space.newfloat(INFINITY)
            return space.send(space.newfloat(float_value),
                              space.newsymbol("**"), [w_other])
        else:
            raise space.error(
                space.w_TypeError, "%s can't be coerced into Bignum" %
                space.obj_to_s(space.getclass(w_other)))
Ejemplo n.º 17
0
class W_FiberError(W_StandardError):
    classdef = ClassDef("FiberError",
                        W_StandardError.classdef,
                        filepath=__file__)
    method_allocate = new_exception_allocate(classdef)
Ejemplo n.º 18
0
class W_TypeError(W_ExceptionObject):
    classdef = ClassDef("TypeError",
                        W_StandardError.classdef,
                        filepath=__file__)
    method_allocate = new_exception_allocate(classdef)
Ejemplo n.º 19
0
class W_SystemStackError(W_ExceptionObject):
    classdef = ClassDef("SystemStackError",
                        W_ExceptionObject.classdef,
                        filepath=__file__)
    method_allocate = new_exception_allocate(classdef)
Ejemplo n.º 20
0
class W_NoMethodError(W_NameError):
    classdef = ClassDef("NoMethodError",
                        W_NameError.classdef,
                        filepath=__file__)
    method_allocate = new_exception_allocate(classdef)
Ejemplo n.º 21
0
class W_StringObject(W_Object):
    classdef = ClassDef("String", W_Object.classdef)
    classdef.include_module(Comparable)

    def __init__(self, space, storage, strategy, klass=None):
        W_Object.__init__(self, space, klass)
        self.str_storage = storage
        self.strategy = strategy

    def __deepcopy__(self, memo):
        obj = super(W_StringObject, self).__deepcopy__(memo)
        obj.str_storage = copy.deepcopy(self.str_storage, memo)
        obj.strategy = copy.deepcopy(self.strategy, memo)
        return obj

    @staticmethod
    def newstr_fromstr(space, strvalue):
        strategy = space.fromcache(ConstantStringStrategy)
        storage = strategy.erase(strvalue)
        return W_StringObject(space, storage, strategy)

    @staticmethod
    @jit.look_inside_iff(lambda space, strs_w: jit.isconstant(len(strs_w)))
    def newstr_fromstrs(space, strs_w):
        total_length = 0
        for w_item in strs_w:
            assert isinstance(w_item, W_StringObject)
            total_length += w_item.length()

        storage = newlist_hint(total_length)
        for w_item in strs_w:
            assert isinstance(w_item, W_StringObject)
            w_item.strategy.extend_into(w_item.str_storage, storage)
        return space.newstr_fromchars(storage)

    @staticmethod
    def newstr_fromchars(space, chars):
        strategy = space.fromcache(MutableStringStrategy)
        storage = strategy.erase(chars)
        return W_StringObject(space, storage, strategy)

    def str_w(self, space):
        return self.strategy.str_w(self.str_storage)

    def symbol_w(self, space):
        return self.str_w(space)

    def liststr_w(self, space):
        return self.strategy.liststr_w(self.str_storage)

    def length(self):
        return self.strategy.length(self.str_storage)

    def copy(self, space):
        return W_StringObject(space, self.strategy.copy(self.str_storage),
                              self.strategy)

    def replace(self, space, chars):
        strategy = space.fromcache(MutableStringStrategy)
        self.str_storage = strategy.erase(chars)
        self.strategy = strategy

    def extend(self, space, w_other):
        self.strategy.to_mutable(space, self)
        strategy = self.strategy
        assert isinstance(strategy, MutableStringStrategy)
        storage = strategy.unerase(self.str_storage)
        w_other.strategy.extend_into(w_other.str_storage, storage)

    def clear(self, space):
        self.strategy.to_mutable(space, self)
        self.strategy.clear(self)

    def tr_trans(self, space, source, replacement, squeeze):
        change_made = False
        string = space.str_w(self)
        new_string = []
        is_negative_set = len(source) > 1 and source[0] == "^"
        if is_negative_set:
            source = source[1:]

        trans_table = create_trans_table(source, replacement, is_negative_set)

        if squeeze:
            last_repl = ""
            for char in string:
                repl = trans_table[ord(char)]
                if last_repl == repl:
                    continue
                if repl != char:
                    last_repl = repl
                    if not change_made:
                        change_made = True
                new_string.append(repl)
        else:
            for char in string:
                repl = trans_table[ord(char)]
                if not change_made and repl != char:
                    change_made = True
                new_string.append(repl)

        return new_string if change_made else None

    @classdef.singleton_method("allocate")
    def singleton_method_allocate(self, space, w_s=None):
        strategy = space.fromcache(ConstantStringStrategy)
        storage = strategy.erase("")
        return W_StringObject(space, storage, strategy, self)

    @classdef.singleton_method("try_convert")
    def method_try_convert(self, space, w_obj):
        if not space.is_kind_of(w_obj, space.w_string):
            w_obj = space.convert_type(w_obj,
                                       space.w_string,
                                       "to_str",
                                       raise_error=False)
        return w_obj

    @classdef.method("initialize")
    def method_initialize(self, space, w_s=None):
        if w_s is not None:
            w_s = space.convert_type(w_s, space.w_string, "to_str")
            assert isinstance(w_s, W_StringObject)
            self.strategy = w_s.strategy
            self.str_storage = w_s.strategy.copy(w_s.str_storage)

    @classdef.method("initialize_copy")
    def method_initialize_copy(self, space, w_other):
        assert isinstance(w_other, W_StringObject)
        self.strategy = w_other.strategy
        self.str_storage = w_other.strategy.copy(w_other.str_storage)
        return self

    @classdef.method("to_str")
    @classdef.method("to_s")
    def method_to_s(self, space):
        return self

    @classdef.method("ord")
    def method_ord(self, space):
        if self.length() == 0:
            raise space.error(space.w_ArgumentError, "empty string")
        return space.newint(ord(self.strategy.getitem(self.str_storage, 0)))

    @classdef.method("inspect")
    def method_inspect(self, space):
        return space.newstr_fromstr('"%s"' % self.str_w(space))

    @classdef.method("+")
    def method_plus(self, space, w_obj):
        if space.is_kind_of(w_obj, space.w_string):
            w_other = w_obj
        else:
            w_other = space.convert_type(w_obj, space.w_string, "to_str")
        assert isinstance(w_other, W_StringObject)
        total_size = self.length() + w_other.length()
        s = space.newstr_fromchars(newlist_hint(total_size))
        s.extend(space, self)
        s.extend(space, w_other)
        return s

    @classdef.method("*", times="int")
    def method_times(self, space, times):
        if times < 0:
            raise space.error(space.w_ArgumentError, "negative argument")
        return self.strategy.mul(space, self.str_storage, times)

    @classdef.method("<<")
    @classdef.method("concat")
    @check_frozen()
    def method_lshift(self, space, w_other):
        assert isinstance(w_other, W_StringObject)
        self.extend(space, w_other)
        return self

    @classdef.method("size")
    @classdef.method("length")
    def method_length(self, space):
        return space.newint(self.length())

    @classdef.method("hash")
    def method_hash(self, space):
        return space.newint(self.strategy.hash(self.str_storage))

    @classdef.method("[]")
    @classdef.method("slice")
    def method_subscript(self, space, w_idx, w_count=None):
        start, end, as_range, nil = space.subscript_access(self.length(),
                                                           w_idx,
                                                           w_count=w_count)
        if nil:
            return space.w_nil
        elif as_range:
            assert start >= 0
            assert end >= 0
            return self.strategy.getslice(space, self.str_storage, start, end)
        else:
            return space.newstr_fromstr(
                self.strategy.getitem(self.str_storage, start))

    @classdef.method("<=>")
    def method_comparator(self, space, w_other):
        if isinstance(w_other, W_StringObject):
            s1 = space.str_w(self)
            s2 = space.str_w(w_other)
            if s1 < s2:
                return space.newint(-1)
            elif s1 == s2:
                return space.newint(0)
            elif s1 > s2:
                return space.newint(1)
        else:
            if space.respond_to(w_other, "to_str") and space.respond_to(
                    w_other, "<=>"):
                tmp = space.send(w_other, "<=>", [self])
                if tmp is not space.w_nil:
                    return space.newint(-space.int_w(tmp))
            return space.w_nil

    @classdef.method("to_sym")
    @classdef.method("intern")
    def method_to_sym(self, space):
        return space.newsymbol(space.str_w(self))

    @classdef.method("clear")
    @check_frozen()
    def method_clear(self, space):
        self.clear(space)
        return self

    @classdef.method("ljust", integer="int", padstr="str")
    def method_ljust(self, space, integer, padstr=" "):
        if not padstr:
            raise space.error(space.w_ArgumentError, "zero width padding")
        elif integer <= self.length():
            return self.copy(space)
        else:
            pad_len = integer - self.length() - 1
            assert pad_len >= 0
            chars = []
            chars += space.str_w(self)
            for i in xrange(pad_len / len(padstr)):
                chars += padstr
            chars += padstr[:pad_len % len(padstr) + 1]
            return space.newstr_fromchars(chars)

    def search_context(self, space, ctx):
        try:
            return rsre_core.search_context(ctx)
        except rsre_core.Error, e:
            raise space.error(space.w_RuntimeError, e.msg)
Ejemplo n.º 22
0
class W_NotImplementedError(W_ScriptError):
    classdef = ClassDef("NotImplementedError",
                        W_ScriptError.classdef,
                        filepath=__file__)
    method_allocate = new_exception_allocate(classdef)
Ejemplo n.º 23
0
class W_NumericObject(W_Object):
    classdef = ClassDef("Numeric", W_Object.classdef)
    classdef.include_module(Comparable)

    @staticmethod
    def retry_binop_coercing(space, w_recv, w_arg, binop, raise_error=True):
        w_ary = None
        try:
            w_ary = space.send(w_recv, "coerce", [w_arg])
        except RubyError as e:
            if not space.is_kind_of(e.w_value, space.w_StandardError):
                raise
            if raise_error:
                raise space.error(
                    space.w_ArgumentError, "comparison of %s with %s failed" %
                    (space.obj_to_s(space.getclass(w_recv)),
                     space.obj_to_s(space.getclass(w_arg))))
        if space.getclass(w_ary) is space.w_array:
            ary = space.listview(w_ary)
            if len(ary) == 2:
                return space.send(ary[1], binop, ary[:1])
        elif raise_error:
            raise space.error(space.w_TypeError, "coerce must return [x, y]")
        else:
            return None

    @classdef.singleton_method("allocate")
    def method_allocate(self, space, args_w):
        return W_NumericObject(space, self)

    @classdef.method("<=>")
    def method_comparator(self, space, w_other):
        if self == w_other:
            return space.newint(0)
        else:
            return space.w_nil

    @classdef.method("<=")
    def method_lte(self, space, w_other):
        w_result = space.send(self, "<=>", [w_other])
        return space.newbool(not (
            w_result is space.w_nil or space.int_w(w_result) > 0))

    @classdef.method("coerce")
    def method_coerce(self, space, w_other):
        if space.getclass(w_other) is space.getclass(self):
            return space.newarray([w_other, self])
        else:
            return space.newarray([space.send(self, "Float", [w_other]), self])

    @classdef.method("ceil")
    def method_ceil(self, space):
        return space.newint(int(math.ceil(Coerce.float(space, self))))

    @classdef.method("floor")
    def method_floor(self, space):
        return space.newint(int(math.floor(Coerce.float(space, self))))

    @classdef.method("round")
    def method_round(self, space):
        return space.newint(int(round_away(Coerce.float(space, self))))
Ejemplo n.º 24
0
class W_FloatDomainError(W_RangeError):
    classdef = ClassDef("FloatDomainError",
                        W_RangeError.classdef,
                        filepath=__file__)
    method_allocate = new_exception_allocate(classdef)
Ejemplo n.º 25
0
class W_FiberObject(W_Object):
    """
    Fibers have a number of possible states:

    * Has not yet begun execution: self.sthread is None
    * Currently execution: self.sthread is not None and self is State.get_current()
    * Suspended execution: self.sthread is not None and self.parent_fiber is None
    * Suspended execution in the stack of fibers: self.sthread is not None and (self.parent_fiber is None or self is space.w_main_fiber)
    * Dead: self.sthread is not None and self.sthread.is_empty_handle(self.h)
    """
    classdef = ClassDef("Fiber", W_Object.classdef)

    def __init__(self, space, klass=None):
        W_Object.__init__(self, space, klass)
        self.w_block = None
        self.sthread = None
        self.parent_fiber = None

    def __deepcopy__(self, memo):
        obj = super(W_FiberObject, self).__deepcopy__(memo)
        obj.w_block = copy.deepcopy(self.w_block, memo)
        obj.sthread = copy.deepcopy(self.sthread, memo)
        obj.parent_fiber = copy.deepcopy(self.parent_fiber, memo)
        return obj

    @staticmethod
    def build_main_fiber(space, ec):
        w_fiber = W_FiberObject(space)
        w_fiber.sthread = W_FiberObject.get_sthread(space, ec)
        return w_fiber

    @staticmethod
    def get_sthread(space, ec):
        sthread = ec.fiber_thread
        if not sthread:
            sthread = ec.fiber_thread = SThread(space.config, ec)
        return sthread

    @classdef.singleton_method("allocate")
    def singleton_method_allocate(self, space):
        return W_FiberObject(space, self)

    @classdef.singleton_method("yield")
    def singleton_method_yield(self, space, args_w):
        current = space.fromcache(State).get_current(space)
        parent_fiber = current.parent_fiber
        if parent_fiber is None:
            raise space.error(space.w_FiberError,
                              "can't yield from root fiber")
        space.fromcache(State).current = parent_fiber

        topframeref = space.getexecutioncontext().topframeref
        current.bottomframe.backref = jit.vref_None
        if len(args_w) == 0:
            global_state.w_result = space.w_nil
        elif len(args_w) == 1:
            global_state.w_result = args_w[0]
        else:
            global_state.w_result = space.newarray(args_w)
        parent_fiber.h = space.getexecutioncontext().fiber_thread.switch(
            parent_fiber.h)
        assert space.fromcache(State).current is current
        current.bottomframe.backref = space.getexecutioncontext().topframeref
        space.getexecutioncontext().topframeref = topframeref

        return get_result()

    @classdef.method("initialize")
    @jit.unroll_safe
    def method_initialize(self, space, block):
        if block is None:
            raise space.error(space.w_ArgumentError)
        self.w_block = block
        self.bottomframe = space.create_frame(
            self.w_block.bytecode,
            w_self=self.w_block.w_self,
            lexical_scope=self.w_block.lexical_scope,
            block=self.w_block.block,
            parent_interp=self.w_block.parent_interp,
            regexp_match_cell=self.w_block.regexp_match_cell,
        )
        for idx, cell in enumerate(self.w_block.cells):
            self.bottomframe.cells[len(self.w_block.bytecode.cellvars) +
                                   idx] = cell

    @classdef.method("resume")
    def method_resume(self, space, args_w):
        if self.parent_fiber is not None:
            raise space.error(space.w_FiberError, "double resume")
        if self.sthread is not None and self.sthread.is_empty_handle(self.h):
            raise space.error(space.w_FiberError, "dead fiber called")

        self.parent_fiber = space.fromcache(State).get_current(space)
        try:
            global_state.space = space
            global_state.space.fromcache(State).current = self
            topframeref = space.getexecutioncontext().topframeref
            if self.sthread is None:
                self.bottomframe.handle_block_args(space,
                                                   self.w_block.bytecode,
                                                   args_w, self.w_block)
                sthread = self.get_sthread(space, space.getexecutioncontext())
                self.sthread = sthread
                self.h = sthread.new(new_stacklet_callback)
            else:
                if len(args_w) == 1:
                    global_state.w_result = args_w[0]
                else:
                    global_state.w_result = space.newarray(args_w)
                self.h = self.sthread.switch(self.h)
            assert space.fromcache(State).current is self.parent_fiber
            space.getexecutioncontext().topframeref = topframeref
            return get_result()
        finally:
            self.parent_fiber = None
Ejemplo n.º 26
0
class W_KeyError(W_IndexError):
    classdef = ClassDef("KeyError", W_IndexError.classdef, filepath=__file__)
    method_allocate = new_exception_allocate(classdef)
Ejemplo n.º 27
0
class W_ModuleObject(W_RootObject):
    _immutable_fields_ = [
        "version?", "included_modules?[*]", "klass?", "name?"
    ]

    classdef = ClassDef("Module", W_RootObject.classdef, filepath=__file__)

    def __init__(self, space, name):
        self.name = name
        self.klass = None
        self.version = VersionTag()
        self.methods_w = {}
        self.constants_w = {}
        self.class_variables = CellDict()
        self.instance_variables = CellDict()
        self.flags = CellDict()
        self.included_modules = []
        self.descendants = []

    def __deepcopy__(self, memo):
        obj = super(W_ModuleObject, self).__deepcopy__(memo)
        obj.name = self.name
        obj.klass = copy.deepcopy(self.klass, memo)
        obj.version = copy.deepcopy(self.version, memo)
        obj.methods_w = copy.deepcopy(self.methods_w, memo)
        obj.constants_w = copy.deepcopy(self.constants_w, memo)
        obj.class_variables = copy.deepcopy(self.class_variables, memo)
        obj.instance_variables = copy.deepcopy(self.instance_variables, memo)
        obj.included_modules = copy.deepcopy(self.included_modules, memo)
        obj.descendants = copy.deepcopy(self.descendants, memo)
        return obj

    def getclass(self, space):
        if self.klass is not None:
            return jit.promote(self).klass
        return W_RootObject.getclass(self, space)

    def getsingletonclass(self, space):
        if self.klass is None:
            self.klass = space.newclass("#<Class:%s>" % self.name,
                                        space.w_module,
                                        is_singleton=True)
        return self.klass

    def mutated(self):
        self.version = VersionTag()

    def define_method(self, space, name, method):
        self.mutated()
        self.methods_w[name] = method

    @jit.unroll_safe
    def find_method(self, space, name):
        method = self._find_method_pure(space, name, self.version)
        if method is None:
            for module in self.included_modules:
                method = module.find_method(space, name)
                if method is not None:
                    return method
        return method

    @jit.unroll_safe
    def find_method_super(self, space, name):
        for module in self.included_modules:
            method = module.find_method(space, name)
            if method is not None:
                return method
        return None

    @jit.elidable
    def _find_method_pure(self, space, method, version):
        return self.methods_w.get(method, None)

    def set_const(self, space, name, w_obj):
        self.mutated()
        self.constants_w[name] = w_obj

    def find_const(self, space, name):
        w_res = self.find_included_const(space, name)
        if w_res is None:
            return space.w_object.find_const(space, name)
        else:
            return w_res

    @jit.unroll_safe
    def find_included_const(self, space, name):
        w_res = self.find_local_const(space, name)
        if w_res is None:
            for w_mod in self.included_modules:
                w_res = w_mod.find_local_const(space, name)
                if w_res is not None:
                    break
        return w_res

    def find_local_const(self, space, name):
        return self._find_const_pure(name, self.version)

    @jit.elidable
    def _find_const_pure(self, name, version):
        return self.constants_w.get(name, None)

    @jit.unroll_safe
    def set_class_var(self, space, name, w_obj):
        ancestors = self.ancestors()
        for idx in xrange(len(ancestors) - 1, -1, -1):
            module = ancestors[idx]
            assert isinstance(module, W_ModuleObject)
            w_res = module.class_variables.get(space, name)
            if w_res is not None or module is self:
                module.class_variables.set(space, name, w_obj)
                if module is self:
                    for descendant in self.descendants:
                        descendant.remove_class_var(space, name)

    @jit.unroll_safe
    def find_class_var(self, space, name):
        w_res = self.class_variables.get(space, name)
        if w_res is None:
            ancestors = self.ancestors()
            for idx in xrange(1, len(ancestors)):
                module = ancestors[idx]
                assert isinstance(module, W_ModuleObject)
                w_res = module.class_variables.get(space, name)
                if w_res is not None:
                    break
        return w_res

    @jit.unroll_safe
    def remove_class_var(self, space, name):
        self.class_variables.delete(name)
        for descendant in self.descendants:
            descendant.remove_class_var(space, name)

    def set_instance_var(self, space, name, w_value):
        return self.instance_variables.set(space, name, w_value)

    def find_instance_var(self, space, name):
        return self.instance_variables.get(space, name) or space.w_nil

    def copy_instance_vars(self, space, w_other):
        assert isinstance(w_other, W_ModuleObject)
        for key in w_other.instance_variables:
            w_value = w_other.instance_variables.get(space, key)
            self.set_instance_var(space, key, w_value)

    def set_flag(self, space, name):
        self.flags.set(space, name, space.w_true)

    def unset_flag(self, space, name):
        self.flags.set(space, name, space.w_false)

    def copy_flags(self, space, w_other):
        assert isinstance(w_other, W_ModuleObject)
        for key in w_other.flags:
            w_value = w_other.flags.get(space, key)
            if w_value is space.w_true:
                self.set_flag(space, key)

    def ancestors(self, include_singleton=True, include_self=True):
        if include_self:
            return [self] + self.included_modules
        else:
            return self.included_modules[:]

    @jit.unroll_safe
    def is_ancestor_of(self, w_cls):
        if self is w_cls:
            return True
        for w_mod in w_cls.included_modules:
            if self is w_mod:
                return True
        if w_cls.superclass is not None:
            return self.is_ancestor_of(w_cls.superclass)
        return False

    def include_module(self, space, w_mod):
        assert isinstance(w_mod, W_ModuleObject)
        if w_mod not in self.ancestors():
            self.included_modules = [w_mod] + self.included_modules
            w_mod.included(space, self)

    def included(self, space, w_mod):
        self.descendants.append(w_mod)
        if space.respond_to(self, space.newsymbol("included")):
            space.send(self, space.newsymbol("included"), [w_mod])

    def extend_object(self, space, w_obj, w_mod):
        if w_mod not in self.ancestors():
            self.included_modules = [w_mod] + self.included_modules
            w_mod.extended(space, w_obj, self)

    def extended(self, space, w_obj, w_mod):
        self.descendants.append(w_mod)
        if space.respond_to(self, space.newsymbol("extended")):
            space.send(self, space.newsymbol("extended"), [w_obj])

    def set_visibility(self, space, names_w, visibility):
        names = [space.symbol_w(w_name) for w_name in names_w]
        if names:
            for name in names:
                self.set_method_visibility(space, name, visibility)
        else:
            self.set_default_visibility(space, visibility)

    def set_default_visibility(self, space, visibility):
        pass

    def set_method_visibility(self, space, name, visibility):
        pass

    @classdef.singleton_method("nesting")
    def singleton_method_nesting(self, space):
        frame = space.getexecutioncontext().gettoprubyframe()
        modules_w = []
        scope = frame.lexical_scope
        while scope is not None:
            modules_w.append(scope.w_mod)
            scope = scope.backscope
        return space.newarray(modules_w)

    @classdef.singleton_method("allocate")
    def method_allocate(self, space):
        return W_ModuleObject(space, None)

    @classdef.method("to_s")
    def method_to_s(self, space):
        name = self.name
        if name is None:
            return space.newstr_fromstr(space.any_to_s(self))
        return space.newstr_fromstr(name)

    @classdef.method("include")
    def method_include(self, space, w_mod):
        space.send(w_mod, space.newsymbol("append_features"), [self])

    @classdef.method("append_features")
    def method_append_features(self, space, w_mod):
        ancestors = self.ancestors()
        for idx in xrange(len(ancestors) - 1, -1, -1):
            w_mod.include_module(space, ancestors[idx])

    @classdef.method("define_method", name="symbol")
    def method_define_method(self, space, name, w_method=None, block=None):
        if w_method is not None:
            if space.is_kind_of(w_method, space.w_method):
                w_method = space.send(w_method, space.newsymbol("unbind"))

            if space.is_kind_of(w_method, space.w_unbound_method):
                self.define_method(space, name,
                                   DefineMethodMethod(name, w_method))
            elif space.is_kind_of(w_method, space.w_proc):
                self.define_method(
                    space, name, DefineMethodBlock(name, w_method.get_block()))
        elif block is not None:
            self.define_method(space, name, DefineMethodBlock(name, block))
        else:
            raise space.error(space.w_ArgumentError,
                              "tried to create Proc object without a block")

    @classdef.method("attr_accessor")
    def method_attr_accessor(self, space, args_w):
        self.method_attr_reader(space, args_w)
        self.method_attr_writer(space, args_w)

    @classdef.method("attr_reader")
    def method_attr_reader(self, space, args_w):
        for w_arg in args_w:
            varname = space.symbol_w(w_arg)
            self.define_method(space, varname, AttributeReader("@" + varname))

    @classdef.method("attr_writer")
    def method_attr_writer(self, space, args_w):
        for w_arg in args_w:
            varname = space.symbol_w(w_arg)
            self.define_method(space, varname + "=",
                               AttributeWriter("@" + varname))

    @classdef.method("attr")
    def method_attr(self, space, args_w):
        if len(args_w) == 2 and (args_w[1] is space.w_true
                                 or args_w[1] is space.w_false):
            [w_name, w_writable] = args_w
            if space.is_true(w_writable):
                self.method_attr_accessor(space, [w_name])
            else:
                self.method_attr_reader(space, [w_name])
        else:
            self.method_attr_reader(space, args_w)

    @classdef.method("module_function")
    def method_module_function(self, space, args_w):
        for w_arg in args_w:
            name = space.symbol_w(w_arg)
            self.attach_method(
                space, name, self._find_method_pure(space, name, self.version))

    @classdef.method("private_class_method")
    def method_private_class_method(self, space, w_name):
        w_cls = self.getsingletonclass(space)
        return space.send(w_cls, space.newsymbol("private"), [w_name])

    @classdef.method("public_class_method")
    def method_public_class_method(self, space, w_name):
        w_cls = self.getsingletonclass(space)
        return space.send(w_cls, space.newsymbol("public"), [w_name])

    @classdef.method("alias_method", new_name="symbol", old_name="symbol")
    def method_alias_method(self, space, new_name, old_name):
        self.define_method(space, new_name, self.find_method(space, old_name))

    @classdef.method("ancestors")
    def method_ancestors(self, space):
        return space.newarray(self.ancestors(include_singleton=False))

    @classdef.method("included")
    def method_included(self, space, w_mod):
        # TODO: should be private
        pass

    @classdef.method("extended")
    def method_extended(self, space, w_mod):
        # TODO: should be private
        pass

    @classdef.method("name")
    def method_name(self, space):
        if self.name is None:
            return space.w_nil
        return space.newstr_fromstr(self.name)

    @classdef.method("private")
    def method_private(self, space, args_w):
        self.set_visibility(space, args_w, "private")

    @classdef.method("public")
    def method_public(self, space, args_w):
        self.set_visibility(space, args_w, "public")

    @classdef.method("protected")
    def method_protected(self, space, args_w):
        self.set_visibility(space, args_w, "protected")

    @classdef.method("private_constant")
    def method_private_constant(self, space, args_w):
        pass

    @classdef.method("constants")
    def method_constants(self, space):
        return space.newarray([space.newsymbol(n) for n in self.constants_w])

    @classdef.method("const_missing", name="symbol")
    def method_const_missing(self, space, name):
        raise space.error(space.w_NameError,
                          "uninitialized constant %s" % name)

    @classdef.method("class_eval", string="str", filename="str")
    @classdef.method("module_eval", string="str", filename="str")
    def method_module_eval(self,
                           space,
                           string=None,
                           filename=None,
                           w_lineno=None,
                           block=None):
        if string is not None:
            if filename is None:
                filename = "module_eval"
            if w_lineno is not None:
                lineno = space.int_w(w_lineno)
            else:
                lineno = 1
            return space.execute(string,
                                 self,
                                 lexical_scope=StaticScope(self, None),
                                 filepath=filename,
                                 initial_lineno=lineno)
        elif block is None:
            raise space.error(space.w_ArgumentError, "block not supplied")
        else:
            space.invoke_block(
                block.copy(w_self=self,
                           lexical_scope=StaticScope(self,
                                                     block.lexical_scope)), [])

    @classdef.method("const_defined?", const="str", inherit="bool")
    def method_const_definedp(self, space, const, inherit=True):
        if inherit:
            return space.newbool(self.find_const(space, const) is not None)
        else:
            return space.newbool(
                self.find_local_const(space, const) is not None)

    @classdef.method("const_get", const="symbol", inherit="bool")
    def method_const_get(self, space, const, inherit=True):
        if inherit:
            w_res = self.find_const(space, const)
        else:
            w_res = self.find_local_const(space, const)
        if w_res is None:
            name = space.obj_to_s(self)
            raise space.error(space.w_NameError,
                              "uninitialized constant %s::%s" % (name, const))
        return w_res

    @classdef.method("const_set", const="symbol")
    def method_const_set(self, space, const, w_value):
        space.set_const(self, const, w_value)
        return w_value

    @classdef.method("class_variable_defined?", name="symbol")
    def method_class_variable_definedp(self, space, name):
        return space.newbool(self.find_class_var(space, name) is not None)

    @classdef.method("remove_class_variable", name="symbol")
    def method_remove_class_variable(self, space, name):
        w_value = self.class_variables.get(space, name)
        if w_value is not None:
            self.class_variables.delete(name)
            return w_value
        if self.find_class_var(space, name) is not None:
            raise space.error(
                space.w_NameError,
                "cannot remove %s for %s" % (name, space.obj_to_s(self)))
        raise space.error(
            space.w_NameError, "class variable %s not defined for %s" %
            (name, space.obj_to_s(self)))

    @classdef.method("method_defined?", name="str")
    def method_method_definedp(self, space, name):
        return space.newbool(self.find_method(space, name) is not None)

    @classdef.method("===")
    def method_eqeqeq(self, space, w_obj):
        return space.newbool(self.is_ancestor_of(space.getclass(w_obj)))

    @classdef.method("instance_method", name="symbol")
    def method_instance_method(self, space, name):
        return space.newmethod(name, self)

    @classdef.method("undef_method", name="symbol")
    def method_undef_method(self, space, name):
        w_method = self.find_method(space, name)
        if w_method is None or isinstance(w_method, UndefMethod):
            cls_name = space.obj_to_s(self)
            raise space.error(
                space.w_NameError,
                "undefined method `%s' for class `%s'" % (name, cls_name))
        self.define_method(space, name, UndefMethod(name))
        return self

    @classdef.method("remove_method", name="symbol")
    def method_remove_method(self, space, name):
        w_method = self._find_method_pure(space, name, self.version)
        if w_method is None or isinstance(w_method, UndefMethod):
            cls_name = space.obj_to_s(self)
            raise space.error(
                space.w_NameError,
                "method `%s' not defined in %s" % (name, cls_name))
        self.define_method(space, name, UndefMethod(name))
        return self
Ejemplo n.º 28
0
class W_StopIteration(W_IndexError):
    classdef = ClassDef("StopIteration",
                        W_IndexError.classdef,
                        filepath=__file__)
    method_allocate = new_exception_allocate(classdef)
Ejemplo n.º 29
0
class W_ClassObject(W_ModuleObject):
    _immutable_fields_ = ["superclass?"]

    classdef = ClassDef("Class", W_ModuleObject.classdef)

    def __init__(self,
                 space,
                 name,
                 superclass,
                 is_singleton=False,
                 attached=None):
        W_ModuleObject.__init__(self, space, name)
        self.superclass = superclass
        self.is_singleton = is_singleton
        self.attached = attached

        if self.superclass is not None:
            self.superclass.inherited(space, self)
            # During bootstrap, we cannot create singleton classes, yet
            if not self.is_singleton and not space.bootstrap:
                self.getsingletonclass(space)

    def __deepcopy__(self, memo):
        obj = super(W_ClassObject, self).__deepcopy__(memo)
        obj.is_singleton = self.is_singleton
        obj.attached = copy.deepcopy(self.attached, memo)
        obj.superclass = copy.deepcopy(self.superclass, memo)
        return obj

    def getsingletonclass(self, space):
        if self.klass is None or not self.klass.is_singleton:
            if self.superclass is None:
                singleton_superclass = space.w_class
            else:
                singleton_superclass = self.superclass.getsingletonclass(space)
            if self.name is None:
                name = None
            else:
                name = "#<Class:%s>" % self.name
            self.klass = space.newclass(name,
                                        singleton_superclass,
                                        is_singleton=True,
                                        attached=self)
        return self.klass

    def find_const(self, space, name):
        w_res = W_ModuleObject.find_included_const(self, space, name)
        if w_res is None and self.superclass is not None:
            w_res = self.superclass.find_const(space, name)
        return w_res

    def inherited_constants(self, space):
        consts = {}
        for const in W_ModuleObject.local_constants(self, space):
            consts[const] = None
        w_cls = self.superclass
        while w_cls is not None:
            for const in w_cls.local_constants(space):
                consts[const] = None
            w_cls = w_cls.superclass

        return consts.keys()

    def find_method(self, space, name):
        method = W_ModuleObject.find_method(self, space, name)
        if method is None and self.superclass is not None:
            method = self.superclass.find_method(space, name)
        return method

    def find_method_super(self, space, name):
        method = W_ModuleObject.find_method_super(self, space, name)
        if method is None and self.superclass is not None:
            method = self.superclass.find_method(space, name)
        return method

    def methods(self, space, inherit=True):
        methods = {}
        for name in W_ModuleObject.methods(self, space, inherit):
            methods[name] = None
        if inherit and self.superclass is not None:
            for name in self.superclass.methods(space, inherit):
                method = self._find_method_pure(space, name, self.version)
                if method is None or not isinstance(method, UndefMethod):
                    methods[name] = None
        return methods.keys()

    def ancestors(self, include_singleton=True, include_self=True):
        assert include_self
        ary = W_ModuleObject.ancestors(
            self, include_singleton,
            not (self.is_singleton and not include_singleton))
        if self.superclass is not None:
            ary += self.superclass.ancestors(include_singleton)
        return ary

    def inherited(self, space, w_mod):
        self.descendants.append(w_mod)
        if not space.bootstrap and space.respond_to(self, "inherited"):
            space.send(self, "inherited", [w_mod])

    def method_removed(self, space, w_name):
        if self.is_singleton:
            space.send(self.attached, "singleton_method_removed", [w_name])
        else:
            W_ModuleObject.method_removed(self, space, w_name)

    def method_added(self, space, w_name):
        if self.is_singleton:
            space.send(self.attached, "singleton_method_added", [w_name])
        else:
            W_ModuleObject.method_added(self, space, w_name)

    def method_undefined(self, space, w_name):
        if self.is_singleton:
            space.send(self.attached, "singleton_method_undefined", [w_name])
        else:
            W_ModuleObject.method_undefined(self, space, w_name)

    @classdef.singleton_method("allocate")
    def singleton_method_allocate(self, space, args_w):
        return space.newclass(None, None)

    @classdef.method("new")
    def method_new(self, space, args_w, block):
        w_obj = space.send(self, "allocate", args_w, block)
        space.send(w_obj, "initialize", args_w, block)
        return w_obj

    @classdef.method("allocate")
    def method_allocate(self, space, args_w):
        return W_Object(space, self)

    @classdef.method("initialize")
    def method_initialize(self, space, w_superclass=None, block=None):
        if self.superclass is not None or self is space.w_basicobject:
            raise space.error(space.w_TypeError, "already initialized class")
        if w_superclass is not None:
            if not isinstance(w_superclass, W_ClassObject):
                raise space.error(
                    space.w_TypeError,
                    "superclass must be a Class (%s given)" %
                    space.obj_to_s(space.getclass(w_superclass)))
            if w_superclass.is_singleton:
                raise space.error(space.w_TypeError,
                                  "can't make subclass of singleton class")
        else:
            w_superclass = space.w_object
        self.superclass = w_superclass
        self.superclass.inherited(space, self)
        self.getsingletonclass(space)
        space.send_super(space.getclassfor(W_ClassObject),
                         self,
                         "initialize", [],
                         block=block)

    @classdef.method("initialize_copy")
    def method_initialize_copy(self, space, w_other):
        if self.superclass is not None or self is space.w_basicobject:
            raise space.error(space.w_TypeError, "already initialized class")
        return space.send_super(space.getclassfor(W_ClassObject), self,
                                "initialize_copy", [w_other])

    @classdef.method("superclass")
    def method_superclass(self, space):
        if self.superclass is not None:
            return self.superclass
        if self is space.w_basicobject:
            return space.w_nil
        raise space.error(space.w_TypeError, "uninitialized class")

    @classdef.method("class_variables")
    def method_class_variables(self, space):
        return space.newarray(
            [space.newsymbol(cvar) for cvar in self.class_variables])

    @classdef.method("instance_variables")
    def method_instance_variables(self, space):
        return space.newarray(
            [space.newsymbol(ivar) for ivar in self.instance_variables])
Ejemplo n.º 30
0
class W_EncodingObject(W_Object):
    classdef = ClassDef("Encoding", W_Object.classdef)