[331] | 1 | #include <mruby.h>
|
---|
| 2 | #include <mruby/proc.h>
|
---|
| 3 | #include <mruby/opcode.h>
|
---|
| 4 | #include <mruby/array.h>
|
---|
| 5 | #include <mruby/string.h>
|
---|
| 6 | #include <mruby/debug.h>
|
---|
[270] | 7 |
|
---|
| 8 | static mrb_value
|
---|
| 9 | mrb_proc_lambda(mrb_state *mrb, mrb_value self)
|
---|
| 10 | {
|
---|
| 11 | struct RProc *p = mrb_proc_ptr(self);
|
---|
| 12 | return mrb_bool_value(MRB_PROC_STRICT_P(p));
|
---|
| 13 | }
|
---|
| 14 |
|
---|
| 15 | static mrb_value
|
---|
| 16 | mrb_proc_source_location(mrb_state *mrb, mrb_value self)
|
---|
| 17 | {
|
---|
| 18 | struct RProc *p = mrb_proc_ptr(self);
|
---|
| 19 |
|
---|
| 20 | if (MRB_PROC_CFUNC_P(p)) {
|
---|
| 21 | return mrb_nil_value();
|
---|
| 22 | }
|
---|
| 23 | else {
|
---|
| 24 | mrb_irep *irep = p->body.irep;
|
---|
| 25 | int32_t line;
|
---|
| 26 | const char *filename;
|
---|
| 27 |
|
---|
[439] | 28 | filename = mrb_debug_get_filename(mrb, irep, 0);
|
---|
| 29 | line = mrb_debug_get_line(mrb, irep, 0);
|
---|
[270] | 30 |
|
---|
| 31 | return (!filename && line == -1)? mrb_nil_value()
|
---|
| 32 | : mrb_assoc_new(mrb, mrb_str_new_cstr(mrb, filename), mrb_fixnum_value(line));
|
---|
| 33 | }
|
---|
| 34 | }
|
---|
| 35 |
|
---|
| 36 | static mrb_value
|
---|
| 37 | mrb_proc_inspect(mrb_state *mrb, mrb_value self)
|
---|
| 38 | {
|
---|
| 39 | struct RProc *p = mrb_proc_ptr(self);
|
---|
| 40 | mrb_value str = mrb_str_new_lit(mrb, "#<Proc:");
|
---|
[439] | 41 | mrb_str_cat_str(mrb, str, mrb_ptr_to_str(mrb, mrb_cptr(self)));
|
---|
[270] | 42 |
|
---|
| 43 | if (!MRB_PROC_CFUNC_P(p)) {
|
---|
| 44 | mrb_irep *irep = p->body.irep;
|
---|
| 45 | const char *filename;
|
---|
| 46 | int32_t line;
|
---|
| 47 | mrb_str_cat_lit(mrb, str, "@");
|
---|
| 48 |
|
---|
[439] | 49 | filename = mrb_debug_get_filename(mrb, irep, 0);
|
---|
[270] | 50 | mrb_str_cat_cstr(mrb, str, filename ? filename : "-");
|
---|
| 51 | mrb_str_cat_lit(mrb, str, ":");
|
---|
| 52 |
|
---|
[439] | 53 | line = mrb_debug_get_line(mrb, irep, 0);
|
---|
[270] | 54 | if (line != -1) {
|
---|
[439] | 55 | mrb_str_concat(mrb, str, mrb_fixnum_value(line));
|
---|
[270] | 56 | }
|
---|
| 57 | else {
|
---|
| 58 | mrb_str_cat_lit(mrb, str, "-");
|
---|
| 59 | }
|
---|
| 60 | }
|
---|
| 61 |
|
---|
| 62 | if (MRB_PROC_STRICT_P(p)) {
|
---|
| 63 | mrb_str_cat_lit(mrb, str, " (lambda)");
|
---|
| 64 | }
|
---|
| 65 |
|
---|
| 66 | mrb_str_cat_lit(mrb, str, ">");
|
---|
| 67 | return str;
|
---|
| 68 | }
|
---|
| 69 |
|
---|
| 70 | static mrb_value
|
---|
| 71 | mrb_kernel_proc(mrb_state *mrb, mrb_value self)
|
---|
| 72 | {
|
---|
| 73 | mrb_value blk;
|
---|
| 74 |
|
---|
[439] | 75 | mrb_get_args(mrb, "&!", &blk);
|
---|
[270] | 76 |
|
---|
| 77 | return blk;
|
---|
| 78 | }
|
---|
| 79 |
|
---|
| 80 | /*
|
---|
| 81 | * call-seq:
|
---|
| 82 | * prc.parameters -> array
|
---|
| 83 | *
|
---|
| 84 | * Returns the parameter information of this proc.
|
---|
| 85 | *
|
---|
| 86 | * prc = lambda{|x, y=42, *other|}
|
---|
| 87 | * prc.parameters #=> [[:req, :x], [:opt, :y], [:rest, :other]]
|
---|
| 88 | */
|
---|
| 89 |
|
---|
| 90 | static mrb_value
|
---|
| 91 | mrb_proc_parameters(mrb_state *mrb, mrb_value self)
|
---|
| 92 | {
|
---|
| 93 | struct parameters_type {
|
---|
[439] | 94 | size_t len;
|
---|
| 95 | const char *name;
|
---|
[270] | 96 | int size;
|
---|
| 97 | } *p, parameters_list [] = {
|
---|
[439] | 98 | {sizeof("req") - 1, "req", 0},
|
---|
| 99 | {sizeof("opt") - 1, "opt", 0},
|
---|
| 100 | {sizeof("rest") - 1, "rest", 0},
|
---|
| 101 | {sizeof("req") - 1, "req", 0},
|
---|
| 102 | {sizeof("block") - 1, "block", 0},
|
---|
| 103 | {0, NULL, 0}
|
---|
[270] | 104 | };
|
---|
| 105 | const struct RProc *proc = mrb_proc_ptr(self);
|
---|
| 106 | const struct mrb_irep *irep = proc->body.irep;
|
---|
| 107 | mrb_aspec aspec;
|
---|
[439] | 108 | mrb_value parameters;
|
---|
[270] | 109 | int i, j;
|
---|
[439] | 110 | int max = -1;
|
---|
[270] | 111 |
|
---|
| 112 | if (MRB_PROC_CFUNC_P(proc)) {
|
---|
| 113 | // TODO cfunc aspec is not implemented yet
|
---|
| 114 | return mrb_ary_new(mrb);
|
---|
| 115 | }
|
---|
[331] | 116 | if (!irep) {
|
---|
| 117 | return mrb_ary_new(mrb);
|
---|
| 118 | }
|
---|
[270] | 119 | if (!irep->lv) {
|
---|
| 120 | return mrb_ary_new(mrb);
|
---|
| 121 | }
|
---|
[439] | 122 | if (*irep->iseq != OP_ENTER) {
|
---|
[270] | 123 | return mrb_ary_new(mrb);
|
---|
| 124 | }
|
---|
| 125 |
|
---|
| 126 | if (!MRB_PROC_STRICT_P(proc)) {
|
---|
[439] | 127 | parameters_list[0].len = sizeof("opt") - 1;
|
---|
[270] | 128 | parameters_list[0].name = "opt";
|
---|
[439] | 129 | parameters_list[3].len = sizeof("opt") - 1;
|
---|
[270] | 130 | parameters_list[3].name = "opt";
|
---|
| 131 | }
|
---|
| 132 |
|
---|
[439] | 133 | aspec = PEEK_W(irep->iseq+1);
|
---|
[270] | 134 | parameters_list[0].size = MRB_ASPEC_REQ(aspec);
|
---|
| 135 | parameters_list[1].size = MRB_ASPEC_OPT(aspec);
|
---|
| 136 | parameters_list[2].size = MRB_ASPEC_REST(aspec);
|
---|
| 137 | parameters_list[3].size = MRB_ASPEC_POST(aspec);
|
---|
| 138 | parameters_list[4].size = MRB_ASPEC_BLOCK(aspec);
|
---|
| 139 |
|
---|
| 140 | parameters = mrb_ary_new_capa(mrb, irep->nlocals-1);
|
---|
[331] | 141 |
|
---|
[439] | 142 | max = irep->nlocals-1;
|
---|
[270] | 143 | for (i = 0, p = parameters_list; p->name; p++) {
|
---|
[439] | 144 | mrb_value sname = mrb_symbol_value(mrb_intern_static(mrb, p->name, p->len));
|
---|
| 145 |
|
---|
[270] | 146 | for (j = 0; j < p->size; i++, j++) {
|
---|
[439] | 147 | mrb_value a;
|
---|
| 148 |
|
---|
| 149 | a = mrb_ary_new(mrb);
|
---|
[331] | 150 | mrb_ary_push(mrb, a, sname);
|
---|
[439] | 151 | if (i < max && irep->lv[i].name) {
|
---|
| 152 | mrb_sym sym = irep->lv[i].name;
|
---|
| 153 | const char *name = mrb_sym_name(mrb, sym);
|
---|
| 154 | switch (name[0]) {
|
---|
| 155 | case '*': case '&':
|
---|
| 156 | break;
|
---|
| 157 | default:
|
---|
| 158 | mrb_ary_push(mrb, a, mrb_symbol_value(sym));
|
---|
| 159 | break;
|
---|
| 160 | }
|
---|
[331] | 161 | }
|
---|
| 162 | mrb_ary_push(mrb, parameters, a);
|
---|
[270] | 163 | }
|
---|
| 164 | }
|
---|
| 165 | return parameters;
|
---|
| 166 | }
|
---|
| 167 |
|
---|
| 168 | void
|
---|
| 169 | mrb_mruby_proc_ext_gem_init(mrb_state* mrb)
|
---|
| 170 | {
|
---|
| 171 | struct RClass *p = mrb->proc_class;
|
---|
| 172 | mrb_define_method(mrb, p, "lambda?", mrb_proc_lambda, MRB_ARGS_NONE());
|
---|
| 173 | mrb_define_method(mrb, p, "source_location", mrb_proc_source_location, MRB_ARGS_NONE());
|
---|
| 174 | mrb_define_method(mrb, p, "to_s", mrb_proc_inspect, MRB_ARGS_NONE());
|
---|
| 175 | mrb_define_method(mrb, p, "inspect", mrb_proc_inspect, MRB_ARGS_NONE());
|
---|
| 176 | mrb_define_method(mrb, p, "parameters", mrb_proc_parameters, MRB_ARGS_NONE());
|
---|
| 177 |
|
---|
[439] | 178 | mrb_define_class_method(mrb, mrb->kernel_module, "proc", mrb_kernel_proc, MRB_ARGS_NONE()|MRB_ARGS_BLOCK());
|
---|
| 179 | mrb_define_method(mrb, mrb->kernel_module, "proc", mrb_kernel_proc, MRB_ARGS_NONE()|MRB_ARGS_BLOCK());
|
---|
[270] | 180 | }
|
---|
| 181 |
|
---|
| 182 | void
|
---|
| 183 | mrb_mruby_proc_ext_gem_final(mrb_state* mrb)
|
---|
| 184 | {
|
---|
| 185 | }
|
---|