[270] | 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"
|
---|
| 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 |
|
---|
| 28 | filename = mrb_debug_get_filename(irep, 0);
|
---|
| 29 | line = mrb_debug_get_line(irep, 0);
|
---|
| 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:");
|
---|
| 41 | mrb_str_concat(mrb, str, mrb_ptr_to_str(mrb, mrb_cptr(self)));
|
---|
| 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 |
|
---|
| 49 | filename = mrb_debug_get_filename(irep, 0);
|
---|
| 50 | mrb_str_cat_cstr(mrb, str, filename ? filename : "-");
|
---|
| 51 | mrb_str_cat_lit(mrb, str, ":");
|
---|
| 52 |
|
---|
| 53 | line = mrb_debug_get_line(irep, 0);
|
---|
| 54 | if (line != -1) {
|
---|
| 55 | mrb_str_append(mrb, str, mrb_fixnum_value(line));
|
---|
| 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 |
|
---|
| 75 | mrb_get_args(mrb, "&", &blk);
|
---|
| 76 | if (mrb_nil_p(blk)) {
|
---|
| 77 | mrb_raise(mrb, E_ARGUMENT_ERROR, "tried to create Proc object without a block");
|
---|
| 78 | }
|
---|
| 79 |
|
---|
| 80 | return blk;
|
---|
| 81 | }
|
---|
| 82 |
|
---|
| 83 | /*
|
---|
| 84 | * call-seq:
|
---|
| 85 | * prc.parameters -> array
|
---|
| 86 | *
|
---|
| 87 | * Returns the parameter information of this proc.
|
---|
| 88 | *
|
---|
| 89 | * prc = lambda{|x, y=42, *other|}
|
---|
| 90 | * prc.parameters #=> [[:req, :x], [:opt, :y], [:rest, :other]]
|
---|
| 91 | */
|
---|
| 92 |
|
---|
| 93 | static mrb_value
|
---|
| 94 | mrb_proc_parameters(mrb_state *mrb, mrb_value self)
|
---|
| 95 | {
|
---|
| 96 | struct parameters_type {
|
---|
| 97 | int size;
|
---|
| 98 | const char *name;
|
---|
| 99 | } *p, parameters_list [] = {
|
---|
| 100 | {0, "req"},
|
---|
| 101 | {0, "opt"},
|
---|
| 102 | {0, "rest"},
|
---|
| 103 | {0, "req"},
|
---|
| 104 | {0, "block"},
|
---|
| 105 | {0, NULL}
|
---|
| 106 | };
|
---|
| 107 | const struct RProc *proc = mrb_proc_ptr(self);
|
---|
| 108 | const struct mrb_irep *irep = proc->body.irep;
|
---|
| 109 | mrb_aspec aspec;
|
---|
| 110 | mrb_value parameters;
|
---|
| 111 | int i, j;
|
---|
| 112 |
|
---|
| 113 | if (MRB_PROC_CFUNC_P(proc)) {
|
---|
| 114 | // TODO cfunc aspec is not implemented yet
|
---|
| 115 | return mrb_ary_new(mrb);
|
---|
| 116 | }
|
---|
| 117 | if (!irep->lv) {
|
---|
| 118 | return mrb_ary_new(mrb);
|
---|
| 119 | }
|
---|
| 120 | if (GET_OPCODE(*irep->iseq) != OP_ENTER) {
|
---|
| 121 | return mrb_ary_new(mrb);
|
---|
| 122 | }
|
---|
| 123 |
|
---|
| 124 | if (!MRB_PROC_STRICT_P(proc)) {
|
---|
| 125 | parameters_list[0].name = "opt";
|
---|
| 126 | parameters_list[3].name = "opt";
|
---|
| 127 | }
|
---|
| 128 |
|
---|
| 129 | aspec = GETARG_Ax(*irep->iseq);
|
---|
| 130 | parameters_list[0].size = MRB_ASPEC_REQ(aspec);
|
---|
| 131 | parameters_list[1].size = MRB_ASPEC_OPT(aspec);
|
---|
| 132 | parameters_list[2].size = MRB_ASPEC_REST(aspec);
|
---|
| 133 | parameters_list[3].size = MRB_ASPEC_POST(aspec);
|
---|
| 134 | parameters_list[4].size = MRB_ASPEC_BLOCK(aspec);
|
---|
| 135 |
|
---|
| 136 | parameters = mrb_ary_new_capa(mrb, irep->nlocals-1);
|
---|
| 137 | for (i = 0, p = parameters_list; p->name; p++) {
|
---|
| 138 | mrb_value sname = mrb_symbol_value(mrb_intern_cstr(mrb, p->name));
|
---|
| 139 | for (j = 0; j < p->size; i++, j++) {
|
---|
| 140 | mrb_assert(i < (irep->nlocals-1));
|
---|
| 141 | mrb_ary_push(mrb, parameters, mrb_assoc_new(mrb,
|
---|
| 142 | sname,
|
---|
| 143 | mrb_symbol_value(irep->lv[i].name)
|
---|
| 144 | ));
|
---|
| 145 | }
|
---|
| 146 | }
|
---|
| 147 | return parameters;
|
---|
| 148 | }
|
---|
| 149 |
|
---|
| 150 | void
|
---|
| 151 | mrb_mruby_proc_ext_gem_init(mrb_state* mrb)
|
---|
| 152 | {
|
---|
| 153 | struct RClass *p = mrb->proc_class;
|
---|
| 154 | mrb_define_method(mrb, p, "lambda?", mrb_proc_lambda, MRB_ARGS_NONE());
|
---|
| 155 | mrb_define_method(mrb, p, "source_location", mrb_proc_source_location, MRB_ARGS_NONE());
|
---|
| 156 | mrb_define_method(mrb, p, "to_s", mrb_proc_inspect, MRB_ARGS_NONE());
|
---|
| 157 | mrb_define_method(mrb, p, "inspect", mrb_proc_inspect, MRB_ARGS_NONE());
|
---|
| 158 | mrb_define_method(mrb, p, "parameters", mrb_proc_parameters, MRB_ARGS_NONE());
|
---|
| 159 |
|
---|
| 160 | mrb_define_class_method(mrb, mrb->kernel_module, "proc", mrb_kernel_proc, MRB_ARGS_NONE());
|
---|
| 161 | mrb_define_method(mrb, mrb->kernel_module, "proc", mrb_kernel_proc, MRB_ARGS_NONE());
|
---|
| 162 | }
|
---|
| 163 |
|
---|
| 164 | void
|
---|
| 165 | mrb_mruby_proc_ext_gem_final(mrb_state* mrb)
|
---|
| 166 | {
|
---|
| 167 | }
|
---|