зеркало из https://github.com/github/ruby.git
Move shareable_constant_value logic from parse.y to compile.c
This commit is contained in:
Родитель
4ef99905a6
Коммит
6056773105
|
@ -3534,6 +3534,7 @@ compile.$(OBJEXT): {$(VPATH)}prism/prism.h
|
|||
compile.$(OBJEXT): {$(VPATH)}prism/version.h
|
||||
compile.$(OBJEXT): {$(VPATH)}prism_compile.c
|
||||
compile.$(OBJEXT): {$(VPATH)}prism_compile.h
|
||||
compile.$(OBJEXT): {$(VPATH)}ractor.h
|
||||
compile.$(OBJEXT): {$(VPATH)}re.h
|
||||
compile.$(OBJEXT): {$(VPATH)}regex.h
|
||||
compile.$(OBJEXT): {$(VPATH)}ruby_assert.h
|
||||
|
|
373
compile.c
373
compile.c
|
@ -36,6 +36,7 @@
|
|||
#include "internal/thread.h"
|
||||
#include "internal/variable.h"
|
||||
#include "iseq.h"
|
||||
#include "ruby/ractor.h"
|
||||
#include "ruby/re.h"
|
||||
#include "ruby/util.h"
|
||||
#include "vm_core.h"
|
||||
|
@ -9375,6 +9376,8 @@ compile_op_asgn2(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node
|
|||
return COMPILE_OK;
|
||||
}
|
||||
|
||||
static int compile_shareable_constant_value(rb_iseq_t *iseq, LINK_ANCHOR *ret, enum rb_parser_shareability shareable, const NODE *lhs, const NODE *value);
|
||||
|
||||
static int
|
||||
compile_op_cdecl(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped)
|
||||
{
|
||||
|
@ -9418,7 +9421,7 @@ compile_op_cdecl(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node
|
|||
/* cref [obj] */
|
||||
if (!popped) ADD_INSN(ret, node, pop); /* cref */
|
||||
if (lassign) ADD_LABEL(ret, lassign);
|
||||
CHECK(COMPILE(ret, "NODE_OP_CDECL#nd_value", RNODE_OP_CDECL(node)->nd_value));
|
||||
CHECK(compile_shareable_constant_value(iseq, ret, RNODE_OP_CDECL(node)->shareability, RNODE_OP_CDECL(node)->nd_head, RNODE_OP_CDECL(node)->nd_value));
|
||||
/* cref value */
|
||||
if (popped)
|
||||
ADD_INSN1(ret, node, topn, INT2FIX(1)); /* cref value cref */
|
||||
|
@ -9432,7 +9435,7 @@ compile_op_cdecl(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node
|
|||
ADD_INSN(ret, node, pop); /* [value] */
|
||||
}
|
||||
else {
|
||||
CHECK(COMPILE(ret, "NODE_OP_CDECL#nd_value", RNODE_OP_CDECL(node)->nd_value));
|
||||
CHECK(compile_shareable_constant_value(iseq, ret, RNODE_OP_CDECL(node)->shareability, RNODE_OP_CDECL(node)->nd_head, RNODE_OP_CDECL(node)->nd_value));
|
||||
/* cref obj value */
|
||||
ADD_CALL(ret, node, RNODE_OP_CDECL(node)->nd_aid, INT2FIX(1));
|
||||
/* cref value */
|
||||
|
@ -9948,6 +9951,368 @@ compile_attrasgn(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node
|
|||
return COMPILE_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
compile_make_shareable_node(rb_iseq_t *iseq, LINK_ANCHOR *ret, LINK_ANCHOR *sub, const NODE *value, bool copy)
|
||||
{
|
||||
ADD_INSN1(ret, value, putobject, rb_mRubyVMFrozenCore);
|
||||
ADD_SEQ(ret, sub);
|
||||
|
||||
if (copy) {
|
||||
/*
|
||||
* NEW_CALL(fcore, rb_intern("make_shareable_copy"),
|
||||
* NEW_LIST(value, loc), loc);
|
||||
*/
|
||||
ADD_SEND_WITH_FLAG(ret, value, rb_intern("make_shareable_copy"), INT2FIX(1), INT2FIX(VM_CALL_ARGS_SIMPLE));
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* NEW_CALL(fcore, rb_intern("make_shareable"),
|
||||
* NEW_LIST(value, loc), loc);
|
||||
*/
|
||||
ADD_SEND_WITH_FLAG(ret, value, rb_intern("make_shareable"), INT2FIX(1), INT2FIX(VM_CALL_ARGS_SIMPLE));
|
||||
}
|
||||
|
||||
return COMPILE_OK;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
node_const_decl_val(const NODE *node)
|
||||
{
|
||||
VALUE path;
|
||||
switch (nd_type(node)) {
|
||||
case NODE_CDECL:
|
||||
if (RNODE_CDECL(node)->nd_vid) {
|
||||
path = rb_id2str(RNODE_CDECL(node)->nd_vid);
|
||||
goto end;
|
||||
}
|
||||
else {
|
||||
node = RNODE_CDECL(node)->nd_else;
|
||||
}
|
||||
break;
|
||||
case NODE_COLON2:
|
||||
break;
|
||||
case NODE_COLON3:
|
||||
// ::Const
|
||||
path = rb_str_new_cstr("::");
|
||||
rb_str_append(path, rb_id2str(RNODE_COLON3(node)->nd_mid));
|
||||
goto end;
|
||||
default:
|
||||
rb_bug("unexpected node: %s", ruby_node_name(nd_type(node)));
|
||||
UNREACHABLE_RETURN(0);
|
||||
}
|
||||
|
||||
path = rb_ary_new();
|
||||
if (node) {
|
||||
for (; node && nd_type_p(node, NODE_COLON2); node = RNODE_COLON2(node)->nd_head) {
|
||||
rb_ary_push(path, rb_id2str(RNODE_COLON2(node)->nd_mid));
|
||||
}
|
||||
if (node && nd_type_p(node, NODE_CONST)) {
|
||||
// Const::Name
|
||||
rb_ary_push(path, rb_id2str(RNODE_CONST(node)->nd_vid));
|
||||
}
|
||||
else if (node && nd_type_p(node, NODE_COLON3)) {
|
||||
// ::Const::Name
|
||||
rb_ary_push(path, rb_id2str(RNODE_COLON3(node)->nd_mid));
|
||||
rb_ary_push(path, rb_str_new(0, 0));
|
||||
}
|
||||
else {
|
||||
// expression::Name
|
||||
rb_ary_push(path, rb_str_new_cstr("..."));
|
||||
}
|
||||
path = rb_ary_join(rb_ary_reverse(path), rb_str_new_cstr("::"));
|
||||
}
|
||||
end:
|
||||
path = rb_fstring(path);
|
||||
return path;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
const_decl_path(NODE *dest)
|
||||
{
|
||||
VALUE path = Qnil;
|
||||
if (!nd_type_p(dest, NODE_CALL)) {
|
||||
path = node_const_decl_val(dest);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
static int
|
||||
compile_ensure_shareable_node(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *dest, const NODE *value)
|
||||
{
|
||||
/*
|
||||
*. RubyVM::FrozenCore.ensure_shareable(value, const_decl_path(dest))
|
||||
*/
|
||||
VALUE path = const_decl_path(dest);
|
||||
ADD_INSN1(ret, value, putobject, rb_mRubyVMFrozenCore);
|
||||
CHECK(COMPILE(ret, "compile_ensure_shareable_node", value));
|
||||
ADD_INSN1(ret, value, putobject, path);
|
||||
RB_OBJ_WRITTEN(iseq, Qundef, path);
|
||||
ADD_SEND_WITH_FLAG(ret, value, rb_intern("ensure_shareable"), INT2FIX(2), INT2FIX(VM_CALL_ARGS_SIMPLE));
|
||||
|
||||
return COMPILE_OK;
|
||||
}
|
||||
|
||||
#ifndef SHAREABLE_BARE_EXPRESSION
|
||||
#define SHAREABLE_BARE_EXPRESSION 1
|
||||
#endif
|
||||
|
||||
static int
|
||||
compile_shareable_literal_constant(rb_iseq_t *iseq, LINK_ANCHOR *ret, enum rb_parser_shareability shareable, NODE *dest, const NODE *node, size_t level, VALUE *value_p, int *shareable_literal_p)
|
||||
{
|
||||
# define compile_shareable_literal_constant_next(node, anchor, value_p, shareable_literal_p) \
|
||||
compile_shareable_literal_constant(iseq, anchor, shareable, dest, node, level+1, value_p, shareable_literal_p)
|
||||
VALUE lit = Qnil;
|
||||
DECL_ANCHOR(anchor);
|
||||
|
||||
enum node_type type = nd_type(node);
|
||||
switch (type) {
|
||||
case NODE_TRUE:
|
||||
*value_p = Qtrue;
|
||||
goto compile;
|
||||
case NODE_FALSE:
|
||||
*value_p = Qfalse;
|
||||
goto compile;
|
||||
case NODE_NIL:
|
||||
*value_p = Qnil;
|
||||
goto compile;
|
||||
case NODE_LIT:
|
||||
*value_p = RNODE_LIT(node)->nd_lit;
|
||||
goto compile;
|
||||
case NODE_SYM:
|
||||
*value_p = rb_node_sym_string_val(node);
|
||||
goto compile;
|
||||
case NODE_REGX:
|
||||
*value_p = rb_node_regx_string_val(node);
|
||||
goto compile;
|
||||
case NODE_LINE:
|
||||
*value_p = rb_node_line_lineno_val(node);
|
||||
goto compile;
|
||||
case NODE_INTEGER:
|
||||
*value_p = rb_node_integer_literal_val(node);
|
||||
goto compile;
|
||||
case NODE_FLOAT:
|
||||
*value_p = rb_node_float_literal_val(node);
|
||||
goto compile;
|
||||
case NODE_RATIONAL:
|
||||
*value_p = rb_node_rational_literal_val(node);
|
||||
goto compile;
|
||||
case NODE_IMAGINARY:
|
||||
*value_p = rb_node_imaginary_literal_val(node);
|
||||
goto compile;
|
||||
case NODE_ENCODING:
|
||||
*value_p = rb_node_encoding_val(node);
|
||||
|
||||
compile:
|
||||
CHECK(COMPILE(ret, "shareable_literal_constant", node));
|
||||
*shareable_literal_p = 1;
|
||||
return COMPILE_OK;
|
||||
|
||||
case NODE_DSTR:
|
||||
CHECK(COMPILE(ret, "shareable_literal_constant", node));
|
||||
if (shareable == rb_parser_shareable_literal) {
|
||||
/*
|
||||
* NEW_CALL(node, idUMinus, 0, loc);
|
||||
*
|
||||
* -"#{var}"
|
||||
*/
|
||||
ADD_SEND_WITH_FLAG(ret, node, idUMinus, INT2FIX(0), INT2FIX(VM_CALL_ARGS_SIMPLE));
|
||||
}
|
||||
*value_p = Qundef;
|
||||
*shareable_literal_p = 1;
|
||||
return COMPILE_OK;
|
||||
|
||||
case NODE_STR:{
|
||||
VALUE lit = rb_fstring(rb_node_str_string_val(node));
|
||||
ADD_INSN1(ret, node, putobject, lit);
|
||||
RB_OBJ_WRITTEN(iseq, Qundef, lit);
|
||||
*value_p = lit;
|
||||
*shareable_literal_p = 1;
|
||||
|
||||
return COMPILE_OK;
|
||||
}
|
||||
|
||||
case NODE_FILE:{
|
||||
VALUE lit = rb_fstring(rb_node_file_path_val(node));
|
||||
ADD_INSN1(ret, node, putobject, lit);
|
||||
RB_OBJ_WRITTEN(iseq, Qundef, lit);
|
||||
*value_p = lit;
|
||||
*shareable_literal_p = 1;
|
||||
|
||||
return COMPILE_OK;
|
||||
}
|
||||
|
||||
case NODE_ZLIST:{
|
||||
VALUE lit = rb_ary_new();
|
||||
OBJ_FREEZE_RAW(lit);
|
||||
ADD_INSN1(ret, node, putobject, lit);
|
||||
RB_OBJ_WRITTEN(iseq, Qundef, lit);
|
||||
*value_p = lit;
|
||||
*shareable_literal_p = 1;
|
||||
|
||||
return COMPILE_OK;
|
||||
}
|
||||
|
||||
case NODE_LIST:{
|
||||
INIT_ANCHOR(anchor);
|
||||
lit = rb_ary_new();
|
||||
for (NODE *n = (NODE *)node; n; n = RNODE_LIST(n)->nd_next) {
|
||||
VALUE val;
|
||||
int shareable_literal_p2;
|
||||
NODE *elt = RNODE_LIST(n)->nd_head;
|
||||
if (elt) {
|
||||
CHECK(compile_shareable_literal_constant_next(elt, anchor, &val, &shareable_literal_p2));
|
||||
if (shareable_literal_p2) {
|
||||
/* noop */
|
||||
}
|
||||
else if (RTEST(lit)) {
|
||||
rb_ary_clear(lit);
|
||||
lit = Qfalse;
|
||||
}
|
||||
}
|
||||
if (RTEST(lit)) {
|
||||
if (!UNDEF_P(val)) {
|
||||
rb_ary_push(lit, val);
|
||||
}
|
||||
else {
|
||||
rb_ary_clear(lit);
|
||||
lit = Qnil; /* make shareable at runtime */
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NODE_HASH:{
|
||||
if (!RNODE_HASH(node)->nd_brace) {
|
||||
*value_p = Qundef;
|
||||
*shareable_literal_p = 0;
|
||||
return COMPILE_OK;
|
||||
}
|
||||
|
||||
INIT_ANCHOR(anchor);
|
||||
lit = rb_hash_new();
|
||||
for (NODE *n = RNODE_HASH(node)->nd_head; n; n = RNODE_LIST(RNODE_LIST(n)->nd_next)->nd_next) {
|
||||
VALUE key_val;
|
||||
VALUE value_val;
|
||||
int shareable_literal_p2;
|
||||
NODE *key = RNODE_LIST(n)->nd_head;
|
||||
NODE *val = RNODE_LIST(RNODE_LIST(n)->nd_next)->nd_head;
|
||||
if (key) {
|
||||
CHECK(compile_shareable_literal_constant_next(key, anchor, &key_val, &shareable_literal_p2));
|
||||
if (shareable_literal_p2) {
|
||||
/* noop */
|
||||
}
|
||||
else if (RTEST(lit)) {
|
||||
rb_hash_clear(lit);
|
||||
lit = Qfalse;
|
||||
}
|
||||
}
|
||||
if (val) {
|
||||
CHECK(compile_shareable_literal_constant_next(val, anchor, &value_val, &shareable_literal_p2));
|
||||
if (shareable_literal_p2) {
|
||||
/* noop */
|
||||
}
|
||||
else if (RTEST(lit)) {
|
||||
rb_hash_clear(lit);
|
||||
lit = Qfalse;
|
||||
}
|
||||
}
|
||||
if (RTEST(lit)) {
|
||||
if (!UNDEF_P(key_val) && !UNDEF_P(value_val)) {
|
||||
rb_hash_aset(lit, key_val, value_val);
|
||||
}
|
||||
else {
|
||||
rb_hash_clear(lit);
|
||||
lit = Qnil; /* make shareable at runtime */
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
if (shareable == rb_parser_shareable_literal &&
|
||||
(SHAREABLE_BARE_EXPRESSION || level > 0)) {
|
||||
CHECK(compile_ensure_shareable_node(iseq, ret, dest, node));
|
||||
*value_p = Qundef;
|
||||
*shareable_literal_p = 1;
|
||||
return COMPILE_OK;
|
||||
}
|
||||
CHECK(COMPILE(ret, "shareable_literal_constant", node));
|
||||
*value_p = Qundef;
|
||||
*shareable_literal_p = 0;
|
||||
return COMPILE_OK;
|
||||
}
|
||||
|
||||
/* Array or Hash */
|
||||
if (!lit) {
|
||||
if (nd_type(node) == NODE_LIST) {
|
||||
ADD_INSN1(anchor, node, newarray, INT2FIX(RNODE_LIST(node)->as.nd_alen));
|
||||
}
|
||||
else if (nd_type(node) == NODE_HASH) {
|
||||
int len = (int)RNODE_LIST(RNODE_HASH(node)->nd_head)->as.nd_alen;
|
||||
ADD_INSN1(anchor, node, newhash, INT2FIX(len));
|
||||
}
|
||||
*value_p = Qundef;
|
||||
*shareable_literal_p = 0;
|
||||
ADD_SEQ(ret, anchor);
|
||||
return COMPILE_OK;
|
||||
}
|
||||
if (NIL_P(lit)) {
|
||||
// if shareable_literal, all elements should have been ensured
|
||||
// as shareable
|
||||
if (nd_type(node) == NODE_LIST) {
|
||||
ADD_INSN1(anchor, node, newarray, INT2FIX(RNODE_LIST(node)->as.nd_alen));
|
||||
}
|
||||
else if (nd_type(node) == NODE_HASH) {
|
||||
int len = (int)RNODE_LIST(RNODE_HASH(node)->nd_head)->as.nd_alen;
|
||||
ADD_INSN1(anchor, node, newhash, INT2FIX(len));
|
||||
}
|
||||
CHECK(compile_make_shareable_node(iseq, ret, anchor, node, false));
|
||||
*value_p = Qundef;
|
||||
*shareable_literal_p = 1;
|
||||
}
|
||||
else {
|
||||
VALUE val = rb_ractor_make_shareable(lit);
|
||||
ADD_INSN1(ret, node, putobject, val);
|
||||
RB_OBJ_WRITTEN(iseq, Qundef, val);
|
||||
*value_p = val;
|
||||
*shareable_literal_p = 1;
|
||||
}
|
||||
|
||||
return COMPILE_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
compile_shareable_constant_value(rb_iseq_t *iseq, LINK_ANCHOR *ret, enum rb_parser_shareability shareable, const NODE *lhs, const NODE *value)
|
||||
{
|
||||
int literal_p = 0;
|
||||
VALUE val;
|
||||
DECL_ANCHOR(anchor);
|
||||
INIT_ANCHOR(anchor);
|
||||
|
||||
switch (shareable) {
|
||||
case rb_parser_shareable_none:
|
||||
CHECK(COMPILE(ret, "compile_shareable_constant_value", value));
|
||||
return COMPILE_OK;
|
||||
|
||||
case rb_parser_shareable_literal:
|
||||
CHECK(compile_shareable_literal_constant(iseq, anchor, shareable, (NODE *)lhs, value, 0, &val, &literal_p));
|
||||
ADD_SEQ(ret, anchor);
|
||||
return COMPILE_OK;
|
||||
|
||||
case rb_parser_shareable_copy:
|
||||
case rb_parser_shareable_everything:
|
||||
CHECK(compile_shareable_literal_constant(iseq, anchor, shareable, (NODE *)lhs, value, 0, &val, &literal_p));
|
||||
if (!literal_p) {
|
||||
CHECK(compile_make_shareable_node(iseq, ret, anchor, value, shareable == rb_parser_shareable_copy));
|
||||
}
|
||||
else {
|
||||
ADD_SEQ(ret, anchor);
|
||||
}
|
||||
return COMPILE_OK;
|
||||
}
|
||||
}
|
||||
|
||||
static int iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped);
|
||||
/**
|
||||
compile each node
|
||||
|
@ -10130,7 +10495,7 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
|
|||
}
|
||||
case NODE_CDECL:{
|
||||
if (RNODE_CDECL(node)->nd_vid) {
|
||||
CHECK(COMPILE(ret, "lvalue", RNODE_CDECL(node)->nd_value));
|
||||
CHECK(compile_shareable_constant_value(iseq, ret, RNODE_CDECL(node)->shareability, node, RNODE_CDECL(node)->nd_value));
|
||||
|
||||
if (!popped) {
|
||||
ADD_INSN(ret, node, dup);
|
||||
|
@ -10142,7 +10507,7 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
|
|||
}
|
||||
else {
|
||||
compile_cpath(ret, iseq, RNODE_CDECL(node)->nd_else);
|
||||
CHECK(COMPILE(ret, "lvalue", RNODE_CDECL(node)->nd_value));
|
||||
CHECK(compile_shareable_constant_value(iseq, ret, RNODE_CDECL(node)->shareability, node, RNODE_CDECL(node)->nd_value));
|
||||
ADD_INSN(ret, node, swap);
|
||||
|
||||
if (!popped) {
|
||||
|
|
|
@ -28,7 +28,6 @@ VALUE rb_node_dregx_string_val(const NODE *);
|
|||
VALUE rb_node_line_lineno_val(const NODE *);
|
||||
VALUE rb_node_file_path_val(const NODE *);
|
||||
VALUE rb_node_encoding_val(const NODE *);
|
||||
VALUE rb_node_const_decl_val(const NODE *node);
|
||||
|
||||
VALUE rb_node_integer_literal_val(const NODE *);
|
||||
VALUE rb_node_float_literal_val(const NODE *);
|
||||
|
|
19
node_dump.c
19
node_dump.c
|
@ -60,6 +60,22 @@
|
|||
field_flag; /* should be optimized away */ \
|
||||
reset, field_flag = 0)
|
||||
|
||||
#define A_SHAREABILITY(shareability) \
|
||||
switch (shareability) { \
|
||||
case rb_parser_shareable_none: \
|
||||
rb_str_cat_cstr(buf, "none"); \
|
||||
break; \
|
||||
case rb_parser_shareable_literal: \
|
||||
rb_str_cat_cstr(buf, "literal"); \
|
||||
break; \
|
||||
case rb_parser_shareable_copy: \
|
||||
rb_str_cat_cstr(buf, "experimental_copy"); \
|
||||
break; \
|
||||
case rb_parser_shareable_everything: \
|
||||
rb_str_cat_cstr(buf, "experimental_everything"); \
|
||||
break; \
|
||||
}
|
||||
|
||||
#define SIMPLE_FIELD1(name, ann) SIMPLE_FIELD(FIELD_NAME_LEN(name, ann), FIELD_NAME_DESC(name, ann))
|
||||
#define F_CUSTOM1(name, ann) SIMPLE_FIELD1(#name, ann)
|
||||
#define F_ID(name, type, ann) SIMPLE_FIELD1(#name, ann) A_ID(type(node)->name)
|
||||
|
@ -68,6 +84,7 @@
|
|||
#define F_LIT(name, type, ann) SIMPLE_FIELD1(#name, ann) A_LIT(type(node)->name)
|
||||
#define F_VALUE(name, val, ann) SIMPLE_FIELD1(#name, ann) A_LIT(val)
|
||||
#define F_MSG(name, ann, desc) SIMPLE_FIELD1(#name, ann) A(desc)
|
||||
#define F_SHAREABILITY(name, type, ann) SIMPLE_FIELD1(#name, ann) A_SHAREABILITY(type(node)->name)
|
||||
|
||||
#define F_NODE(name, type, ann) \
|
||||
COMPOUND_FIELD1(#name, ann) {dump_node(buf, indent, comment, RNODE(type(node)->name));}
|
||||
|
@ -463,6 +480,7 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
|
|||
F_MSG(nd_vid, "constant", "0 (see extension field)");
|
||||
F_NODE(nd_else, RNODE_CDECL, "extension");
|
||||
}
|
||||
F_SHAREABILITY(shareability, RNODE_CDECL, "shareability");
|
||||
LAST_NODE;
|
||||
F_NODE(nd_value, RNODE_CDECL, "rvalue");
|
||||
return;
|
||||
|
@ -513,6 +531,7 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
|
|||
ANN("example: A::B ||= 1");
|
||||
F_NODE(nd_head, RNODE_OP_CDECL, "constant");
|
||||
F_ID(nd_aid, RNODE_OP_CDECL, "operator");
|
||||
F_SHAREABILITY(shareability, RNODE_OP_CDECL, "shareability");
|
||||
LAST_NODE;
|
||||
F_NODE(nd_value, RNODE_OP_CDECL, "rvalue");
|
||||
return;
|
||||
|
|
319
parse.y
319
parse.y
|
@ -302,13 +302,6 @@ VALUE rb_ripper_none;
|
|||
#include "ripper_init.h"
|
||||
#endif
|
||||
|
||||
enum shareability {
|
||||
shareable_none,
|
||||
shareable_literal,
|
||||
shareable_copy,
|
||||
shareable_everything,
|
||||
};
|
||||
|
||||
enum rescue_context {
|
||||
before_rescue,
|
||||
after_rescue,
|
||||
|
@ -322,7 +315,7 @@ struct lex_context {
|
|||
unsigned int in_argdef: 1;
|
||||
unsigned int in_def: 1;
|
||||
unsigned int in_class: 1;
|
||||
BITFIELD(enum shareability, shareable_constant_value, 2);
|
||||
BITFIELD(enum rb_parser_shareability, shareable_constant_value, 2);
|
||||
BITFIELD(enum rescue_context, in_rescue, 2);
|
||||
};
|
||||
|
||||
|
@ -1095,13 +1088,13 @@ static rb_node_lasgn_t *rb_node_lasgn_new(struct parser_params *p, ID nd_vid, NO
|
|||
static rb_node_dasgn_t *rb_node_dasgn_new(struct parser_params *p, ID nd_vid, NODE *nd_value, const YYLTYPE *loc);
|
||||
static rb_node_gasgn_t *rb_node_gasgn_new(struct parser_params *p, ID nd_vid, NODE *nd_value, const YYLTYPE *loc);
|
||||
static rb_node_iasgn_t *rb_node_iasgn_new(struct parser_params *p, ID nd_vid, NODE *nd_value, const YYLTYPE *loc);
|
||||
static rb_node_cdecl_t *rb_node_cdecl_new(struct parser_params *p, ID nd_vid, NODE *nd_value, NODE *nd_else, const YYLTYPE *loc);
|
||||
static rb_node_cdecl_t *rb_node_cdecl_new(struct parser_params *p, ID nd_vid, NODE *nd_value, NODE *nd_else, enum rb_parser_shareability shareability, const YYLTYPE *loc);
|
||||
static rb_node_cvasgn_t *rb_node_cvasgn_new(struct parser_params *p, ID nd_vid, NODE *nd_value, const YYLTYPE *loc);
|
||||
static rb_node_op_asgn1_t *rb_node_op_asgn1_new(struct parser_params *p, NODE *nd_recv, ID nd_mid, NODE *index, NODE *rvalue, const YYLTYPE *loc);
|
||||
static rb_node_op_asgn2_t *rb_node_op_asgn2_new(struct parser_params *p, NODE *nd_recv, NODE *nd_value, ID nd_vid, ID nd_mid, bool nd_aid, const YYLTYPE *loc);
|
||||
static rb_node_op_asgn_or_t *rb_node_op_asgn_or_new(struct parser_params *p, NODE *nd_head, NODE *nd_value, const YYLTYPE *loc);
|
||||
static rb_node_op_asgn_and_t *rb_node_op_asgn_and_new(struct parser_params *p, NODE *nd_head, NODE *nd_value, const YYLTYPE *loc);
|
||||
static rb_node_op_cdecl_t *rb_node_op_cdecl_new(struct parser_params *p, NODE *nd_head, NODE *nd_value, ID nd_aid, const YYLTYPE *loc);
|
||||
static rb_node_op_cdecl_t *rb_node_op_cdecl_new(struct parser_params *p, NODE *nd_head, NODE *nd_value, ID nd_aid, enum rb_parser_shareability shareability, const YYLTYPE *loc);
|
||||
static rb_node_call_t *rb_node_call_new(struct parser_params *p, NODE *nd_recv, ID nd_mid, NODE *nd_args, const YYLTYPE *loc);
|
||||
static rb_node_opcall_t *rb_node_opcall_new(struct parser_params *p, NODE *nd_recv, ID nd_mid, NODE *nd_args, const YYLTYPE *loc);
|
||||
static rb_node_fcall_t *rb_node_fcall_new(struct parser_params *p, ID nd_mid, NODE *nd_args, const YYLTYPE *loc);
|
||||
|
@ -1125,7 +1118,6 @@ static rb_node_nth_ref_t *rb_node_nth_ref_new(struct parser_params *p, long nd_n
|
|||
static rb_node_back_ref_t *rb_node_back_ref_new(struct parser_params *p, long nd_nth, const YYLTYPE *loc);
|
||||
static rb_node_match2_t *rb_node_match2_new(struct parser_params *p, NODE *nd_recv, NODE *nd_value, const YYLTYPE *loc);
|
||||
static rb_node_match3_t *rb_node_match3_new(struct parser_params *p, NODE *nd_recv, NODE *nd_value, const YYLTYPE *loc);
|
||||
static rb_node_lit_t *rb_node_lit_new(struct parser_params *p, VALUE nd_lit, const YYLTYPE *loc);
|
||||
static rb_node_integer_t * rb_node_integer_new(struct parser_params *p, char* val, int base, const YYLTYPE *loc);
|
||||
static rb_node_float_t * rb_node_float_new(struct parser_params *p, char* val, const YYLTYPE *loc);
|
||||
static rb_node_rational_t * rb_node_rational_new(struct parser_params *p, char* val, int base, int seen_point, const YYLTYPE *loc);
|
||||
|
@ -1204,13 +1196,13 @@ static rb_node_error_t *rb_node_error_new(struct parser_params *p, const YYLTYPE
|
|||
#define NEW_DASGN(v,val,loc) (NODE *)rb_node_dasgn_new(p,v,val,loc)
|
||||
#define NEW_GASGN(v,val,loc) (NODE *)rb_node_gasgn_new(p,v,val,loc)
|
||||
#define NEW_IASGN(v,val,loc) (NODE *)rb_node_iasgn_new(p,v,val,loc)
|
||||
#define NEW_CDECL(v,val,path,loc) (NODE *)rb_node_cdecl_new(p,v,val,path,loc)
|
||||
#define NEW_CDECL(v,val,path,share,loc) (NODE *)rb_node_cdecl_new(p,v,val,path,share,loc)
|
||||
#define NEW_CVASGN(v,val,loc) (NODE *)rb_node_cvasgn_new(p,v,val,loc)
|
||||
#define NEW_OP_ASGN1(r,id,idx,rval,loc) (NODE *)rb_node_op_asgn1_new(p,r,id,idx,rval,loc)
|
||||
#define NEW_OP_ASGN2(r,t,i,o,val,loc) (NODE *)rb_node_op_asgn2_new(p,r,val,i,o,t,loc)
|
||||
#define NEW_OP_ASGN_OR(i,val,loc) (NODE *)rb_node_op_asgn_or_new(p,i,val,loc)
|
||||
#define NEW_OP_ASGN_AND(i,val,loc) (NODE *)rb_node_op_asgn_and_new(p,i,val,loc)
|
||||
#define NEW_OP_CDECL(v,op,val,loc) (NODE *)rb_node_op_cdecl_new(p,v,val,op,loc)
|
||||
#define NEW_OP_CDECL(v,op,val,share,loc) (NODE *)rb_node_op_cdecl_new(p,v,val,op,share,loc)
|
||||
#define NEW_CALL(r,m,a,loc) (NODE *)rb_node_call_new(p,r,m,a,loc)
|
||||
#define NEW_OPCALL(r,m,a,loc) (NODE *)rb_node_opcall_new(p,r,m,a,loc)
|
||||
#define NEW_FCALL(m,a,loc) rb_node_fcall_new(p,m,a,loc)
|
||||
|
@ -1234,7 +1226,6 @@ static rb_node_error_t *rb_node_error_new(struct parser_params *p, const YYLTYPE
|
|||
#define NEW_BACK_REF(n,loc) (NODE *)rb_node_back_ref_new(p,n,loc)
|
||||
#define NEW_MATCH2(n1,n2,loc) (NODE *)rb_node_match2_new(p,n1,n2,loc)
|
||||
#define NEW_MATCH3(r,n2,loc) (NODE *)rb_node_match3_new(p,r,n2,loc)
|
||||
#define NEW_LIT(l,loc) (NODE *)rb_node_lit_new(p,l,loc)
|
||||
#define NEW_INTEGER(val, base,loc) (NODE *)rb_node_integer_new(p,val,base,loc)
|
||||
#define NEW_FLOAT(val,loc) (NODE *)rb_node_float_new(p,val,loc)
|
||||
#define NEW_RATIONAL(val,base,seen_point,loc) (NODE *)rb_node_rational_new(p,val,base,seen_point,loc)
|
||||
|
@ -9751,23 +9742,23 @@ parser_set_shareable_constant_value(struct parser_params *p, const char *name, c
|
|||
switch (*val) {
|
||||
case 'n': case 'N':
|
||||
if (STRCASECMP(val, "none") == 0) {
|
||||
p->ctxt.shareable_constant_value = shareable_none;
|
||||
p->ctxt.shareable_constant_value = rb_parser_shareable_none;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 'l': case 'L':
|
||||
if (STRCASECMP(val, "literal") == 0) {
|
||||
p->ctxt.shareable_constant_value = shareable_literal;
|
||||
p->ctxt.shareable_constant_value = rb_parser_shareable_literal;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 'e': case 'E':
|
||||
if (STRCASECMP(val, "experimental_copy") == 0) {
|
||||
p->ctxt.shareable_constant_value = shareable_copy;
|
||||
p->ctxt.shareable_constant_value = rb_parser_shareable_copy;
|
||||
return;
|
||||
}
|
||||
if (STRCASECMP(val, "experimental_everything") == 0) {
|
||||
p->ctxt.shareable_constant_value = shareable_everything;
|
||||
p->ctxt.shareable_constant_value = rb_parser_shareable_everything;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
@ -12233,15 +12224,6 @@ rb_node_back_ref_new(struct parser_params *p, long nd_nth, const YYLTYPE *loc)
|
|||
return n;
|
||||
}
|
||||
|
||||
static rb_node_lit_t *
|
||||
rb_node_lit_new(struct parser_params *p, VALUE nd_lit, const YYLTYPE *loc)
|
||||
{
|
||||
rb_node_lit_t *n = NODE_NEWNODE(NODE_LIT, rb_node_lit_t, loc);
|
||||
n->nd_lit = nd_lit;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
static rb_node_integer_t *
|
||||
rb_node_integer_new(struct parser_params *p, char* val, int base, const YYLTYPE *loc)
|
||||
{
|
||||
|
@ -12652,23 +12634,25 @@ rb_node_encoding_new(struct parser_params *p, const YYLTYPE *loc)
|
|||
}
|
||||
|
||||
static rb_node_cdecl_t *
|
||||
rb_node_cdecl_new(struct parser_params *p, ID nd_vid, NODE *nd_value, NODE *nd_else, const YYLTYPE *loc)
|
||||
rb_node_cdecl_new(struct parser_params *p, ID nd_vid, NODE *nd_value, NODE *nd_else, enum rb_parser_shareability shareability, const YYLTYPE *loc)
|
||||
{
|
||||
rb_node_cdecl_t *n = NODE_NEWNODE(NODE_CDECL, rb_node_cdecl_t, loc);
|
||||
n->nd_vid = nd_vid;
|
||||
n->nd_value = nd_value;
|
||||
n->nd_else = nd_else;
|
||||
n->shareability = shareability;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
static rb_node_op_cdecl_t *
|
||||
rb_node_op_cdecl_new(struct parser_params *p, NODE *nd_head, NODE *nd_value, ID nd_aid, const YYLTYPE *loc)
|
||||
rb_node_op_cdecl_new(struct parser_params *p, NODE *nd_head, NODE *nd_value, ID nd_aid, enum rb_parser_shareability shareability, const YYLTYPE *loc)
|
||||
{
|
||||
rb_node_op_cdecl_t *n = NODE_NEWNODE(NODE_OP_CDECL, rb_node_op_cdecl_t, loc);
|
||||
n->nd_head = nd_head;
|
||||
n->nd_value = nd_value;
|
||||
n->nd_aid = nd_aid;
|
||||
n->shareability = shareability;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
@ -13772,7 +13756,7 @@ assignable(struct parser_params *p, ID id, NODE *val, const YYLTYPE *loc)
|
|||
case NODE_LASGN: return NEW_LASGN(id, val, loc);
|
||||
case NODE_GASGN: return NEW_GASGN(id, val, loc);
|
||||
case NODE_IASGN: return NEW_IASGN(id, val, loc);
|
||||
case NODE_CDECL: return NEW_CDECL(id, val, 0, loc);
|
||||
case NODE_CDECL: return NEW_CDECL(id, val, 0, p->ctxt.shareable_constant_value, loc);
|
||||
case NODE_CVASGN: return NEW_CVASGN(id, val, loc);
|
||||
}
|
||||
/* TODO: FIXME */
|
||||
|
@ -14043,256 +14027,8 @@ mark_lvar_used(struct parser_params *p, NODE *rhs)
|
|||
}
|
||||
}
|
||||
|
||||
static NODE *
|
||||
const_decl_path(struct parser_params *p, NODE *dest)
|
||||
{
|
||||
NODE *n = dest;
|
||||
if (!nd_type_p(dest, NODE_CALL)) {
|
||||
const YYLTYPE *loc = &dest->nd_loc;
|
||||
VALUE path = rb_node_const_decl_val(dest);
|
||||
n = NEW_LIT(path, loc);
|
||||
RB_OBJ_WRITTEN(p->ast, Qnil, RNODE_LIT(n)->nd_lit);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
static NODE *
|
||||
make_shareable_node(struct parser_params *p, NODE *value, bool copy, const YYLTYPE *loc)
|
||||
{
|
||||
NODE *fcore = NEW_LIT(rb_mRubyVMFrozenCore, loc);
|
||||
|
||||
if (copy) {
|
||||
return NEW_CALL(fcore, rb_intern("make_shareable_copy"),
|
||||
NEW_LIST(value, loc), loc);
|
||||
}
|
||||
else {
|
||||
return NEW_CALL(fcore, rb_intern("make_shareable"),
|
||||
NEW_LIST(value, loc), loc);
|
||||
}
|
||||
}
|
||||
|
||||
static NODE *
|
||||
ensure_shareable_node(struct parser_params *p, NODE *dest, NODE *value, const YYLTYPE *loc)
|
||||
{
|
||||
NODE *fcore = NEW_LIT(rb_mRubyVMFrozenCore, loc);
|
||||
NODE *args = NEW_LIST(value, loc);
|
||||
args = list_append(p, args, const_decl_path(p, dest));
|
||||
return NEW_CALL(fcore, rb_intern("ensure_shareable"), args, loc);
|
||||
}
|
||||
|
||||
static int is_static_content(NODE *node);
|
||||
|
||||
static VALUE
|
||||
shareable_literal_value(struct parser_params *p, NODE *node)
|
||||
{
|
||||
if (!node) return Qnil;
|
||||
enum node_type type = nd_type(node);
|
||||
switch (type) {
|
||||
case NODE_TRUE:
|
||||
return Qtrue;
|
||||
case NODE_FALSE:
|
||||
return Qfalse;
|
||||
case NODE_NIL:
|
||||
return Qnil;
|
||||
case NODE_SYM:
|
||||
return rb_node_sym_string_val(node);
|
||||
case NODE_LINE:
|
||||
return rb_node_line_lineno_val(node);
|
||||
case NODE_INTEGER:
|
||||
return rb_node_integer_literal_val(node);
|
||||
case NODE_FLOAT:
|
||||
return rb_node_float_literal_val(node);
|
||||
case NODE_RATIONAL:
|
||||
return rb_node_rational_literal_val(node);
|
||||
case NODE_IMAGINARY:
|
||||
return rb_node_imaginary_literal_val(node);
|
||||
case NODE_ENCODING:
|
||||
return rb_node_encoding_val(node);
|
||||
case NODE_REGX:
|
||||
return rb_node_regx_string_val(node);
|
||||
case NODE_LIT:
|
||||
return RNODE_LIT(node)->nd_lit;
|
||||
default:
|
||||
return Qundef;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef SHAREABLE_BARE_EXPRESSION
|
||||
#define SHAREABLE_BARE_EXPRESSION 1
|
||||
#endif
|
||||
|
||||
static NODE *
|
||||
shareable_literal_constant(struct parser_params *p, enum shareability shareable,
|
||||
NODE *dest, NODE *value, const YYLTYPE *loc, size_t level)
|
||||
{
|
||||
# define shareable_literal_constant_next(n) \
|
||||
shareable_literal_constant(p, shareable, dest, (n), &(n)->nd_loc, level+1)
|
||||
VALUE lit = Qnil;
|
||||
|
||||
if (!value) return 0;
|
||||
enum node_type type = nd_type(value);
|
||||
switch (type) {
|
||||
case NODE_TRUE:
|
||||
case NODE_FALSE:
|
||||
case NODE_NIL:
|
||||
case NODE_LIT:
|
||||
case NODE_SYM:
|
||||
case NODE_REGX:
|
||||
case NODE_LINE:
|
||||
case NODE_INTEGER:
|
||||
case NODE_FLOAT:
|
||||
case NODE_RATIONAL:
|
||||
case NODE_IMAGINARY:
|
||||
case NODE_ENCODING:
|
||||
return value;
|
||||
|
||||
case NODE_DSTR:
|
||||
if (shareable == shareable_literal) {
|
||||
value = NEW_CALL(value, idUMinus, 0, loc);
|
||||
}
|
||||
return value;
|
||||
|
||||
case NODE_STR:
|
||||
lit = rb_str_to_interned_str(rb_node_str_string_val(value));
|
||||
value = NEW_LIT(lit, loc);
|
||||
RB_OBJ_WRITE(p->ast, &RNODE_LIT(value)->nd_lit, lit);
|
||||
return value;
|
||||
|
||||
case NODE_FILE:
|
||||
lit = rb_str_to_interned_str(rb_node_file_path_val(value));
|
||||
value = NEW_LIT(lit, loc);
|
||||
RB_OBJ_WRITTEN(p->ast, Qnil, RNODE_LIT(value)->nd_lit);
|
||||
return value;
|
||||
|
||||
case NODE_ZLIST:
|
||||
lit = rb_ary_new();
|
||||
OBJ_FREEZE_RAW(lit);
|
||||
NODE *n = NEW_LIT(lit, loc);
|
||||
RB_OBJ_WRITTEN(p->ast, Qnil, RNODE_LIT(n)->nd_lit);
|
||||
return n;
|
||||
|
||||
case NODE_LIST:
|
||||
lit = rb_ary_new();
|
||||
for (NODE *n = value; n; n = RNODE_LIST(n)->nd_next) {
|
||||
NODE *elt = RNODE_LIST(n)->nd_head;
|
||||
if (elt) {
|
||||
elt = shareable_literal_constant_next(elt);
|
||||
if (elt) {
|
||||
RNODE_LIST(n)->nd_head = elt;
|
||||
}
|
||||
else if (RTEST(lit)) {
|
||||
rb_ary_clear(lit);
|
||||
lit = Qfalse;
|
||||
}
|
||||
}
|
||||
if (RTEST(lit)) {
|
||||
VALUE e = shareable_literal_value(p, elt);
|
||||
if (!UNDEF_P(e)) {
|
||||
rb_ary_push(lit, e);
|
||||
}
|
||||
else {
|
||||
rb_ary_clear(lit);
|
||||
lit = Qnil; /* make shareable at runtime */
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case NODE_HASH:
|
||||
if (!RNODE_HASH(value)->nd_brace) return 0;
|
||||
lit = rb_hash_new();
|
||||
for (NODE *n = RNODE_HASH(value)->nd_head; n; n = RNODE_LIST(RNODE_LIST(n)->nd_next)->nd_next) {
|
||||
NODE *key = RNODE_LIST(n)->nd_head;
|
||||
NODE *val = RNODE_LIST(RNODE_LIST(n)->nd_next)->nd_head;
|
||||
if (key) {
|
||||
key = shareable_literal_constant_next(key);
|
||||
if (key) {
|
||||
RNODE_LIST(n)->nd_head = key;
|
||||
}
|
||||
else if (RTEST(lit)) {
|
||||
rb_hash_clear(lit);
|
||||
lit = Qfalse;
|
||||
}
|
||||
}
|
||||
if (val) {
|
||||
val = shareable_literal_constant_next(val);
|
||||
if (val) {
|
||||
RNODE_LIST(RNODE_LIST(n)->nd_next)->nd_head = val;
|
||||
}
|
||||
else if (RTEST(lit)) {
|
||||
rb_hash_clear(lit);
|
||||
lit = Qfalse;
|
||||
}
|
||||
}
|
||||
if (RTEST(lit)) {
|
||||
VALUE k = shareable_literal_value(p, key);
|
||||
VALUE v = shareable_literal_value(p, val);
|
||||
if (!UNDEF_P(k) && !UNDEF_P(v)) {
|
||||
rb_hash_aset(lit, k, v);
|
||||
}
|
||||
else {
|
||||
rb_hash_clear(lit);
|
||||
lit = Qnil; /* make shareable at runtime */
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (shareable == shareable_literal &&
|
||||
(SHAREABLE_BARE_EXPRESSION || level > 0)) {
|
||||
return ensure_shareable_node(p, dest, value, loc);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Array or Hash */
|
||||
if (!lit) return 0;
|
||||
if (NIL_P(lit)) {
|
||||
// if shareable_literal, all elements should have been ensured
|
||||
// as shareable
|
||||
value = make_shareable_node(p, value, false, loc);
|
||||
}
|
||||
else {
|
||||
value = NEW_LIT(rb_ractor_make_shareable(lit), loc);
|
||||
RB_OBJ_WRITTEN(p->ast, Qnil, RNODE_LIT(value)->nd_lit);
|
||||
}
|
||||
|
||||
return value;
|
||||
# undef shareable_literal_constant_next
|
||||
}
|
||||
|
||||
static NODE *
|
||||
shareable_constant_value(struct parser_params *p, enum shareability shareable,
|
||||
NODE *lhs, NODE *value, const YYLTYPE *loc)
|
||||
{
|
||||
if (!value) return 0;
|
||||
switch (shareable) {
|
||||
case shareable_none:
|
||||
return value;
|
||||
|
||||
case shareable_literal:
|
||||
{
|
||||
NODE *lit = shareable_literal_constant(p, shareable, lhs, value, loc, 0);
|
||||
if (lit) return lit;
|
||||
return value;
|
||||
}
|
||||
break;
|
||||
|
||||
case shareable_copy:
|
||||
case shareable_everything:
|
||||
{
|
||||
NODE *lit = shareable_literal_constant(p, shareable, lhs, value, loc, 0);
|
||||
if (lit) return lit;
|
||||
return make_shareable_node(p, value, shareable == shareable_copy, loc);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
UNREACHABLE_RETURN(0);
|
||||
}
|
||||
}
|
||||
|
||||
static NODE *
|
||||
node_assign(struct parser_params *p, NODE *lhs, NODE *rhs, struct lex_context ctxt, const YYLTYPE *loc)
|
||||
{
|
||||
|
@ -14300,9 +14036,6 @@ node_assign(struct parser_params *p, NODE *lhs, NODE *rhs, struct lex_context ct
|
|||
|
||||
switch (nd_type(lhs)) {
|
||||
case NODE_CDECL:
|
||||
rhs = shareable_constant_value(p, ctxt.shareable_constant_value, lhs, rhs, loc);
|
||||
/* fallthru */
|
||||
|
||||
case NODE_GASGN:
|
||||
case NODE_IASGN:
|
||||
case NODE_LASGN:
|
||||
|
@ -15281,28 +15014,12 @@ new_op_assign(struct parser_params *p, NODE *lhs, ID op, NODE *rhs, struct lex_c
|
|||
if (lhs) {
|
||||
ID vid = get_nd_vid(p, lhs);
|
||||
YYLTYPE lhs_loc = lhs->nd_loc;
|
||||
int shareable = ctxt.shareable_constant_value;
|
||||
if (shareable) {
|
||||
switch (nd_type(lhs)) {
|
||||
case NODE_CDECL:
|
||||
case NODE_COLON2:
|
||||
case NODE_COLON3:
|
||||
break;
|
||||
default:
|
||||
shareable = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (op == tOROP) {
|
||||
rhs = shareable_constant_value(p, shareable, lhs, rhs, &rhs->nd_loc);
|
||||
set_nd_value(p, lhs, rhs);
|
||||
nd_set_loc(lhs, loc);
|
||||
asgn = NEW_OP_ASGN_OR(gettable(p, vid, &lhs_loc), lhs, loc);
|
||||
}
|
||||
else if (op == tANDOP) {
|
||||
if (shareable) {
|
||||
rhs = shareable_constant_value(p, shareable, lhs, rhs, &rhs->nd_loc);
|
||||
}
|
||||
set_nd_value(p, lhs, rhs);
|
||||
nd_set_loc(lhs, loc);
|
||||
asgn = NEW_OP_ASGN_AND(gettable(p, vid, &lhs_loc), lhs, loc);
|
||||
|
@ -15310,9 +15027,6 @@ new_op_assign(struct parser_params *p, NODE *lhs, ID op, NODE *rhs, struct lex_c
|
|||
else {
|
||||
asgn = lhs;
|
||||
rhs = NEW_CALL(gettable(p, vid, &lhs_loc), op, NEW_LIST(rhs, &rhs->nd_loc), loc);
|
||||
if (shareable) {
|
||||
rhs = shareable_constant_value(p, shareable, lhs, rhs, &rhs->nd_loc);
|
||||
}
|
||||
set_nd_value(p, asgn, rhs);
|
||||
nd_set_loc(asgn, loc);
|
||||
}
|
||||
|
@ -15353,8 +15067,7 @@ new_const_op_assign(struct parser_params *p, NODE *lhs, ID op, NODE *rhs, struct
|
|||
NODE *asgn;
|
||||
|
||||
if (lhs) {
|
||||
rhs = shareable_constant_value(p, ctxt.shareable_constant_value, lhs, rhs, loc);
|
||||
asgn = NEW_OP_CDECL(lhs, op, rhs, loc);
|
||||
asgn = NEW_OP_CDECL(lhs, op, rhs, ctxt.shareable_constant_value, loc);
|
||||
}
|
||||
else {
|
||||
asgn = NEW_ERROR(loc);
|
||||
|
@ -15369,7 +15082,7 @@ const_decl(struct parser_params *p, NODE *path, const YYLTYPE *loc)
|
|||
if (p->ctxt.in_def) {
|
||||
yyerror1(loc, "dynamic constant assignment");
|
||||
}
|
||||
return NEW_CDECL(0, 0, (path), loc);
|
||||
return NEW_CDECL(0, 0, (path), p->ctxt.shareable_constant_value, loc);
|
||||
}
|
||||
#ifdef RIPPER
|
||||
static VALUE
|
||||
|
|
|
@ -994,54 +994,3 @@ rb_node_encoding_val(const NODE *node)
|
|||
{
|
||||
return rb_enc_from_encoding(RNODE_ENCODING(node)->enc);
|
||||
}
|
||||
|
||||
VALUE
|
||||
rb_node_const_decl_val(const NODE *node)
|
||||
{
|
||||
VALUE path;
|
||||
switch (nd_type(node)) {
|
||||
case NODE_CDECL:
|
||||
if (RNODE_CDECL(node)->nd_vid) {
|
||||
path = rb_id2str(RNODE_CDECL(node)->nd_vid);
|
||||
goto end;
|
||||
}
|
||||
else {
|
||||
node = RNODE_CDECL(node)->nd_else;
|
||||
}
|
||||
break;
|
||||
case NODE_COLON2:
|
||||
break;
|
||||
case NODE_COLON3:
|
||||
// ::Const
|
||||
path = rb_str_new_cstr("::");
|
||||
rb_str_append(path, rb_id2str(RNODE_COLON3(node)->nd_mid));
|
||||
goto end;
|
||||
default:
|
||||
rb_bug("unexpected node: %s", ruby_node_name(nd_type(node)));
|
||||
UNREACHABLE_RETURN(0);
|
||||
}
|
||||
|
||||
path = rb_ary_new();
|
||||
if (node) {
|
||||
for (; node && nd_type_p(node, NODE_COLON2); node = RNODE_COLON2(node)->nd_head) {
|
||||
rb_ary_push(path, rb_id2str(RNODE_COLON2(node)->nd_mid));
|
||||
}
|
||||
if (node && nd_type_p(node, NODE_CONST)) {
|
||||
// Const::Name
|
||||
rb_ary_push(path, rb_id2str(RNODE_CONST(node)->nd_vid));
|
||||
}
|
||||
else if (node && nd_type_p(node, NODE_COLON3)) {
|
||||
// ::Const::Name
|
||||
rb_ary_push(path, rb_id2str(RNODE_COLON3(node)->nd_mid));
|
||||
rb_ary_push(path, rb_str_new(0, 0));
|
||||
}
|
||||
else {
|
||||
// expression::Name
|
||||
rb_ary_push(path, rb_str_new_cstr("..."));
|
||||
}
|
||||
path = rb_ary_join(rb_ary_reverse(path), rb_str_new_cstr("::"));
|
||||
}
|
||||
end:
|
||||
path = rb_fstring(path);
|
||||
return path;
|
||||
}
|
||||
|
|
|
@ -66,6 +66,13 @@ typedef struct rb_parser_string {
|
|||
char *ptr;
|
||||
} rb_parser_string_t;
|
||||
|
||||
enum rb_parser_shareability {
|
||||
rb_parser_shareable_none,
|
||||
rb_parser_shareable_literal,
|
||||
rb_parser_shareable_copy,
|
||||
rb_parser_shareable_everything,
|
||||
};
|
||||
|
||||
/*
|
||||
* AST Node
|
||||
*/
|
||||
|
@ -444,6 +451,7 @@ typedef struct RNode_CDECL {
|
|||
ID nd_vid;
|
||||
struct RNode *nd_value;
|
||||
struct RNode *nd_else;
|
||||
enum rb_parser_shareability shareability;
|
||||
} rb_node_cdecl_t;
|
||||
|
||||
typedef struct RNode_CVASGN {
|
||||
|
@ -492,6 +500,7 @@ typedef struct RNode_OP_CDECL {
|
|||
struct RNode *nd_head;
|
||||
struct RNode *nd_value;
|
||||
ID nd_aid;
|
||||
enum rb_parser_shareability shareability;
|
||||
} rb_node_op_cdecl_t;
|
||||
|
||||
typedef struct RNode_CALL {
|
||||
|
|
Загрузка…
Ссылка в новой задаче