Spec-Zone.ru › Ruby 2.2

класс RubyVM::InstructionSequence

Родитель:
Объект

Класс InstructionSequence представляет собой скомпилированную последовательность инструкций для виртуальной машины Ruby.

С его помощью можно получить доступ к инструкциям, составляющим метод или процедуру, скомпилировать строки кода Ruby в инструкции VM и разобрать последовательность инструкций в строки для удобного просмотра. Он в основном полезен, если вы хотите узнать, как работает виртуальная машина Ruby, но также позволяет управлять различными настройками компилятора Ruby iseq.

Исходный код инструкций VM можно найти в insns.def в исходном коде Ruby.

Результаты последовательности инструкций почти наверняка изменятся по мере изменения Ruby, поэтому примеры вывода в этой документации могут отличаться от того, что вы увидите.

Публичные методы класса

compile(source[, file[, path[, line[, options]]]]) → iseq Показать исходный код
static VALUE
iseq_s_compile(int argc, VALUE *argv, VALUE self)
{
    VALUE src, file = Qnil, path = Qnil, line = INT2FIX(1), opt = Qnil;

    rb_secure(1);

    rb_scan_args(argc, argv, "14", &src, &file, &path, &line, &opt);
    if (NIL_P(file)) file = rb_str_new2("<compiled>");
    if (NIL_P(line)) line = INT2FIX(1);

    return rb_iseq_compile_with_option(src, file, path, line, 0, opt);
}

Принимает source, строку кода Ruby, и компилирует её в InstructionSequence.

Опционально принимает file, path, и line, которые описывают имя файла, абсолютный путь и номер первой строки кода Ruby в source, которые являются метаданными, прикреплёнными к возвращаемому iseq.

options, который может быть true, false или Hash, используется для изменения поведения компилятора Ruby iseq по умолчанию.

Для получения подробной информации о допустимых параметрах компиляции см. ::compile_option=.

RubyVM::InstructionSequence.compile("a = 1 + 2")
#=> <RubyVM::InstructionSequence:<compiled>@<compiled>>
compile_file(file[, options]) → iseq Показать исходный код
static VALUE
iseq_s_compile_file(int argc, VALUE *argv, VALUE self)
{
    VALUE file, line = INT2FIX(1), opt = Qnil;
    VALUE parser;
    VALUE f;
    NODE *node;
    const char *fname;
    rb_compile_option_t option;

    rb_secure(1);
    rb_scan_args(argc, argv, "11", &file, &opt);
    FilePathValue(file);
    fname = StringValueCStr(file);

    f = rb_file_open_str(file, "r");

    parser = rb_parser_new();
    node = rb_parser_compile_file(parser, fname, f, NUM2INT(line));

    rb_io_close(f);

    make_compile_option(&option, opt);
    return rb_iseq_new_with_opt(node, rb_str_new2("<main>"), file,
                                rb_realpath_internal(Qnil, file, 1), line, Qfalse,
                                ISEQ_TYPE_TOP, &option);
}

Принимает file, строку с расположением файла исходного кода Ruby, считывает, анализирует и компилирует файл и возвращает iseq, скомпилированный InstructionSequence с метаданными о расположении источника.

Опционально принимает options, который может быть true, false или Hash, для изменения поведения компилятора Ruby iseq по умолчанию.

Для получения подробной информации о допустимых параметрах компиляции см. ::compile_option=.

# /tmp/hello.rb
puts "Hello, world!"

# elsewhere
RubyVM::InstructionSequence.compile_file("/tmp/hello.rb")
#=> <RubyVM::InstructionSequence:<main>@/tmp/hello.rb>
compile_option → options Показать исходный код
static VALUE
iseq_s_compile_option_get(VALUE self)
{
    return make_compile_option_value(&COMPILE_OPTION_DEFAULT);
}

Возвращает хеш значений параметров по умолчанию, используемых компилятором Ruby iseq.

Для получения подробной информации см. ::compile_option=.

compile_option = options Показать исходный код
static VALUE
iseq_s_compile_option_set(VALUE self, VALUE opt)
{
    rb_compile_option_t option;
    rb_secure(1);
    make_compile_option(&option, opt);
    COMPILE_OPTION_DEFAULT = option;
    return opt;
}

Устанавливает значения по умолчанию для различных оптимизаций в компиляторе Ruby iseq.

Возможные значения для options включают true, что включает все параметры, false, что отключает все параметры, и nil, что оставляет все параметры без изменений.

Вы также можете передать Hash options, которые вы хотите изменить, любые параметры, отсутствующие в хеше, останутся без изменений.

Возможные имена параметров (которые являются ключами в options), которые можно установить в true или false, включают:

  • :inline_const_cache

  • :instructions_unification

  • :operands_unification

  • :peephole_optimization

  • :specialized_instruction

  • :stack_caching

  • :tailcall_optimization

  • :trace_instruction

Кроме того, :debug_level может быть установлен в целое число.

Эти параметры по умолчанию могут быть перезаписаны для одного запуска компилятора iseq, передав любое из вышеперечисленных значений как параметр options к ::new, ::compile и ::compile_file.

disasm(body) → str Показать исходный код
disassemble(body) → str
static VALUE
iseq_s_disasm(VALUE klass, VALUE body)
{
    VALUE iseqval = iseq_s_of(klass, body);
    return NIL_P(iseqval) ? Qnil : rb_iseq_disasm(iseqval);
}

Принимает body, объект Method или Proc, и возвращает строку с инструкциями в удобочитаемом формате для body.

Для объекта Method:

# /tmp/method.rb
def hello
  puts "hello, world"
end

puts RubyVM::InstructionSequence.disasm(method(:hello))

Выводит:

== disasm: <RubyVM::InstructionSequence:hello@/tmp/method.rb>============
0000 trace            8                                               (   1)
0002 trace            1                                               (   2)
0004 putself
0005 putstring        "hello, world"
0007 send             :puts, 1, nil, 8, <ic:0>
0013 trace            16                                              (   3)
0015 leave                                                            (   2)

Для процедуры:

# /tmp/proc.rb
p = proc { num = 1 + 2 }
puts RubyVM::InstructionSequence.disasm(p)

Выводит:

== disasm: <RubyVM::InstructionSequence:block in <main>@/tmp/proc.rb>===
== catch table
| catch type: redo   st: 0000 ed: 0012 sp: 0000 cont: 0000
| catch type: next   st: 0000 ed: 0012 sp: 0000 cont: 0012
|------------------------------------------------------------------------
local table (size: 2, argc: 0 [opts: 0, rest: -1, post: 0, block: -1] s1)
[ 2] num
0000 trace            1                                               (   1)
0002 putobject        1
0004 putobject        2
0006 opt_plus         <ic:1>
0008 dup
0009 setlocal         num, 0
0012 leave
disasm(body) → str Показать исходный код
disassemble(body) → str
static VALUE
iseq_s_disasm(VALUE klass, VALUE body)
{
    VALUE iseqval = iseq_s_of(klass, body);
    return NIL_P(iseqval) ? Qnil : rb_iseq_disasm(iseqval);
}

Принимает body, объект Method или Proc, и возвращает строку с инструкциями в удобочитаемом формате для body.

Для объекта Method:

# /tmp/method.rb
def hello
  puts "hello, world"
end

puts RubyVM::InstructionSequence.disasm(method(:hello))

Выводит:

== disasm: <RubyVM::InstructionSequence:hello@/tmp/method.rb>============
0000 trace            8                                               (   1)
0002 trace            1                                               (   2)
0004 putself
0005 putstring        "hello, world"
0007 send             :puts, 1, nil, 8, <ic:0>
0013 trace            16                                              (   3)
0015 leave                                                            (   2)

Для процедуры:

# /tmp/proc.rb
p = proc { num = 1 + 2 }
puts RubyVM::InstructionSequence.disasm(p)

Выводит:

== disasm: <RubyVM::InstructionSequence:block in <main>@/tmp/proc.rb>===
== catch table
| catch type: redo   st: 0000 ed: 0012 sp: 0000 cont: 0000
| catch type: next   st: 0000 ed: 0012 sp: 0000 cont: 0012
|------------------------------------------------------------------------
local table (size: 2, argc: 0 [opts: 0, rest: -1, post: 0, block: -1] s1)
[ 2] num
0000 trace            1                                               (   1)
0002 putobject        1
0004 putobject        2
0006 opt_plus         <ic:1>
0008 dup
0009 setlocal         num, 0
0012 leave
new(source[, file[, path[, line[, options]]]]) → iseq Показать исходный код
static VALUE
iseq_s_compile(int argc, VALUE *argv, VALUE self)
{
    VALUE src, file = Qnil, path = Qnil, line = INT2FIX(1), opt = Qnil;

    rb_secure(1);

    rb_scan_args(argc, argv, "14", &src, &file, &path, &line, &opt);
    if (NIL_P(file)) file = rb_str_new2("<compiled>");
    if (NIL_P(line)) line = INT2FIX(1);

    return rb_iseq_compile_with_option(src, file, path, line, 0, opt);
}

Принимает source, строку кода Ruby, и компилирует её в InstructionSequence.

Опционально принимает file, path, и line, которые описывают имя файла, абсолютный путь и номер первой строки кода Ruby в source, которые являются метаданными, прикреплёнными к возвращаемому iseq.

options, который может быть true, false или Hash, используется для изменения поведения компилятора Ruby iseq по умолчанию.

Для получения подробной информации о допустимых параметрах компиляции см. ::compile_option=.

RubyVM::InstructionSequence.compile("a = 1 + 2")
#=> <RubyVM::InstructionSequence:<compiled>@<compiled>>
of(p1) Показать исходный код
static VALUE
iseq_s_of(VALUE klass, VALUE body)
{
    VALUE ret = Qnil;
    rb_iseq_t *iseq;

    rb_secure(1);

    if (rb_obj_is_proc(body)) {
        rb_proc_t *proc;
        GetProcPtr(body, proc);
        iseq = proc->block.iseq;
        if (RUBY_VM_NORMAL_ISEQ_P(iseq)) {
            ret = iseq->self;
        }
    }
    else if ((iseq = rb_method_get_iseq(body)) != 0) {
        ret = iseq->self;
    }
    return ret;
}

Возвращает последовательность инструкций, содержащую данную процедуру или метод.

Например, используя irb:

# a proc
> p = proc { num = 1 + 2 }
> RubyVM::InstructionSequence.of(p)
> #=> <RubyVM::InstructionSequence:block in irb_binding@(irb)>

# for a method
> def foo(bar); puts bar; end
> RubyVM::InstructionSequence.of(method(:foo))
> #=> <RubyVM::InstructionSequence:foo@(irb)>

Используя ::compile_file:

# /tmp/iseq_of.rb
def hello
  puts "hello, world"
end

$a_global_proc = proc { str = 'a' + 'b' }

# in irb
> require '/tmp/iseq_of.rb'

# first the method hello
> RubyVM::InstructionSequence.of(method(:hello))
> #=> #<RubyVM::InstructionSequence:0x007fb73d7cb1d0>

# then the global proc
> RubyVM::InstructionSequence.of($a_global_proc)
> #=> #<RubyVM::InstructionSequence:0x007fb73d7caf78>

Методы публичного экземпляра

absolute_path() Показать исходный код
VALUE
rb_iseq_absolute_path(VALUE self)
{
    rb_iseq_t *iseq;
    GetISeqPtr(self, iseq);
    return iseq->location.absolute_path;
}

Возвращает абсолютный путь этого последовательности инструкций.

nil если iseq был вычислен из строки.

Например, используя ::compile_file:

# /tmp/method.rb
def hello
  puts "hello, world"
end

# in irb
> iseq = RubyVM::InstructionSequence.compile_file('/tmp/method.rb')
> iseq.absolute_path #=> /tmp/method.rb
base_label() Показать исходный код
VALUE
rb_iseq_base_label(VALUE self)
{
    rb_iseq_t *iseq;
    GetISeqPtr(self, iseq);
    return iseq->location.base_label;
}

Возвращает базовый метку этой последовательности инструкций.

Например, используя irb:

iseq = RubyVM::InstructionSequence.compile('num = 1 + 2')
#=> <RubyVM::InstructionSequence:<compiled>@<compiled>>
iseq.base_label
#=> "<compiled>"

Используя ::compile_file:

# /tmp/method.rb
def hello
  puts "hello, world"
end

# in irb
> iseq = RubyVM::InstructionSequence.compile_file('/tmp/method.rb')
> iseq.base_label #=> <main>
disasm → str Показать исходный код
VALUE
rb_iseq_disasm(VALUE self)
{
    rb_iseq_t *iseqdat = iseq_check(self); /* TODO: rename to iseq */
    VALUE *iseq;
    VALUE str = rb_str_new(0, 0);
    VALUE child = rb_ary_new();
    unsigned int size;
    int i;
    long l;
    ID *tbl;
    size_t n;
    enum {header_minlen = 72};

    rb_secure(1);

    size = iseqdat->iseq_size;

    rb_str_cat2(str, "== disasm: ");

    rb_str_concat(str, iseq_inspect(iseqdat->self));
    if ((l = RSTRING_LEN(str)) < header_minlen) {
        rb_str_resize(str, header_minlen);
        memset(RSTRING_PTR(str) + l, '=', header_minlen - l);
    }
    rb_str_cat2(str, "\n");

    /* show catch table information */
    if (iseqdat->catch_table) {
        rb_str_cat2(str, "== catch table\n");
    }
    if (iseqdat->catch_table) for (i = 0; i < iseqdat->catch_table->size; i++) {
        struct iseq_catch_table_entry *entry = &iseqdat->catch_table->entries[i];
        rb_str_catf(str,
                    "| catch type: %-6s st: %04d ed: %04d sp: %04d cont: %04d\n",
                    catch_type((int)entry->type), (int)entry->start,
                    (int)entry->end, (int)entry->sp, (int)entry->cont);
        if (entry->iseq) {
            rb_str_concat(str, rb_iseq_disasm(entry->iseq));
        }
    }
    if (iseqdat->catch_table) {
        rb_str_cat2(str, "|-------------------------------------"
                    "-----------------------------------\n");
    }

    /* show local table information */
    tbl = iseqdat->local_table;

    if (tbl) {
        rb_str_catf(str,
                    "local table (size: %d, argc: %d "
                    "[opts: %d, rest: %d, post: %d, block: %d, kw: %d@%d, kwrest: %d])\n",
                    iseqdat->local_size,
                    iseqdat->param.lead_num,
                    iseqdat->param.opt_num,
                    iseqdat->param.flags.has_rest ? iseqdat->param.rest_start : -1,
                    iseqdat->param.post_num,
                    iseqdat->param.flags.has_block ? iseqdat->param.block_start : -1,
                    iseqdat->param.flags.has_kw ? iseqdat->param.keyword->num : -1,
                    iseqdat->param.flags.has_kw ? iseqdat->param.keyword->required_num : -1,
                    iseqdat->param.flags.has_kwrest ? iseqdat->param.keyword->rest_start : -1);

        for (i = 0; i < iseqdat->local_table_size; i++) {
            long width;
            VALUE name = id_to_name(tbl[i], 0);
            char argi[0x100] = "";
            char opti[0x100] = "";

            if (iseqdat->param.flags.has_opt) {
                int argc = iseqdat->param.lead_num;
                int opts = iseqdat->param.opt_num;
                if (i >= argc && i < argc + opts) {
                    snprintf(opti, sizeof(opti), "Opt=%"PRIdVALUE,
                             iseqdat->param.opt_table[i - argc]);
                }
            }

            snprintf(argi, sizeof(argi), "%s%s%s%s%s", /* arg, opts, rest, post  block */
                     iseqdat->param.lead_num > i ? "Arg" : "",
                     opti,
                     (iseqdat->param.flags.has_rest && iseqdat->param.rest_start == i) ? "Rest" : "",
                     (iseqdat->param.flags.has_post && iseqdat->param.post_start <= i && i < iseqdat->param.post_start + iseqdat->param.post_num) ? "Post" : "",
                     (iseqdat->param.flags.has_block && iseqdat->param.block_start == i) ? "Block" : "");

            rb_str_catf(str, "[%2d] ", iseqdat->local_size - i);
            width = RSTRING_LEN(str) + 11;
            if (name)
                rb_str_append(str, name);
            else
                rb_str_cat2(str, "?");
            if (*argi) rb_str_catf(str, "<%s>", argi);
            if ((width -= RSTRING_LEN(str)) > 0) rb_str_catf(str, "%*s", (int)width, "");
        }
        rb_str_cat2(str, "\n");
    }

    /* show each line */
    iseq = rb_iseq_original_iseq(iseqdat);
    for (n = 0; n < size;) {
        n += rb_iseq_disasm_insn(str, iseq, n, iseqdat, child);
    }

    for (i = 0; i < RARRAY_LEN(child); i++) {
        VALUE isv = rb_ary_entry(child, i);
        rb_str_concat(str, rb_iseq_disasm(isv));
    }

    return str;
}

Возвращает последовательность инструкций как String в удобочитаемой форме.

puts RubyVM::InstructionSequence.compile('1 + 2').disasm

Производит:

== disasm: <RubyVM::InstructionSequence:<compiled>@<compiled>>==========
0000 trace            1                                               (   1)
0002 putobject        1
0004 putobject        2
0006 opt_plus         <ic:1>
0008 leave
disassemble → str Показать исходный код
VALUE
rb_iseq_disasm(VALUE self)
{
    rb_iseq_t *iseqdat = iseq_check(self); /* TODO: rename to iseq */
    VALUE *iseq;
    VALUE str = rb_str_new(0, 0);
    VALUE child = rb_ary_new();
    unsigned int size;
    int i;
    long l;
    ID *tbl;
    size_t n;
    enum {header_minlen = 72};

    rb_secure(1);

    size = iseqdat->iseq_size;

    rb_str_cat2(str, "== disasm: ");

    rb_str_concat(str, iseq_inspect(iseqdat->self));
    if ((l = RSTRING_LEN(str)) < header_minlen) {
        rb_str_resize(str, header_minlen);
        memset(RSTRING_PTR(str) + l, '=', header_minlen - l);
    }
    rb_str_cat2(str, "\n");

    /* show catch table information */
    if (iseqdat->catch_table) {
        rb_str_cat2(str, "== catch table\n");
    }
    if (iseqdat->catch_table) for (i = 0; i < iseqdat->catch_table->size; i++) {
        struct iseq_catch_table_entry *entry = &iseqdat->catch_table->entries[i];
        rb_str_catf(str,
                    "| catch type: %-6s st: %04d ed: %04d sp: %04d cont: %04d\n",
                    catch_type((int)entry->type), (int)entry->start,
                    (int)entry->end, (int)entry->sp, (int)entry->cont);
        if (entry->iseq) {
            rb_str_concat(str, rb_iseq_disasm(entry->iseq));
        }
    }
    if (iseqdat->catch_table) {
        rb_str_cat2(str, "|-------------------------------------"
                    "-----------------------------------\n");
    }

    /* show local table information */
    tbl = iseqdat->local_table;

    if (tbl) {
        rb_str_catf(str,
                    "local table (size: %d, argc: %d "
                    "[opts: %d, rest: %d, post: %d, block: %d, kw: %d@%d, kwrest: %d])\n",
                    iseqdat->local_size,
                    iseqdat->param.lead_num,
                    iseqdat->param.opt_num,
                    iseqdat->param.flags.has_rest ? iseqdat->param.rest_start : -1,
                    iseqdat->param.post_num,
                    iseqdat->param.flags.has_block ? iseqdat->param.block_start : -1,
                    iseqdat->param.flags.has_kw ? iseqdat->param.keyword->num : -1,
                    iseqdat->param.flags.has_kw ? iseqdat->param.keyword->required_num : -1,
                    iseqdat->param.flags.has_kwrest ? iseqdat->param.keyword->rest_start : -1);

        for (i = 0; i < iseqdat->local_table_size; i++) {
            long width;
            VALUE name = id_to_name(tbl[i], 0);
            char argi[0x100] = "";
            char opti[0x100] = "";

            if (iseqdat->param.flags.has_opt) {
                int argc = iseqdat->param.lead_num;
                int opts = iseqdat->param.opt_num;
                if (i >= argc && i < argc + opts) {
                    snprintf(opti, sizeof(opti), "Opt=%"PRIdVALUE,
                             iseqdat->param.opt_table[i - argc]);
                }
            }

            snprintf(argi, sizeof(argi), "%s%s%s%s%s", /* arg, opts, rest, post  block */
                     iseqdat->param.lead_num > i ? "Arg" : "",
                     opti,
                     (iseqdat->param.flags.has_rest && iseqdat->param.rest_start == i) ? "Rest" : "",
                     (iseqdat->param.flags.has_post && iseqdat->param.post_start <= i && i < iseqdat->param.post_start + iseqdat->param.post_num) ? "Post" : "",
                     (iseqdat->param.flags.has_block && iseqdat->param.block_start == i) ? "Block" : "");

            rb_str_catf(str, "[%2d] ", iseqdat->local_size - i);
            width = RSTRING_LEN(str) + 11;
            if (name)
                rb_str_append(str, name);
            else
                rb_str_cat2(str, "?");
            if (*argi) rb_str_catf(str, "<%s>", argi);
            if ((width -= RSTRING_LEN(str)) > 0) rb_str_catf(str, "%*s", (int)width, "");
        }
        rb_str_cat2(str, "\n");
    }

    /* show each line */
    iseq = rb_iseq_original_iseq(iseqdat);
    for (n = 0; n < size;) {
        n += rb_iseq_disasm_insn(str, iseq, n, iseqdat, child);
    }

    for (i = 0; i < RARRAY_LEN(child); i++) {
        VALUE isv = rb_ary_entry(child, i);
        rb_str_concat(str, rb_iseq_disasm(isv));
    }

    return str;
}

Возвращает последовательность инструкций как String в удобочитаемой форме.

puts RubyVM::InstructionSequence.compile('1 + 2').disasm

Производит:

== disasm: <RubyVM::InstructionSequence:<compiled>@<compiled>>==========
0000 trace            1                                               (   1)
0002 putobject        1
0004 putobject        2
0006 opt_plus         <ic:1>
0008 leave
eval → obj Показать исходный код
static VALUE
iseq_eval(VALUE self)
{
    rb_secure(1);
    return rb_iseq_eval(self);
}

Вычисляет последовательность инструкций и возвращает результат.

RubyVM::InstructionSequence.compile("1 + 2").eval #=> 3
first_lineno() Показать исходный код
VALUE
rb_iseq_first_lineno(VALUE self)
{
    rb_iseq_t *iseq;
    GetISeqPtr(self, iseq);
    return iseq->location.first_lineno;
}

Возвращает номер первой строки исходного кода, откуда была загружена последовательность инструкций.

Например, используя irb:

iseq = RubyVM::InstructionSequence.compile('num = 1 + 2')
#=> <RubyVM::InstructionSequence:<compiled>@<compiled>>
iseq.first_lineno
#=> 1
inspect() Показать исходный код
static VALUE
iseq_inspect(VALUE self)
{
    rb_iseq_t *iseq;
    GetISeqPtr(self, iseq);
    if (!iseq->location.label) {
        return rb_sprintf("#<%s: uninitialized>", rb_obj_classname(self));
    }

    return rb_sprintf("<%s:%s@%s>",
                      rb_obj_classname(self),
                      RSTRING_PTR(iseq->location.label), RSTRING_PTR(iseq->location.path));
}

Возвращает строку, представляющую эту последовательность инструкций в удобочитаемом виде, включая метку и путь.

label() Показать исходный код
VALUE
rb_iseq_label(VALUE self)
{
    rb_iseq_t *iseq;
    GetISeqPtr(self, iseq);
    return iseq->location.label;
}

Возвращает метку этой последовательности инструкций.

<main> если она находится на верхнем уровне, <compiled> если она была вычислена из строки.

Например, используя irb:

iseq = RubyVM::InstructionSequence.compile('num = 1 + 2')
#=> <RubyVM::InstructionSequence:<compiled>@<compiled>>
iseq.label
#=> "<compiled>"

Используя ::compile_file:

# /tmp/method.rb
def hello
  puts "hello, world"
end

# in irb
> iseq = RubyVM::InstructionSequence.compile_file('/tmp/method.rb')
> iseq.label #=> <main>
line_trace_all() Показать исходный код
VALUE
rb_iseq_line_trace_all(VALUE iseqval)
{
    VALUE result = rb_ary_new();
    rb_iseq_line_trace_each(iseqval, collect_trace, (void *)result);
    return result;
}

Экспериментальная функция, специфичная для MRI, доступна только в API уровня C.

Возвращает все specified_line события.

line_trace_specify(p1, p2) Показать исходный код
VALUE
rb_iseq_line_trace_specify(VALUE iseqval, VALUE pos, VALUE set)
{
    struct set_specifc_data data;

    data.prev = 0;
    data.pos = NUM2INT(pos);
    if (data.pos < 0) rb_raise(rb_eTypeError, "`pos' is negative");

    switch (set) {
      case Qtrue:  data.set = 1; break;
      case Qfalse: data.set = 0; break;
      default:
        rb_raise(rb_eTypeError, "`set' should be true/false");
    }

    rb_iseq_line_trace_each(iseqval, line_trace_specify, (void *)&data);

    if (data.prev == 0) {
        rb_raise(rb_eTypeError, "`pos' is out of range.");
    }
    return data.prev == 1 ? Qtrue : Qfalse;
}

Экспериментальная функция, специфичная для MRI, доступна только в API уровня C.

Устанавливает specified_line событие в заданной позиции строки, если параметр set равен true.

Этот метод полезен для создания точки останова отладчика в определенной строке.

Исключение TypeError генерируется, если set не является булевым значением.

Если pos отрицательное целое число, генерируется исключение TypeError.

path() Показать исходный код
VALUE
rb_iseq_path(VALUE self)
{
    rb_iseq_t *iseq;
    GetISeqPtr(self, iseq);
    return iseq->location.path;
}

Возвращает путь этой последовательности инструкций.

<compiled> если iseq был вычислен из строки.

Например, используя irb:

iseq = RubyVM::InstructionSequence.compile('num = 1 + 2')
#=> <RubyVM::InstructionSequence:<compiled>@<compiled>>
iseq.path
#=> "<compiled>"

Используя ::compile_file:

# /tmp/method.rb
def hello
  puts "hello, world"
end

# in irb
> iseq = RubyVM::InstructionSequence.compile_file('/tmp/method.rb')
> iseq.path #=> /tmp/method.rb
to_a → ary Показать исходный код
static VALUE
iseq_to_a(VALUE self)
{
    rb_iseq_t *iseq = iseq_check(self);
    rb_secure(1);
    return iseq_data_to_ary(iseq);
}

Возвращает массив из 14 элементов, представляющих последовательность инструкций со следующими данными:

magic

Строка, идентифицирующая формат данных. Всегда YARVInstructionSequence/SimpleDataFormat.

major_version

Основная версия последовательности инструкций.

minor_version

Дополнительная версия последовательности инструкций.

format_type

Число, идентифицирующее формат данных. Всегда 1.

misc

Хэш, содержащий:

:arg_size

общее количество аргументов, принимаемых методом или блоком (0, если iseq не представляет метод или блок)

:local_size

количество локальных переменных + 1

:stack_max

используется для расчета глубины стека, на которой возникает SystemStackError.

label

Имя контекста (блока, метода, класса, модуля и т.д.), к которому относится эта последовательность инструкций.

<main> если она находится на верхнем уровне, <compiled> если она была вычислена из строки.

path

Относительный путь к файлу Ruby, откуда была загружена последовательность инструкций.

<compiled> если iseq был вычислен из строки.

absolute_path

Абсолютный путь к файлу Ruby, откуда была загружена последовательность инструкций.

nil если iseq был вычислен из строки.

first_lineno

Номер первой строки исходного кода, откуда была загружена последовательность инструкций.

type

Тип последовательности инструкций.

Допустимые значения — :top, :method, :block, :class, :rescue, :ensure, :eval, :main, и :defined_guard.

locals

Массив, содержащий имена всех аргументов и локальных переменных в виде символов.

params

Объект Hash, содержащий информацию о параметрах.

Дополнительную информацию о значениях можно найти в vm_core.h.

catch_table

Список исключений и операторов управления потоком (rescue, next, redo, break и т.д.).

bytecode

Массив массивов, содержащий имена инструкций и операнды, составляющие тело последовательности инструкций.

Обратите внимание, что этот формат специфичен для MRI и зависит от версии.

Ruby Core © 1993–2017 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API