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