Groonga 3.0.9 Source Code Document
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
proc.c
Go to the documentation of this file.
1 /*
2 ** proc.c - Proc class
3 **
4 ** See Copyright Notice in mruby.h
5 */
6 
7 #include "mruby.h"
8 #include "mruby/class.h"
9 #include "mruby/proc.h"
10 #include "opcode.h"
11 
12 static mrb_code call_iseq[] = {
13  MKOP_A(OP_CALL, 0),
14 };
15 
16 struct RProc *
18 {
19  struct RProc *p;
20 
21  p = (struct RProc*)mrb_obj_alloc(mrb, MRB_TT_PROC, mrb->proc_class);
22  p->target_class = (mrb->c->ci) ? mrb->c->ci->target_class : 0;
23  p->body.irep = irep;
24  p->env = 0;
25 
26  return p;
27 }
28 
29 static inline void
30 closure_setup(mrb_state *mrb, struct RProc *p, int nlocals)
31 {
32  struct REnv *e;
33 
34  if (!mrb->c->ci->env) {
35  e = (struct REnv*)mrb_obj_alloc(mrb, MRB_TT_ENV, (struct RClass*)mrb->c->ci->proc->env);
36  e->flags= (unsigned int)nlocals;
37  e->mid = mrb->c->ci->mid;
38  e->cioff = mrb->c->ci - mrb->c->cibase;
39  e->stack = mrb->c->stack;
40  mrb->c->ci->env = e;
41  }
42  else {
43  e = mrb->c->ci->env;
44  }
45  p->env = e;
46 }
47 
48 struct RProc *
50 {
51  struct RProc *p = mrb_proc_new(mrb, irep);
52 
53  closure_setup(mrb, p, mrb->c->ci->proc->body.irep->nlocals);
54  return p;
55 }
56 
57 struct RProc *
59 {
60  struct RProc *p;
61 
62  p = (struct RProc*)mrb_obj_alloc(mrb, MRB_TT_PROC, mrb->proc_class);
63  p->body.func = func;
64  p->flags |= MRB_PROC_CFUNC;
65 
66  return p;
67 }
68 
69 struct RProc *
71 {
72  struct RProc *p = mrb_proc_new_cfunc(mrb, func);
73 
74  closure_setup(mrb, p, nlocals);
75  return p;
76 }
77 
78 void
79 mrb_proc_copy(struct RProc *a, struct RProc *b)
80 {
81  a->flags = b->flags;
82  a->body = b->body;
83  a->target_class = b->target_class;
84  a->env = b->env;
85 }
86 
87 static mrb_value
88 mrb_proc_initialize(mrb_state *mrb, mrb_value self)
89 {
90  mrb_value blk;
91 
92  mrb_get_args(mrb, "&", &blk);
93  if (mrb_nil_p(blk)) {
94  /* Calling Proc.new without a block is not implemented yet */
95  mrb_raise(mrb, E_ARGUMENT_ERROR, "tried to create Proc object without a block");
96  }
97  else {
99  }
100  return self;
101 }
102 
103 static mrb_value
104 mrb_proc_init_copy(mrb_state *mrb, mrb_value self)
105 {
106  mrb_value proc;
107 
108  mrb_get_args(mrb, "o", &proc);
109  if (mrb_type(proc) != MRB_TT_PROC) {
110  mrb_raise(mrb, E_ARGUMENT_ERROR, "not a proc");
111  }
113  return self;
114 }
115 
116 int
118 {
119  return MRB_PROC_CFUNC_P(p);
120 }
121 
122 mrb_value
124 {
125  return (p->body.func)(mrb, self);
126 }
127 
128 mrb_code*
129 mrb_proc_iseq(mrb_state *mrb, struct RProc *p)
130 {
131  return p->body.irep->iseq;
132 }
133 
134 /* 15.2.17.4.2 */
135 static mrb_value
136 mrb_proc_arity(mrb_state *mrb, mrb_value self)
137 {
138  struct RProc *p = mrb_proc_ptr(self);
139  mrb_code *iseq = mrb_proc_iseq(mrb, p);
140  mrb_aspec aspec = GETARG_Ax(*iseq);
141  int ma, ra, pa, arity;
142 
143  ma = MRB_ASPEC_REQ(aspec);
144  ra = MRB_ASPEC_REST(aspec);
145  pa = MRB_ASPEC_POST(aspec);
146  arity = ra ? -(ma + pa + 1) : ma + pa;
147 
148  return mrb_fixnum_value(arity);
149 }
150 
151 /* 15.3.1.2.6 */
152 /* 15.3.1.3.27 */
153 /*
154  * call-seq:
155  * lambda { |...| block } -> a_proc
156  *
157  * Equivalent to <code>Proc.new</code>, except the resulting Proc objects
158  * check the number of parameters passed when called.
159  */
160 static mrb_value
161 proc_lambda(mrb_state *mrb, mrb_value self)
162 {
163  mrb_value blk;
164  struct RProc *p;
165 
166  mrb_get_args(mrb, "&", &blk);
167  if (mrb_nil_p(blk)) {
168  mrb_raise(mrb, E_ARGUMENT_ERROR, "tried to create Proc object without a block");
169  }
170  p = mrb_proc_ptr(blk);
171  if (!MRB_PROC_STRICT_P(p)) {
172  struct RProc *p2 = (struct RProc*)mrb_obj_alloc(mrb, MRB_TT_PROC, p->c);
173  mrb_proc_copy(p2, p);
174  p2->flags |= MRB_PROC_STRICT;
175  return mrb_obj_value(p2);
176  }
177  return blk;
178 }
179 
180 void
182 {
183  struct RProc *m;
184  mrb_irep *call_irep = (mrb_irep *)mrb_alloca(mrb, sizeof(mrb_irep));
185  static const mrb_irep mrb_irep_zero = { 0 };
186 
187  if ( call_iseq == NULL || call_irep == NULL )
188  return;
189 
190  *call_irep = mrb_irep_zero;
191  call_irep->flags = MRB_ISEQ_NO_FREE;
192  call_irep->idx = -1;
193  call_irep->iseq = call_iseq;
194  call_irep->ilen = 1;
195 
196  mrb->proc_class = mrb_define_class(mrb, "Proc", mrb->object_class);
198 
199  mrb_define_method(mrb, mrb->proc_class, "initialize", mrb_proc_initialize, MRB_ARGS_NONE());
200  mrb_define_method(mrb, mrb->proc_class, "initialize_copy", mrb_proc_init_copy, MRB_ARGS_REQ(1));
201  mrb_define_method(mrb, mrb->proc_class, "arity", mrb_proc_arity, MRB_ARGS_NONE());
202 
203  m = mrb_proc_new(mrb, call_irep);
204  mrb_define_method_raw(mrb, mrb->proc_class, mrb_intern2(mrb, "call", 4), m);
205  mrb_define_method_raw(mrb, mrb->proc_class, mrb_intern2(mrb, "[]", 2), m);
206 
207  mrb_define_class_method(mrb, mrb->kernel_module, "lambda", proc_lambda, MRB_ARGS_NONE()); /* 15.3.1.2.6 */
208  mrb_define_method(mrb, mrb->kernel_module, "lambda", proc_lambda, MRB_ARGS_NONE()); /* 15.3.1.3.27 */
209 }