summaryrefslogtreecommitdiffhomepage
path: root/src/proc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/proc.c')
-rw-r--r--src/proc.c92
1 files changed, 92 insertions, 0 deletions
diff --git a/src/proc.c b/src/proc.c
new file mode 100644
index 000000000..aae9b1932
--- /dev/null
+++ b/src/proc.c
@@ -0,0 +1,92 @@
+#include "mruby.h"
+#include "mruby/proc.h"
+#include "mruby/array.h"
+#include "mruby/class.h"
+#include "opcode.h"
+
+struct RProc *
+mrb_proc_new(mrb_state *mrb, mrb_irep *irep)
+{
+ struct RProc *p;
+
+ p = mrb_obj_alloc(mrb, MRB_TT_PROC, mrb->proc_class);
+ p->body.irep = irep;
+ p->target_class = (mrb->ci) ? mrb->ci->target_class : 0;
+ p->env = 0;
+
+ return p;
+}
+
+struct RProc *
+mrb_closure_new(mrb_state *mrb, mrb_irep *irep)
+{
+ struct RProc *p = mrb_proc_new(mrb, irep);
+ struct REnv *e;
+
+ if (!mrb->ci->env) {
+ e = mrb_obj_alloc(mrb, MRB_TT_ENV, mrb->ci->proc->env);
+ e->flags= (unsigned int)irep->nlocals;
+ e->mid = mrb->ci->mid;
+ e->cioff = mrb->ci - mrb->cibase;
+ e->stack = mrb->stack;
+ mrb->ci->env = e;
+ }
+ else {
+ e = mrb->ci->env;
+ }
+ p->env = e;
+ return p;
+}
+
+struct RProc *
+mrb_proc_new_cfunc(mrb_state *mrb, mrb_func_t func)
+{
+ struct RProc *p;
+
+ p = mrb_obj_alloc(mrb, MRB_TT_PROC, mrb->proc_class);
+ p->body.func = func;
+ p->flags |= MRB_PROC_CFUNC;
+
+ return p;
+}
+
+int
+mrb_proc_cfunc_p(struct RProc *p)
+{
+ return MRB_PROC_CFUNC_P(p);
+}
+
+mrb_value
+mrb_proc_call_cfunc(mrb_state *mrb, struct RProc *p, mrb_value self)
+{
+ return (p->body.func)(mrb, self);
+}
+
+mrb_code*
+mrb_proc_iseq(mrb_state *mrb, struct RProc *p)
+{
+ return p->body.irep->iseq;
+}
+
+void
+mrb_init_proc(mrb_state *mrb)
+{
+ struct RProc *m;
+ mrb_code *call_iseq = mrb_malloc(mrb, sizeof(mrb_code));
+ mrb_irep *call_irep = mrb_calloc(mrb, sizeof(mrb_irep), 1);
+
+ if ( call_iseq == NULL || call_irep == NULL )
+ return;
+
+ *call_iseq = MKOP_A(OP_CALL, 0);
+ call_irep->idx = -1;
+ call_irep->flags = MRB_IREP_NOFREE;
+ call_irep->iseq = call_iseq;
+ call_irep->ilen = 1;
+
+ mrb->proc_class = mrb_define_class(mrb, "Proc", mrb->object_class);
+
+ m = mrb_proc_new(mrb, call_irep);
+ mrb_define_method_raw(mrb, mrb->proc_class, mrb_intern(mrb, "call"), m);
+ mrb_define_method_raw(mrb, mrb->proc_class, mrb_intern(mrb, "[]"), m);
+}