Imported Upstream version 1.46.0
[platform/upstream/nghttp2.git] / third-party / mruby / mrbgems / mruby-method / src / method.c
1 #include "mruby.h"
2 #include "mruby/array.h"
3 #include "mruby/class.h"
4 #include "mruby/variable.h"
5 #include "mruby/proc.h"
6 #include "mruby/string.h"
7
8 static struct RObject *
9 method_object_alloc(mrb_state *mrb, struct RClass *mclass)
10 {
11   return (struct RObject*)mrb_obj_alloc(mrb, MRB_TT_OBJECT, mclass);
12 }
13
14 static void
15 bind_check(mrb_state *mrb, mrb_value recv, mrb_value owner)
16 {
17   if (!mrb_module_p(owner) &&
18       mrb_class_ptr(owner) != mrb_obj_class(mrb, recv) &&
19       !mrb_obj_is_kind_of(mrb, recv, mrb_class_ptr(owner))) {
20     if (mrb_sclass_p(owner)) {
21       mrb_raise(mrb, E_TYPE_ERROR, "singleton method called for a different object");
22     } else {
23       mrb_raisef(mrb, E_TYPE_ERROR, "bind argument must be an instance of %v", owner);
24     }
25   }
26 }
27
28 static mrb_value
29 unbound_method_bind(mrb_state *mrb, mrb_value self)
30 {
31   struct RObject *me;
32   mrb_value owner = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_owner"));
33   mrb_value name = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_name"));
34   mrb_value proc = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_proc"));
35   mrb_value klass = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_klass"));
36   mrb_value recv = mrb_get_arg1(mrb);
37
38   bind_check(mrb, recv, owner);
39   me = method_object_alloc(mrb, mrb_class_get(mrb, "Method"));
40   mrb_obj_iv_set(mrb, me, mrb_intern_lit(mrb, "_owner"), owner);
41   mrb_obj_iv_set(mrb, me, mrb_intern_lit(mrb, "_recv"), recv);
42   mrb_obj_iv_set(mrb, me, mrb_intern_lit(mrb, "_name"), name);
43   mrb_obj_iv_set(mrb, me, mrb_intern_lit(mrb, "_proc"), proc);
44   mrb_obj_iv_set(mrb, me, mrb_intern_lit(mrb, "_klass"), klass);
45
46   return mrb_obj_value(me);
47 }
48
49 #define IV_GET(value, name) mrb_iv_get(mrb, value, mrb_intern_lit(mrb, name))
50 static mrb_value
51 method_eql(mrb_state *mrb, mrb_value self)
52 {
53   mrb_value other = mrb_get_arg1(mrb);
54   mrb_value receiver, orig_proc, other_proc;
55   struct RClass *owner, *klass;
56   struct RProc *orig_rproc, *other_rproc;
57
58   if (!mrb_obj_is_instance_of(mrb, other, mrb_class(mrb, self)))
59     return mrb_false_value();
60
61   if (mrb_class(mrb, self) != mrb_class(mrb, other))
62     return mrb_false_value();
63
64   klass = mrb_class_ptr(IV_GET(self, "_klass"));
65   if (klass != mrb_class_ptr(IV_GET(other, "_klass")))
66     return mrb_false_value();
67
68   owner = mrb_class_ptr(IV_GET(self, "_owner"));
69   if (owner != mrb_class_ptr(IV_GET(other, "_owner")))
70     return mrb_false_value();
71
72   receiver = IV_GET(self, "_recv");
73   if (!mrb_obj_equal(mrb, receiver, IV_GET(other, "_recv")))
74     return mrb_false_value();
75
76   orig_proc = IV_GET(self, "_proc");
77   other_proc = IV_GET(other, "_proc");
78   if (mrb_nil_p(orig_proc) && mrb_nil_p(other_proc)) {
79     if (mrb_symbol(IV_GET(self, "_name")) == mrb_symbol(IV_GET(other, "_name")))
80       return mrb_true_value();
81     else
82       return mrb_false_value();
83   }
84
85   if (mrb_nil_p(orig_proc))
86     return mrb_false_value();
87   if (mrb_nil_p(other_proc))
88     return mrb_false_value();
89
90   orig_rproc = mrb_proc_ptr(orig_proc);
91   other_rproc = mrb_proc_ptr(other_proc);
92   if (MRB_PROC_CFUNC_P(orig_rproc)) {
93     if (!MRB_PROC_CFUNC_P(other_rproc))
94       return mrb_false_value();
95     if (orig_rproc->body.func != other_rproc->body.func)
96       return mrb_false_value();
97   }
98   else {
99     if (MRB_PROC_CFUNC_P(other_rproc))
100       return mrb_false_value();
101     if (orig_rproc->body.irep != other_rproc->body.irep)
102       return mrb_false_value();
103   }
104
105   return mrb_true_value();
106 }
107
108 #undef IV_GET
109
110 static mrb_value
111 mcall(mrb_state *mrb, mrb_value recv, mrb_value proc, mrb_value name, struct RClass *owner,
112       mrb_int argc, mrb_value *argv, mrb_value block)
113 {
114   mrb_value ret;
115   mrb_sym orig_mid = mrb->c->ci->mid;
116
117   mrb->c->ci->mid = mrb_symbol(name);
118   if (mrb_nil_p(proc)) {
119     mrb_value missing_argv = mrb_ary_new_from_values(mrb, argc, argv);
120     mrb_ary_unshift(mrb, missing_argv, name);
121     ret = mrb_funcall_argv(mrb, recv, mrb_intern_lit(mrb, "method_missing"), argc + 1, RARRAY_PTR(missing_argv));
122   }
123   else if (!mrb_nil_p(block)) {
124     /*
125       workaround since `mrb_yield_with_class` does not support passing block as parameter
126       need new API that initializes `mrb->c->stack[argc+1]` with block passed by argument
127     */
128     ret = mrb_funcall_with_block(mrb, recv, mrb_symbol(name), argc, argv, block);
129   }
130   else {
131     ret = mrb_yield_with_class(mrb, proc, argc, argv, recv, owner);
132   }
133   mrb->c->ci->mid = orig_mid;
134   return ret;
135 }
136
137 static mrb_value
138 method_call(mrb_state *mrb, mrb_value self)
139 {
140   mrb_value proc = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_proc"));
141   mrb_value name = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_name"));
142   mrb_value recv = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_recv"));
143   struct RClass *owner = mrb_class_ptr(mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_owner")));
144   mrb_int argc;
145   mrb_value *argv, block;
146
147   mrb_get_args(mrb, "*&", &argv, &argc, &block);
148   return mcall(mrb, recv, proc, name, owner, argc, argv, block);
149 }
150
151 static mrb_value
152 method_bcall(mrb_state *mrb, mrb_value self)
153 {
154   mrb_value proc = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_proc"));
155   mrb_value name = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_name"));
156   mrb_value recv = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_recv"));
157   mrb_value owner = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_owner"));
158   mrb_int argc;
159   mrb_value *argv, block;
160
161   mrb_get_args(mrb, "o*&", &recv, &argv, &argc, &block);
162   bind_check(mrb, recv, owner);
163   return mcall(mrb, recv, proc, name, mrb_class_ptr(owner), argc, argv, block);
164 }
165
166 static mrb_value
167 method_unbind(mrb_state *mrb, mrb_value self)
168 {
169   struct RObject *ume;
170   mrb_value owner = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_owner"));
171   mrb_value name = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_name"));
172   mrb_value proc = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_proc"));
173   mrb_value klass = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_klass"));
174
175   ume = method_object_alloc(mrb, mrb_class_get(mrb, "UnboundMethod"));
176   mrb_obj_iv_set(mrb, ume, mrb_intern_lit(mrb, "_owner"), owner);
177   mrb_obj_iv_set(mrb, ume, mrb_intern_lit(mrb, "_recv"), mrb_nil_value());
178   mrb_obj_iv_set(mrb, ume, mrb_intern_lit(mrb, "_name"), name);
179   mrb_obj_iv_set(mrb, ume, mrb_intern_lit(mrb, "_proc"), proc);
180   mrb_obj_iv_set(mrb, ume, mrb_intern_lit(mrb, "_klass"), klass);
181
182   return mrb_obj_value(ume);
183 }
184
185 static struct RProc *
186 method_search_vm(mrb_state *mrb, struct RClass **cp, mrb_sym mid)
187 {
188   mrb_method_t m = mrb_method_search_vm(mrb, cp, mid);
189   if (MRB_METHOD_UNDEF_P(m))
190     return NULL;
191   if (MRB_METHOD_PROC_P(m))
192     return MRB_METHOD_PROC(m);
193   return mrb_proc_new_cfunc(mrb, MRB_METHOD_FUNC(m));
194 }
195
196 static mrb_value
197 method_super_method(mrb_state *mrb, mrb_value self)
198 {
199   mrb_value recv = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_recv"));
200   mrb_value klass = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_klass"));
201   mrb_value owner = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_owner"));
202   mrb_value name = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_name"));
203   struct RClass *super, *rklass;
204   struct RProc *proc;
205   struct RObject *me;
206
207   switch (mrb_type(klass)) {
208     case MRB_TT_SCLASS:
209       super = mrb_class_ptr(klass)->super->super;
210       break;
211     case MRB_TT_ICLASS:
212       super = mrb_class_ptr(klass)->super;
213       break;
214     default:
215       super = mrb_class_ptr(owner)->super;
216       break;
217   }
218
219   proc = method_search_vm(mrb, &super, mrb_symbol(name));
220   if (!proc)
221     return mrb_nil_value();
222
223   rklass = super;
224   while (super->tt == MRB_TT_ICLASS)
225     super = super->c;
226
227   me = method_object_alloc(mrb, mrb_obj_class(mrb, self));
228   mrb_obj_iv_set(mrb, me, mrb_intern_lit(mrb, "_owner"), mrb_obj_value(super));
229   mrb_obj_iv_set(mrb, me, mrb_intern_lit(mrb, "_recv"), recv);
230   mrb_obj_iv_set(mrb, me, mrb_intern_lit(mrb, "_name"), name);
231   mrb_obj_iv_set(mrb, me, mrb_intern_lit(mrb, "_proc"), mrb_obj_value(proc));
232   mrb_obj_iv_set(mrb, me, mrb_intern_lit(mrb, "_klass"), mrb_obj_value(rklass));
233
234   return mrb_obj_value(me);
235 }
236
237 static mrb_value
238 method_arity(mrb_state *mrb, mrb_value self)
239 {
240   mrb_value proc = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_proc"));
241   mrb_int arity = mrb_nil_p(proc) ? -1 : mrb_proc_arity(mrb_proc_ptr(proc));
242   return mrb_fixnum_value(arity);
243 }
244
245 static mrb_value
246 method_source_location(mrb_state *mrb, mrb_value self)
247 {
248   mrb_value proc = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_proc"));
249   struct RProc *rproc;
250   struct RClass *orig;
251   mrb_value ret;
252
253   if (mrb_nil_p(proc))
254     return mrb_nil_value();
255
256   rproc = mrb_proc_ptr(proc);
257   orig = rproc->c;
258   rproc->c = mrb->proc_class;
259   ret = mrb_funcall(mrb, proc, "source_location", 0);
260   rproc->c = orig;
261   return ret;
262 }
263
264 static mrb_value
265 method_parameters(mrb_state *mrb, mrb_value self)
266 {
267   mrb_value proc = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_proc"));
268   struct RProc *rproc;
269   struct RClass *orig;
270   mrb_value ret;
271
272   if (mrb_nil_p(proc)) {
273     mrb_value rest = mrb_symbol_value(mrb_intern_lit(mrb, "rest"));
274     mrb_value arest = mrb_ary_new_from_values(mrb, 1, &rest);
275     return mrb_ary_new_from_values(mrb, 1, &arest);
276   }
277
278   rproc = mrb_proc_ptr(proc);
279   orig = rproc->c;
280   rproc->c = mrb->proc_class;
281   ret = mrb_funcall(mrb, proc, "parameters", 0);
282   rproc->c = orig;
283   return ret;
284 }
285
286 static mrb_value
287 method_to_s(mrb_state *mrb, mrb_value self)
288 {
289   mrb_value owner = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_owner"));
290   mrb_value klass = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_klass"));
291   mrb_value name = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_name"));
292   mrb_value str = mrb_str_new_lit(mrb, "#<");
293   struct RClass *rklass;
294
295   mrb_str_cat_cstr(mrb, str, mrb_obj_classname(mrb, self));
296   mrb_str_cat_lit(mrb, str, ": ");
297   rklass = mrb_class_ptr(klass);
298   if (mrb_class_ptr(owner) == rklass) {
299     mrb_str_concat(mrb, str, owner);
300     mrb_str_cat_lit(mrb, str, "#");
301     mrb_str_concat(mrb, str, name);
302   }
303   else {
304     mrb_str_cat_cstr(mrb, str, mrb_class_name(mrb, rklass));
305     mrb_str_cat_lit(mrb, str, "(");
306     mrb_str_concat(mrb, str, owner);
307     mrb_str_cat_lit(mrb, str, ")#");
308     mrb_str_concat(mrb, str, name);
309   }
310   mrb_str_cat_lit(mrb, str, ">");
311   return str;
312 }
313
314 static void
315 mrb_search_method_owner(mrb_state *mrb, struct RClass *c, mrb_value obj, mrb_sym name, struct RClass **owner, struct RProc **proc, mrb_bool unbound)
316 {
317   mrb_value ret;
318
319   *owner = c;
320   *proc = method_search_vm(mrb, owner, name);
321   if (!*proc) {
322     if (unbound) {
323       goto name_error;
324     }
325     if (!mrb_respond_to(mrb, obj, mrb_intern_lit(mrb, "respond_to_missing?"))) {
326       goto name_error;
327     }
328     ret = mrb_funcall(mrb, obj, "respond_to_missing?", 2, mrb_symbol_value(name), mrb_true_value());
329     if (!mrb_test(ret)) {
330       goto name_error;
331     }
332     *owner = c;
333   }
334
335   while ((*owner)->tt == MRB_TT_ICLASS)
336     *owner = (*owner)->c;
337
338   return;
339
340 name_error:
341   mrb_raisef(mrb, E_NAME_ERROR, "undefined method '%n' for class '%C'", name, c);
342 }
343
344 static mrb_value
345 mrb_kernel_method(mrb_state *mrb, mrb_value self)
346 {
347   struct RClass *owner;
348   struct RProc *proc;
349   struct RObject *me;
350   mrb_sym name;
351
352   mrb_get_args(mrb, "n", &name);
353
354   mrb_search_method_owner(mrb, mrb_class(mrb, self), self, name, &owner, &proc, FALSE);
355
356   me = method_object_alloc(mrb, mrb_class_get(mrb, "Method"));
357   mrb_obj_iv_set(mrb, me, mrb_intern_lit(mrb, "_owner"), mrb_obj_value(owner));
358   mrb_obj_iv_set(mrb, me, mrb_intern_lit(mrb, "_recv"), self);
359   mrb_obj_iv_set(mrb, me, mrb_intern_lit(mrb, "_name"), mrb_symbol_value(name));
360   mrb_obj_iv_set(mrb, me, mrb_intern_lit(mrb, "_proc"), proc ? mrb_obj_value(proc) : mrb_nil_value());
361   mrb_obj_iv_set(mrb, me, mrb_intern_lit(mrb, "_klass"), mrb_obj_value(mrb_class(mrb, self)));
362
363   return mrb_obj_value(me);
364 }
365
366 static mrb_value
367 mrb_module_instance_method(mrb_state *mrb, mrb_value self)
368 {
369   struct RClass *owner;
370   struct RProc *proc;
371   struct RObject *ume;
372   mrb_sym name;
373
374   mrb_get_args(mrb, "n", &name);
375
376   mrb_search_method_owner(mrb, mrb_class_ptr(self), self, name, &owner, &proc, TRUE);
377
378   ume = method_object_alloc(mrb, mrb_class_get(mrb, "UnboundMethod"));
379   mrb_obj_iv_set(mrb, ume, mrb_intern_lit(mrb, "_owner"), mrb_obj_value(owner));
380   mrb_obj_iv_set(mrb, ume, mrb_intern_lit(mrb, "_recv"), mrb_nil_value());
381   mrb_obj_iv_set(mrb, ume, mrb_intern_lit(mrb, "_name"), mrb_symbol_value(name));
382   mrb_obj_iv_set(mrb, ume, mrb_intern_lit(mrb, "_proc"), proc ? mrb_obj_value(proc) : mrb_nil_value());
383   mrb_obj_iv_set(mrb, ume, mrb_intern_lit(mrb, "_klass"), self);
384
385   return mrb_obj_value(ume);
386 }
387
388 static mrb_value
389 method_owner(mrb_state *mrb, mrb_value self)
390 {
391   return mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_owner"));
392 }
393
394 static mrb_value
395 method_receiver(mrb_state *mrb, mrb_value self)
396 {
397   return mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_recv"));
398 }
399
400 static mrb_value
401 method_name(mrb_state *mrb, mrb_value self)
402 {
403   return mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_name"));
404 }
405
406 void
407 mrb_mruby_method_gem_init(mrb_state* mrb)
408 {
409   struct RClass *unbound_method = mrb_define_class(mrb, "UnboundMethod", mrb->object_class);
410   struct RClass *method = mrb_define_class(mrb, "Method", mrb->object_class);
411
412   mrb_undef_class_method(mrb, unbound_method, "new");
413   mrb_define_method(mrb, unbound_method, "bind", unbound_method_bind, MRB_ARGS_REQ(1));
414   mrb_define_method(mrb, unbound_method, "super_method", method_super_method, MRB_ARGS_NONE());
415   mrb_define_method(mrb, unbound_method, "==", method_eql, MRB_ARGS_REQ(1));
416   mrb_define_method(mrb, unbound_method, "eql?", method_eql, MRB_ARGS_REQ(1));
417   mrb_define_method(mrb, unbound_method, "to_s", method_to_s, MRB_ARGS_NONE());
418   mrb_define_method(mrb, unbound_method, "inspect", method_to_s, MRB_ARGS_NONE());
419   mrb_define_method(mrb, unbound_method, "arity", method_arity, MRB_ARGS_NONE());
420   mrb_define_method(mrb, unbound_method, "source_location", method_source_location, MRB_ARGS_NONE());
421   mrb_define_method(mrb, unbound_method, "parameters", method_parameters, MRB_ARGS_NONE());
422   mrb_define_method(mrb, unbound_method, "bind_call", method_bcall, MRB_ARGS_REQ(1)|MRB_ARGS_ANY());
423   mrb_define_method(mrb, unbound_method, "owner", method_owner, MRB_ARGS_NONE());
424   mrb_define_method(mrb, unbound_method, "name", method_name, MRB_ARGS_NONE());
425
426   mrb_undef_class_method(mrb, method, "new");
427   mrb_define_method(mrb, method, "==", method_eql, MRB_ARGS_REQ(1));
428   mrb_define_method(mrb, method, "eql?", method_eql, MRB_ARGS_REQ(1));
429   mrb_define_method(mrb, method, "to_s", method_to_s, MRB_ARGS_NONE());
430   mrb_define_method(mrb, method, "inspect", method_to_s, MRB_ARGS_NONE());
431   mrb_define_method(mrb, method, "call", method_call, MRB_ARGS_ANY());
432   mrb_define_method(mrb, method, "[]", method_call, MRB_ARGS_ANY());
433   mrb_define_method(mrb, method, "unbind", method_unbind, MRB_ARGS_NONE());
434   mrb_define_method(mrb, method, "super_method", method_super_method, MRB_ARGS_NONE());
435   mrb_define_method(mrb, method, "arity", method_arity, MRB_ARGS_NONE());
436   mrb_define_method(mrb, method, "source_location", method_source_location, MRB_ARGS_NONE());
437   mrb_define_method(mrb, method, "parameters", method_parameters, MRB_ARGS_NONE());
438   mrb_define_method(mrb, method, "owner", method_owner, MRB_ARGS_NONE());
439   mrb_define_method(mrb, method, "receiver", method_receiver, MRB_ARGS_NONE());
440   mrb_define_method(mrb, method, "name", method_name, MRB_ARGS_NONE());
441
442   mrb_define_method(mrb, mrb->kernel_module, "method", mrb_kernel_method, MRB_ARGS_REQ(1));
443
444   mrb_define_method(mrb, mrb->module_class, "instance_method", mrb_module_instance_method, MRB_ARGS_REQ(1));
445 }
446
447 void
448 mrb_mruby_method_gem_final(mrb_state* mrb)
449 {
450 }