зеркало из https://github.com/github/ruby.git
[YARP] Implement ConstantPathTargetNode
Co-Authored-By: kddnewton <kevin.newton@shopify.com>
This commit is contained in:
Родитель
48b141b49d
Коммит
bf129370d3
|
@ -133,6 +133,22 @@ module YARP
|
|||
Object.send(:remove_const, constant_name)
|
||||
end
|
||||
|
||||
def test_ConstantPathTargetNode
|
||||
# Create some temporary nested constants
|
||||
Object.send(:const_set, "MyFoo", Object)
|
||||
Object.const_get("MyFoo").send(:const_set, "Bar", Object)
|
||||
|
||||
constant_names = ["MyBar", "MyFoo::Bar", "MyFoo::Bar::Baz"]
|
||||
source = "#{constant_names.join(",")} = Object"
|
||||
yarp_eval = RubyVM::InstructionSequence.compile_yarp(source).eval
|
||||
assert_equal yarp_eval, Object
|
||||
|
||||
## Teardown temp constants
|
||||
Object.const_get("MyFoo").send(:remove_const, "Bar")
|
||||
Object.send(:remove_const, "MyFoo")
|
||||
Object.send(:remove_const, "MyBar")
|
||||
end
|
||||
|
||||
def test_ConstantPathWriteNode
|
||||
# test_yarp_eval("YARP::YCT = 1")
|
||||
end
|
||||
|
|
|
@ -515,6 +515,58 @@ yp_compile_class_path(LINK_ANCHOR *const ret, rb_iseq_t *iseq, const yp_node_t *
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* In order to properly compile multiple-assignment, some preprocessing needs to
|
||||
* be performed in the case of call or constant path targets. This is when they
|
||||
* are read, the "parent" of each of these nodes should only be read once (the
|
||||
* receiver in the case of a call, the parent constant in the case of a constant
|
||||
* path).
|
||||
*/
|
||||
static uint8_t
|
||||
yp_compile_multi_write_lhs(rb_iseq_t *iseq, NODE dummy_line_node, const yp_node_t *node, LINK_ANCHOR *const ret, yp_compile_context_t *compile_context, uint8_t pushed, bool nested) {
|
||||
switch (YP_NODE_TYPE(node)) {
|
||||
case YP_MULTI_TARGET_NODE: {
|
||||
yp_multi_target_node_t *cast = (yp_multi_target_node_t *) node;
|
||||
for (size_t index = 0; index < cast->targets.size; index++) {
|
||||
pushed = yp_compile_multi_write_lhs(iseq, dummy_line_node, cast->targets.nodes[index], ret, compile_context, pushed, false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case YP_CONSTANT_PATH_TARGET_NODE: {
|
||||
yp_constant_path_target_node_t *cast = (yp_constant_path_target_node_t *)node;
|
||||
if (cast->parent) {
|
||||
ADD_INSN(ret, &dummy_line_node, putnil);
|
||||
pushed = yp_compile_multi_write_lhs(iseq, dummy_line_node, cast->parent, ret, compile_context, pushed, false);
|
||||
} else {
|
||||
ADD_INSN1(ret, &dummy_line_node, putobject, rb_cObject);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case YP_CONSTANT_PATH_NODE: {
|
||||
yp_constant_path_node_t *cast = (yp_constant_path_node_t *) node;
|
||||
if (cast->parent) {
|
||||
pushed = yp_compile_multi_write_lhs(iseq, dummy_line_node, cast->parent, ret, compile_context, pushed, false);
|
||||
} else {
|
||||
ADD_INSN(ret, &dummy_line_node, pop);
|
||||
ADD_INSN1(ret, &dummy_line_node, putobject, rb_cObject);
|
||||
}
|
||||
pushed = yp_compile_multi_write_lhs(iseq, dummy_line_node, cast->child, ret, compile_context, pushed, cast->parent);
|
||||
break;
|
||||
}
|
||||
case YP_CONSTANT_READ_NODE: {
|
||||
yp_constant_read_node_t *cast = (yp_constant_read_node_t *) node;
|
||||
ADD_INSN1(ret, &dummy_line_node, putobject, RBOOL(!nested));
|
||||
ADD_INSN1(ret, &dummy_line_node, getconstant, ID2SYM(yp_constant_id_lookup(compile_context, cast->name)));
|
||||
pushed = pushed + 2;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return pushed;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compiles a YARP node into instruction sequences
|
||||
*
|
||||
|
@ -848,6 +900,13 @@ yp_compile_node(rb_iseq_t *iseq, const yp_node_t *node, LINK_ANCHOR *const ret,
|
|||
YP_POP_IF_POPPED;
|
||||
return;
|
||||
}
|
||||
case YP_CONSTANT_PATH_TARGET_NODE: {
|
||||
yp_constant_path_target_node_t *cast = (yp_constant_path_target_node_t *)node;
|
||||
|
||||
YP_COMPILE(cast->parent);
|
||||
|
||||
return;
|
||||
}
|
||||
case YP_CONSTANT_PATH_WRITE_NODE: {
|
||||
yp_constant_path_write_node_t *constant_path_write_node = (yp_constant_path_write_node_t*) node;
|
||||
YP_COMPILE(constant_path_write_node->value);
|
||||
|
@ -1527,8 +1586,23 @@ yp_compile_node(rb_iseq_t *iseq, const yp_node_t *node, LINK_ANCHOR *const ret,
|
|||
YP_POP_IF_POPPED;
|
||||
return;
|
||||
}
|
||||
case YP_MULTI_TARGET_NODE: {
|
||||
yp_multi_target_node_t *cast = (yp_multi_target_node_t *) node;
|
||||
for (size_t index = 0; index < cast->targets.size; index++) {
|
||||
YP_COMPILE(cast->targets.nodes[index]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
case YP_MULTI_WRITE_NODE: {
|
||||
yp_multi_write_node_t *multi_write_node = (yp_multi_write_node_t *)node;
|
||||
yp_node_list_t node_list = multi_write_node->targets;
|
||||
|
||||
// pre-process the left hand side of multi-assignments.
|
||||
uint8_t pushed = 0;
|
||||
for (size_t index = 0; index < node_list.size; index++) {
|
||||
pushed = yp_compile_multi_write_lhs(iseq, dummy_line_node, node_list.nodes[index], ret, compile_context, pushed, false);
|
||||
}
|
||||
|
||||
YP_COMPILE_NOT_POPPED(multi_write_node->value);
|
||||
|
||||
// TODO: int flag = 0x02 | (NODE_NAMED_REST_P(restn) ? 0x01 : 0x00);
|
||||
|
@ -1538,10 +1612,28 @@ yp_compile_node(rb_iseq_t *iseq, const yp_node_t *node, LINK_ANCHOR *const ret,
|
|||
ADD_INSN(ret, &dummy_line_node, dup);
|
||||
}
|
||||
ADD_INSN2(ret, &dummy_line_node, expandarray, INT2FIX(multi_write_node->targets.size), INT2FIX(flag));
|
||||
yp_node_list_t node_list = multi_write_node->targets;
|
||||
|
||||
for (size_t index = 0; index < node_list.size; index++) {
|
||||
YP_COMPILE(node_list.nodes[index]);
|
||||
yp_node_t *considered_node = node_list.nodes[index];
|
||||
|
||||
if (YP_NODE_TYPE_P(considered_node, YP_CONSTANT_PATH_TARGET_NODE) && pushed > 0) {
|
||||
yp_constant_path_target_node_t *cast = (yp_constant_path_target_node_t *)considered_node;
|
||||
ID name = yp_constant_id_lookup(compile_context, ((yp_constant_read_node_t * ) cast->child)->name);
|
||||
|
||||
pushed -= 2;
|
||||
|
||||
ADD_INSN1(ret, &dummy_line_node, topn, INT2FIX(pushed));
|
||||
ADD_INSN1(ret, &dummy_line_node, setconstant, ID2SYM(name));
|
||||
} else {
|
||||
YP_COMPILE(node_list.nodes[index]);
|
||||
}
|
||||
}
|
||||
|
||||
if (pushed) {
|
||||
ADD_INSN1(ret, &dummy_line_node, setn, INT2FIX(pushed));
|
||||
for (uint8_t index = 0; index < pushed; index++) {
|
||||
ADD_INSN(ret, &dummy_line_node, pop);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
|
|
Загрузка…
Ссылка в новой задаче