зеркало из 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/version.h
|
||||||
compile.$(OBJEXT): {$(VPATH)}prism_compile.c
|
compile.$(OBJEXT): {$(VPATH)}prism_compile.c
|
||||||
compile.$(OBJEXT): {$(VPATH)}prism_compile.h
|
compile.$(OBJEXT): {$(VPATH)}prism_compile.h
|
||||||
|
compile.$(OBJEXT): {$(VPATH)}ractor.h
|
||||||
compile.$(OBJEXT): {$(VPATH)}re.h
|
compile.$(OBJEXT): {$(VPATH)}re.h
|
||||||
compile.$(OBJEXT): {$(VPATH)}regex.h
|
compile.$(OBJEXT): {$(VPATH)}regex.h
|
||||||
compile.$(OBJEXT): {$(VPATH)}ruby_assert.h
|
compile.$(OBJEXT): {$(VPATH)}ruby_assert.h
|
||||||
|
|
373
compile.c
373
compile.c
|
@ -36,6 +36,7 @@
|
||||||
#include "internal/thread.h"
|
#include "internal/thread.h"
|
||||||
#include "internal/variable.h"
|
#include "internal/variable.h"
|
||||||
#include "iseq.h"
|
#include "iseq.h"
|
||||||
|
#include "ruby/ractor.h"
|
||||||
#include "ruby/re.h"
|
#include "ruby/re.h"
|
||||||
#include "ruby/util.h"
|
#include "ruby/util.h"
|
||||||
#include "vm_core.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;
|
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
|
static int
|
||||||
compile_op_cdecl(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped)
|
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] */
|
/* cref [obj] */
|
||||||
if (!popped) ADD_INSN(ret, node, pop); /* cref */
|
if (!popped) ADD_INSN(ret, node, pop); /* cref */
|
||||||
if (lassign) ADD_LABEL(ret, lassign);
|
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 */
|
/* cref value */
|
||||||
if (popped)
|
if (popped)
|
||||||
ADD_INSN1(ret, node, topn, INT2FIX(1)); /* cref value cref */
|
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] */
|
ADD_INSN(ret, node, pop); /* [value] */
|
||||||
}
|
}
|
||||||
else {
|
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 */
|
/* cref obj value */
|
||||||
ADD_CALL(ret, node, RNODE_OP_CDECL(node)->nd_aid, INT2FIX(1));
|
ADD_CALL(ret, node, RNODE_OP_CDECL(node)->nd_aid, INT2FIX(1));
|
||||||
/* cref value */
|
/* cref value */
|
||||||
|
@ -9948,6 +9951,368 @@ compile_attrasgn(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node
|
||||||
return COMPILE_OK;
|
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);
|
static int iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped);
|
||||||
/**
|
/**
|
||||||
compile each node
|
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:{
|
case NODE_CDECL:{
|
||||||
if (RNODE_CDECL(node)->nd_vid) {
|
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) {
|
if (!popped) {
|
||||||
ADD_INSN(ret, node, dup);
|
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 {
|
else {
|
||||||
compile_cpath(ret, iseq, RNODE_CDECL(node)->nd_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);
|
ADD_INSN(ret, node, swap);
|
||||||
|
|
||||||
if (!popped) {
|
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_line_lineno_val(const NODE *);
|
||||||
VALUE rb_node_file_path_val(const NODE *);
|
VALUE rb_node_file_path_val(const NODE *);
|
||||||
VALUE rb_node_encoding_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_integer_literal_val(const NODE *);
|
||||||
VALUE rb_node_float_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 */ \
|
field_flag; /* should be optimized away */ \
|
||||||
reset, field_flag = 0)
|
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 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_CUSTOM1(name, ann) SIMPLE_FIELD1(#name, ann)
|
||||||
#define F_ID(name, type, ann) SIMPLE_FIELD1(#name, ann) A_ID(type(node)->name)
|
#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_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_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_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) \
|
#define F_NODE(name, type, ann) \
|
||||||
COMPOUND_FIELD1(#name, ann) {dump_node(buf, indent, comment, RNODE(type(node)->name));}
|
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_MSG(nd_vid, "constant", "0 (see extension field)");
|
||||||
F_NODE(nd_else, RNODE_CDECL, "extension");
|
F_NODE(nd_else, RNODE_CDECL, "extension");
|
||||||
}
|
}
|
||||||
|
F_SHAREABILITY(shareability, RNODE_CDECL, "shareability");
|
||||||
LAST_NODE;
|
LAST_NODE;
|
||||||
F_NODE(nd_value, RNODE_CDECL, "rvalue");
|
F_NODE(nd_value, RNODE_CDECL, "rvalue");
|
||||||
return;
|
return;
|
||||||
|
@ -513,6 +531,7 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
|
||||||
ANN("example: A::B ||= 1");
|
ANN("example: A::B ||= 1");
|
||||||
F_NODE(nd_head, RNODE_OP_CDECL, "constant");
|
F_NODE(nd_head, RNODE_OP_CDECL, "constant");
|
||||||
F_ID(nd_aid, RNODE_OP_CDECL, "operator");
|
F_ID(nd_aid, RNODE_OP_CDECL, "operator");
|
||||||
|
F_SHAREABILITY(shareability, RNODE_OP_CDECL, "shareability");
|
||||||
LAST_NODE;
|
LAST_NODE;
|
||||||
F_NODE(nd_value, RNODE_OP_CDECL, "rvalue");
|
F_NODE(nd_value, RNODE_OP_CDECL, "rvalue");
|
||||||
return;
|
return;
|
||||||
|
|
319
parse.y
319
parse.y
|
@ -302,13 +302,6 @@ VALUE rb_ripper_none;
|
||||||
#include "ripper_init.h"
|
#include "ripper_init.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
enum shareability {
|
|
||||||
shareable_none,
|
|
||||||
shareable_literal,
|
|
||||||
shareable_copy,
|
|
||||||
shareable_everything,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum rescue_context {
|
enum rescue_context {
|
||||||
before_rescue,
|
before_rescue,
|
||||||
after_rescue,
|
after_rescue,
|
||||||
|
@ -322,7 +315,7 @@ struct lex_context {
|
||||||
unsigned int in_argdef: 1;
|
unsigned int in_argdef: 1;
|
||||||
unsigned int in_def: 1;
|
unsigned int in_def: 1;
|
||||||
unsigned int in_class: 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);
|
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_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_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_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_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_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_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_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_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_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_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);
|
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_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_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_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_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_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);
|
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_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_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_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_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_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_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_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_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_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_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)
|
#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_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_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_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_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_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)
|
#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) {
|
switch (*val) {
|
||||||
case 'n': case 'N':
|
case 'n': case 'N':
|
||||||
if (STRCASECMP(val, "none") == 0) {
|
if (STRCASECMP(val, "none") == 0) {
|
||||||
p->ctxt.shareable_constant_value = shareable_none;
|
p->ctxt.shareable_constant_value = rb_parser_shareable_none;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'l': case 'L':
|
case 'l': case 'L':
|
||||||
if (STRCASECMP(val, "literal") == 0) {
|
if (STRCASECMP(val, "literal") == 0) {
|
||||||
p->ctxt.shareable_constant_value = shareable_literal;
|
p->ctxt.shareable_constant_value = rb_parser_shareable_literal;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'e': case 'E':
|
case 'e': case 'E':
|
||||||
if (STRCASECMP(val, "experimental_copy") == 0) {
|
if (STRCASECMP(val, "experimental_copy") == 0) {
|
||||||
p->ctxt.shareable_constant_value = shareable_copy;
|
p->ctxt.shareable_constant_value = rb_parser_shareable_copy;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (STRCASECMP(val, "experimental_everything") == 0) {
|
if (STRCASECMP(val, "experimental_everything") == 0) {
|
||||||
p->ctxt.shareable_constant_value = shareable_everything;
|
p->ctxt.shareable_constant_value = rb_parser_shareable_everything;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -12233,15 +12224,6 @@ rb_node_back_ref_new(struct parser_params *p, long nd_nth, const YYLTYPE *loc)
|
||||||
return n;
|
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 *
|
static rb_node_integer_t *
|
||||||
rb_node_integer_new(struct parser_params *p, char* val, int base, const YYLTYPE *loc)
|
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 *
|
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);
|
rb_node_cdecl_t *n = NODE_NEWNODE(NODE_CDECL, rb_node_cdecl_t, loc);
|
||||||
n->nd_vid = nd_vid;
|
n->nd_vid = nd_vid;
|
||||||
n->nd_value = nd_value;
|
n->nd_value = nd_value;
|
||||||
n->nd_else = nd_else;
|
n->nd_else = nd_else;
|
||||||
|
n->shareability = shareability;
|
||||||
|
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
static rb_node_op_cdecl_t *
|
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);
|
rb_node_op_cdecl_t *n = NODE_NEWNODE(NODE_OP_CDECL, rb_node_op_cdecl_t, loc);
|
||||||
n->nd_head = nd_head;
|
n->nd_head = nd_head;
|
||||||
n->nd_value = nd_value;
|
n->nd_value = nd_value;
|
||||||
n->nd_aid = nd_aid;
|
n->nd_aid = nd_aid;
|
||||||
|
n->shareability = shareability;
|
||||||
|
|
||||||
return n;
|
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_LASGN: return NEW_LASGN(id, val, loc);
|
||||||
case NODE_GASGN: return NEW_GASGN(id, val, loc);
|
case NODE_GASGN: return NEW_GASGN(id, val, loc);
|
||||||
case NODE_IASGN: return NEW_IASGN(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);
|
case NODE_CVASGN: return NEW_CVASGN(id, val, loc);
|
||||||
}
|
}
|
||||||
/* TODO: FIXME */
|
/* 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 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 *
|
static NODE *
|
||||||
node_assign(struct parser_params *p, NODE *lhs, NODE *rhs, struct lex_context ctxt, const YYLTYPE *loc)
|
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)) {
|
switch (nd_type(lhs)) {
|
||||||
case NODE_CDECL:
|
case NODE_CDECL:
|
||||||
rhs = shareable_constant_value(p, ctxt.shareable_constant_value, lhs, rhs, loc);
|
|
||||||
/* fallthru */
|
|
||||||
|
|
||||||
case NODE_GASGN:
|
case NODE_GASGN:
|
||||||
case NODE_IASGN:
|
case NODE_IASGN:
|
||||||
case NODE_LASGN:
|
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) {
|
if (lhs) {
|
||||||
ID vid = get_nd_vid(p, lhs);
|
ID vid = get_nd_vid(p, lhs);
|
||||||
YYLTYPE lhs_loc = lhs->nd_loc;
|
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) {
|
if (op == tOROP) {
|
||||||
rhs = shareable_constant_value(p, shareable, lhs, rhs, &rhs->nd_loc);
|
|
||||||
set_nd_value(p, lhs, rhs);
|
set_nd_value(p, lhs, rhs);
|
||||||
nd_set_loc(lhs, loc);
|
nd_set_loc(lhs, loc);
|
||||||
asgn = NEW_OP_ASGN_OR(gettable(p, vid, &lhs_loc), lhs, loc);
|
asgn = NEW_OP_ASGN_OR(gettable(p, vid, &lhs_loc), lhs, loc);
|
||||||
}
|
}
|
||||||
else if (op == tANDOP) {
|
else if (op == tANDOP) {
|
||||||
if (shareable) {
|
|
||||||
rhs = shareable_constant_value(p, shareable, lhs, rhs, &rhs->nd_loc);
|
|
||||||
}
|
|
||||||
set_nd_value(p, lhs, rhs);
|
set_nd_value(p, lhs, rhs);
|
||||||
nd_set_loc(lhs, loc);
|
nd_set_loc(lhs, loc);
|
||||||
asgn = NEW_OP_ASGN_AND(gettable(p, vid, &lhs_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 {
|
else {
|
||||||
asgn = lhs;
|
asgn = lhs;
|
||||||
rhs = NEW_CALL(gettable(p, vid, &lhs_loc), op, NEW_LIST(rhs, &rhs->nd_loc), loc);
|
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);
|
set_nd_value(p, asgn, rhs);
|
||||||
nd_set_loc(asgn, loc);
|
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;
|
NODE *asgn;
|
||||||
|
|
||||||
if (lhs) {
|
if (lhs) {
|
||||||
rhs = shareable_constant_value(p, ctxt.shareable_constant_value, lhs, rhs, loc);
|
asgn = NEW_OP_CDECL(lhs, op, rhs, ctxt.shareable_constant_value, loc);
|
||||||
asgn = NEW_OP_CDECL(lhs, op, rhs, loc);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
asgn = NEW_ERROR(loc);
|
asgn = NEW_ERROR(loc);
|
||||||
|
@ -15369,7 +15082,7 @@ const_decl(struct parser_params *p, NODE *path, const YYLTYPE *loc)
|
||||||
if (p->ctxt.in_def) {
|
if (p->ctxt.in_def) {
|
||||||
yyerror1(loc, "dynamic constant assignment");
|
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
|
#ifdef RIPPER
|
||||||
static VALUE
|
static VALUE
|
||||||
|
|
|
@ -994,54 +994,3 @@ rb_node_encoding_val(const NODE *node)
|
||||||
{
|
{
|
||||||
return rb_enc_from_encoding(RNODE_ENCODING(node)->enc);
|
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;
|
char *ptr;
|
||||||
} rb_parser_string_t;
|
} 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
|
* AST Node
|
||||||
*/
|
*/
|
||||||
|
@ -444,6 +451,7 @@ typedef struct RNode_CDECL {
|
||||||
ID nd_vid;
|
ID nd_vid;
|
||||||
struct RNode *nd_value;
|
struct RNode *nd_value;
|
||||||
struct RNode *nd_else;
|
struct RNode *nd_else;
|
||||||
|
enum rb_parser_shareability shareability;
|
||||||
} rb_node_cdecl_t;
|
} rb_node_cdecl_t;
|
||||||
|
|
||||||
typedef struct RNode_CVASGN {
|
typedef struct RNode_CVASGN {
|
||||||
|
@ -492,6 +500,7 @@ typedef struct RNode_OP_CDECL {
|
||||||
struct RNode *nd_head;
|
struct RNode *nd_head;
|
||||||
struct RNode *nd_value;
|
struct RNode *nd_value;
|
||||||
ID nd_aid;
|
ID nd_aid;
|
||||||
|
enum rb_parser_shareability shareability;
|
||||||
} rb_node_op_cdecl_t;
|
} rb_node_op_cdecl_t;
|
||||||
|
|
||||||
typedef struct RNode_CALL {
|
typedef struct RNode_CALL {
|
||||||
|
|
Загрузка…
Ссылка в новой задаче