class DataConverter(object):
    # A rather abstract base class

    moduledef = ModuleDef('FFI::DataConverter')

    @moduledef.method('native_type')
    def native_type(self, space, args_w):
        # if len(args_w) == 0:
        #    raise space.error(space.w_NotImplementedError,
        #                      "native_type method not overridden and no "
        #                      "native_type set")
        if len(args_w) == 0:
            w_void = space.execute("FFI::Type::VOID")
            space.set_instance_var(self, '@native_type', w_void)
            return w_void
        elif len(args_w) == 1:
            w_arg_as_type = type_object(space, args_w[0])
            space.set_instance_var(self, '@native_type', w_arg_as_type)
            return w_arg_as_type
        raise space.error(space.w_ArgumentError, "incorrect arguments")

    @moduledef.method('to_native')
    def to_native(self, space, w_value, w_ctx):
        return w_value

    @moduledef.method('from_native')
    def from_native(self, space, w_value, w_ctx):
        return w_value
Exemple #2
0
class ObjectSpace(object):
    moduledef = ModuleDef("ObjectSpace", filepath=__file__)

    @moduledef.function("each_object")
    def method_each_object(self, space, w_mod, block):
        if block is None:
            return space.send(self, space.newsymbol("enum_for"),
                              [space.newsymbol("each_object"), w_mod], block)
        match_w = []
        roots = [gcref for gcref in rgc.get_rpy_roots() if gcref]
        pending = roots[:]
        while pending:
            gcref = pending.pop()
            if not rgc.get_gcflag_extra(gcref):
                rgc.toggle_gcflag_extra(gcref)
                w_obj = try_cast_gcref_to_w_baseobject(gcref)
                if w_obj is not None and space.is_kind_of(w_obj, w_mod):
                    match_w.append(w_obj)
                pending.extend(rgc.get_rpy_referents(gcref))
        clear_gcflag_extra(roots)
        for w_obj in match_w:
            space.invoke_block(block, [w_obj])
        return space.newint(len(match_w))

    @moduledef.function("garbage_collect")
    @jit.dont_look_inside
    def method_garbage_collect(self):
        rgc.collect()
Exemple #3
0
class Fcntl(object):
    moduledef = ModuleDef("Fcntl")

    @moduledef.setup_module
    def setup_module(space, w_mod):
        if not IS_WINDOWS:
            for key, value in fcntl_constants.items():
                space.set_const(w_mod, const, space.newint(value))
Exemple #4
0
class Signal(object):
    moduledef = ModuleDef("Signal")

    @moduledef.function("trap")
    def method_trap(self, args_w):
        pass

    @moduledef.function("list")
    def method_list(self, space):
        w_res = space.newhash()
        for sig_name, sig_num in SIGNALS.iteritems():
            space.send(w_res, "[]=", [space.newstr_fromstr(sig_name), space.newint(sig_num)])
        return w_res
Exemple #5
0
class Topaz(object):
    moduledef = ModuleDef("Topaz")

    @moduledef.setup_module
    def setup_module(space, w_mod):
        space.set_const(w_mod, "FIXNUM_MAX", space.newint(sys.maxint))

    @moduledef.function("intmask")
    def method_intmask(self, space, w_int):
        if space.is_kind_of(w_int, space.w_fixnum):
            return w_int
        elif space.is_kind_of(w_int, space.w_bignum):
            bigint = space.bigint_w(w_int)
            return space.newint(intmask(bigint.uintmask()))

    @moduledef.function("convert_type", method="symbol")
    def method_convert_type(self, space, w_obj, w_type, method):
        if not isinstance(w_type, W_ClassObject):
            raise space.error(space.w_TypeError,
                              "type argument must be a class")
        return space.convert_type(w_obj, w_type, method)

    @moduledef.function("try_convert_type", method="symbol")
    def method_try_convert_type(self, space, w_obj, w_type, method):
        if not isinstance(w_type, W_ClassObject):
            raise space.error(space.w_TypeError,
                              "type argument must be a class")
        return space.convert_type(w_obj, w_type, method, raise_error=False)

    @moduledef.function("compare")
    def method_compare(self, space, w_a, w_b, block=None):
        return space.compare(w_a, w_b, block)

    @moduledef.function("infect", taint="bool", untrust="bool", freeze="bool")
    def method_infect(self,
                      space,
                      w_dest,
                      w_src,
                      taint=True,
                      untrust=True,
                      freeze=False):
        space.infect(w_dest,
                     w_src,
                     taint=taint,
                     untrust=untrust,
                     freeze=freeze)
        return self
Exemple #6
0
class Process(object):
    moduledef = ModuleDef("Process")

    @moduledef.function("euid")
    def method_euid(self, space):
        return space.newint(geteuid())

    @moduledef.function("pid")
    def method_pid(self, space):
        return space.newint(os.getpid())

    @moduledef.function("waitpid", pid="int")
    def method_waitpid(self, space, pid=-1):
        try:
            pid, status = os.waitpid(pid, 0)
        except OSError as e:
            raise error_for_oserror(space, e)
        status = WEXITSTATUS(status)
        w_status = space.send(
            space.find_const(self, "Status"), "new",
            [space.newint(pid), space.newint(status)])
        space.globals.set(space, "$?", w_status)
        return space.newint(pid)

    @moduledef.function("exit", status="int")
    def method_exit(self, space, status=0):
        raise space.error(space.w_SystemExit, "exit", [space.newint(status)])

    @moduledef.function("exit!", status="int")
    def method_exit_bang(self, space, status=0):
        os._exit(status)

    @moduledef.function("fork")
    def method_fork(self, space, block):
        pid = fork()
        if pid == 0:
            if block is not None:
                space.invoke_block(block, [])
                space.send(self, "exit")
            else:
                return space.w_nil
        else:
            return space.newint(pid)
Exemple #7
0
class Topaz(object):
    moduledef = ModuleDef("Topaz", filepath=__file__)

    @moduledef.setup_module
    def setup_module(space, w_mod):
        space.set_const(w_mod, "FIXNUM_MAX", space.newint(sys.maxint))

    @moduledef.function("intmask")
    def method_intmask(self, space, w_int):
        if space.is_kind_of(w_int, space.w_fixnum):
            return w_int
        elif space.is_kind_of(w_int, space.w_bignum):
            bigint = space.bigint_w(w_int)
            return space.newint(intmask(bigint.uintmask()))

    @moduledef.function("convert_type", method="symbol")
    def method_convert_type(self, space, w_obj, w_type, method):
        if not isinstance(w_type, W_ClassObject):
            raise space.error(space.w_TypeError, "type argument must be a class")
        return space.convert_type(w_obj, w_type, method)

    @moduledef.function("compare")
    def method_compare(self, space, w_a, w_b, block=None):
        return space.compare(w_a, w_b, block)
Exemple #8
0
class Enumerable(object):
    moduledef = ModuleDef("Enumerable", filepath=__file__)
Exemple #9
0
class Topaz(object):
    moduledef = ModuleDef("Topaz")

    @moduledef.setup_module
    def setup_module(space, w_mod):
        space.set_const(w_mod, "FIXNUM_MAX", space.newint(sys.maxint))
        w_termioconsts = space.newmodule("TermIOConstants", None)
        space.set_const(w_mod, "TermIOConstants", w_termioconsts)
        for name, value in all_constants.iteritems():
            space.set_const(w_termioconsts, name, space.newint(value))

    @moduledef.function("intmask")
    def method_intmask(self, space, w_int):
        if space.is_kind_of(w_int, space.w_fixnum):
            return w_int
        elif space.is_kind_of(w_int, space.w_bignum):
            bigint = space.bigint_w(w_int)
            return space.newint(intmask(bigint.uintmask()))

    @moduledef.function("convert_type", method="symbol")
    def method_convert_type(self, space, w_obj, w_type, method):
        if not isinstance(w_type, W_ClassObject):
            raise space.error(space.w_TypeError,
                              "type argument must be a class")
        return space.convert_type(w_obj, w_type, method)

    @moduledef.function("try_convert_type", method="symbol")
    def method_try_convert_type(self, space, w_obj, w_type, method):
        if not isinstance(w_type, W_ClassObject):
            raise space.error(space.w_TypeError,
                              "type argument must be a class")
        return space.convert_type(w_obj, w_type, method, raise_error=False)

    @moduledef.function("compare")
    def method_compare(self, space, w_a, w_b, block=None):
        return space.compare(w_a, w_b, block)

    @moduledef.function("infect", taint="bool", untrust="bool", freeze="bool")
    def method_infect(self,
                      space,
                      w_dest,
                      w_src,
                      taint=True,
                      untrust=True,
                      freeze=False):
        space.infect(w_dest,
                     w_src,
                     taint=taint,
                     untrust=untrust,
                     freeze=freeze)
        return self

    @moduledef.function("tcsetattr", fd="int", when="int", mode_w="array")
    def method_tcsetattr(self, space, fd, when, mode_w):
        cc = [space.str_w(w_char) for w_char in space.listview(mode_w[6])]
        mode = (
            space.int_w(mode_w[0]),  # iflag
            space.int_w(mode_w[1]),  # oflag
            space.int_w(mode_w[2]),  # cflag
            space.int_w(mode_w[3]),  # lflag
            space.int_w(mode_w[4]),  # ispeed
            space.int_w(mode_w[5]),  # ospeed
            cc)
        try:
            tcsetattr(fd, when, mode)
        except OSError as e:
            raise error_for_oserror(space, e)
        return self

    @moduledef.function("tcgetattr", fd="int")
    def method_tcsetattr(self, space, fd):
        try:
            mode = tcgetattr(fd)
        except OSError as e:
            raise error_for_oserror(space, e)
        mode_w = [
            space.newint(mode[0]),  # iflag
            space.newint(mode[1]),  # oflag
            space.newint(mode[2]),  # cflag
            space.newint(mode[3]),  # lflag
            space.newint(mode[4]),  # ispeed
            space.newint(mode[5]),  # ospeed
            space.newarray([space.newstr_fromstr(cc) for cc in mode[6]])
        ]
        return space.newarray(mode_w)
Exemple #10
0
class Process(object):
    moduledef = ModuleDef("Process")

    @moduledef.setup_module
    def setup_module(space, w_mod):
        if rtime.HAS_CLOCK_GETTIME:
            for name in rtime.ALL_DEFINED_CLOCKS:
                space.set_const(w_mod, name, space.newint(getattr(rtime,
                                                                  name)))
        else:
            space.set_const(w_mod, "CLOCK_PROCESS_CPUTIME_ID",
                            CLOCK_PROCESS_CPUTIME_ID)

    @moduledef.function("euid")
    def method_euid(self, space):
        return space.newint(intmask(geteuid()))

    @moduledef.function("pid")
    def method_pid(self, space):
        return space.newint(os.getpid())

    @moduledef.function("waitpid", pid="int")
    def method_waitpid(self, space, pid=-1):
        try:
            pid, status = os.waitpid(pid, 0)
        except OSError as e:
            raise error_for_oserror(space, e)
        status = WEXITSTATUS(status)
        w_status = space.send(
            space.find_const(self, "Status"), "new",
            [space.newint(pid), space.newint(status)])
        space.globals.set(space, "$?", w_status)
        return space.newint(pid)

    @moduledef.function("exit", status="int")
    def method_exit(self, space, status=0):
        raise space.error(space.w_SystemExit, "exit", [space.newint(status)])

    @moduledef.function("exit!", status="int")
    def method_exit_bang(self, space, status=0):
        os._exit(status)

    @moduledef.function("fork")
    def method_fork(self, space, block):
        pid = fork()
        if pid == 0:
            if block is not None:
                space.invoke_block(block, [])
                space.send(self, "exit")
            else:
                return space.w_nil
        else:
            return space.newint(pid)

    @moduledef.function("times")
    def method_times(self, space):
        tms = space.find_const(space.find_const(space.w_object, "Struct"),
                               "Tms")
        return space.send(tms, "new",
                          [space.newfloat(t) for t in list(os.times()[0:4])])

    @moduledef.function("kill")
    def method_kill(self, space, w_signal, args_w):
        if not args_w:
            raise space.error(
                space.w_ArgumentError,
                "wrong number of arguments (%d for at least 2)" %
                (len(args_w) + 1))
        if space.is_kind_of(w_signal, space.w_fixnum):
            sig = space.int_w(w_signal)
        else:
            s = Coerce.str(space, w_signal)
            if s.startswith("SIG"):
                s = s[len("SIG"):]
            try:
                sig = SIGNALS[s]
            except KeyError:
                raise space.error(space.w_ArgumentError,
                                  "unsupported name `SIG%s'" % s)

        if sig < 0:
            for w_arg in args_w:
                pid = Coerce.int(space, w_arg)
                try:
                    killpg(pid, -sig)
                except OSError as e:
                    raise error_for_oserror(space, e)
        else:
            for w_arg in args_w:
                pid = Coerce.int(space, w_arg)
                try:
                    kill(pid, sig)
                except OSError as e:
                    raise error_for_oserror(space, e)
        return space.newint(len(args_w))

    @moduledef.function("clock_gettime", clockid="int")
    def method_clock_gettime(self, space, clockid, args_w):
        if len(args_w) > 1:
            raise space.error(
                space.w_ArgumentError,
                "wrong number of arguments (given %d, expected 1..2)")
        if len(args_w) == 1:
            unit = Coerce.symbol(space, args_w[0])
        else:
            unit = "float_second"
        if rtime.HAS_CLOCK_GETTIME:
            with lltype.scoped_alloc(rtime.TIMESPEC) as a:
                if rtime.c_clock_gettime(clockid, a) == 0:
                    sec = rffi.getintfield(a, 'c_tv_sec')
                    nsec = rffi.getintfield(a, 'c_tv_nsec')
                else:
                    raise error_for_oserror(
                        space, OSError(errno.EINVAL, "clock_gettime"))
        elif clockid == CLOCK_PROCESS_CPUTIME_ID:
            r = rtime.clock()
            sec = int(r)
            nsec = r * 1000000000
        else:
            raise error_for_oserror(space,
                                    OSError(errno.EINVAL, "clock_gettime"))
        if unit == "float_second":
            return space.newfloat(sec + nsec * 0.000000001)
        elif unit == "float_millisecond":
            return space.newfloat(sec * 1000 + nsec * 0.000001)
        elif unit == "float_microsecond":
            return space.newfloat(sec * 1000000 + nsec * 0.001)
        elif unit == "second":
            return space.newint(int(sec))
        elif unit == "millisecond":
            return space.newint(int(sec) * 1000)
        elif unit == "microsecond":
            return space.newint(sec * 1000000)
        elif unit == "nanosecond":
            return space.newint(sec * 1000000000 + nsec)
        else:
            raise space.error(space.w_ArgumentError,
                              "unexpected unit: %s" % unit)
Exemple #11
0
class Comparable(object):
    moduledef = ModuleDef("Comparable", filepath=__file__)
Exemple #12
0
class FFI(object):
    moduledef = ModuleDef("FFI")

    @moduledef.setup_module
    def setup_module(space, w_mod):
        # setup modules from other files
        w_Type = space.getclassfor(W_TypeObject)
        space.set_const(w_mod, 'Type', w_Type)
        space.set_const(w_Type, 'Builtin', space.getclassfor(W_BuiltinType))
        space.set_const(w_mod, 'DynamicLibrary',
                        space.getclassfor(W_DynamicLibraryObject))
        space.set_const(w_mod, 'Function',
                        space.getclassfor(W_FFIFunctionObject))
        w_FunctionType = space.getclassfor(W_FunctionTypeObject)
        space.set_const(w_mod, 'FunctionType', w_FunctionType)
        space.set_const(w_mod, 'FunctionInfo', w_FunctionType)
        space.set_const(w_mod, 'CallbackInfo', w_FunctionType)
        space.set_const(w_mod, 'VariadicInvoker',
                        space.getclassfor(W_VariadicInvokerObject))
        space.set_const(w_mod, 'AbstractMemory',
                        space.getclassfor(W_AbstractMemoryObject))
        space.set_const(w_mod, 'Pointer', space.getclassfor(W_PointerObject))
        space.set_const(w_mod, 'MemoryPointer',
                        space.getclassfor(W_MemoryPointerObject))
        space.set_const(w_mod, 'DataConverter',
                        space.getmoduleobject(DataConverter.moduledef))

        w_native_type = space.newmodule('NativeType')
        # This assumes that FFI::Type and the type constants already exist
        for typename in type_names:
            try:
                w_ffi_type = space.find_const(w_Type, typename)
                # setup type constants
                space.set_const(w_mod, 'TYPE_' + typename, w_ffi_type)
                # setup NativeType
                space.set_const(w_native_type, typename, w_ffi_type)
            except RubyError:
                pass
        space.set_const(w_mod, 'NativeType', w_native_type)

        # setup Platform
        w_platform = space.newmodule('Platform')
        w_cpu = space.newstr_fromstr(platform.machine())
        space.set_const(w_platform, 'CPU', w_cpu)
        name_postfix = '_SIZE'
        for name_prefix in [
                'INT8', 'INT16', 'INT32', 'INT64', 'LONG', 'FLOAT', 'DOUBLE'
        ]:
            w_type = space.find_const(w_mod, 'Type')
            w_tp = space.find_const(w_type, name_prefix)
            space.set_const(w_platform, name_prefix + name_postfix,
                            space.send(w_tp, 'size'))
        space.set_const(w_platform, 'ADDRESS_SIZE',
                        space.newint(lltype_sizes[POINTER]))
        space.set_const(w_mod, 'Platform', w_platform)

        # setup StructLayout
        w_struct_layout = space.newclass('StructLayout', None)
        w_struct_layout_field = space.newclass('Field', None)
        space.set_const(w_struct_layout, 'Field', w_struct_layout_field)
        space.set_const(w_mod, 'StructLayout', w_struct_layout)

        # setup StructByReference
        w_struct_by_reference = space.newclass('StructByReference', None)
        space.set_const(w_mod, 'StructByReference', w_struct_by_reference)
class Comparable(object):
    moduledef = ModuleDef("Comparable")
Exemple #14
0
class Math(object):
    moduledef = ModuleDef("Math")

    @moduledef.setup_module
    def setup_module(space, w_mod):
        space.set_const(w_mod, "PI", space.newfloat(math.pi))
        space.set_const(w_mod, "E", space.newfloat(math.e))
        space.set_const(w_mod, "DomainError", space.getclassfor(W_DomainError))

    @moduledef.function("acos", value="strictfloat")
    def method_acos(self, space, value):
        return space.newfloat(math.acos(value))

    @moduledef.function("acosh", value="strictfloat")
    def method_acosh(self, space, value):
        try:
            res = math.acosh(value)
        except ValueError:
            raise space.error(space.getclassfor(W_DomainError),
                              'Numerical argument is out of domain - "acosh"')
        return space.newfloat(res)

    @moduledef.function("asin", value="strictfloat")
    def method_asin(self, space, value):
        return space.newfloat(math.asin(value))

    @moduledef.function("asinh", value="strictfloat")
    def method_asinh(self, space, value):
        return space.newfloat(math.asinh(value))

    @moduledef.function("atan", value="strictfloat")
    def method_atan(self, space, value):
        return space.newfloat(math.atan(value))

    @moduledef.function("atan2", value1="strictfloat", value2="strictfloat")
    def method_atan2(self, space, value1, value2):
        return space.newfloat(math.atan2(value1, value2))

    @moduledef.function("atanh", value="strictfloat")
    def method_atanh(self, space, value):
        try:
            res = math.atanh(value)
        except ValueError:
            if value == 1.0 or value == -1.0:
                # produce an infinity with the right sign
                res = rfloat.copysign(rfloat.INFINITY, value)
            else:
                raise space.error(
                    space.getclassfor(W_DomainError),
                    'Numerical argument is out of domain - "atanh"')
        return space.newfloat(res)

    @moduledef.function("cbrt", value="strictfloat")
    def method_cbrt(self, space, value):
        if value < 0:
            return space.newfloat(-math.pow(-value, 1.0 / 3.0))
        else:
            return space.newfloat(math.pow(value, 1.0 / 3.0))

    @moduledef.function("cos", value="strictfloat")
    def method_cos(self, space, value):
        return space.newfloat(math.cos(value))

    @moduledef.function("cosh", value="strictfloat")
    def method_cosh(self, space, value):
        try:
            res = math.cosh(value)
        except OverflowError:
            res = rfloat.copysign(rfloat.INFINITY, value)
        return space.newfloat(res)

    @moduledef.function("exp", value="strictfloat")
    def method_exp(self, space, value):
        return space.newfloat(math.exp(value))

    @moduledef.function("frexp", value="strictfloat")
    def method_frexp(self, space, value):
        mant, exp = math.frexp(value)
        w_mant = space.newfloat(mant)
        w_exp = space.newint(exp)
        return space.newarray([w_mant, w_exp])

    @moduledef.function("gamma", value="strictfloat")
    def method_gamma(self, space, value):
        try:
            res = rfloat.gamma(value)
        except ValueError:
            if value == 0.0:
                # produce an infinity with the right sign
                res = rfloat.copysign(rfloat.INFINITY, value)
            else:
                raise space.error(
                    space.getclassfor(W_DomainError),
                    'Numerical argument is out of domain - "gamma"')
        except OverflowError:
            res = rfloat.INFINITY
        return space.newfloat(res)

    @moduledef.function("lgamma", value="strictfloat")
    def method_lgamma(self, space, value):
        try:
            res = rfloat.lgamma(value)
        except (ValueError, OverflowError):
            res = rfloat.INFINITY
        gamma = (1 if value == -1 or math.isnan(value) else space.float_w(
            space.send(self, "gamma", [space.newfloat(value)])))
        sign = 1 if gamma > 0 else -1 if gamma < 0 else 0
        return space.newarray([space.newfloat(res), space.newint(sign)])

    @moduledef.function("hypot", value1="strictfloat", value2="strictfloat")
    def method_hypot(self, space, value1, value2):
        return space.newfloat(math.hypot(value1, value2))

    @moduledef.function("ldexp", value1="strictfloat", value2="int")
    def method_ldexp(self, space, value1, value2):
        return space.newfloat(math.ldexp(value1, value2))

    @moduledef.function("log", value="strictfloat", base="strictfloat")
    def method_log(self, space, value, base=math.e):
        try:
            res = 0.0
            if base == math.e:
                res = math.log(value)
            else:
                res = math.log(value) / math.log(base)
        except ValueError:
            if value == 0.0:
                res = float(-rfloat.INFINITY)
            else:
                raise space.error(
                    space.getclassfor(W_DomainError),
                    'Numerical argument is out of domain - "log"')

        return space.newfloat(res)

    @moduledef.function("log10", value="strictfloat")
    def method_log10(self, space, value):
        try:
            res = math.log10(value)
        except ValueError:
            if value == 0.0:
                res = float(-rfloat.INFINITY)
            else:
                raise space.error(
                    space.getclassfor(W_DomainError),
                    'Numerical argument is out of domain - "log10"')

        return space.newfloat(res)

    @moduledef.function("log2", value="strictfloat")
    def method_log2(self, space, value):
        try:
            res = math.log(value) / math.log(2)
        except ValueError:
            if value == 0.0:
                res = float(-rfloat.INFINITY)
            else:
                raise space.error(
                    space.getclassfor(W_DomainError),
                    'Numerical argument is out of domain - "log2"')

        return space.newfloat(res)

    @moduledef.function("sin", value="strictfloat")
    def method_sin(self, space, value):
        return space.newfloat(math.sin(value))

    @moduledef.function("sinh", value="strictfloat")
    def method_sinh(self, space, value):
        try:
            res = math.sinh(value)
        except OverflowError:
            res = rfloat.copysign(rfloat.INFINITY, value)
        return space.newfloat(res)

    @moduledef.function("sqrt", value="strictfloat")
    def method_sqrt(self, space, value):
        return space.newfloat(math.sqrt(value))

    @moduledef.function("tan", value="strictfloat")
    def method_tan(self, space, value):
        try:
            res = math.tan(value)
        except ValueError:
            res = rfloat.NAN
        return space.newfloat(res)

    @moduledef.function("tanh", value="strictfloat")
    def method_tanh(self, space, value):
        return space.newfloat(math.tanh(value))

    @moduledef.function("erf", value="strictfloat")
    def method_erf(self, space, value):
        return space.newfloat(rfloat.erf(value))

    @moduledef.function("erfc", value="strictfloat")
    def method_erfc(self, space, value):
        return space.newfloat(rfloat.erfc(value))
class Enumerable(object):
    moduledef = ModuleDef("Enumerable")
Exemple #16
0
class Kernel(object):
    moduledef = ModuleDef("Kernel")

    @moduledef.method("class")
    def function_class(self, space):
        return space.getnonsingletonclass(self)

    @moduledef.method("singleton_methods", all="bool")
    def method_singleton_methods(self, space, all=True):
        methods = []
        w_cls = space.getclass(self)
        if w_cls.is_singleton:
            methods.extend(w_cls.methods_w.keys())
            w_cls = w_cls.superclass
        if all:
            while w_cls and w_cls.is_singleton:
                methods.extend(w_cls.methods_w.keys())
                w_cls = w_cls.superclass
        return space.newarray([space.newsymbol(m) for m in methods])

    @moduledef.method("methods", inherit="bool")
    def method_methods(self, space, inherit=True):
        w_cls = space.getclass(self)
        return space.newarray([
            space.newsymbol(m) for m in w_cls.methods(space, inherit=inherit)
        ])

    @moduledef.method("private_methods", inherit="bool")
    def method_private_methods(self, space, inherit=True):
        w_cls = space.getclass(self)
        return space.newarray([
            space.newsymbol(m) for m in w_cls.methods(
                space, visibility=W_FunctionObject.PRIVATE, inherit=inherit)
        ])

    @moduledef.method("protected_methods", inherit="bool")
    def method_protected_methods(self, space, inherit=True):
        w_cls = space.getclass(self)
        return space.newarray([
            space.newsymbol(m) for m in w_cls.methods(
                space, visibility=W_FunctionObject.PROTECTED, inherit=inherit)
        ])

    @moduledef.method("public_methods", inherit="bool")
    def method_public_methods(self, space, inherit=True):
        w_cls = space.getclass(self)
        return space.newarray([
            space.newsymbol(m) for m in w_cls.methods(
                space, visibility=W_FunctionObject.PUBLIC, inherit=inherit)
        ])

    @moduledef.method("lambda")
    def function_lambda(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 lambda object without a block")
        else:
            return block.copy(space, is_lambda=True)

    @moduledef.method("proc")
    def function_proc(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)

    @staticmethod
    def find_feature(space, path):
        assert path is not None
        if os.path.isfile(path):
            return path
        if not path.endswith(".rb"):
            path += ".rb"

        if not (path.startswith("/") or path.startswith("./")
                or path.startswith("../")):
            w_load_path = space.globals.get(space, "$LOAD_PATH")
            for w_base in space.listview(w_load_path):
                base = Coerce.path(space, w_base)
                full = os.path.join(base, path)
                if os.path.isfile(full):
                    path = os.path.join(base, path)
                    break
        return path

    @staticmethod
    def load_feature(space, path, orig_path, wrap=False):
        if not os.path.exists(path):
            raise space.error(space.w_LoadError, orig_path)

        try:
            f = open_file_as_stream(path, buffering=0)
            try:
                contents = f.readall()
            finally:
                f.close()
        except OSError as e:
            raise error_for_oserror(space, e)

        if wrap:
            lexical_scope = StaticScope(space.newmodule("Anonymous"), None)
        else:
            lexical_scope = None
        space.execute(contents, filepath=path, lexical_scope=lexical_scope)

    @moduledef.function("require", path="path")
    def function_require(self, space, path):
        assert path is not None
        orig_path = path
        path = Kernel.find_feature(space, path)

        w_loaded_features = space.globals.get(space, '$"')
        w_already_loaded = space.send(w_loaded_features, "include?",
                                      [space.newstr_fromstr(path)])
        if space.is_true(w_already_loaded):
            return space.w_false

        Kernel.load_feature(space, path, orig_path)
        w_loaded_features.method_lshift(space, space.newstr_fromstr(path))
        return space.w_true

    @moduledef.function("load", path="path", wrap="bool")
    def function_load(self, space, path, wrap=False):
        assert path is not None
        orig_path = path
        path = Kernel.find_feature(space, path)
        Kernel.load_feature(space, path, orig_path, wrap=wrap)
        return space.w_true

    @moduledef.method("fail")
    @moduledef.method("raise")
    def method_raise(self,
                     space,
                     w_str_or_exception=None,
                     w_string=None,
                     w_array=None):
        w_exception = None
        if w_str_or_exception is None:
            w_exception = space.globals.get(space, "$!") or space.w_nil
            if w_exception is space.w_nil:
                w_exception = space.w_RuntimeError
        elif isinstance(w_str_or_exception, W_StringObject):
            w_exception = space.w_RuntimeError
            w_string = w_str_or_exception
        else:
            w_exception = w_str_or_exception

        if not space.respond_to(w_exception, "exception"):
            raise space.error(space.w_TypeError,
                              "exception class/object expected")

        if w_string is not None:
            w_exc = space.send(w_exception, "exception", [w_string])
        else:
            w_exc = space.send(w_exception, "exception")

        if w_array is not None:
            raise space.error(space.w_NotImplementedError,
                              "custom backtrace for Kernel#raise")

        if not isinstance(w_exc, W_ExceptionObject):
            raise space.error(space.w_TypeError, "exception object expected")

        raise RubyError(w_exc)

    @moduledef.function("exit")
    def method_exit(self, space, args_w):
        return space.send(space.getmoduleobject(Process.moduledef), "exit",
                          args_w)

    @moduledef.function("exit!")
    def method_exit_bang(self, space, args_w):
        return space.send(space.getmoduleobject(Process.moduledef), "exit!",
                          args_w)

    @moduledef.function("abort", msg="str")
    def method_abort(self, space, msg=None):
        if msg:
            os.write(2, msg)
        return space.send(self, "exit", [space.newint(1)])

    @moduledef.function("block_given?")
    @moduledef.function("iterator?")
    def method_block_givenp(self, space):
        return space.newbool(
            space.getexecutioncontext().gettoprubyframe().block is not None)

    @moduledef.function("binding")
    def method_binding(self, space):
        return space.newbinding_fromframe(
            space.getexecutioncontext().gettoprubyframe())

    @moduledef.function("__method__")
    @moduledef.function("__callee__")
    def method_callee(self, space):
        frame = space.getexecutioncontext().gettoprubyframe()
        return space.newsymbol(frame.bytecode.name)

    @moduledef.function("exec")
    def method_exec(self, space, args_w):
        if len(args_w) > 1 and space.respond_to(args_w[0], "to_hash"):
            raise space.error(space.w_NotImplementedError,
                              "exec with environment")

        if len(args_w) > 1 and space.respond_to(args_w[-1], "to_hash"):
            raise space.error(space.w_NotImplementedError, "exec with options")

        if space.respond_to(args_w[0], "to_ary"):
            w_cmd = space.convert_type(args_w[0], space.w_array, "to_ary")
            cmd_w = space.listview(w_cmd)
            if len(cmd_w) != 2:
                raise space.error(space.w_ArgumentError,
                                  "wrong first argument")
            cmd, argv0 = [
                space.str0_w(space.convert_type(w_e, space.w_string, "to_str"))
                for w_e in cmd_w
            ]
        else:
            w_cmd = space.convert_type(args_w[0], space.w_string, "to_str")
            cmd = space.str0_w(w_cmd)
            argv0 = None

        if len(args_w) > 1 or argv0 is not None:
            if argv0 is None:
                sepidx = cmd.rfind(os.sep) + 1
                if sepidx > 0:
                    argv0 = cmd[sepidx:]
                else:
                    argv0 = cmd
            args = [argv0]
            args += [
                space.str0_w(
                    space.convert_type(w_arg, space.w_string, "to_str"))
                for w_arg in args_w[1:]
            ]
            try:
                os.execv(cmd, args)
            except OSError as e:
                raise error_for_oserror(space, e)
        else:
            if not cmd:
                raise error_for_errno(space, errno.ENOENT)
            shell = os.environ.get("RUBYSHELL") or os.environ.get(
                "COMSPEC") or "/bin/sh"
            sepidx = shell.rfind(os.sep) + 1
            if sepidx > 0:
                argv0 = shell[sepidx:]
            else:
                argv0 = shell
            try:
                os.execv(shell, [argv0, "-c", cmd])
            except OSError as e:
                raise error_for_oserror(space, e)

    @moduledef.function("system")
    def method_system(self, space, args_w):
        raise space.error(space.w_NotImplementedError, "Kernel#system()")

    @moduledef.function("fork")
    def method_fork(self, space, block):
        return space.send(space.getmoduleobject(Process.moduledef),
                          "fork",
                          block=block)

    @moduledef.function("at_exit")
    def method_at_exit(self, space, block):
        space.register_exit_handler(block)
        return block

    @moduledef.function("=~")
    def method_match(self, space, w_other):
        return space.w_nil

    @moduledef.function("!~")
    def method_not_match(self, space, w_other):
        return space.newbool(
            not space.is_true(space.send(self, "=~", [w_other])))

    @moduledef.function("eql?")
    def method_eqlp(self, space, w_other):
        return space.newbool(self is w_other)

    @moduledef.function("instance_variable_defined?", name="symbol")
    def method_instance_variable_definedp(self, space, name):
        return space.newbool(self.find_instance_var(space, name) is not None)

    @moduledef.method("respond_to?", include_private="bool")
    def method_respond_top(self, space, w_name, include_private=False):
        if space.respond_to(self, space.symbol_w(w_name)):
            return space.newbool(True)

        w_found = space.send(self, "respond_to_missing?",
                             [w_name, space.newbool(include_private)])
        return space.newbool(space.is_true(w_found))

    @moduledef.method("respond_to_missing?")
    def method_respond_to_missingp(self, space, w_name, w_include_private):
        return space.newbool(False)

    @moduledef.method("dup")
    def method_dup(self, space):
        if (self is space.w_nil or self is space.w_true
                or self is space.w_false
                or space.is_kind_of(self, space.w_symbol)
                or space.is_kind_of(self, space.w_fixnum)):
            raise space.error(space.w_TypeError,
                              "can't dup %s" % space.getclass(self).name)
        w_dup = space.send(space.getnonsingletonclass(self), "allocate")
        w_dup.copy_instance_vars(space, self)
        space.infect(w_dup, self, freeze=False)
        space.send(w_dup, "initialize_dup", [self])
        return w_dup

    @moduledef.method("clone")
    def method_clone(self, space):
        if (self is space.w_nil or self is space.w_true
                or self is space.w_false
                or space.is_kind_of(self, space.w_symbol)
                or space.is_kind_of(self, space.w_fixnum)):
            raise space.error(space.w_TypeError,
                              "can't dup %s" % space.getclass(self).name)
        w_dup = space.send(space.getnonsingletonclass(self), "allocate")
        w_dup.copy_instance_vars(space, self)
        w_dup.copy_singletonclass(space, space.getsingletonclass(self))
        space.send(w_dup, "initialize_clone", [self])
        space.infect(w_dup, self, freeze=True)
        return w_dup

    @moduledef.method("sleep")
    def method_sleep(self, space, w_duration=None):
        if w_duration is None:
            raise space.error(space.w_NotImplementedError)
        elif space.is_kind_of(w_duration, space.w_string):
            raise space.error(space.w_TypeError,
                              "can't convert String into time interval")
        start = time.time()
        time.sleep(Coerce.float(space, w_duration))
        return space.newint(int(round_double(time.time() - start, 0)))

    @moduledef.method("initialize_clone")
    @moduledef.method("initialize_dup")
    def method_initialize_dup(self, space, w_other):
        space.send(self, "initialize_copy", [w_other])
        return self

    @moduledef.method("initialize_copy")
    def method_initialize_copy(self, space, w_other):
        return self

    @moduledef.function("Float")
    def method_Float(self, space, w_arg):
        if w_arg is space.w_nil:
            raise space.error(space.w_TypeError,
                              "can't convert nil into Float")
        elif space.is_kind_of(w_arg, space.w_float):
            return space.newfloat(space.float_w(w_arg))
        elif space.is_kind_of(w_arg, space.w_string):
            string = space.str_w(w_arg).strip(" ")
            try:
                return space.newfloat(float(string))
            except ValueError:
                raise space.error(space.w_ArgumentError,
                                  "invalid value for Float(): %s" % string)
        else:
            return space.convert_type(w_arg, space.w_float, "to_f")

    @moduledef.method("kind_of?")
    @moduledef.method("is_a?")
    def method_is_kind_ofp(self, space, w_mod):
        if not isinstance(w_mod, W_ModuleObject):
            raise space.error(space.w_TypeError, "class or module required")
        return space.newbool(self.is_kind_of(space, w_mod))

    @moduledef.method("instance_of?")
    def method_instance_of(self, space, w_mod):
        if not isinstance(w_mod, W_ModuleObject):
            raise space.error(space.w_TypeError, "class or module required")
        return space.newbool(space.getnonsingletonclass(self) is w_mod)

    @moduledef.method("eval")
    def method_eval(self, space, w_source, w_binding=None):
        if w_binding is None:
            frame = space.getexecutioncontext().gettoprubyframe()
            w_binding = space.newbinding_fromframe(frame)
        elif not isinstance(w_binding, W_BindingObject):
            raise space.error(
                space.w_TypeError,
                "wrong argument type %s (expected Binding)" %
                space.getclass(w_binding).name)
        return space.send(w_binding, "eval", [w_source])

    @moduledef.method("set_trace_func")
    def method_set_trace_func(self, space, w_proc):
        if w_proc is space.w_nil:
            w_proc = None
        else:
            assert isinstance(w_proc, W_ProcObject)
        space.getexecutioncontext().settraceproc(w_proc)

    def new_flag(moduledef, setter, getter, remover):
        @moduledef.method(setter)
        def setter_method(self, space):
            self.set_flag(space, getter)
            return self

        @moduledef.method(getter)
        def getter_method(self, space):
            return self.get_flag(space, getter)

        if remover is None:
            return (setter_method, getter_method)
        else:

            @moduledef.method(remover)
            def remover_method(self, space):
                self.unset_flag(space, getter)
                return self

            return (setter_method, getter_method, remover_method)

    method_untrust, method_untrusted, method_trust = new_flag(
        moduledef, "untrust", "untrusted?", "trust")
    method_taint, method_tainted, method_untaint = new_flag(
        moduledef, "taint", "tainted?", "untaint")
    method_freeze, method_frozen = new_flag(moduledef, "freeze", "frozen?",
                                            None)

    @moduledef.method("throw", name="symbol")
    def method_throw(self, space, name, w_value=None):
        from topaz.interpreter import Throw
        if not space.getexecutioncontext().is_in_catch_block_for_name(name):
            raise space.error(space.w_ArgumentError,
                              "uncaught throw :%s" % name)
        if w_value is None:
            w_value = space.w_nil
        raise Throw(name, w_value)

    @moduledef.method("catch", name="symbol")
    def method_catch(self, space, name, block):
        if block is None:
            raise space.error(space.w_LocalJumpError, "no block given")
        from topaz.interpreter import Throw
        with space.getexecutioncontext().catch_block(name):
            try:
                return space.invoke_block(block, [])
            except Throw as e:
                if e.name == name:
                    return e.w_value
                raise

    @moduledef.method("srand")
    def method_srand(self, space, w_seed=None):
        random_class = space.getclassfor(W_RandomObject)
        default = space.find_const(random_class, "DEFAULT")
        return default.srand(space, w_seed)

    @moduledef.method("autoload")
    def method_autoload(self, space, args_w):
        return space.send(space.getclass(self), "autoload", args_w)

    @moduledef.method("autoload?")
    def method_autoload(self, space, args_w):
        return space.send(space.getclass(self), "autoload?", args_w)

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

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

    @moduledef.method("extend")
    @check_frozen()
    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)
        space.send(w_mod, "extend_object", [self])
        space.send(w_mod, "extended", [self])

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

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

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

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

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

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

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

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

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

    @moduledef.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

    @moduledef.method("define_singleton_method", name="symbol")
    @check_frozen()
    def method_define_singleton_method(self,
                                       space,
                                       name,
                                       w_method=None,
                                       block=None):
        args_w = [space.newsymbol(name)]
        if w_method is not None:
            args_w.append(w_method)
        return space.send(space.getsingletonclass(self), "define_method",
                          args_w, block)
Exemple #17
0
class Process(object):
    moduledef = ModuleDef("Process")

    @moduledef.function("euid")
    def method_euid(self, space):
        return space.newint(geteuid())

    @moduledef.function("pid")
    def method_pid(self, space):
        return space.newint(os.getpid())

    @moduledef.function("waitpid", pid="int")
    def method_waitpid(self, space, pid=-1):
        try:
            pid, status = os.waitpid(pid, 0)
        except OSError as e:
            raise error_for_oserror(space, e)
        status = WEXITSTATUS(status)
        w_status = space.send(
            space.find_const(self, "Status"), "new",
            [space.newint(pid), space.newint(status)])
        space.globals.set(space, "$?", w_status)
        return space.newint(pid)

    @moduledef.function("exit", status="int")
    def method_exit(self, space, status=0):
        raise space.error(space.w_SystemExit, "exit", [space.newint(status)])

    @moduledef.function("exit!", status="int")
    def method_exit_bang(self, space, status=0):
        os._exit(status)

    @moduledef.function("fork")
    def method_fork(self, space, block):
        pid = fork()
        if pid == 0:
            if block is not None:
                space.invoke_block(block, [])
                space.send(self, "exit")
            else:
                return space.w_nil
        else:
            return space.newint(pid)

    @moduledef.function("times")
    def method_times(self, space):
        tms = space.find_const(space.find_const(space.w_object, "Struct"),
                               "Tms")
        return space.send(tms, "new",
                          [space.newfloat(t) for t in list(os.times()[0:4])])

    @moduledef.function("kill")
    def method_kill(self, space, w_signal, args_w):
        if not args_w:
            raise space.error(
                space.w_ArgumentError,
                "wrong number of arguments (%d for at least 2)" %
                (len(args_w) + 1))
        if space.is_kind_of(w_signal, space.w_fixnum):
            sig = space.int_w(w_signal)
        else:
            s = Coerce.str(space, w_signal)
            if s.startswith("SIG"):
                s = s[len("SIG"):]
            try:
                sig = SIGNALS[s]
            except KeyError:
                raise space.error(space.w_ArgumentError,
                                  "unsupported name `SIG%s'" % s)

        if sig < 0:
            for w_arg in args_w:
                pid = Coerce.int(space, w_arg)
                try:
                    killpg(pid, -sig)
                except OSError as e:
                    raise error_for_oserror(space, e)
        else:
            for w_arg in args_w:
                pid = Coerce.int(space, w_arg)
                try:
                    kill(pid, sig)
                except OSError as e:
                    raise error_for_oserror(space, e)
        return space.newint(len(args_w))
Exemple #18
0
class Marshal(object):
    moduledef = ModuleDef("Marshal")

    MAJOR_VERSION = 4
    MINOR_VERSION = 8

    NIL = 0x30
    TRUE = 0x54
    FALSE = 0x46
    FIXNUM = 0x69
    ARRAY = 0x5b
    SYMBOL = 0x3a
    IVAR = 0x49
    STRING = 0x22
    HASH = 0x7b
    FLOAT = 0x66

    @moduledef.setup_module
    def setup_module(space, w_mod):
        space.set_const(w_mod, "MAJOR_VERSION",
                        space.newint(Marshal.MAJOR_VERSION))
        space.set_const(w_mod, "MINOR_VERSION",
                        space.newint(Marshal.MINOR_VERSION))

    @staticmethod
    def dump(space, w_obj):
        bytes = []
        if isinstance(w_obj, W_NilObject):
            bytes.append(Marshal.NIL)
        elif isinstance(w_obj, W_TrueObject):
            bytes.append(Marshal.TRUE)
        elif isinstance(w_obj, W_FalseObject):
            bytes.append(Marshal.FALSE)
        elif isinstance(w_obj, W_FixnumObject):
            bytes.append(Marshal.FIXNUM)
            bytes += Marshal.integer2bytes(space.int_w(w_obj))
        elif isinstance(w_obj, W_FloatObject):
            bytes.append(Marshal.FLOAT)
            raw_value = space.float_w(w_obj)
            int_value = int(raw_value)
            float_value = raw_value
            string = ""  # None

            if raw_value == int_value:
                float_value = int_value
                # repr would be more accurate here, but it weirdly does not translate
                if str(raw_value) == "-0.0":  # slowing things down
                    string = "-0"
                else:
                    string = str(float_value)
            else:  # encode float
                string = str(float_value)

            length = len(string)
            bytes += Marshal.integer2bytes(length)
            for c in string:
                bytes.append(ord(c))
        elif isinstance(w_obj, W_ArrayObject):
            array = space.listview(w_obj)
            bytes.append(Marshal.ARRAY)
            bytes += Marshal.integer2bytes(len(array))
            for item in array:
                bytes += Marshal.dump(space, item)
        elif isinstance(w_obj, W_SymbolObject):
            bytes.append(Marshal.SYMBOL)
            symbol = space.symbol_w(w_obj)
            bytes += Marshal.integer2bytes(len(symbol))
            for char in symbol:
                bytes.append(ord(char))
        elif isinstance(w_obj, W_StringObject):
            string = space.str_w(w_obj)
            bytes.append(Marshal.IVAR)
            bytes.append(Marshal.STRING)
            bytes += Marshal.integer2bytes(len(string))
            for char in string:
                bytes.append(ord(char))
            bytes.append(0x06)
            # TODO: respect encoding
            bytes += Marshal.dump(space, space.newsymbol("E"))
            bytes += Marshal.dump(space, space.w_true)
        elif isinstance(w_obj, W_HashObject):
            bytes.append(Marshal.HASH)
            hash_len = w_obj.strategy.len(w_obj.dict_storage)
            hash_keys_w = w_obj.strategy.keys(w_obj.dict_storage)
            bytes += Marshal.integer2bytes(hash_len)
            for w_key in hash_keys_w:
                bytes += Marshal.dump(space, w_key)
                w_value = w_obj.strategy.getitem(w_obj.dict_storage, w_key)
                bytes += Marshal.dump(space, w_value)
        else:
            raise NotImplementedError(type(w_obj))

        return bytes

    @staticmethod
    def load(space, bytes, offset=0):
        byte = bytes[offset]
        if byte == Marshal.NIL:
            return space.w_nil, 1
        elif byte == Marshal.TRUE:
            return space.w_true, 1
        elif byte == Marshal.FALSE:
            return space.w_false, 1
        elif byte == Marshal.FIXNUM:
            value, length = Marshal.bytes2integer(bytes, offset + 1)
            return space.newint(value), length
        elif byte == Marshal.FLOAT:
            count, length = Marshal.bytes2integer(bytes, offset + 1)

            chars = []
            for i in range(length, length + count):
                chars.append(chr(bytes[offset + i]))

            return space.newfloat(float("".join(chars))), length
        elif byte == Marshal.ARRAY:
            count, skip = Marshal.bytes2integer(bytes, offset + 1)

            array = []
            for i in range(0, count):
                assert skip > 0
                element, l = Marshal.load(space, bytes, offset + skip)
                skip += l
                array.append(element)

            return space.newarray(array), skip
        elif byte == Marshal.SYMBOL:
            count, length = Marshal.bytes2integer(bytes, offset + 1)

            chars = []
            for i in range(length, length + count):
                chars.append(chr(bytes[offset + i]))

            return space.newsymbol("".join(chars)), length + count
        elif byte == Marshal.IVAR:
            # TODO: fully interpret IVARS
            if bytes[offset + 1] == Marshal.STRING:
                count, length = Marshal.bytes2integer(bytes, offset + 2)
                encoding = 6
                chars = []
                # TODO: take encoding into consideration
                for i in range(length + 1, length + count + 1):
                    chars.append(chr(bytes[offset + i]))
                return space.newstr_fromstr(
                    "".join(chars)), count + length + encoding
            else:
                raise NotImplementedError(bytes[offset + 1])
        elif byte == Marshal.HASH:
            count, skip = Marshal.bytes2integer(bytes, offset + 1)
            w_hash = space.newhash()
            for i in range(0, count):
                assert skip > 0
                k, s = Marshal.load(space, bytes, offset + skip)
                skip += s
                assert skip > 0
                v, s = Marshal.load(space, bytes, offset + skip)
                skip += s
                w_hash.method_subscript_assign(space, k, v)
            return w_hash, skip
        else:
            raise NotImplementedError(byte)

    @moduledef.function("dump")
    def method_dump(self, space, w_obj, w_io=None):
        bytes = [4, 8]
        bytes += Marshal.dump(space, w_obj)
        string = "".join([chr(byte) for byte in bytes])

        if w_io is not None:
            assert isinstance(w_io, W_IOObject)
            w_io.ensure_not_closed(space)
            os.write(w_io.fd, string)
            return w_io
        else:
            return space.newstr_fromstr(string)

    @moduledef.function("load")
    @moduledef.function("restore")
    def method_load(self, space, w_obj):
        string = ""

        if isinstance(w_obj, W_IOObject):
            w_obj.ensure_not_closed(space)
            string = os.read(w_obj.fd, int(os.fstat(w_obj.fd).st_size))
        elif isinstance(w_obj, W_StringObject):
            string = space.str_w(w_obj)
        else:
            raise space.error(space.w_TypeError, "instance of IO needed")

        if len(string) < 2:
            raise space.error(space.w_ArgumentError, "marshal data too short")

        bytes = [ord(string[i]) for i in range(0, len(string))]
        if int(bytes[0]) != Marshal.MAJOR_VERSION or int(
                bytes[1]) != Marshal.MINOR_VERSION:
            raise space.error(
                space.w_TypeError,
                "incompatible marshal file format (can't be read)\n"
                "format version %s.%s required; %s.%s given" %
                (Marshal.MAJOR_VERSION, Marshal.MINOR_VERSION, bytes[0],
                 bytes[1]))

        return Marshal.load(space, bytes, 2)[0]

    # extract integer from marshalled byte array
    # least significant byte first
    @staticmethod
    def bytes2integer(bytes, offset):
        if bytes[offset] >= 252:
            value = 256 - bytes[offset + 1]
            for i in range(2, 256 - bytes[offset] + 1):
                value += (255 - bytes[offset + i]) * int(math.pow(256, i - 1))
            return -value, 256 - bytes[offset] + 2
        elif bytes[offset] > 0 and bytes[offset] < 6:
            value = bytes[offset + 1]
            for i in range(2, bytes[offset] + 1):
                value += bytes[offset + i] * int(math.pow(256, i - 1))
            return value, bytes[offset] + 2
        else:
            value = bytes[offset]
            if value == 0:
                return 0, 2
            elif value > 127:
                return value - 251, 2
            else:
                return value - 5, 2

    # least significant byte first
    @staticmethod
    def integer2bytes(value):
        bytes = []

        if value > 2**30 - 1:
            raise NotImplementedError("Bignum")

        if value > 2**24 - 1:
            bytes.append(4)
            bytes.append(value % 256)
            bytes.append((value >> 8) % 256)
            bytes.append((value >> 16) % 256)
            bytes.append((value >> 24) % 256)
        elif value > 2**16 - 1:
            bytes.append(3)
            bytes.append(value % 256)
            bytes.append((value >> 8) % 256)
            bytes.append((value >> 16) % 256)
        elif value > 255:
            bytes.append(2)
            bytes.append(value % 256)
            bytes.append((value >> 8) % 256)
        elif value > 122:
            bytes.append(1)
            bytes.append(value)
        elif value > 0:
            bytes.append(value + 5)
        elif value == 0:
            bytes.append(0)
        elif value > -124:
            bytes.append(251 + value)
        elif value > -257:
            bytes.append(0xff)
            bytes.append(256 + value)
        elif value > -(2**16 + 1):
            bytes.append(0xfe)
            bytes.append(value % 256)
            bytes.append((value >> 8) % 256)
        elif value > -(2**24 + 1):
            bytes.append(0xfd)
            bytes.append(value % 256)
            bytes.append((value >> 8) % 256)
            bytes.append((value >> 16) % 256)
        elif value > -(2**30 + 1):
            bytes.append(0xfc)
            bytes.append(value % 256)
            bytes.append((value >> 8) % 256)
            bytes.append((value >> 16) % 256)
            bytes.append((value >> 24) % 256)
        else:
            raise NotImplementedError("number too small")
        return bytes
Exemple #19
0
class Signal(object):
    moduledef = ModuleDef("Signal", filepath=__file__)

    @moduledef.function("trap")
    def method_trap(self, args_w):
        pass