refinements in string interpolation
* compile.c (iseq_compile_each0): insert to_s method call, so that refinements activated at the caller should take place. [Feature #13812] * insns.def (tostring): fix up converted object to a string, infect and fallback. * insns.def (branchiftype): new instruction for conversion. branches if TOS is an instance of the given type. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@59950 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
d1e63172c6
commit
b2da3824c5
2
NEWS
2
NEWS
@ -18,6 +18,8 @@ with all sufficient information, see the ChangeLog file or Redmine
|
|||||||
|
|
||||||
* rescue/else/ensure are allowed inside do/end blocks. [Feature #12906]
|
* rescue/else/ensure are allowed inside do/end blocks. [Feature #12906]
|
||||||
|
|
||||||
|
* refinements take place in string interpolations. [Feature #13812]
|
||||||
|
|
||||||
=== Core classes updates (outstanding ones only)
|
=== Core classes updates (outstanding ones only)
|
||||||
|
|
||||||
* Array
|
* Array
|
||||||
|
@ -6180,7 +6180,15 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int popp
|
|||||||
ADD_INSN(ret, line, pop);
|
ADD_INSN(ret, line, pop);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
const unsigned int flag = VM_CALL_FCALL;
|
||||||
|
LABEL *isstr = NEW_LABEL(line);
|
||||||
|
ADD_INSN(ret, line, dup);
|
||||||
|
ADD_INSN2(ret, line, branchiftype, INT2FIX(T_STRING), isstr);
|
||||||
|
LABEL_REF(isstr);
|
||||||
|
ADD_INSN(ret, line, dup);
|
||||||
|
ADD_SEND_R(ret, line, idTo_s, INT2FIX(0), NULL, INT2FIX(flag), NULL);
|
||||||
ADD_INSN(ret, line, tostring);
|
ADD_INSN(ret, line, tostring);
|
||||||
|
ADD_LABEL(ret, isstr);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
22
insns.def
22
insns.def
@ -356,10 +356,11 @@ concatstrings
|
|||||||
DEFINE_INSN
|
DEFINE_INSN
|
||||||
tostring
|
tostring
|
||||||
()
|
()
|
||||||
(VALUE val)
|
(VALUE val, VALUE str)
|
||||||
(VALUE val)
|
(VALUE val)
|
||||||
{
|
{
|
||||||
val = rb_obj_as_string(val);
|
VALUE rb_obj_as_string_result(VALUE str, VALUE obj);
|
||||||
|
val = rb_obj_as_string_result(str, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1038,6 +1039,23 @@ branchnil
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
@c jump
|
||||||
|
@e if val is type, set PC to (PC + dst).
|
||||||
|
@j もし val が type ならば、PC を (PC + dst) にする。
|
||||||
|
*/
|
||||||
|
DEFINE_INSN
|
||||||
|
branchiftype
|
||||||
|
(rb_num_t type, OFFSET dst)
|
||||||
|
(VALUE val)
|
||||||
|
()
|
||||||
|
{
|
||||||
|
if (TYPE(val) == (int)type) {
|
||||||
|
RUBY_VM_CHECK_INTS(th);
|
||||||
|
JUMP(dst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**********************************************************/
|
/**********************************************************/
|
||||||
/* for optimize */
|
/* for optimize */
|
||||||
|
8
string.c
8
string.c
@ -1404,6 +1404,8 @@ str_shared_replace(VALUE str, VALUE str2)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VALUE rb_obj_as_string_result(VALUE str, VALUE obj);
|
||||||
|
|
||||||
VALUE
|
VALUE
|
||||||
rb_obj_as_string(VALUE obj)
|
rb_obj_as_string(VALUE obj)
|
||||||
{
|
{
|
||||||
@ -1413,6 +1415,12 @@ rb_obj_as_string(VALUE obj)
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
str = rb_funcall(obj, idTo_s, 0);
|
str = rb_funcall(obj, idTo_s, 0);
|
||||||
|
return rb_obj_as_string_result(str, obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
VALUE
|
||||||
|
rb_obj_as_string_result(VALUE str, VALUE obj)
|
||||||
|
{
|
||||||
if (!RB_TYPE_P(str, T_STRING))
|
if (!RB_TYPE_P(str, T_STRING))
|
||||||
return rb_any_to_s(obj);
|
return rb_any_to_s(obj);
|
||||||
if (!FL_TEST_RAW(str, RSTRING_FSTR) && FL_ABLE(obj))
|
if (!FL_TEST_RAW(str, RSTRING_FSTR) && FL_ABLE(obj))
|
||||||
|
@ -1961,6 +1961,19 @@ class TestRefinement < Test::Unit::TestCase
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class ToString
|
||||||
|
c = self
|
||||||
|
using Module.new {refine(c) {def to_s; "ok"; end}}
|
||||||
|
def string
|
||||||
|
"#{self}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_tostring
|
||||||
|
assert_equal("ok", ToString.new.string)
|
||||||
|
assert_predicate(ToString.new.taint.string, :tainted?)
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def eval_using(mod, s)
|
def eval_using(mod, s)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user