source: EcnlProtoTool/trunk/mruby-1.3.0/src/proc.c@ 331

Last change on this file since 331 was 331, checked in by coas-nagasima, 6 years ago

prototoolに関連するプロジェクトをnewlibからmuslを使うよう変更・更新
ntshellをnewlibの下位の実装から、muslのsyscallの実装に変更・更新
以下のOSSをアップデート
・mruby-1.3.0
・musl-1.1.18
・onigmo-6.1.3
・tcc-0.9.27
以下のOSSを追加
・openssl-1.1.0e
・curl-7.57.0
・zlib-1.2.11
以下のmrbgemsを追加
・iij/mruby-digest
・iij/mruby-env
・iij/mruby-errno
・iij/mruby-iijson
・iij/mruby-ipaddr
・iij/mruby-mock
・iij/mruby-require
・iij/mruby-tls-openssl

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 6.9 KB
Line 
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 <mruby/opcode.h>
11
12static mrb_code call_iseq[] = {
13 MKOP_A(OP_CALL, 0),
14};
15
16struct RProc *
17mrb_proc_new(mrb_state *mrb, mrb_irep *irep)
18{
19 struct RProc *p;
20 mrb_callinfo *ci = mrb->c->ci;
21
22 p = (struct RProc*)mrb_obj_alloc(mrb, MRB_TT_PROC, mrb->proc_class);
23 p->target_class = 0;
24 if (ci) {
25 if (ci->proc)
26 p->target_class = ci->proc->target_class;
27 if (!p->target_class)
28 p->target_class = ci->target_class;
29 }
30 p->body.irep = irep;
31 p->env = 0;
32 mrb_irep_incref(mrb, irep);
33
34 return p;
35}
36
37static struct REnv*
38env_new(mrb_state *mrb, int nlocals)
39{
40 struct REnv *e;
41
42 e = (struct REnv*)mrb_obj_alloc(mrb, MRB_TT_ENV, (struct RClass*)mrb->c->ci->proc->env);
43 MRB_SET_ENV_STACK_LEN(e, nlocals);
44 e->cxt.c = mrb->c;
45 e->cioff = mrb->c->ci - mrb->c->cibase;
46 e->stack = mrb->c->stack;
47
48 return e;
49}
50
51static void
52closure_setup(mrb_state *mrb, struct RProc *p, int nlocals)
53{
54 struct REnv *e;
55
56 if (!mrb->c->ci->env) {
57 e = env_new(mrb, nlocals);
58 mrb->c->ci->env = e;
59 }
60 else {
61 e = mrb->c->ci->env;
62 }
63 p->env = e;
64 mrb_field_write_barrier(mrb, (struct RBasic *)p, (struct RBasic *)p->env);
65}
66
67struct RProc *
68mrb_closure_new(mrb_state *mrb, mrb_irep *irep)
69{
70 struct RProc *p = mrb_proc_new(mrb, irep);
71
72 closure_setup(mrb, p, mrb->c->ci->proc->body.irep->nlocals);
73 return p;
74}
75
76MRB_API struct RProc *
77mrb_proc_new_cfunc(mrb_state *mrb, mrb_func_t func)
78{
79 struct RProc *p;
80
81 p = (struct RProc*)mrb_obj_alloc(mrb, MRB_TT_PROC, mrb->proc_class);
82 p->body.func = func;
83 p->flags |= MRB_PROC_CFUNC;
84 p->env = 0;
85
86 return p;
87}
88
89MRB_API struct RProc *
90mrb_proc_new_cfunc_with_env(mrb_state *mrb, mrb_func_t func, mrb_int argc, const mrb_value *argv)
91{
92 struct RProc *p = mrb_proc_new_cfunc(mrb, func);
93 struct REnv *e;
94 int i;
95
96 p->env = e = env_new(mrb, argc);
97 mrb_field_write_barrier(mrb, (struct RBasic *)p, (struct RBasic *)p->env);
98 MRB_ENV_UNSHARE_STACK(e);
99 e->stack = (mrb_value*)mrb_malloc(mrb, sizeof(mrb_value) * argc);
100 if (argv) {
101 for (i = 0; i < argc; ++i) {
102 e->stack[i] = argv[i];
103 }
104 }
105 else {
106 for (i = 0; i < argc; ++i) {
107 SET_NIL_VALUE(e->stack[i]);
108 }
109 }
110 return p;
111}
112
113MRB_API struct RProc *
114mrb_closure_new_cfunc(mrb_state *mrb, mrb_func_t func, int nlocals)
115{
116 return mrb_proc_new_cfunc_with_env(mrb, func, nlocals, NULL);
117}
118
119MRB_API mrb_value
120mrb_proc_cfunc_env_get(mrb_state *mrb, mrb_int idx)
121{
122 struct RProc *p = mrb->c->ci->proc;
123 struct REnv *e = p->env;
124
125 if (!MRB_PROC_CFUNC_P(p)) {
126 mrb_raise(mrb, E_TYPE_ERROR, "Can't get cfunc env from non-cfunc proc.");
127 }
128 if (!e) {
129 mrb_raise(mrb, E_TYPE_ERROR, "Can't get cfunc env from cfunc Proc without REnv.");
130 }
131 if (idx < 0 || MRB_ENV_STACK_LEN(e) <= idx) {
132 mrb_raisef(mrb, E_INDEX_ERROR, "Env index out of range: %S (expected: 0 <= index < %S)",
133 mrb_fixnum_value(idx), mrb_fixnum_value(MRB_ENV_STACK_LEN(e)));
134 }
135
136 return e->stack[idx];
137}
138
139void
140mrb_proc_copy(struct RProc *a, struct RProc *b)
141{
142 a->flags = b->flags;
143 a->body = b->body;
144 if (!MRB_PROC_CFUNC_P(a) && a->body.irep) {
145 a->body.irep->refcnt++;
146 }
147 a->target_class = b->target_class;
148 a->env = b->env;
149}
150
151static mrb_value
152mrb_proc_s_new(mrb_state *mrb, mrb_value proc_class)
153{
154 mrb_value blk;
155 mrb_value proc;
156 struct RProc *p;
157
158 mrb_get_args(mrb, "&", &blk);
159 if (mrb_nil_p(blk)) {
160 /* Calling Proc.new without a block is not implemented yet */
161 mrb_raise(mrb, E_ARGUMENT_ERROR, "tried to create Proc object without a block");
162 }
163 p = (struct RProc *)mrb_obj_alloc(mrb, MRB_TT_PROC, mrb_class_ptr(proc_class));
164 mrb_proc_copy(p, mrb_proc_ptr(blk));
165 proc = mrb_obj_value(p);
166 mrb_funcall_with_block(mrb, proc, mrb_intern_lit(mrb, "initialize"), 0, NULL, blk);
167 return proc;
168}
169
170static mrb_value
171mrb_proc_init_copy(mrb_state *mrb, mrb_value self)
172{
173 mrb_value proc;
174
175 mrb_get_args(mrb, "o", &proc);
176 if (mrb_type(proc) != MRB_TT_PROC) {
177 mrb_raise(mrb, E_ARGUMENT_ERROR, "not a proc");
178 }
179 mrb_proc_copy(mrb_proc_ptr(self), mrb_proc_ptr(proc));
180 return self;
181}
182
183int
184mrb_proc_cfunc_p(struct RProc *p)
185{
186 return MRB_PROC_CFUNC_P(p);
187}
188
189mrb_value
190mrb_proc_call_cfunc(mrb_state *mrb, struct RProc *p, mrb_value self)
191{
192 return (p->body.func)(mrb, self);
193}
194
195/* 15.2.17.4.2 */
196static mrb_value
197mrb_proc_arity(mrb_state *mrb, mrb_value self)
198{
199 struct RProc *p = mrb_proc_ptr(self);
200 struct mrb_irep *irep;
201 mrb_code *iseq;
202 mrb_aspec aspec;
203 int ma, op, ra, pa, arity;
204
205 if (MRB_PROC_CFUNC_P(p)) {
206 /* TODO cfunc aspec not implemented yet */
207 return mrb_fixnum_value(-1);
208 }
209
210 irep = p->body.irep;
211 if (!irep) {
212 return mrb_fixnum_value(0);
213 }
214
215 iseq = irep->iseq;
216 /* arity is depend on OP_ENTER */
217 if (GET_OPCODE(*iseq) != OP_ENTER) {
218 return mrb_fixnum_value(0);
219 }
220
221 aspec = GETARG_Ax(*iseq);
222 ma = MRB_ASPEC_REQ(aspec);
223 op = MRB_ASPEC_OPT(aspec);
224 ra = MRB_ASPEC_REST(aspec);
225 pa = MRB_ASPEC_POST(aspec);
226 arity = ra || (MRB_PROC_STRICT_P(p) && op) ? -(ma + pa + 1) : ma + pa;
227
228 return mrb_fixnum_value(arity);
229}
230
231/* 15.3.1.2.6 */
232/* 15.3.1.3.27 */
233/*
234 * call-seq:
235 * lambda { |...| block } -> a_proc
236 *
237 * Equivalent to <code>Proc.new</code>, except the resulting Proc objects
238 * check the number of parameters passed when called.
239 */
240static mrb_value
241proc_lambda(mrb_state *mrb, mrb_value self)
242{
243 mrb_value blk;
244 struct RProc *p;
245
246 mrb_get_args(mrb, "&", &blk);
247 if (mrb_nil_p(blk)) {
248 mrb_raise(mrb, E_ARGUMENT_ERROR, "tried to create Proc object without a block");
249 }
250 if (mrb_type(blk) != MRB_TT_PROC) {
251 mrb_raise(mrb, E_ARGUMENT_ERROR, "not a proc");
252 }
253 p = mrb_proc_ptr(blk);
254 if (!MRB_PROC_STRICT_P(p)) {
255 struct RProc *p2 = (struct RProc*)mrb_obj_alloc(mrb, MRB_TT_PROC, p->c);
256 mrb_proc_copy(p2, p);
257 p2->flags |= MRB_PROC_STRICT;
258 return mrb_obj_value(p2);
259 }
260 return blk;
261}
262
263void
264mrb_init_proc(mrb_state *mrb)
265{
266 struct RProc *m;
267 mrb_irep *call_irep = (mrb_irep *)mrb_malloc(mrb, sizeof(mrb_irep));
268 static const mrb_irep mrb_irep_zero = { 0 };
269
270 *call_irep = mrb_irep_zero;
271 call_irep->flags = MRB_ISEQ_NO_FREE;
272 call_irep->iseq = call_iseq;
273 call_irep->ilen = 1;
274 call_irep->nregs = 2; /* receiver and block */
275
276 mrb_define_class_method(mrb, mrb->proc_class, "new", mrb_proc_s_new, MRB_ARGS_ANY());
277 mrb_define_method(mrb, mrb->proc_class, "initialize_copy", mrb_proc_init_copy, MRB_ARGS_REQ(1));
278 mrb_define_method(mrb, mrb->proc_class, "arity", mrb_proc_arity, MRB_ARGS_NONE());
279
280 m = mrb_proc_new(mrb, call_irep);
281 mrb_define_method_raw(mrb, mrb->proc_class, mrb_intern_lit(mrb, "call"), m);
282 mrb_define_method_raw(mrb, mrb->proc_class, mrb_intern_lit(mrb, "[]"), m);
283
284 mrb_define_class_method(mrb, mrb->kernel_module, "lambda", proc_lambda, MRB_ARGS_NONE()); /* 15.3.1.2.6 */
285 mrb_define_method(mrb, mrb->kernel_module, "lambda", proc_lambda, MRB_ARGS_NONE()); /* 15.3.1.3.27 */
286}
Note: See TracBrowser for help on using the repository browser.