diff options
| -rw-r--r-- | doc/mrbconf/README.md | 19 | ||||
| -rw-r--r-- | include/mruby/proc.h | 2 | ||||
| -rw-r--r-- | mrbgems/mruby-proc-ext/src/proc.c | 69 | ||||
| -rw-r--r-- | mrbgems/mruby-proc-ext/test/proc.rb | 12 | ||||
| -rw-r--r-- | src/vm.c | 14 |
5 files changed, 108 insertions, 8 deletions
diff --git a/doc/mrbconf/README.md b/doc/mrbconf/README.md index f0dd50da5..698d2526f 100644 --- a/doc/mrbconf/README.md +++ b/doc/mrbconf/README.md @@ -17,6 +17,10 @@ You can use mrbconfs with following ways: `DISABLE_STDIO` * When defined `<stdio.h>` functions won't be used. +* Some features will be disabled when this is enabled: + * `mrb_irep` load/dump from/to file. + * Compiling mruby script from file. + * Printing features in **src/print.c**. ## Debug macros. `ENABLE_DEBUG` @@ -104,3 +108,18 @@ largest value of required alignment. `MRB_FIXED_STATE_ATEXIT_STACK_SIZE` * Default value is `5`. * If `MRB_FIXED_STATE_ATEXIT_STACK` isn't defined this macro is ignored. + +## `mrb_value` configuration. + +`MRB_ENDIAN_BIG` +* If defined compiles mruby for big endian machines. +* Used in `MRB_NAN_BOXING`. +* Some mrbgem use this mrbconf. + +`MRB_NAN_BOXING` +* If defined represent `mrb_value` in boxed `double`. +* Conflicts with `MRB_USE_FLOAT`. + +`MRB_WORD_BOXING` +* If defined represent `mrb_value` as a word. +* If defined `Float` will be a mruby object with `RBasic`. diff --git a/include/mruby/proc.h b/include/mruby/proc.h index 39f5eca22..82b93ddef 100644 --- a/include/mruby/proc.h +++ b/include/mruby/proc.h @@ -37,7 +37,7 @@ struct RProc { /* aspec access */ #define MRB_ASPEC_REQ(a) (((a) >> 18) & 0x1f) #define MRB_ASPEC_OPT(a) (((a) >> 13) & 0x1f) -#define MRB_ASPEC_REST(a) ((a) & (1<<12)) +#define MRB_ASPEC_REST(a) (((a) >> 12) & 0x1) #define MRB_ASPEC_POST(a) (((a) >> 7) & 0x1f) #define MRB_ASPEC_KEY(a) (((a) >> 2) & 0x1f) #define MRB_ASPEC_KDICT(a) ((a) & (1<<1)) diff --git a/mrbgems/mruby-proc-ext/src/proc.c b/mrbgems/mruby-proc-ext/src/proc.c index b105c95d7..f4a238803 100644 --- a/mrbgems/mruby-proc-ext/src/proc.c +++ b/mrbgems/mruby-proc-ext/src/proc.c @@ -1,5 +1,6 @@ #include "mruby.h" #include "mruby/proc.h" +#include "mruby/opcode.h" #include "mruby/array.h" #include "mruby/string.h" #include "mruby/debug.h" @@ -122,6 +123,73 @@ mrb_kernel_proc(mrb_state *mrb, mrb_value self) return blk; } +/* + * call-seq: + * prc.parameters -> array + * + * Returns the parameter information of this proc. + * + * prc = lambda{|x, y=42, *other|} + * prc.parameters #=> [[:req, :x], [:opt, :y], [:rest, :other]] + */ + +static mrb_value +mrb_proc_parameters(mrb_state *mrb, mrb_value self) +{ + struct parameters_type { + int size; + const char *name; + } *p, parameters_list [] = { + {0, "req"}, + {0, "opt"}, + {0, "rest"}, + {0, "req"}, + {0, "block"}, + {0, NULL} + }; + const struct RProc *proc = mrb_proc_ptr(self); + const struct mrb_irep *irep = proc->body.irep; + mrb_aspec aspec; + mrb_value parameters; + int i, j; + + if (MRB_PROC_CFUNC_P(proc)) { + // TODO cfunc aspec is not implemented yet + return mrb_ary_new(mrb); + } + if (!irep->lv) { + return mrb_ary_new(mrb); + } + if (GET_OPCODE(*irep->iseq) != OP_ENTER) { + return mrb_ary_new(mrb); + } + + if (!MRB_PROC_STRICT_P(proc)) { + parameters_list[0].name = "opt"; + parameters_list[3].name = "opt"; + } + + aspec = GETARG_Ax(*irep->iseq); + parameters_list[0].size = MRB_ASPEC_REQ(aspec); + parameters_list[1].size = MRB_ASPEC_OPT(aspec); + parameters_list[2].size = MRB_ASPEC_REST(aspec); + parameters_list[3].size = MRB_ASPEC_POST(aspec); + parameters_list[4].size = MRB_ASPEC_BLOCK(aspec); + + parameters = mrb_ary_new_capa(mrb, irep->nlocals-1); + for (i = 0, p = parameters_list; p->name; p++) { + mrb_value sname = mrb_symbol_value(mrb_intern_cstr(mrb, p->name)); + for (j = 0; j < p->size; i++, j++) { + mrb_assert(i < (irep->nlocals-1)); + mrb_ary_push(mrb, parameters, mrb_assoc_new(mrb, + sname, + mrb_symbol_value(irep->lv[i].name) + )); + } + } + return parameters; +} + void mrb_mruby_proc_ext_gem_init(mrb_state* mrb) { @@ -130,6 +198,7 @@ mrb_mruby_proc_ext_gem_init(mrb_state* mrb) mrb_define_method(mrb, p, "source_location", mrb_proc_source_location, MRB_ARGS_NONE()); mrb_define_method(mrb, p, "to_s", mrb_proc_inspect, MRB_ARGS_NONE()); mrb_define_method(mrb, p, "inspect", mrb_proc_inspect, MRB_ARGS_NONE()); + mrb_define_method(mrb, p, "parameters", mrb_proc_parameters, MRB_ARGS_NONE()); mrb_define_class_method(mrb, mrb->kernel_module, "proc", mrb_kernel_proc, MRB_ARGS_NONE()); mrb_define_method(mrb, mrb->kernel_module, "proc", mrb_kernel_proc, MRB_ARGS_NONE()); diff --git a/mrbgems/mruby-proc-ext/test/proc.rb b/mrbgems/mruby-proc-ext/test/proc.rb index 1565873a0..bca9b463a 100644 --- a/mrbgems/mruby-proc-ext/test/proc.rb +++ b/mrbgems/mruby-proc-ext/test/proc.rb @@ -43,6 +43,18 @@ assert('Proc#curry') do assert_raise(ArgumentError) { b.curry(1) } end +assert('Proc#parameters') do + assert_equal([], Proc.new {}.parameters) + assert_equal([], Proc.new {||}.parameters) + assert_equal([[:opt, :a]], Proc.new {|a|}.parameters) + assert_equal([[:req, :a]], lambda {|a|}.parameters) + assert_equal([[:opt, :a]], lambda {|a=nil|}.parameters) + assert_equal([[:req, :a]], ->(a){}.parameters) + assert_equal([[:rest, :a]], Proc.new {|*a|}.parameters) + assert_equal([[:opt, :a], [:opt, :b], [:opt, :c], [:opt, :d], [:rest, :e], [:opt, :f], [:opt, :g], [:block, :h]], Proc.new {|a,b,c=:c,d=:d,*e,f,g,&h|}.parameters) + assert_equal([[:req, :a], [:req, :b], [:opt, :c], [:opt, :d], [:rest, :e], [:req, :f], [:req, :g], [:block, :h]], lambda {|a,b,c=:c,d=:d,*e,f,g,&h|}.parameters) +end + assert('Proc#to_proc') do proc = Proc.new {} assert_equal proc, proc.to_proc @@ -1364,14 +1364,14 @@ RETRY_TRY_BLOCK: /* Ax arg setup according to flags (23=5:5:1:5:5:1:1) */ /* number of optional arguments times OP_JMP should follow */ mrb_aspec ax = GETARG_Ax(i); - int m1 = (ax>>18)&0x1f; - int o = (ax>>13)&0x1f; - int r = (ax>>12)&0x1; - int m2 = (ax>>7)&0x1f; + int m1 = MRB_ASPEC_REQ(ax); + int o = MRB_ASPEC_OPT(ax); + int r = MRB_ASPEC_REST(ax); + int m2 = MRB_ASPEC_POST(ax); /* unused - int k = (ax>>2)&0x1f; - int kd = (ax>>1)&0x1; - int b = (ax>>0)& 0x1; + int k = MRB_ASPEC_KEY(ax); + int kd = MRB_ASPEC_KDICT(ax); + int b = MRB_ASPEC_BLOCK(ax); */ int argc = mrb->c->ci->argc; mrb_value *argv = regs+1; |
