@@ -409,7 +409,7 @@ bind_eval(int argc, VALUE *argv, VALUE bindval)
409409}
410410
411411static const VALUE *
412- get_local_variable_ptr (const rb_env_t * * envp , ID lid )
412+ get_local_variable_ptr (const rb_env_t * * envp , ID lid , bool search_outer )
413413{
414414 const rb_env_t * env = * envp ;
415415 do {
@@ -446,7 +446,7 @@ get_local_variable_ptr(const rb_env_t **envp, ID lid)
446446 * envp = NULL ;
447447 return NULL ;
448448 }
449- } while ((env = rb_vm_env_prev_env (env )) != NULL );
449+ } while (search_outer && (env = rb_vm_env_prev_env (env )) != NULL );
450450
451451 * envp = NULL ;
452452 return NULL ;
@@ -548,7 +548,7 @@ bind_local_variable_get(VALUE bindval, VALUE sym)
548548 GetBindingPtr (bindval , bind );
549549
550550 env = VM_ENV_ENVVAL_PTR (vm_block_ep (& bind -> block ));
551- if ((ptr = get_local_variable_ptr (& env , lid )) != NULL ) {
551+ if ((ptr = get_local_variable_ptr (& env , lid , TRUE )) != NULL ) {
552552 return * ptr ;
553553 }
554554
@@ -600,7 +600,7 @@ bind_local_variable_set(VALUE bindval, VALUE sym, VALUE val)
600600
601601 GetBindingPtr (bindval , bind );
602602 env = VM_ENV_ENVVAL_PTR (vm_block_ep (& bind -> block ));
603- if ((ptr = get_local_variable_ptr (& env , lid )) == NULL ) {
603+ if ((ptr = get_local_variable_ptr (& env , lid , TRUE )) == NULL ) {
604604 /* not found. create new env */
605605 ptr = rb_binding_add_dynavars (bindval , bind , 1 , & lid );
606606 env = VM_ENV_ENVVAL_PTR (vm_block_ep (& bind -> block ));
@@ -647,7 +647,80 @@ bind_local_variable_defined_p(VALUE bindval, VALUE sym)
647647
648648 GetBindingPtr (bindval , bind );
649649 env = VM_ENV_ENVVAL_PTR (vm_block_ep (& bind -> block ));
650- return RBOOL (get_local_variable_ptr (& env , lid ));
650+ return RBOOL (get_local_variable_ptr (& env , lid , TRUE));
651+ }
652+
653+ /*
654+ * call-seq:
655+ * binding.implicit_parameters -> Array
656+ *
657+ * TODO
658+ */
659+ static VALUE
660+ bind_implicit_parameters (VALUE bindval )
661+ {
662+ const rb_binding_t * bind ;
663+ const rb_env_t * env ;
664+
665+ // TODO: it
666+
667+ GetBindingPtr (bindval , bind );
668+ env = VM_ENV_ENVVAL_PTR (vm_block_ep (& bind -> block ));
669+ return rb_vm_env_numbered_parameters (env );
670+ }
671+
672+ /*
673+ * call-seq:
674+ * binding.implicit_parameter_get(symbol) -> obj
675+ *
676+ * TODO
677+ */
678+ static VALUE
679+ bind_implicit_parameter_get (VALUE bindval , VALUE sym )
680+ {
681+ ID lid = check_local_id (bindval , & sym );
682+ const rb_binding_t * bind ;
683+ const VALUE * ptr ;
684+ const rb_env_t * env ;
685+
686+ if (!lid || !rb_numparam_id_p (lid )) {
687+ rb_name_err_raise ("'%1$s' is not an implicit parameter" ,
688+ bindval , ID2SYM (lid ));
689+ }
690+
691+ GetBindingPtr (bindval , bind );
692+
693+ env = VM_ENV_ENVVAL_PTR (vm_block_ep (& bind -> block ));
694+ if ((ptr = get_local_variable_ptr (& env , lid , FALSE)) != NULL ) {
695+ return * ptr ;
696+ }
697+
698+ rb_name_err_raise ("implicit parameter '%1$s' is not defined for %2$s" , bindval , ID2SYM (lid ));
699+ UNREACHABLE_RETURN (Qundef );
700+ }
701+
702+ /*
703+ * call-seq:
704+ * binding.implicit_parameter_defined?(symbol) -> obj
705+ *
706+ * TODO
707+ *
708+ */
709+ static VALUE
710+ bind_implicit_parameter_defined_p (VALUE bindval , VALUE sym )
711+ {
712+ ID lid = check_local_id (bindval , & sym );
713+ const rb_binding_t * bind ;
714+ const rb_env_t * env ;
715+
716+ if (!lid || !rb_numparam_id_p (lid )) {
717+ rb_name_err_raise ("'%1$s' is not an implicit parameter" ,
718+ bindval , ID2SYM (lid ));
719+ }
720+
721+ GetBindingPtr (bindval , bind );
722+ env = VM_ENV_ENVVAL_PTR (vm_block_ep (& bind -> block ));
723+ return RBOOL (get_local_variable_ptr (& env , lid , FALSE));
651724}
652725
653726/*
@@ -4607,6 +4680,9 @@ Init_Binding(void)
46074680 rb_define_method (rb_cBinding , "local_variable_get" , bind_local_variable_get , 1 );
46084681 rb_define_method (rb_cBinding , "local_variable_set" , bind_local_variable_set , 2 );
46094682 rb_define_method (rb_cBinding , "local_variable_defined?" , bind_local_variable_defined_p , 1 );
4683+ rb_define_method (rb_cBinding , "implicit_parameters" , bind_implicit_parameters , 0 );
4684+ rb_define_method (rb_cBinding , "implicit_parameter_get" , bind_implicit_parameter_get , 1 );
4685+ rb_define_method (rb_cBinding , "implicit_parameter_defined?" , bind_implicit_parameter_defined_p , 1 );
46104686 rb_define_method (rb_cBinding , "receiver" , bind_receiver , 0 );
46114687 rb_define_method (rb_cBinding , "source_location" , bind_location , 0 );
46124688 rb_define_global_function ("binding" , rb_f_binding , 0 );
0 commit comments