/src/mruby/mrbgems/mruby-binding/src/binding.c
Line | Count | Source |
1 | | #include <mruby.h> |
2 | | #include <mruby/array.h> |
3 | | #include <mruby/class.h> |
4 | | #include <mruby/hash.h> |
5 | | #include <mruby/proc.h> |
6 | | #include <mruby/variable.h> |
7 | | #include <mruby/opcode.h> |
8 | | #include <mruby/debug.h> |
9 | | #include <mruby/internal.h> |
10 | | |
11 | 0 | #define BINDING_UPPER_DEFAULT 20 |
12 | | #define BINDING_UPPER_MINIMUM 10 |
13 | | #define BINDING_UPPER_MAXIMUM 100 |
14 | | |
15 | | #ifndef MRB_BINDING_UPPER_MAX |
16 | 0 | # define BINDING_UPPER_MAX BINDING_UPPER_DEFAULT |
17 | | #else |
18 | | # if (MRB_BINDING_UPPER_MAX) > BINDING_UPPER_MAXIMUM |
19 | | # define BINDING_UPPER_MAX BINDING_UPPER_MAXIMUM |
20 | | # elif (MRB_BINDING_UPPER_MAX) < BINDING_UPPER_MINIMUM |
21 | | # define BINDING_UPPER_MAX BINDING_UPPER_MINIMUM |
22 | | # else |
23 | | # define BINDING_UPPER_MAX MRB_BINDING_UPPER_MAX |
24 | | # endif |
25 | | #endif |
26 | | |
27 | | static mrb_int |
28 | | binding_extract_pc(mrb_state *mrb, mrb_value binding) |
29 | 0 | { |
30 | 0 | mrb_value obj = mrb_iv_get(mrb, binding, MRB_SYM(pc)); |
31 | 0 | if (mrb_nil_p(obj)) { |
32 | 0 | return -1; |
33 | 0 | } |
34 | 0 | else { |
35 | 0 | mrb_check_type(mrb, obj, MRB_TT_INTEGER); |
36 | 0 | return mrb_int(mrb, obj); |
37 | 0 | } |
38 | 0 | } |
39 | | |
40 | | const struct RProc * |
41 | | mrb_binding_extract_proc(mrb_state *mrb, mrb_value binding) |
42 | 2 | { |
43 | 2 | mrb_value obj = mrb_iv_get(mrb, binding, MRB_SYM(proc)); |
44 | 2 | mrb_check_type(mrb, obj, MRB_TT_PROC); |
45 | 2 | return mrb_proc_ptr(obj); |
46 | 2 | } |
47 | | |
48 | | struct REnv * |
49 | | mrb_binding_extract_env(mrb_state *mrb, mrb_value binding) |
50 | 2 | { |
51 | 2 | mrb_value obj = mrb_iv_get(mrb, binding, MRB_SYM(env)); |
52 | 2 | if (mrb_nil_p(obj)) { |
53 | 0 | return NULL; |
54 | 0 | } |
55 | 2 | else { |
56 | 2 | mrb_check_type(mrb, obj, MRB_TT_ENV); |
57 | 2 | return (struct REnv*)mrb_obj_ptr(obj); |
58 | 2 | } |
59 | 2 | } |
60 | | |
61 | | static mrb_irep * |
62 | | binding_irep_new_lvspace(mrb_state *mrb) |
63 | 4 | { |
64 | 4 | static const mrb_code iseq_dummy[] = { OP_RETURN, 0 }; |
65 | | |
66 | 4 | mrb_irep *irep = mrb_add_irep(mrb); |
67 | 4 | irep->flags = MRB_ISEQ_NO_FREE; |
68 | 4 | irep->iseq = iseq_dummy; |
69 | 4 | irep->ilen = sizeof(iseq_dummy) / sizeof(iseq_dummy[0]); |
70 | 4 | irep->lv = NULL; |
71 | 4 | irep->nlocals = 1; |
72 | 4 | irep->nregs = 1; |
73 | 4 | return irep; |
74 | 4 | } |
75 | | |
76 | | static struct RProc * |
77 | | binding_proc_new_lvspace(mrb_state *mrb, const struct RProc *upper, struct REnv *env) |
78 | 4 | { |
79 | 4 | struct RProc *lvspace = MRB_OBJ_ALLOC(mrb, MRB_TT_PROC, mrb->proc_class); |
80 | 4 | lvspace->body.irep = binding_irep_new_lvspace(mrb); |
81 | 4 | lvspace->upper = upper; |
82 | 4 | if (env && env->tt == MRB_TT_ENV) { |
83 | 4 | lvspace->e.env = env; |
84 | 4 | lvspace->flags |= MRB_PROC_ENVSET; |
85 | 4 | } |
86 | 4 | return lvspace; |
87 | 4 | } |
88 | | |
89 | | static struct REnv * |
90 | | binding_env_new_lvspace(mrb_state *mrb, const struct REnv *e) |
91 | 4 | { |
92 | 4 | struct REnv *env = MRB_OBJ_ALLOC(mrb, MRB_TT_ENV, NULL); |
93 | 4 | mrb_value *stacks = (mrb_value*)mrb_calloc(mrb, 1, sizeof(mrb_value)); |
94 | 4 | env->mid = 0; |
95 | 4 | env->stack = stacks; |
96 | 4 | if (e && e->stack && MRB_ENV_LEN(e) > 0) { |
97 | 4 | env->stack[0] = e->stack[0]; |
98 | 4 | } |
99 | 0 | else { |
100 | 0 | env->stack[0] = mrb_nil_value(); |
101 | 0 | } |
102 | 4 | MRB_ENV_SET_LEN(env, 1); |
103 | 4 | return env; |
104 | 4 | } |
105 | | |
106 | | static void |
107 | | binding_check_proc_upper_count(mrb_state *mrb, const struct RProc *proc) |
108 | 0 | { |
109 | 0 | for (size_t count = 0; proc && !MRB_PROC_CFUNC_P(proc); proc = proc->upper) { |
110 | 0 | count++; |
111 | 0 | if (count > BINDING_UPPER_MAX) { |
112 | 0 | mrb_raise(mrb, E_RUNTIME_ERROR, |
113 | 0 | "too many upper procs for local variables (mruby limitation; maximum is " MRB_STRINGIZE(BINDING_UPPER_MAX) ")"); |
114 | 0 | } |
115 | 0 | if (MRB_PROC_SCOPE_P(proc)) break; |
116 | 0 | } |
117 | 0 | } |
118 | | |
119 | | mrb_bool |
120 | | mrb_binding_p(mrb_state *mrb, mrb_value obj) |
121 | 2 | { |
122 | 2 | if (!mrb_obj_is_kind_of(mrb, obj, mrb_class_get_id(mrb, MRB_SYM(Binding)))) return FALSE; |
123 | 2 | if (mrb_type(obj) != MRB_TT_OBJECT) return FALSE; |
124 | 2 | if (!mrb_obj_iv_defined(mrb, mrb_obj_ptr(obj), MRB_SYM(proc))) return FALSE; |
125 | 2 | if (!mrb_obj_iv_defined(mrb, mrb_obj_ptr(obj), MRB_SYM(recv))) return FALSE; |
126 | 2 | if (!mrb_obj_iv_defined(mrb, mrb_obj_ptr(obj), MRB_SYM(env))) return FALSE; |
127 | 2 | return TRUE; |
128 | 2 | } |
129 | | |
130 | | static void |
131 | | binding_type_ensure(mrb_state *mrb, mrb_value obj) |
132 | 2 | { |
133 | 2 | if (mrb_binding_p(mrb, obj)) return; |
134 | 0 | mrb_raise(mrb, E_TYPE_ERROR, "not a binding"); |
135 | 2 | } |
136 | | |
137 | | static struct RProc* |
138 | | binding_wrap_lvspace(mrb_state *mrb, const struct RProc *proc, struct REnv **envp) |
139 | 4 | { |
140 | | /* |
141 | | * local variable space: It is a space to hold the top-level variable of |
142 | | * binding.eval and binding.local_variable_set. |
143 | | */ |
144 | | |
145 | 4 | struct RProc *lvspace = binding_proc_new_lvspace(mrb, proc, *envp); |
146 | 4 | *envp = binding_env_new_lvspace(mrb, *envp); |
147 | 4 | return lvspace; |
148 | 4 | } |
149 | | |
150 | | static mrb_value |
151 | | binding_initialize_copy(mrb_state *mrb, mrb_value binding) |
152 | 2 | { |
153 | 2 | mrb_value src = mrb_get_arg1(mrb); |
154 | 2 | binding_type_ensure(mrb, src); |
155 | 2 | const struct RProc *src_proc = mrb_binding_extract_proc(mrb, src); |
156 | 2 | struct REnv *src_env = mrb_binding_extract_env(mrb, src); |
157 | | |
158 | 2 | mrb_check_frozen(mrb, mrb_obj_ptr(binding)); |
159 | | |
160 | 2 | struct RProc *lvspace; |
161 | 2 | struct REnv *env; |
162 | 2 | if (MRB_ENV_LEN(src_env) < 2) { |
163 | | /* when local variables of src are self only */ |
164 | 2 | env = src_proc->e.env; |
165 | 2 | lvspace = binding_wrap_lvspace(mrb, src_proc->upper, &env); |
166 | 2 | } |
167 | 0 | else { |
168 | 0 | binding_check_proc_upper_count(mrb, src_proc); |
169 | |
|
170 | 0 | env = src_env; |
171 | 0 | lvspace = binding_wrap_lvspace(mrb, src_proc, &env); |
172 | | |
173 | | // The reason for using the mrb_obj_iv_set_force() function is to allow local |
174 | | // variables to be modified even if src is frozen. This behavior is CRuby imitation. |
175 | 0 | src_proc = binding_wrap_lvspace(mrb, src_proc, &src_env); |
176 | 0 | struct RObject *o = mrb_obj_ptr(src); |
177 | 0 | mrb_obj_iv_set_force(mrb, o, MRB_SYM(proc), mrb_obj_value((struct RProc*)src_proc)); |
178 | 0 | mrb_obj_iv_set_force(mrb, o, MRB_SYM(env), mrb_obj_value(src_env)); |
179 | 0 | } |
180 | 2 | mrb_iv_set(mrb, binding, MRB_SYM(proc), mrb_obj_value(lvspace)); |
181 | 2 | mrb_iv_set(mrb, binding, MRB_SYM(env), mrb_obj_value(env)); |
182 | | |
183 | 2 | return binding; |
184 | 2 | } |
185 | | |
186 | | static mrb_noreturn void |
187 | | badname_error(mrb_state *mrb, mrb_sym id) |
188 | 0 | { |
189 | 0 | mrb_raisef(mrb, E_NAME_ERROR, "wrong local variable name %!n for binding", id); |
190 | 0 | } |
191 | | |
192 | | static void |
193 | | binding_local_variable_name_check(mrb_state *mrb, mrb_sym id) |
194 | 0 | { |
195 | 0 | if (id == 0) { |
196 | 0 | badname_error(mrb, id); |
197 | 0 | } |
198 | | |
199 | 0 | mrb_int len; |
200 | 0 | const char *name = mrb_sym_name_len(mrb, id, &len); |
201 | 0 | if (len == 0) { |
202 | 0 | badname_error(mrb, id); |
203 | 0 | } |
204 | | |
205 | 0 | if (ISASCII(*name) && !(*name == '_' || ISLOWER(*name))) { |
206 | 0 | badname_error(mrb, id); |
207 | 0 | } |
208 | 0 | len--; |
209 | 0 | name++; |
210 | |
|
211 | 0 | for (; len > 0; len--, name++) { |
212 | 0 | if (ISASCII(*name) && !(*name == '_' || ISALNUM(*name))) { |
213 | 0 | badname_error(mrb, id); |
214 | 0 | } |
215 | 0 | } |
216 | 0 | } |
217 | | |
218 | | static mrb_value * |
219 | | binding_local_variable_search(mrb_state *mrb, const struct RProc *proc, struct REnv *env, mrb_sym varname) |
220 | 0 | { |
221 | 0 | binding_local_variable_name_check(mrb, varname); |
222 | |
|
223 | 0 | while (proc) { |
224 | 0 | if (MRB_PROC_CFUNC_P(proc)) break; |
225 | | |
226 | 0 | const mrb_irep *irep = proc->body.irep; |
227 | 0 | const mrb_sym *lv; |
228 | 0 | if (irep && (lv = irep->lv)) { |
229 | 0 | for (int i = 0; i + 1 < irep->nlocals; i++, lv++) { |
230 | 0 | if (varname == *lv) { |
231 | 0 | return (env && MRB_ENV_LEN(env) > i) ? &env->stack[i + 1] : NULL; |
232 | 0 | } |
233 | 0 | } |
234 | 0 | } |
235 | | |
236 | 0 | if (MRB_PROC_SCOPE_P(proc)) break; |
237 | 0 | env = MRB_PROC_ENV(proc); |
238 | 0 | proc = proc->upper; |
239 | 0 | } |
240 | | |
241 | 0 | return NULL; |
242 | 0 | } |
243 | | |
244 | | /* |
245 | | * call-seq: |
246 | | * local_variable_defined?(symbol) -> bool |
247 | | * |
248 | | * Returns true if a local variable with the given name is defined |
249 | | * in the binding's context, false otherwise. |
250 | | * |
251 | | * def foo |
252 | | * a = 1 |
253 | | * b = binding |
254 | | * b.local_variable_defined?(:a) #=> true |
255 | | * b.local_variable_defined?(:c) #=> false |
256 | | * end |
257 | | * |
258 | | * x = 10 |
259 | | * bind = binding |
260 | | * bind.local_variable_defined?(:x) #=> true |
261 | | * bind.local_variable_defined?(:y) #=> false |
262 | | * bind.local_variable_set(:y, 20) |
263 | | * bind.local_variable_defined?(:y) #=> true |
264 | | */ |
265 | | static mrb_value |
266 | | binding_local_variable_defined_p(mrb_state *mrb, mrb_value self) |
267 | 0 | { |
268 | 0 | mrb_sym varname; |
269 | 0 | mrb_get_args(mrb, "n", &varname); |
270 | |
|
271 | 0 | const struct RProc *proc = mrb_binding_extract_proc(mrb, self); |
272 | 0 | struct REnv *env = mrb_binding_extract_env(mrb, self); |
273 | 0 | mrb_value *e = binding_local_variable_search(mrb, proc, env, varname); |
274 | 0 | if (e) { |
275 | 0 | return mrb_true_value(); |
276 | 0 | } |
277 | 0 | else { |
278 | 0 | return mrb_false_value(); |
279 | 0 | } |
280 | 0 | } |
281 | | |
282 | | /* |
283 | | * call-seq: |
284 | | * local_variable_get(symbol) -> object |
285 | | * |
286 | | * Returns the value of the local variable with the given name |
287 | | * in the binding's context. Raises NameError if the variable |
288 | | * is not defined. |
289 | | * |
290 | | * def foo |
291 | | * a = 42 |
292 | | * b = "hello" |
293 | | * bind = binding |
294 | | * bind.local_variable_get(:a) #=> 42 |
295 | | * bind.local_variable_get(:b) #=> "hello" |
296 | | * bind.local_variable_get(:c) #=> NameError |
297 | | * end |
298 | | * |
299 | | * x = [1, 2, 3] |
300 | | * bind = binding |
301 | | * bind.local_variable_get(:x) #=> [1, 2, 3] |
302 | | * x = "modified" |
303 | | * bind.local_variable_get(:x) #=> "modified" |
304 | | */ |
305 | | static mrb_value |
306 | | binding_local_variable_get(mrb_state *mrb, mrb_value self) |
307 | 0 | { |
308 | 0 | mrb_sym varname; |
309 | 0 | mrb_get_args(mrb, "n", &varname); |
310 | |
|
311 | 0 | const struct RProc *proc = mrb_binding_extract_proc(mrb, self); |
312 | 0 | struct REnv *env = mrb_binding_extract_env(mrb, self); |
313 | 0 | mrb_value *e = binding_local_variable_search(mrb, proc, env, varname); |
314 | 0 | if (!e) { |
315 | 0 | mrb_raisef(mrb, E_NAME_ERROR, "local variable %!n is not defined", varname); |
316 | 0 | } |
317 | | |
318 | 0 | return *e; |
319 | 0 | } |
320 | | |
321 | | /* |
322 | | * call-seq: |
323 | | * binding.local_variable_set(symbol, obj) -> obj |
324 | | * |
325 | | * Set local variable named symbol as obj in binding's context. |
326 | | * If the variable is not defined in the binding, it will be created. |
327 | | * |
328 | | * def foo |
329 | | * a = 1 |
330 | | * binding.local_variable_set(:a, 2) |
331 | | * binding.local_variable_set(:b, 3) |
332 | | * [a, b] #=> [2, 3] |
333 | | * end |
334 | | */ |
335 | | static mrb_value |
336 | | binding_local_variable_set(mrb_state *mrb, mrb_value self) |
337 | 0 | { |
338 | 0 | mrb_sym varname; |
339 | 0 | mrb_value obj; |
340 | 0 | mrb_get_args(mrb, "no", &varname, &obj); |
341 | |
|
342 | 0 | const struct RProc *proc = mrb_binding_extract_proc(mrb, self); |
343 | 0 | struct REnv *env = mrb_binding_extract_env(mrb, self); |
344 | 0 | mrb_value *e = binding_local_variable_search(mrb, proc, env, varname); |
345 | 0 | if (e) { |
346 | 0 | *e = obj; |
347 | 0 | if (!mrb_immediate_p(obj)) { |
348 | 0 | mrb_field_write_barrier(mrb, (struct RBasic*)env, (struct RBasic*)mrb_obj_ptr(obj)); |
349 | 0 | } |
350 | 0 | } |
351 | 0 | else { |
352 | 0 | mrb_proc_merge_lvar(mrb, (mrb_irep*)proc->body.irep, env, 1, &varname, &obj); |
353 | 0 | } |
354 | |
|
355 | 0 | return obj; |
356 | 0 | } |
357 | | |
358 | | /* |
359 | | * call-seq: |
360 | | * binding.local_variables -> array |
361 | | * |
362 | | * Returns an array of symbols representing the names of the local variables |
363 | | * in the binding. |
364 | | * |
365 | | * def foo |
366 | | * a = 1 |
367 | | * b = 2 |
368 | | * binding.local_variables #=> [:a, :b] |
369 | | * end |
370 | | */ |
371 | | static mrb_value |
372 | | binding_local_variables(mrb_state *mrb, mrb_value self) |
373 | 0 | { |
374 | 0 | const struct RProc *proc = mrb_proc_ptr(mrb_iv_get(mrb, self, MRB_SYM(proc))); |
375 | 0 | return mrb_proc_local_variables(mrb, proc); |
376 | 0 | } |
377 | | |
378 | | /* |
379 | | * call-seq: |
380 | | * binding.receiver -> object |
381 | | * |
382 | | * Returns the bound receiver of the binding object. |
383 | | * |
384 | | * class Demo |
385 | | * def get_binding |
386 | | * binding |
387 | | * end |
388 | | * end |
389 | | * Demo.new.get_binding.receiver #=> #<Demo:0x...> |
390 | | */ |
391 | | static mrb_value |
392 | | binding_receiver(mrb_state *mrb, mrb_value self) |
393 | 0 | { |
394 | 0 | return mrb_iv_get(mrb, self, MRB_SYM(recv)); |
395 | 0 | } |
396 | | |
397 | | /* |
398 | | * call-seq: |
399 | | * source_location -> [String, Integer] |
400 | | */ |
401 | | static mrb_value |
402 | | binding_source_location(mrb_state *mrb, mrb_value self) |
403 | 0 | { |
404 | 0 | if (mrb_iv_defined(mrb, self, MRB_SYM(source_location))) { |
405 | 0 | return mrb_iv_get(mrb, self, MRB_SYM(source_location)); |
406 | 0 | } |
407 | | |
408 | 0 | mrb_value srcloc; |
409 | 0 | const struct RProc *proc = mrb_binding_extract_proc(mrb, self); |
410 | 0 | if (!proc || MRB_PROC_CFUNC_P(proc) || |
411 | 0 | !proc->upper || MRB_PROC_CFUNC_P(proc->upper)) { |
412 | 0 | srcloc = mrb_nil_value(); |
413 | 0 | } |
414 | 0 | else { |
415 | 0 | const mrb_irep *irep = proc->upper->body.irep; |
416 | 0 | mrb_int pc = binding_extract_pc(mrb, self); |
417 | 0 | if (pc < 0) { |
418 | 0 | srcloc = mrb_nil_value(); |
419 | 0 | } |
420 | 0 | else { |
421 | 0 | const char *fname; |
422 | 0 | int32_t line; |
423 | |
|
424 | 0 | if (!mrb_debug_get_position(mrb, irep, (uint32_t)pc, &line, &fname)) { |
425 | 0 | srcloc = mrb_nil_value(); |
426 | 0 | } |
427 | 0 | else { |
428 | 0 | srcloc = mrb_assoc_new(mrb, mrb_str_new_cstr(mrb, fname), mrb_fixnum_value(line)); |
429 | 0 | } |
430 | 0 | } |
431 | 0 | } |
432 | |
|
433 | 0 | if (!mrb_frozen_p(mrb_obj_ptr(self))) { |
434 | 0 | mrb_iv_set(mrb, self, MRB_SYM(source_location), srcloc); |
435 | 0 | } |
436 | 0 | return srcloc; |
437 | 0 | } |
438 | | |
439 | | mrb_value |
440 | | mrb_binding_new(mrb_state *mrb, const struct RProc *proc, mrb_value recv, struct REnv *env) |
441 | 2 | { |
442 | 2 | struct RObject *binding = MRB_OBJ_ALLOC(mrb, MRB_TT_OBJECT, mrb_class_get_id(mrb, MRB_SYM(Binding))); |
443 | | |
444 | 2 | if (proc && !MRB_PROC_CFUNC_P(proc)) { |
445 | 2 | const mrb_irep *irep = proc->body.irep; |
446 | 2 | mrb_obj_iv_set(mrb, binding, MRB_SYM(pc), mrb_fixnum_value(mrb->c->ci[-1].pc - irep->iseq - 1 /* step back */)); |
447 | 2 | } |
448 | 2 | proc = binding_wrap_lvspace(mrb, proc, &env); |
449 | | |
450 | 2 | mrb_obj_iv_set(mrb, binding, MRB_SYM(proc), mrb_obj_value((void*)proc)); |
451 | 2 | mrb_obj_iv_set(mrb, binding, MRB_SYM(recv), recv); |
452 | 2 | mrb_obj_iv_set(mrb, binding, MRB_SYM(env), mrb_obj_value(env)); |
453 | | |
454 | 2 | return mrb_obj_value(binding); |
455 | 2 | } |
456 | | |
457 | | /* |
458 | | * call-seq: |
459 | | * binding -> binding |
460 | | * |
461 | | * Returns a Binding object, describing the variable and method bindings |
462 | | * at the point of call. This object can be used when calling eval to |
463 | | * execute the evaluated command in this environment. |
464 | | * |
465 | | * def get_binding(param) |
466 | | * binding |
467 | | * end |
468 | | * b = get_binding("hello") |
469 | | * b.eval("param") #=> "hello" |
470 | | */ |
471 | | static mrb_noreturn void |
472 | | caller_error(mrb_state *mrb) |
473 | 0 | { |
474 | 0 | mrb_raise(mrb, E_RUNTIME_ERROR, "Cannot create Binding object for non-Ruby caller"); |
475 | 0 | } |
476 | | |
477 | | static mrb_value |
478 | | mrb_f_binding(mrb_state *mrb, mrb_value self) |
479 | 2 | { |
480 | 2 | struct RProc *proc; |
481 | 2 | struct REnv *env; |
482 | | |
483 | 2 | if (mrb->c->ci->cci != 0) { |
484 | 0 | caller_error(mrb); |
485 | 0 | } |
486 | 2 | proc = (struct RProc*)mrb_proc_get_caller(mrb, &env); |
487 | 2 | if (!env || MRB_PROC_CFUNC_P(proc)) { |
488 | 0 | caller_error(mrb); |
489 | 0 | } |
490 | 2 | return mrb_binding_new(mrb, proc, self, env); |
491 | 2 | } |
492 | | |
493 | | void |
494 | | mrb_mruby_binding_gem_init(mrb_state *mrb) |
495 | 15.3k | { |
496 | 15.3k | struct RClass *binding = mrb_define_class_id(mrb, MRB_SYM(Binding), mrb->object_class); |
497 | 15.3k | MRB_SET_INSTANCE_TT(binding, MRB_TT_OBJECT); |
498 | 15.3k | MRB_UNDEF_ALLOCATOR(binding); |
499 | 15.3k | mrb_undef_class_method_id(mrb, binding, MRB_SYM(new)); |
500 | 15.3k | mrb_undef_class_method_id(mrb, binding, MRB_SYM(allocate)); |
501 | | |
502 | 15.3k | mrb_define_module_function_id(mrb, mrb->kernel_module, MRB_SYM(binding), mrb_f_binding, MRB_ARGS_NONE()); |
503 | | |
504 | 15.3k | mrb_define_private_method_id(mrb, binding, MRB_SYM(initialize_copy), binding_initialize_copy, MRB_ARGS_REQ(1)); |
505 | 15.3k | mrb_define_method_id(mrb, binding, MRB_SYM_Q(local_variable_defined), binding_local_variable_defined_p, MRB_ARGS_REQ(1)); |
506 | 15.3k | mrb_define_method_id(mrb, binding, MRB_SYM(local_variable_get), binding_local_variable_get, MRB_ARGS_REQ(1)); |
507 | 15.3k | mrb_define_method_id(mrb, binding, MRB_SYM(local_variable_set), binding_local_variable_set, MRB_ARGS_REQ(2)); |
508 | 15.3k | mrb_define_method_id(mrb, binding, MRB_SYM(local_variables), binding_local_variables, MRB_ARGS_NONE()); |
509 | 15.3k | mrb_define_method_id(mrb, binding, MRB_SYM(receiver), binding_receiver, MRB_ARGS_NONE()); |
510 | 15.3k | mrb_define_method_id(mrb, binding, MRB_SYM(source_location), binding_source_location, MRB_ARGS_NONE()); |
511 | 15.3k | mrb_define_method_id(mrb, binding, MRB_SYM(inspect), mrb_any_to_s, MRB_ARGS_NONE()); |
512 | 15.3k | } |
513 | | |
514 | | void |
515 | | mrb_mruby_binding_gem_final(mrb_state *mrb) |
516 | 15.3k | { |
517 | 15.3k | } |