summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--doc/mrbconf/README.md19
-rw-r--r--include/mruby/proc.h2
-rw-r--r--mrbgems/mruby-proc-ext/src/proc.c69
-rw-r--r--mrbgems/mruby-proc-ext/test/proc.rb12
-rw-r--r--src/vm.c14
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
diff --git a/src/vm.c b/src/vm.c
index 9a0f03aba..d1d4b7bd4 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -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;