00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "eval_intern.h"
00013 #include "internal.h"
00014 #include "gc.h"
00015 #include "iseq.h"
00016
00017 NODE *rb_vm_cref_in_context(VALUE self);
00018
00019 struct METHOD {
00020 VALUE recv;
00021 VALUE rclass;
00022 VALUE defined_class;
00023 ID id;
00024 rb_method_entry_t *me;
00025 struct unlinked_method_entry_list_entry *ume;
00026 };
00027
00028 VALUE rb_cUnboundMethod;
00029 VALUE rb_cMethod;
00030 VALUE rb_cBinding;
00031 VALUE rb_cProc;
00032
00033 static VALUE bmcall(VALUE, VALUE, int, VALUE *, VALUE);
00034 static int method_arity(VALUE);
00035 static int method_min_max_arity(VALUE, int *max);
00036 #define attached id__attached__
00037
00038
00039
00040 #define IS_METHOD_PROC_NODE(node) (nd_type(node) == NODE_IFUNC && (node)->nd_cfnc == bmcall)
00041
00042 static void
00043 proc_free(void *ptr)
00044 {
00045 RUBY_FREE_ENTER("proc");
00046 if (ptr) {
00047 ruby_xfree(ptr);
00048 }
00049 RUBY_FREE_LEAVE("proc");
00050 }
00051
00052 static void
00053 proc_mark(void *ptr)
00054 {
00055 rb_proc_t *proc;
00056 RUBY_MARK_ENTER("proc");
00057 if (ptr) {
00058 proc = ptr;
00059 RUBY_MARK_UNLESS_NULL(proc->envval);
00060 RUBY_MARK_UNLESS_NULL(proc->blockprocval);
00061 RUBY_MARK_UNLESS_NULL(proc->block.proc);
00062 RUBY_MARK_UNLESS_NULL(proc->block.self);
00063 if (proc->block.iseq && RUBY_VM_IFUNC_P(proc->block.iseq)) {
00064 RUBY_MARK_UNLESS_NULL((VALUE)(proc->block.iseq));
00065 }
00066 }
00067 RUBY_MARK_LEAVE("proc");
00068 }
00069
00070 static size_t
00071 proc_memsize(const void *ptr)
00072 {
00073 return ptr ? sizeof(rb_proc_t) : 0;
00074 }
00075
00076 static const rb_data_type_t proc_data_type = {
00077 "proc",
00078 {
00079 proc_mark,
00080 proc_free,
00081 proc_memsize,
00082 },
00083 NULL, NULL, RUBY_TYPED_FREE_IMMEDIATELY
00084 };
00085
00086 VALUE
00087 rb_proc_alloc(VALUE klass)
00088 {
00089 rb_proc_t *proc;
00090 return TypedData_Make_Struct(klass, rb_proc_t, &proc_data_type, proc);
00091 }
00092
00093 VALUE
00094 rb_obj_is_proc(VALUE proc)
00095 {
00096 if (rb_typeddata_is_kind_of(proc, &proc_data_type)) {
00097 return Qtrue;
00098 }
00099 else {
00100 return Qfalse;
00101 }
00102 }
00103
00104
00105 static VALUE
00106 proc_dup(VALUE self)
00107 {
00108 VALUE procval = rb_proc_alloc(rb_cProc);
00109 rb_proc_t *src, *dst;
00110 GetProcPtr(self, src);
00111 GetProcPtr(procval, dst);
00112
00113 dst->block = src->block;
00114 dst->block.proc = procval;
00115 dst->blockprocval = src->blockprocval;
00116 dst->envval = src->envval;
00117 dst->safe_level = src->safe_level;
00118 dst->is_lambda = src->is_lambda;
00119
00120 return procval;
00121 }
00122
00123
00124 static VALUE
00125 proc_clone(VALUE self)
00126 {
00127 VALUE procval = proc_dup(self);
00128 CLONESETUP(procval, self);
00129 return procval;
00130 }
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233 VALUE
00234 rb_proc_lambda_p(VALUE procval)
00235 {
00236 rb_proc_t *proc;
00237 GetProcPtr(procval, proc);
00238
00239 return proc->is_lambda ? Qtrue : Qfalse;
00240 }
00241
00242
00243
00244 static void
00245 binding_free(void *ptr)
00246 {
00247 rb_binding_t *bind;
00248 RUBY_FREE_ENTER("binding");
00249 if (ptr) {
00250 bind = ptr;
00251 ruby_xfree(bind);
00252 }
00253 RUBY_FREE_LEAVE("binding");
00254 }
00255
00256 static void
00257 binding_mark(void *ptr)
00258 {
00259 rb_binding_t *bind;
00260 RUBY_MARK_ENTER("binding");
00261 if (ptr) {
00262 bind = ptr;
00263 RUBY_MARK_UNLESS_NULL(bind->env);
00264 RUBY_MARK_UNLESS_NULL(bind->path);
00265 RUBY_MARK_UNLESS_NULL(bind->blockprocval);
00266 }
00267 RUBY_MARK_LEAVE("binding");
00268 }
00269
00270 static size_t
00271 binding_memsize(const void *ptr)
00272 {
00273 return ptr ? sizeof(rb_binding_t) : 0;
00274 }
00275
00276 const rb_data_type_t ruby_binding_data_type = {
00277 "binding",
00278 {
00279 binding_mark,
00280 binding_free,
00281 binding_memsize,
00282 },
00283 NULL, NULL, RUBY_TYPED_FREE_IMMEDIATELY
00284 };
00285
00286 VALUE
00287 rb_binding_alloc(VALUE klass)
00288 {
00289 VALUE obj;
00290 rb_binding_t *bind;
00291 obj = TypedData_Make_Struct(klass, rb_binding_t, &ruby_binding_data_type, bind);
00292 return obj;
00293 }
00294
00295
00296 static VALUE
00297 binding_dup(VALUE self)
00298 {
00299 VALUE bindval = rb_binding_alloc(rb_cBinding);
00300 rb_binding_t *src, *dst;
00301 GetBindingPtr(self, src);
00302 GetBindingPtr(bindval, dst);
00303 dst->env = src->env;
00304 dst->path = src->path;
00305 dst->blockprocval = src->blockprocval;
00306 dst->first_lineno = src->first_lineno;
00307 return bindval;
00308 }
00309
00310
00311 static VALUE
00312 binding_clone(VALUE self)
00313 {
00314 VALUE bindval = binding_dup(self);
00315 CLONESETUP(bindval, self);
00316 return bindval;
00317 }
00318
00319 VALUE
00320 rb_binding_new_with_cfp(rb_thread_t *th, const rb_control_frame_t *src_cfp)
00321 {
00322 return rb_vm_make_binding(th, src_cfp);
00323 }
00324
00325 VALUE
00326 rb_binding_new(void)
00327 {
00328 rb_thread_t *th = GET_THREAD();
00329 return rb_binding_new_with_cfp(th, th->cfp);
00330 }
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348 static VALUE
00349 rb_f_binding(VALUE self)
00350 {
00351 return rb_binding_new();
00352 }
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370 static VALUE
00371 bind_eval(int argc, VALUE *argv, VALUE bindval)
00372 {
00373 VALUE args[4];
00374
00375 rb_scan_args(argc, argv, "12", &args[0], &args[2], &args[3]);
00376 args[1] = bindval;
00377 return rb_f_eval(argc+1, args, Qnil );
00378 }
00379
00380 static VALUE *
00381 get_local_variable_ptr(VALUE envval, ID lid)
00382 {
00383 const rb_env_t *env;
00384
00385 do {
00386 const rb_iseq_t *iseq;
00387 int i;
00388
00389 GetEnvPtr(envval, env);
00390 iseq = env->block.iseq;
00391
00392 for (i=0; i<iseq->local_table_size; i++) {
00393 if (iseq->local_table[i] == lid) {
00394 return &env->env[i];
00395 }
00396 }
00397 } while ((envval = env->prev_envval) != 0);
00398
00399 return 0;
00400 }
00401
00402
00403
00404
00405
00406
00407 static ID
00408 check_local_id(VALUE bindval, volatile VALUE *pname)
00409 {
00410 ID lid = rb_check_id(pname);
00411 VALUE name = *pname, sym = name;
00412
00413 if (lid) {
00414 if (!rb_is_local_id(lid)) {
00415 name = rb_id2str(lid);
00416 wrong:
00417 rb_name_error_str(sym, "wrong local variable name `% "PRIsVALUE"' for %"PRIsVALUE,
00418 name, bindval);
00419 }
00420 }
00421 else {
00422 if (!rb_is_local_name(sym)) goto wrong;
00423 return 0;
00424 }
00425 return lid;
00426 }
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445 static VALUE
00446 bind_local_variable_get(VALUE bindval, VALUE sym)
00447 {
00448 ID lid = check_local_id(bindval, &sym);
00449 const rb_binding_t *bind;
00450 const VALUE *ptr;
00451
00452 if (!lid) goto undefined;
00453
00454 GetBindingPtr(bindval, bind);
00455
00456 if ((ptr = get_local_variable_ptr(bind->env, lid)) == NULL) {
00457 undefined:
00458 rb_name_error_str(sym, "local variable `%"PRIsVALUE"' not defined for %"PRIsVALUE,
00459 sym, bindval);
00460 }
00461
00462 return *ptr;
00463 }
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489 static VALUE
00490 bind_local_variable_set(VALUE bindval, VALUE sym, VALUE val)
00491 {
00492 ID lid = check_local_id(bindval, &sym);
00493 rb_binding_t *bind;
00494 VALUE *ptr;
00495
00496 if (!lid) lid = rb_intern_str(sym);
00497
00498 GetBindingPtr(bindval, bind);
00499 if ((ptr = get_local_variable_ptr(bind->env, lid)) == NULL) {
00500
00501 ptr = rb_binding_add_dynavars(bind, 1, &lid);
00502 }
00503
00504 *ptr = val;
00505
00506 return val;
00507 }
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526 static VALUE
00527 bind_local_variable_defined_p(VALUE bindval, VALUE sym)
00528 {
00529 ID lid = check_local_id(bindval, &sym);
00530 const rb_binding_t *bind;
00531
00532 if (!lid) return Qfalse;
00533
00534 GetBindingPtr(bindval, bind);
00535 return get_local_variable_ptr(bind->env, lid) ? Qtrue : Qfalse;
00536 }
00537
00538 static VALUE
00539 proc_new(VALUE klass, int is_lambda)
00540 {
00541 VALUE procval = Qnil;
00542 rb_thread_t *th = GET_THREAD();
00543 rb_control_frame_t *cfp = th->cfp;
00544 rb_block_t *block;
00545
00546 if ((block = rb_vm_control_frame_block_ptr(cfp)) != 0) {
00547
00548 }
00549 else {
00550 cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
00551
00552 if ((block = rb_vm_control_frame_block_ptr(cfp)) != 0) {
00553 if (is_lambda) {
00554 rb_warn("tried to create Proc object without a block");
00555 }
00556 }
00557 else {
00558 rb_raise(rb_eArgError,
00559 "tried to create Proc object without a block");
00560 }
00561 }
00562
00563 procval = block->proc;
00564
00565 if (procval) {
00566 if (RBASIC(procval)->klass == klass) {
00567 return procval;
00568 }
00569 else {
00570 VALUE newprocval = proc_dup(procval);
00571 RBASIC_SET_CLASS(newprocval, klass);
00572 return newprocval;
00573 }
00574 }
00575
00576 procval = rb_vm_make_proc(th, block, klass);
00577
00578 if (is_lambda) {
00579 rb_proc_t *proc;
00580 GetProcPtr(procval, proc);
00581 proc->is_lambda = TRUE;
00582 }
00583 return procval;
00584 }
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603 static VALUE
00604 rb_proc_s_new(int argc, VALUE *argv, VALUE klass)
00605 {
00606 VALUE block = proc_new(klass, FALSE);
00607
00608 rb_obj_call_init(block, argc, argv);
00609 return block;
00610 }
00611
00612
00613
00614
00615
00616
00617
00618
00619 VALUE
00620 rb_block_proc(void)
00621 {
00622 return proc_new(rb_cProc, FALSE);
00623 }
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633 VALUE
00634 rb_block_lambda(void)
00635 {
00636 return proc_new(rb_cProc, TRUE);
00637 }
00638
00639 VALUE
00640 rb_f_lambda(void)
00641 {
00642 rb_warn("rb_f_lambda() is deprecated; use rb_block_proc() instead");
00643 return rb_block_lambda();
00644 }
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693 static VALUE
00694 proc_call(int argc, VALUE *argv, VALUE procval)
00695 {
00696 VALUE vret;
00697 rb_proc_t *proc;
00698 rb_block_t *blockptr = 0;
00699 rb_iseq_t *iseq;
00700 VALUE passed_procval;
00701 GetProcPtr(procval, proc);
00702
00703 iseq = proc->block.iseq;
00704 if (BUILTIN_TYPE(iseq) == T_NODE || iseq->arg_block != -1) {
00705 if (rb_block_given_p()) {
00706 rb_proc_t *passed_proc;
00707 RB_GC_GUARD(passed_procval) = rb_block_proc();
00708 GetProcPtr(passed_procval, passed_proc);
00709 blockptr = &passed_proc->block;
00710 }
00711 }
00712
00713 vret = rb_vm_invoke_proc(GET_THREAD(), proc, argc, argv, blockptr);
00714 RB_GC_GUARD(procval);
00715 return vret;
00716 }
00717
00718 #if SIZEOF_LONG > SIZEOF_INT
00719 static inline int
00720 check_argc(long argc)
00721 {
00722 if (argc > INT_MAX || argc < 0) {
00723 rb_raise(rb_eArgError, "too many arguments (%lu)",
00724 (unsigned long)argc);
00725 }
00726 return (int)argc;
00727 }
00728 #else
00729 #define check_argc(argc) (argc)
00730 #endif
00731
00732 VALUE
00733 rb_proc_call(VALUE self, VALUE args)
00734 {
00735 VALUE vret;
00736 rb_proc_t *proc;
00737 GetProcPtr(self, proc);
00738 vret = rb_vm_invoke_proc(GET_THREAD(), proc, check_argc(RARRAY_LEN(args)), RARRAY_CONST_PTR(args), 0);
00739 RB_GC_GUARD(self);
00740 RB_GC_GUARD(args);
00741 return vret;
00742 }
00743
00744 VALUE
00745 rb_proc_call_with_block(VALUE self, int argc, const VALUE *argv, VALUE pass_procval)
00746 {
00747 VALUE vret;
00748 rb_proc_t *proc;
00749 rb_block_t *block = 0;
00750 GetProcPtr(self, proc);
00751
00752 if (!NIL_P(pass_procval)) {
00753 rb_proc_t *pass_proc;
00754 GetProcPtr(pass_procval, pass_proc);
00755 block = &pass_proc->block;
00756 }
00757
00758 vret = rb_vm_invoke_proc(GET_THREAD(), proc, argc, argv, block);
00759 RB_GC_GUARD(self);
00760 RB_GC_GUARD(pass_procval);
00761 return vret;
00762 }
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797 static VALUE
00798 proc_arity(VALUE self)
00799 {
00800 int arity = rb_proc_arity(self);
00801 return INT2FIX(arity);
00802 }
00803
00804 static inline int
00805 rb_iseq_min_max_arity(const rb_iseq_t *iseq, int *max)
00806 {
00807 *max = iseq->arg_rest == -1 ?
00808 iseq->argc + iseq->arg_post_len + iseq->arg_opts -
00809 (iseq->arg_opts > 0) + (iseq->arg_keyword != -1)
00810 : UNLIMITED_ARGUMENTS;
00811 return iseq->argc + iseq->arg_post_len + (iseq->arg_keyword_required > 0);
00812 }
00813
00814 static int
00815 rb_block_min_max_arity(rb_block_t *block, int *max)
00816 {
00817 rb_iseq_t *iseq = block->iseq;
00818 if (iseq) {
00819 if (BUILTIN_TYPE(iseq) != T_NODE) {
00820 return rb_iseq_min_max_arity(iseq, max);
00821 }
00822 else {
00823 NODE *node = (NODE *)iseq;
00824 if (IS_METHOD_PROC_NODE(node)) {
00825
00826 return method_min_max_arity(node->nd_tval, max);
00827 }
00828 }
00829 }
00830 *max = UNLIMITED_ARGUMENTS;
00831 return 0;
00832 }
00833
00834
00835
00836
00837
00838
00839
00840 static int
00841 rb_proc_min_max_arity(VALUE self, int *max)
00842 {
00843 rb_proc_t *proc;
00844 rb_block_t *block;
00845 GetProcPtr(self, proc);
00846 block = &proc->block;
00847 return rb_block_min_max_arity(block, max);
00848 }
00849
00850 int
00851 rb_proc_arity(VALUE self)
00852 {
00853 rb_proc_t *proc;
00854 int max, min = rb_proc_min_max_arity(self, &max);
00855 GetProcPtr(self, proc);
00856 return (proc->is_lambda ? min == max : max != UNLIMITED_ARGUMENTS) ? min : -min-1;
00857 }
00858
00859 int
00860 rb_block_arity(void)
00861 {
00862 int min, max;
00863 rb_thread_t *th = GET_THREAD();
00864 rb_control_frame_t *cfp = th->cfp;
00865 rb_block_t *block = rb_vm_control_frame_block_ptr(cfp);
00866 VALUE proc_value;
00867
00868 if (!block) rb_raise(rb_eArgError, "no block given");
00869 min = rb_block_min_max_arity(block, &max);
00870 proc_value = block->proc;
00871 if (proc_value) {
00872 rb_proc_t *proc;
00873 GetProcPtr(proc_value, proc);
00874 if (proc)
00875 return (proc->is_lambda ? min == max : max != UNLIMITED_ARGUMENTS) ? min : -min-1;
00876 }
00877 return max != UNLIMITED_ARGUMENTS ? min : -min-1;
00878 }
00879
00880 #define get_proc_iseq rb_proc_get_iseq
00881
00882 rb_iseq_t *
00883 rb_proc_get_iseq(VALUE self, int *is_proc)
00884 {
00885 rb_proc_t *proc;
00886 rb_iseq_t *iseq;
00887
00888 GetProcPtr(self, proc);
00889 iseq = proc->block.iseq;
00890 if (is_proc) *is_proc = !proc->is_lambda;
00891 if (!RUBY_VM_NORMAL_ISEQ_P(iseq)) {
00892 NODE *node = (NODE *)iseq;
00893 iseq = 0;
00894 if (IS_METHOD_PROC_NODE(node)) {
00895
00896 iseq = rb_method_get_iseq(node->nd_tval);
00897 if (is_proc) *is_proc = 0;
00898 }
00899 }
00900 return iseq;
00901 }
00902
00903 static VALUE
00904 iseq_location(rb_iseq_t *iseq)
00905 {
00906 VALUE loc[2];
00907
00908 if (!iseq) return Qnil;
00909 loc[0] = iseq->location.path;
00910 if (iseq->line_info_table) {
00911 loc[1] = rb_iseq_first_lineno(iseq->self);
00912 }
00913 else {
00914 loc[1] = Qnil;
00915 }
00916 return rb_ary_new4(2, loc);
00917 }
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927 VALUE
00928 rb_proc_location(VALUE self)
00929 {
00930 return iseq_location(get_proc_iseq(self, 0));
00931 }
00932
00933 static VALUE
00934 unnamed_parameters(int arity)
00935 {
00936 VALUE a, param = rb_ary_new2((arity < 0) ? -arity : arity);
00937 int n = (arity < 0) ? ~arity : arity;
00938 ID req, rest;
00939 CONST_ID(req, "req");
00940 a = rb_ary_new3(1, ID2SYM(req));
00941 OBJ_FREEZE(a);
00942 for (; n; --n) {
00943 rb_ary_push(param, a);
00944 }
00945 if (arity < 0) {
00946 CONST_ID(rest, "rest");
00947 rb_ary_store(param, ~arity, rb_ary_new3(1, ID2SYM(rest)));
00948 }
00949 return param;
00950 }
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962 static VALUE
00963 rb_proc_parameters(VALUE self)
00964 {
00965 int is_proc;
00966 rb_iseq_t *iseq = get_proc_iseq(self, &is_proc);
00967 if (!iseq) {
00968 return unnamed_parameters(rb_proc_arity(self));
00969 }
00970 return rb_iseq_parameters(iseq, is_proc);
00971 }
00972
00973 st_index_t
00974 rb_hash_proc(st_index_t hash, VALUE prc)
00975 {
00976 rb_proc_t *proc;
00977 GetProcPtr(prc, proc);
00978 hash = rb_hash_uint(hash, (st_index_t)proc->block.iseq);
00979 hash = rb_hash_uint(hash, (st_index_t)proc->envval);
00980 return rb_hash_uint(hash, (st_index_t)proc->block.ep >> 16);
00981 }
00982
00983
00984
00985
00986
00987
00988
00989
00990 static VALUE
00991 proc_hash(VALUE self)
00992 {
00993 st_index_t hash;
00994 hash = rb_hash_start(0);
00995 hash = rb_hash_proc(hash, self);
00996 hash = rb_hash_end(hash);
00997 return LONG2FIX(hash);
00998 }
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008 static VALUE
01009 proc_to_s(VALUE self)
01010 {
01011 VALUE str = 0;
01012 rb_proc_t *proc;
01013 const char *cname = rb_obj_classname(self);
01014 rb_iseq_t *iseq;
01015 const char *is_lambda;
01016
01017 GetProcPtr(self, proc);
01018 iseq = proc->block.iseq;
01019 is_lambda = proc->is_lambda ? " (lambda)" : "";
01020
01021 if (RUBY_VM_NORMAL_ISEQ_P(iseq)) {
01022 int first_lineno = 0;
01023
01024 if (iseq->line_info_table) {
01025 first_lineno = FIX2INT(rb_iseq_first_lineno(iseq->self));
01026 }
01027 str = rb_sprintf("#<%s:%p@%"PRIsVALUE":%d%s>", cname, (void *)self,
01028 iseq->location.path, first_lineno, is_lambda);
01029 }
01030 else {
01031 str = rb_sprintf("#<%s:%p%s>", cname, (void *)proc->block.iseq,
01032 is_lambda);
01033 }
01034
01035 if (OBJ_TAINTED(self)) {
01036 OBJ_TAINT(str);
01037 }
01038 return str;
01039 }
01040
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050 static VALUE
01051 proc_to_proc(VALUE self)
01052 {
01053 return self;
01054 }
01055
01056 static void
01057 bm_mark(void *ptr)
01058 {
01059 struct METHOD *data = ptr;
01060 rb_gc_mark(data->defined_class);
01061 rb_gc_mark(data->rclass);
01062 rb_gc_mark(data->recv);
01063 if (data->me) rb_mark_method_entry(data->me);
01064 }
01065
01066 static void
01067 bm_free(void *ptr)
01068 {
01069 struct METHOD *data = ptr;
01070 struct unlinked_method_entry_list_entry *ume = data->ume;
01071 data->me->mark = 0;
01072 ume->me = data->me;
01073 ume->next = GET_VM()->unlinked_method_entry_list;
01074 GET_VM()->unlinked_method_entry_list = ume;
01075 xfree(ptr);
01076 }
01077
01078 static size_t
01079 bm_memsize(const void *ptr)
01080 {
01081 return ptr ? sizeof(struct METHOD) : 0;
01082 }
01083
01084 static const rb_data_type_t method_data_type = {
01085 "method",
01086 {
01087 bm_mark,
01088 bm_free,
01089 bm_memsize,
01090 },
01091 NULL, NULL, RUBY_TYPED_FREE_IMMEDIATELY
01092 };
01093
01094 VALUE
01095 rb_obj_is_method(VALUE m)
01096 {
01097 if (rb_typeddata_is_kind_of(m, &method_data_type)) {
01098 return Qtrue;
01099 }
01100 else {
01101 return Qfalse;
01102 }
01103 }
01104
01105 static VALUE
01106 mnew_from_me(rb_method_entry_t *me, VALUE defined_class, VALUE klass,
01107 VALUE obj, ID id, VALUE mclass, int scope)
01108 {
01109 VALUE method;
01110 VALUE rclass = klass;
01111 ID rid = id;
01112 struct METHOD *data;
01113 rb_method_definition_t *def = 0;
01114 rb_method_flag_t flag = NOEX_UNDEF;
01115
01116 again:
01117 if (UNDEFINED_METHOD_ENTRY_P(me)) {
01118 ID rmiss = idRespond_to_missing;
01119 VALUE sym = ID2SYM(id);
01120
01121 if (obj != Qundef && !rb_method_basic_definition_p(klass, rmiss)) {
01122 if (RTEST(rb_funcall(obj, rmiss, 2, sym, scope ? Qfalse : Qtrue))) {
01123 me = 0;
01124 defined_class = klass;
01125
01126 goto gen_method;
01127 }
01128 }
01129 rb_print_undef(klass, id, 0);
01130 }
01131 def = me->def;
01132 if (flag == NOEX_UNDEF) {
01133 flag = me->flag;
01134 if (scope && (flag & NOEX_MASK) != NOEX_PUBLIC) {
01135 const char *v = "";
01136 switch (flag & NOEX_MASK) {
01137 case NOEX_PRIVATE: v = "private"; break;
01138 case NOEX_PROTECTED: v = "protected"; break;
01139 }
01140 rb_name_error(id, "method `%s' for %s `% "PRIsVALUE"' is %s",
01141 rb_id2name(id),
01142 (RB_TYPE_P(klass, T_MODULE)) ? "module" : "class",
01143 rb_class_name(klass),
01144 v);
01145 }
01146 }
01147 if (def && def->type == VM_METHOD_TYPE_ZSUPER) {
01148 klass = RCLASS_SUPER(defined_class);
01149 id = def->original_id;
01150 me = rb_method_entry_without_refinements(klass, id, &defined_class);
01151 goto again;
01152 }
01153
01154 klass = defined_class;
01155
01156 while (rclass != klass &&
01157 (FL_TEST(rclass, FL_SINGLETON) || RB_TYPE_P(rclass, T_ICLASS))) {
01158 rclass = RCLASS_SUPER(rclass);
01159 }
01160
01161 gen_method:
01162 method = TypedData_Make_Struct(mclass, struct METHOD, &method_data_type, data);
01163
01164 data->recv = obj;
01165 data->rclass = rclass;
01166 data->defined_class = defined_class;
01167 data->id = rid;
01168 data->me = ALLOC(rb_method_entry_t);
01169 if (me) {
01170 *data->me = *me;
01171 }
01172 else {
01173 me = data->me;
01174 me->flag = 0;
01175 me->mark = 0;
01176 me->called_id = id;
01177 me->klass = klass;
01178 me->def = 0;
01179
01180 def = ALLOC(rb_method_definition_t);
01181 me->def = def;
01182
01183 def->type = VM_METHOD_TYPE_MISSING;
01184 def->original_id = id;
01185 def->alias_count = 0;
01186
01187 }
01188 data->ume = ALLOC(struct unlinked_method_entry_list_entry);
01189 data->me->def->alias_count++;
01190
01191 OBJ_INFECT(method, klass);
01192
01193 return method;
01194 }
01195
01196 static VALUE
01197 mnew(VALUE klass, VALUE obj, ID id, VALUE mclass, int scope)
01198 {
01199 VALUE defined_class;
01200 rb_method_entry_t *me =
01201 rb_method_entry_without_refinements(klass, id, &defined_class);
01202 return mnew_from_me(me, defined_class, klass, obj, id, mclass, scope);
01203 }
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240 static VALUE
01241 method_eq(VALUE method, VALUE other)
01242 {
01243 struct METHOD *m1, *m2;
01244
01245 if (!rb_obj_is_method(other))
01246 return Qfalse;
01247 if (CLASS_OF(method) != CLASS_OF(other))
01248 return Qfalse;
01249
01250 Check_TypedStruct(method, &method_data_type);
01251 m1 = (struct METHOD *)DATA_PTR(method);
01252 m2 = (struct METHOD *)DATA_PTR(other);
01253
01254 if (!rb_method_entry_eq(m1->me, m2->me) ||
01255 m1->rclass != m2->rclass ||
01256 m1->recv != m2->recv) {
01257 return Qfalse;
01258 }
01259
01260 return Qtrue;
01261 }
01262
01263
01264
01265
01266
01267
01268
01269
01270 static VALUE
01271 method_hash(VALUE method)
01272 {
01273 struct METHOD *m;
01274 st_index_t hash;
01275
01276 TypedData_Get_Struct(method, struct METHOD, &method_data_type, m);
01277 hash = rb_hash_start((st_index_t)m->rclass);
01278 hash = rb_hash_uint(hash, (st_index_t)m->recv);
01279 hash = rb_hash_method_entry(hash, m->me);
01280 hash = rb_hash_end(hash);
01281
01282 return INT2FIX(hash);
01283 }
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294 static VALUE
01295 method_unbind(VALUE obj)
01296 {
01297 VALUE method;
01298 struct METHOD *orig, *data;
01299
01300 TypedData_Get_Struct(obj, struct METHOD, &method_data_type, orig);
01301 method = TypedData_Make_Struct(rb_cUnboundMethod, struct METHOD,
01302 &method_data_type, data);
01303 data->recv = Qundef;
01304 data->id = orig->id;
01305 data->me = ALLOC(rb_method_entry_t);
01306 *data->me = *orig->me;
01307 if (orig->me->def) orig->me->def->alias_count++;
01308 data->rclass = orig->rclass;
01309 data->defined_class = orig->defined_class;
01310 data->ume = ALLOC(struct unlinked_method_entry_list_entry);
01311 OBJ_INFECT(method, obj);
01312
01313 return method;
01314 }
01315
01316
01317
01318
01319
01320
01321
01322
01323 static VALUE
01324 method_receiver(VALUE obj)
01325 {
01326 struct METHOD *data;
01327
01328 TypedData_Get_Struct(obj, struct METHOD, &method_data_type, data);
01329 return data->recv;
01330 }
01331
01332
01333
01334
01335
01336
01337
01338
01339 static VALUE
01340 method_name(VALUE obj)
01341 {
01342 struct METHOD *data;
01343
01344 TypedData_Get_Struct(obj, struct METHOD, &method_data_type, data);
01345 return ID2SYM(data->id);
01346 }
01347
01348
01349
01350
01351
01352
01353
01354
01355 static VALUE
01356 method_original_name(VALUE obj)
01357 {
01358 struct METHOD *data;
01359
01360 TypedData_Get_Struct(obj, struct METHOD, &method_data_type, data);
01361 return ID2SYM(data->me->def->original_id);
01362 }
01363
01364
01365
01366
01367
01368
01369
01370
01371 static VALUE
01372 method_owner(VALUE obj)
01373 {
01374 struct METHOD *data;
01375 VALUE defined_class;
01376
01377 TypedData_Get_Struct(obj, struct METHOD, &method_data_type, data);
01378 defined_class = data->defined_class;
01379
01380 if (RB_TYPE_P(defined_class, T_ICLASS)) {
01381 defined_class = RBASIC_CLASS(defined_class);
01382 }
01383
01384 return defined_class;
01385 }
01386
01387 void
01388 rb_method_name_error(VALUE klass, VALUE str)
01389 {
01390 const char *s0 = " class";
01391 VALUE c = klass;
01392
01393 if (FL_TEST(c, FL_SINGLETON)) {
01394 VALUE obj = rb_ivar_get(klass, attached);
01395
01396 switch (TYPE(obj)) {
01397 case T_MODULE:
01398 case T_CLASS:
01399 c = obj;
01400 s0 = "";
01401 }
01402 }
01403 else if (RB_TYPE_P(c, T_MODULE)) {
01404 s0 = " module";
01405 }
01406 rb_name_error_str(str, "undefined method `%"PRIsVALUE"' for%s `%"PRIsVALUE"'",
01407 QUOTE(str), s0, rb_class_name(c));
01408 }
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418
01419
01420
01421
01422
01423
01424
01425
01426
01427
01428
01429
01430
01431
01432
01433
01434
01435
01436
01437
01438 VALUE
01439 rb_obj_method(VALUE obj, VALUE vid)
01440 {
01441 ID id = rb_check_id(&vid);
01442 if (!id) {
01443 rb_method_name_error(CLASS_OF(obj), vid);
01444 }
01445 return mnew(CLASS_OF(obj), obj, id, rb_cMethod, FALSE);
01446 }
01447
01448
01449
01450
01451
01452
01453
01454
01455 VALUE
01456 rb_obj_public_method(VALUE obj, VALUE vid)
01457 {
01458 ID id = rb_check_id(&vid);
01459 if (!id) {
01460 rb_method_name_error(CLASS_OF(obj), vid);
01461 }
01462 return mnew(CLASS_OF(obj), obj, id, rb_cMethod, TRUE);
01463 }
01464
01465
01466
01467
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486
01487
01488
01489 VALUE
01490 rb_obj_singleton_method(VALUE obj, VALUE vid)
01491 {
01492 rb_method_entry_t *me;
01493 VALUE klass;
01494 ID id = rb_check_id(&vid);
01495 if (!id) {
01496 rb_name_error_str(vid, "undefined singleton method `%"PRIsVALUE"' for `%"PRIsVALUE"'",
01497 QUOTE(vid), obj);
01498 }
01499 if (NIL_P(klass = rb_singleton_class_get(obj)) ||
01500 !(me = rb_method_entry_at(klass, id))) {
01501 rb_name_error(id, "undefined singleton method `%"PRIsVALUE"' for `%"PRIsVALUE"'",
01502 QUOTE_ID(id), obj);
01503 }
01504 return mnew_from_me(me, klass, klass, obj, id, rb_cMethod, FALSE);
01505 }
01506
01507
01508
01509
01510
01511
01512
01513
01514
01515
01516
01517
01518
01519
01520
01521
01522
01523
01524
01525
01526
01527
01528
01529
01530
01531
01532
01533
01534
01535
01536
01537
01538 static VALUE
01539 rb_mod_instance_method(VALUE mod, VALUE vid)
01540 {
01541 ID id = rb_check_id(&vid);
01542 if (!id) {
01543 rb_method_name_error(mod, vid);
01544 }
01545 return mnew(mod, Qundef, id, rb_cUnboundMethod, FALSE);
01546 }
01547
01548
01549
01550
01551
01552
01553
01554
01555 static VALUE
01556 rb_mod_public_instance_method(VALUE mod, VALUE vid)
01557 {
01558 ID id = rb_check_id(&vid);
01559 if (!id) {
01560 rb_method_name_error(mod, vid);
01561 }
01562 return mnew(mod, Qundef, id, rb_cUnboundMethod, TRUE);
01563 }
01564
01565
01566
01567
01568
01569
01570
01571
01572
01573
01574
01575
01576
01577
01578
01579
01580
01581
01582
01583
01584
01585
01586
01587
01588
01589
01590
01591
01592
01593
01594
01595
01596
01597
01598
01599
01600
01601
01602 static VALUE
01603 rb_mod_define_method(int argc, VALUE *argv, VALUE mod)
01604 {
01605 ID id;
01606 VALUE body;
01607 int noex = NOEX_PUBLIC;
01608 const NODE *cref = rb_vm_cref_in_context(mod);
01609
01610 if (cref && cref->nd_clss == mod) {
01611 noex = (int)cref->nd_visi;
01612 }
01613
01614 if (argc == 1) {
01615 id = rb_to_id(argv[0]);
01616 body = rb_block_lambda();
01617 }
01618 else {
01619 rb_check_arity(argc, 1, 2);
01620 id = rb_to_id(argv[0]);
01621 body = argv[1];
01622 if (!rb_obj_is_method(body) && !rb_obj_is_proc(body)) {
01623 rb_raise(rb_eTypeError,
01624 "wrong argument type %s (expected Proc/Method)",
01625 rb_obj_classname(body));
01626 }
01627 }
01628
01629 if (rb_obj_is_method(body)) {
01630 struct METHOD *method = (struct METHOD *)DATA_PTR(body);
01631 VALUE rclass = method->rclass;
01632 if (rclass != mod && !RB_TYPE_P(rclass, T_MODULE) &&
01633 !RTEST(rb_class_inherited_p(mod, rclass))) {
01634 if (FL_TEST(rclass, FL_SINGLETON)) {
01635 rb_raise(rb_eTypeError,
01636 "can't bind singleton method to a different class");
01637 }
01638 else {
01639 rb_raise(rb_eTypeError,
01640 "bind argument must be a subclass of % "PRIsVALUE,
01641 rb_class_name(rclass));
01642 }
01643 }
01644 rb_method_entry_set(mod, id, method->me, noex);
01645 if (noex == NOEX_MODFUNC) {
01646 rb_method_entry_set(rb_singleton_class(mod), id, method->me, NOEX_PUBLIC);
01647 }
01648 RB_GC_GUARD(body);
01649 }
01650 else if (rb_obj_is_proc(body)) {
01651 rb_proc_t *proc;
01652 body = proc_dup(body);
01653 GetProcPtr(body, proc);
01654 if (BUILTIN_TYPE(proc->block.iseq) != T_NODE) {
01655 proc->block.iseq->defined_method_id = id;
01656 RB_OBJ_WRITE(proc->block.iseq->self, &proc->block.iseq->klass, mod);
01657 proc->is_lambda = TRUE;
01658 proc->is_from_method = TRUE;
01659 proc->block.klass = mod;
01660 }
01661 rb_add_method(mod, id, VM_METHOD_TYPE_BMETHOD, (void *)body, noex);
01662 if (noex == NOEX_MODFUNC) {
01663 rb_add_method(rb_singleton_class(mod), id, VM_METHOD_TYPE_BMETHOD, (void *)body, NOEX_PUBLIC);
01664 }
01665 }
01666 else {
01667
01668 rb_raise(rb_eTypeError, "wrong argument type (expected Proc/Method)");
01669 }
01670
01671 return ID2SYM(id);
01672 }
01673
01674
01675
01676
01677
01678
01679
01680
01681
01682
01683
01684
01685
01686
01687
01688
01689
01690
01691
01692
01693
01694
01695
01696
01697
01698
01699
01700 static VALUE
01701 rb_obj_define_method(int argc, VALUE *argv, VALUE obj)
01702 {
01703 VALUE klass = rb_singleton_class(obj);
01704
01705 return rb_mod_define_method(argc, argv, klass);
01706 }
01707
01708
01709
01710
01711
01712
01713
01714
01715 static VALUE
01716 top_define_method(int argc, VALUE *argv, VALUE obj)
01717 {
01718 rb_thread_t *th = GET_THREAD();
01719 VALUE klass;
01720
01721 klass = th->top_wrapper;
01722 if (klass) {
01723 rb_warning("main.define_method in the wrapped load is effective only in wrapper module");
01724 }
01725 else {
01726 klass = rb_cObject;
01727 }
01728 return rb_mod_define_method(argc, argv, klass);
01729 }
01730
01731
01732
01733
01734
01735
01736
01737
01738
01739
01740
01741
01742
01743
01744
01745
01746
01747
01748 static VALUE
01749 method_clone(VALUE self)
01750 {
01751 VALUE clone;
01752 struct METHOD *orig, *data;
01753
01754 TypedData_Get_Struct(self, struct METHOD, &method_data_type, orig);
01755 clone = TypedData_Make_Struct(CLASS_OF(self), struct METHOD, &method_data_type, data);
01756 CLONESETUP(clone, self);
01757 *data = *orig;
01758 data->me = ALLOC(rb_method_entry_t);
01759 *data->me = *orig->me;
01760 if (data->me->def) data->me->def->alias_count++;
01761 data->ume = ALLOC(struct unlinked_method_entry_list_entry);
01762
01763 return clone;
01764 }
01765
01766
01767
01768
01769
01770
01771
01772
01773
01774
01775
01776
01777
01778
01779 VALUE
01780 rb_method_call(int argc, VALUE *argv, VALUE method)
01781 {
01782 VALUE proc = rb_block_given_p() ? rb_block_proc() : Qnil;
01783 return rb_method_call_with_block(argc, argv, method, proc);
01784 }
01785
01786 VALUE
01787 rb_method_call_with_block(int argc, VALUE *argv, VALUE method, VALUE pass_procval)
01788 {
01789 VALUE result = Qnil;
01790 struct METHOD *data;
01791 int state;
01792 volatile int safe = -1;
01793
01794 TypedData_Get_Struct(method, struct METHOD, &method_data_type, data);
01795 if (data->recv == Qundef) {
01796 rb_raise(rb_eTypeError, "can't call unbound method; bind first");
01797 }
01798 PUSH_TAG();
01799 if (OBJ_TAINTED(method)) {
01800 const int safe_level_to_run = 4 ;
01801 safe = rb_safe_level();
01802 if (rb_safe_level() < safe_level_to_run) {
01803 rb_set_safe_level_force(safe_level_to_run);
01804 }
01805 }
01806 if ((state = EXEC_TAG()) == 0) {
01807 rb_thread_t *th = GET_THREAD();
01808 rb_block_t *block = 0;
01809 VALUE defined_class;
01810
01811 if (!NIL_P(pass_procval)) {
01812 rb_proc_t *pass_proc;
01813 GetProcPtr(pass_procval, pass_proc);
01814 block = &pass_proc->block;
01815 }
01816
01817 th->passed_block = block;
01818 defined_class = data->defined_class;
01819 if (BUILTIN_TYPE(defined_class) == T_MODULE) defined_class = data->rclass;
01820 result = rb_vm_call(th, data->recv, data->id, argc, argv, data->me, defined_class);
01821 }
01822 POP_TAG();
01823 if (safe >= 0)
01824 rb_set_safe_level_force(safe);
01825 if (state)
01826 JUMP_TAG(state);
01827 return result;
01828 }
01829
01830
01831
01832
01833
01834
01835
01836
01837
01838
01839
01840
01841
01842
01843
01844
01845
01846
01847
01848
01849
01850
01851
01852
01853
01854
01855
01856
01857
01858
01859
01860
01861
01862
01863
01864
01865
01866
01867
01868
01869
01870
01871
01872
01873
01874
01875
01876
01877
01878
01879
01880
01881
01882
01883
01884
01885
01886
01887
01888
01889
01890
01891
01892
01893
01894
01895
01896
01897
01898
01899
01900
01901
01902
01903
01904
01905
01906
01907
01908
01909
01910
01911
01912
01913
01914
01915
01916
01917
01918
01919
01920
01921 static VALUE
01922 umethod_bind(VALUE method, VALUE recv)
01923 {
01924 struct METHOD *data, *bound;
01925 VALUE methclass;
01926 VALUE rclass;
01927
01928 TypedData_Get_Struct(method, struct METHOD, &method_data_type, data);
01929
01930 methclass = data->rclass;
01931 if (!RB_TYPE_P(methclass, T_MODULE) &&
01932 methclass != CLASS_OF(recv) && !rb_obj_is_kind_of(recv, methclass)) {
01933 if (FL_TEST(methclass, FL_SINGLETON)) {
01934 rb_raise(rb_eTypeError,
01935 "singleton method called for a different object");
01936 }
01937 else {
01938 rb_raise(rb_eTypeError, "bind argument must be an instance of % "PRIsVALUE,
01939 rb_class_name(methclass));
01940 }
01941 }
01942
01943 method = TypedData_Make_Struct(rb_cMethod, struct METHOD, &method_data_type, bound);
01944 *bound = *data;
01945 bound->me = ALLOC(rb_method_entry_t);
01946 *bound->me = *data->me;
01947 if (bound->me->def) bound->me->def->alias_count++;
01948 rclass = CLASS_OF(recv);
01949 if (BUILTIN_TYPE(bound->defined_class) == T_MODULE) {
01950 VALUE ic = rb_class_search_ancestor(rclass, bound->defined_class);
01951 if (ic) {
01952 rclass = ic;
01953 }
01954 else {
01955 rclass = rb_include_class_new(methclass, rclass);
01956 }
01957 }
01958 bound->recv = recv;
01959 bound->rclass = rclass;
01960 data->ume = ALLOC(struct unlinked_method_entry_list_entry);
01961
01962 return method;
01963 }
01964
01965
01966
01967
01968
01969
01970 static int
01971 rb_method_entry_min_max_arity(const rb_method_entry_t *me, int *max)
01972 {
01973 const rb_method_definition_t *def = me->def;
01974 if (!def) return *max = 0;
01975 switch (def->type) {
01976 case VM_METHOD_TYPE_CFUNC:
01977 if (def->body.cfunc.argc < 0) {
01978 *max = UNLIMITED_ARGUMENTS;
01979 return 0;
01980 }
01981 return *max = check_argc(def->body.cfunc.argc);
01982 case VM_METHOD_TYPE_ZSUPER:
01983 *max = UNLIMITED_ARGUMENTS;
01984 return 0;
01985 case VM_METHOD_TYPE_ATTRSET:
01986 return *max = 1;
01987 case VM_METHOD_TYPE_IVAR:
01988 return *max = 0;
01989 case VM_METHOD_TYPE_BMETHOD:
01990 return rb_proc_min_max_arity(def->body.proc, max);
01991 case VM_METHOD_TYPE_ISEQ: {
01992 rb_iseq_t *iseq = def->body.iseq;
01993 return rb_iseq_min_max_arity(iseq, max);
01994 }
01995 case VM_METHOD_TYPE_UNDEF:
01996 case VM_METHOD_TYPE_NOTIMPLEMENTED:
01997 return *max = 0;
01998 case VM_METHOD_TYPE_MISSING:
01999 *max = UNLIMITED_ARGUMENTS;
02000 return 0;
02001 case VM_METHOD_TYPE_OPTIMIZED: {
02002 switch (def->body.optimize_type) {
02003 case OPTIMIZED_METHOD_TYPE_SEND:
02004 *max = UNLIMITED_ARGUMENTS;
02005 return 0;
02006 default:
02007 break;
02008 }
02009 break;
02010 }
02011 case VM_METHOD_TYPE_REFINED:
02012 *max = UNLIMITED_ARGUMENTS;
02013 return 0;
02014 }
02015 rb_bug("rb_method_entry_min_max_arity: invalid method entry type (%d)", def->type);
02016 UNREACHABLE;
02017 }
02018
02019 int
02020 rb_method_entry_arity(const rb_method_entry_t *me)
02021 {
02022 int max, min = rb_method_entry_min_max_arity(me, &max);
02023 return min == max ? min : -min-1;
02024 }
02025
02026
02027
02028
02029
02030
02031
02032
02033
02034
02035
02036
02037
02038
02039
02040
02041
02042
02043
02044
02045
02046
02047
02048
02049
02050
02051
02052
02053
02054
02055
02056
02057
02058
02059 static VALUE
02060 method_arity_m(VALUE method)
02061 {
02062 int n = method_arity(method);
02063 return INT2FIX(n);
02064 }
02065
02066 static int
02067 method_arity(VALUE method)
02068 {
02069 struct METHOD *data;
02070
02071 TypedData_Get_Struct(method, struct METHOD, &method_data_type, data);
02072 return rb_method_entry_arity(data->me);
02073 }
02074
02075 static rb_method_entry_t *
02076 original_method_entry(VALUE mod, ID id)
02077 {
02078 VALUE rclass;
02079 rb_method_entry_t *me;
02080 while ((me = rb_method_entry(mod, id, &rclass)) != 0) {
02081 rb_method_definition_t *def = me->def;
02082 if (!def) break;
02083 if (def->type != VM_METHOD_TYPE_ZSUPER) break;
02084 mod = RCLASS_SUPER(rclass);
02085 id = def->original_id;
02086 }
02087 return me;
02088 }
02089
02090 static int
02091 method_min_max_arity(VALUE method, int *max)
02092 {
02093 struct METHOD *data;
02094
02095 TypedData_Get_Struct(method, struct METHOD, &method_data_type, data);
02096 return rb_method_entry_min_max_arity(data->me, max);
02097 }
02098
02099 int
02100 rb_mod_method_arity(VALUE mod, ID id)
02101 {
02102 rb_method_entry_t *me = original_method_entry(mod, id);
02103 if (!me) return 0;
02104 return rb_method_entry_arity(me);
02105 }
02106
02107 int
02108 rb_obj_method_arity(VALUE obj, ID id)
02109 {
02110 return rb_mod_method_arity(CLASS_OF(obj), id);
02111 }
02112
02113 static inline rb_method_definition_t *
02114 method_get_def(VALUE method)
02115 {
02116 struct METHOD *data;
02117
02118 TypedData_Get_Struct(method, struct METHOD, &method_data_type, data);
02119 return data->me->def;
02120 }
02121
02122 static rb_iseq_t *
02123 method_get_iseq(rb_method_definition_t *def)
02124 {
02125 switch (def->type) {
02126 case VM_METHOD_TYPE_BMETHOD:
02127 return get_proc_iseq(def->body.proc, 0);
02128 case VM_METHOD_TYPE_ISEQ:
02129 return def->body.iseq;
02130 default:
02131 return 0;
02132 }
02133 }
02134
02135 rb_iseq_t *
02136 rb_method_get_iseq(VALUE method)
02137 {
02138 return method_get_iseq(method_get_def(method));
02139 }
02140
02141 static VALUE
02142 method_def_location(rb_method_definition_t *def)
02143 {
02144 if (def->type == VM_METHOD_TYPE_ATTRSET || def->type == VM_METHOD_TYPE_IVAR) {
02145 if (!def->body.attr.location)
02146 return Qnil;
02147 return rb_ary_dup(def->body.attr.location);
02148 }
02149 return iseq_location(method_get_iseq(def));
02150 }
02151
02152 VALUE
02153 rb_method_entry_location(rb_method_entry_t *me)
02154 {
02155 if (!me || !me->def) return Qnil;
02156 return method_def_location(me->def);
02157 }
02158
02159 VALUE
02160 rb_mod_method_location(VALUE mod, ID id)
02161 {
02162 rb_method_entry_t *me = original_method_entry(mod, id);
02163 return rb_method_entry_location(me);
02164 }
02165
02166 VALUE
02167 rb_obj_method_location(VALUE obj, ID id)
02168 {
02169 return rb_mod_method_location(CLASS_OF(obj), id);
02170 }
02171
02172
02173
02174
02175
02176
02177
02178
02179
02180 VALUE
02181 rb_method_location(VALUE method)
02182 {
02183 rb_method_definition_t *def = method_get_def(method);
02184 return method_def_location(def);
02185 }
02186
02187
02188
02189
02190
02191
02192
02193
02194 static VALUE
02195 rb_method_parameters(VALUE method)
02196 {
02197 rb_iseq_t *iseq = rb_method_get_iseq(method);
02198 if (!iseq) {
02199 return unnamed_parameters(method_arity(method));
02200 }
02201 return rb_iseq_parameters(iseq, 0);
02202 }
02203
02204
02205
02206
02207
02208
02209
02210
02211
02212
02213
02214 static VALUE
02215 method_inspect(VALUE method)
02216 {
02217 struct METHOD *data;
02218 VALUE str;
02219 const char *s;
02220 const char *sharp = "#";
02221 VALUE mklass;
02222
02223 TypedData_Get_Struct(method, struct METHOD, &method_data_type, data);
02224 str = rb_str_buf_new2("#<");
02225 s = rb_obj_classname(method);
02226 rb_str_buf_cat2(str, s);
02227 rb_str_buf_cat2(str, ": ");
02228
02229 mklass = data->me->klass;
02230 if (FL_TEST(mklass, FL_SINGLETON)) {
02231 VALUE v = rb_ivar_get(mklass, attached);
02232
02233 if (data->recv == Qundef) {
02234 rb_str_buf_append(str, rb_inspect(mklass));
02235 }
02236 else if (data->recv == v) {
02237 rb_str_buf_append(str, rb_inspect(v));
02238 sharp = ".";
02239 }
02240 else {
02241 rb_str_buf_append(str, rb_inspect(data->recv));
02242 rb_str_buf_cat2(str, "(");
02243 rb_str_buf_append(str, rb_inspect(v));
02244 rb_str_buf_cat2(str, ")");
02245 sharp = ".";
02246 }
02247 }
02248 else {
02249 rb_str_buf_append(str, rb_class_name(data->rclass));
02250 if (data->rclass != mklass) {
02251 rb_str_buf_cat2(str, "(");
02252 rb_str_buf_append(str, rb_class_name(mklass));
02253 rb_str_buf_cat2(str, ")");
02254 }
02255 }
02256 rb_str_buf_cat2(str, sharp);
02257 rb_str_append(str, rb_id2str(data->id));
02258 if (data->id != data->me->def->original_id) {
02259 rb_str_catf(str, "(%"PRIsVALUE")",
02260 rb_id2str(data->me->def->original_id));
02261 }
02262 if (data->me->def->type == VM_METHOD_TYPE_NOTIMPLEMENTED) {
02263 rb_str_buf_cat2(str, " (not-implemented)");
02264 }
02265 rb_str_buf_cat2(str, ">");
02266
02267 return str;
02268 }
02269
02270 static VALUE
02271 mproc(VALUE method)
02272 {
02273 return rb_funcall2(rb_mRubyVMFrozenCore, idProc, 0, 0);
02274 }
02275
02276 static VALUE
02277 mlambda(VALUE method)
02278 {
02279 return rb_funcall(rb_mRubyVMFrozenCore, idLambda, 0, 0);
02280 }
02281
02282 static VALUE
02283 bmcall(VALUE args, VALUE method, int argc, VALUE *argv, VALUE passed_proc)
02284 {
02285 volatile VALUE a;
02286 VALUE ret;
02287
02288 if (CLASS_OF(args) != rb_cArray) {
02289 args = rb_ary_new3(1, args);
02290 argc = 1;
02291 }
02292 else {
02293 argc = check_argc(RARRAY_LEN(args));
02294 }
02295 ret = rb_method_call_with_block(argc, RARRAY_PTR(args), method, passed_proc);
02296 RB_GC_GUARD(a) = args;
02297 return ret;
02298 }
02299
02300 VALUE
02301 rb_proc_new(
02302 VALUE (*func)(ANYARGS),
02303 VALUE val)
02304 {
02305 VALUE procval = rb_iterate(mproc, 0, func, val);
02306 return procval;
02307 }
02308
02309
02310
02311
02312
02313
02314
02315
02316 static VALUE
02317 method_proc(VALUE method)
02318 {
02319 VALUE procval;
02320 rb_proc_t *proc;
02321
02322
02323
02324
02325
02326
02327
02328
02329
02330 procval = rb_iterate(mlambda, 0, bmcall, method);
02331 GetProcPtr(procval, proc);
02332 proc->is_from_method = 1;
02333 return procval;
02334 }
02335
02336
02337
02338
02339
02340
02341
02342 static VALUE
02343 localjump_xvalue(VALUE exc)
02344 {
02345 return rb_iv_get(exc, "@exit_value");
02346 }
02347
02348
02349
02350
02351
02352
02353
02354
02355
02356 static VALUE
02357 localjump_reason(VALUE exc)
02358 {
02359 return rb_iv_get(exc, "@reason");
02360 }
02361
02362
02363
02364
02365
02366
02367
02368
02369
02370
02371
02372
02373
02374
02375
02376
02377 static VALUE
02378 proc_binding(VALUE self)
02379 {
02380 rb_proc_t *proc;
02381 VALUE bindval;
02382 rb_binding_t *bind;
02383
02384 GetProcPtr(self, proc);
02385 if (RB_TYPE_P((VALUE)proc->block.iseq, T_NODE)) {
02386 if (!IS_METHOD_PROC_NODE((NODE *)proc->block.iseq)) {
02387 rb_raise(rb_eArgError, "Can't create Binding from C level Proc");
02388 }
02389 }
02390
02391 bindval = rb_binding_alloc(rb_cBinding);
02392 GetBindingPtr(bindval, bind);
02393 bind->env = proc->envval;
02394 bind->blockprocval = proc->blockprocval;
02395 if (RUBY_VM_NORMAL_ISEQ_P(proc->block.iseq)) {
02396 bind->path = proc->block.iseq->location.path;
02397 bind->first_lineno = FIX2INT(rb_iseq_first_lineno(proc->block.iseq->self));
02398 }
02399 else {
02400 bind->path = Qnil;
02401 bind->first_lineno = 0;
02402 }
02403 return bindval;
02404 }
02405
02406 static VALUE curry(VALUE dummy, VALUE args, int argc, VALUE *argv, VALUE passed_proc);
02407
02408 static VALUE
02409 make_curry_proc(VALUE proc, VALUE passed, VALUE arity)
02410 {
02411 VALUE args = rb_ary_new3(3, proc, passed, arity);
02412 rb_proc_t *procp;
02413 int is_lambda;
02414
02415 GetProcPtr(proc, procp);
02416 is_lambda = procp->is_lambda;
02417 rb_ary_freeze(passed);
02418 rb_ary_freeze(args);
02419 proc = rb_proc_new(curry, args);
02420 GetProcPtr(proc, procp);
02421 procp->is_lambda = is_lambda;
02422 return proc;
02423 }
02424
02425 static VALUE
02426 curry(VALUE dummy, VALUE args, int argc, VALUE *argv, VALUE passed_proc)
02427 {
02428 VALUE proc, passed, arity;
02429 proc = RARRAY_AREF(args, 0);
02430 passed = RARRAY_AREF(args, 1);
02431 arity = RARRAY_AREF(args, 2);
02432
02433 passed = rb_ary_plus(passed, rb_ary_new4(argc, argv));
02434 rb_ary_freeze(passed);
02435
02436 if (RARRAY_LEN(passed) < FIX2INT(arity)) {
02437 if (!NIL_P(passed_proc)) {
02438 rb_warn("given block not used");
02439 }
02440 arity = make_curry_proc(proc, passed, arity);
02441 return arity;
02442 }
02443 else {
02444 return rb_proc_call_with_block(proc, check_argc(RARRAY_LEN(passed)), RARRAY_CONST_PTR(passed), passed_proc);
02445 }
02446 }
02447
02448
02449
02450
02451
02452
02453
02454
02455
02456
02457
02458
02459
02460
02461
02462
02463
02464
02465
02466
02467
02468
02469
02470
02471
02472
02473
02474
02475
02476
02477
02478
02479
02480
02481
02482
02483
02484
02485
02486
02487
02488
02489
02490 static VALUE
02491 proc_curry(int argc, VALUE *argv, VALUE self)
02492 {
02493 int sarity, max_arity, min_arity = rb_proc_min_max_arity(self, &max_arity);
02494 VALUE arity;
02495
02496 rb_scan_args(argc, argv, "01", &arity);
02497 if (NIL_P(arity)) {
02498 arity = INT2FIX(min_arity);
02499 }
02500 else {
02501 sarity = FIX2INT(arity);
02502 if (rb_proc_lambda_p(self)) {
02503 rb_check_arity(sarity, min_arity, max_arity);
02504 }
02505 }
02506
02507 return make_curry_proc(self, rb_ary_new(), arity);
02508 }
02509
02510
02511
02512
02513
02514
02515
02516
02517
02518
02519
02520
02521
02522
02523
02524
02525
02526
02527
02528
02529
02530
02531
02532
02533
02534
02535
02536
02537
02538
02539
02540
02541
02542
02543
02544
02545
02546
02547
02548
02549
02550
02551
02552
02553
02554
02555
02556
02557
02558
02559
02560
02561
02562
02563
02564
02565
02566
02567
02568
02569
02570
02571 void
02572 Init_Proc(void)
02573 {
02574
02575 rb_cProc = rb_define_class("Proc", rb_cObject);
02576 rb_undef_alloc_func(rb_cProc);
02577 rb_define_singleton_method(rb_cProc, "new", rb_proc_s_new, -1);
02578
02579 #if 0
02580 rb_add_method(rb_cProc, rb_intern("call"), VM_METHOD_TYPE_OPTIMIZED,
02581 (void *)OPTIMIZED_METHOD_TYPE_CALL, 0);
02582 rb_add_method(rb_cProc, rb_intern("[]"), VM_METHOD_TYPE_OPTIMIZED,
02583 (void *)OPTIMIZED_METHOD_TYPE_CALL, 0);
02584 rb_add_method(rb_cProc, rb_intern("==="), VM_METHOD_TYPE_OPTIMIZED,
02585 (void *)OPTIMIZED_METHOD_TYPE_CALL, 0);
02586 rb_add_method(rb_cProc, rb_intern("yield"), VM_METHOD_TYPE_OPTIMIZED,
02587 (void *)OPTIMIZED_METHOD_TYPE_CALL, 0);
02588 #else
02589 rb_define_method(rb_cProc, "call", proc_call, -1);
02590 rb_define_method(rb_cProc, "[]", proc_call, -1);
02591 rb_define_method(rb_cProc, "===", proc_call, -1);
02592 rb_define_method(rb_cProc, "yield", proc_call, -1);
02593 #endif
02594 rb_define_method(rb_cProc, "to_proc", proc_to_proc, 0);
02595 rb_define_method(rb_cProc, "arity", proc_arity, 0);
02596 rb_define_method(rb_cProc, "clone", proc_clone, 0);
02597 rb_define_method(rb_cProc, "dup", proc_dup, 0);
02598 rb_define_method(rb_cProc, "hash", proc_hash, 0);
02599 rb_define_method(rb_cProc, "to_s", proc_to_s, 0);
02600 rb_define_alias(rb_cProc, "inspect", "to_s");
02601 rb_define_method(rb_cProc, "lambda?", rb_proc_lambda_p, 0);
02602 rb_define_method(rb_cProc, "binding", proc_binding, 0);
02603 rb_define_method(rb_cProc, "curry", proc_curry, -1);
02604 rb_define_method(rb_cProc, "source_location", rb_proc_location, 0);
02605 rb_define_method(rb_cProc, "parameters", rb_proc_parameters, 0);
02606
02607
02608 rb_eLocalJumpError = rb_define_class("LocalJumpError", rb_eStandardError);
02609 rb_define_method(rb_eLocalJumpError, "exit_value", localjump_xvalue, 0);
02610 rb_define_method(rb_eLocalJumpError, "reason", localjump_reason, 0);
02611
02612 rb_eSysStackError = rb_define_class("SystemStackError", rb_eException);
02613 sysstack_error = rb_exc_new3(rb_eSysStackError,
02614 rb_obj_freeze(rb_str_new2("stack level too deep")));
02615 OBJ_TAINT(sysstack_error);
02616
02617
02618 rb_define_global_function("proc", rb_block_proc, 0);
02619 rb_define_global_function("lambda", rb_block_lambda, 0);
02620
02621
02622 rb_cMethod = rb_define_class("Method", rb_cObject);
02623 rb_undef_alloc_func(rb_cMethod);
02624 rb_undef_method(CLASS_OF(rb_cMethod), "new");
02625 rb_define_method(rb_cMethod, "==", method_eq, 1);
02626 rb_define_method(rb_cMethod, "eql?", method_eq, 1);
02627 rb_define_method(rb_cMethod, "hash", method_hash, 0);
02628 rb_define_method(rb_cMethod, "clone", method_clone, 0);
02629 rb_define_method(rb_cMethod, "call", rb_method_call, -1);
02630 rb_define_method(rb_cMethod, "[]", rb_method_call, -1);
02631 rb_define_method(rb_cMethod, "arity", method_arity_m, 0);
02632 rb_define_method(rb_cMethod, "inspect", method_inspect, 0);
02633 rb_define_method(rb_cMethod, "to_s", method_inspect, 0);
02634 rb_define_method(rb_cMethod, "to_proc", method_proc, 0);
02635 rb_define_method(rb_cMethod, "receiver", method_receiver, 0);
02636 rb_define_method(rb_cMethod, "name", method_name, 0);
02637 rb_define_method(rb_cMethod, "original_name", method_original_name, 0);
02638 rb_define_method(rb_cMethod, "owner", method_owner, 0);
02639 rb_define_method(rb_cMethod, "unbind", method_unbind, 0);
02640 rb_define_method(rb_cMethod, "source_location", rb_method_location, 0);
02641 rb_define_method(rb_cMethod, "parameters", rb_method_parameters, 0);
02642 rb_define_method(rb_mKernel, "method", rb_obj_method, 1);
02643 rb_define_method(rb_mKernel, "public_method", rb_obj_public_method, 1);
02644 rb_define_method(rb_mKernel, "singleton_method", rb_obj_singleton_method, 1);
02645
02646
02647 rb_cUnboundMethod = rb_define_class("UnboundMethod", rb_cObject);
02648 rb_undef_alloc_func(rb_cUnboundMethod);
02649 rb_undef_method(CLASS_OF(rb_cUnboundMethod), "new");
02650 rb_define_method(rb_cUnboundMethod, "==", method_eq, 1);
02651 rb_define_method(rb_cUnboundMethod, "eql?", method_eq, 1);
02652 rb_define_method(rb_cUnboundMethod, "hash", method_hash, 0);
02653 rb_define_method(rb_cUnboundMethod, "clone", method_clone, 0);
02654 rb_define_method(rb_cUnboundMethod, "arity", method_arity_m, 0);
02655 rb_define_method(rb_cUnboundMethod, "inspect", method_inspect, 0);
02656 rb_define_method(rb_cUnboundMethod, "to_s", method_inspect, 0);
02657 rb_define_method(rb_cUnboundMethod, "name", method_name, 0);
02658 rb_define_method(rb_cUnboundMethod, "original_name", method_original_name, 0);
02659 rb_define_method(rb_cUnboundMethod, "owner", method_owner, 0);
02660 rb_define_method(rb_cUnboundMethod, "bind", umethod_bind, 1);
02661 rb_define_method(rb_cUnboundMethod, "source_location", rb_method_location, 0);
02662 rb_define_method(rb_cUnboundMethod, "parameters", rb_method_parameters, 0);
02663
02664
02665 rb_define_method(rb_cModule, "instance_method", rb_mod_instance_method, 1);
02666 rb_define_method(rb_cModule, "public_instance_method", rb_mod_public_instance_method, 1);
02667 rb_define_private_method(rb_cModule, "define_method", rb_mod_define_method, -1);
02668
02669
02670 rb_define_method(rb_mKernel, "define_singleton_method", rb_obj_define_method, -1);
02671
02672 rb_define_private_method(rb_singleton_class(rb_vm_top_self()),
02673 "define_method", top_define_method, -1);
02674 }
02675
02676
02677
02678
02679
02680
02681
02682
02683
02684
02685
02686
02687
02688
02689
02690
02691
02692
02693
02694
02695
02696
02697
02698
02699
02700
02701
02702
02703
02704
02705
02706
02707
02708
02709
02710
02711 void
02712 Init_Binding(void)
02713 {
02714 rb_cBinding = rb_define_class("Binding", rb_cObject);
02715 rb_undef_alloc_func(rb_cBinding);
02716 rb_undef_method(CLASS_OF(rb_cBinding), "new");
02717 rb_define_method(rb_cBinding, "clone", binding_clone, 0);
02718 rb_define_method(rb_cBinding, "dup", binding_dup, 0);
02719 rb_define_method(rb_cBinding, "eval", bind_eval, -1);
02720 rb_define_method(rb_cBinding, "local_variable_get", bind_local_variable_get, 1);
02721 rb_define_method(rb_cBinding, "local_variable_set", bind_local_variable_set, 2);
02722 rb_define_method(rb_cBinding, "local_variable_defined?", bind_local_variable_defined_p, 1);
02723 rb_define_global_function("binding", rb_f_binding, 0);
02724 }
02725
02726