diff --git a/ast.c b/ast.c index 6c3b2bf04c..ab6f1ce53d 100644 --- a/ast.c +++ b/ast.c @@ -558,6 +558,14 @@ node_children(rb_ast_t *ast, const NODE *node) case NODE_STR: case NODE_XSTR: return rb_ary_new_from_args(1, RNODE_LIT(node)->nd_lit); + case NODE_INTEGER: + return rb_ary_new_from_args(1, rb_node_integer_literal_val(RNODE_INTEGER(node))); + case NODE_FLOAT: + return rb_ary_new_from_args(1, rb_node_float_literal_val(RNODE_FLOAT(node))); + case NODE_RATIONAL: + return rb_ary_new_from_args(1, rb_node_rational_literal_val(RNODE_RATIONAL(node))); + case NODE_IMAGINARY: + return rb_ary_new_from_args(1, rb_node_imaginary_literal_val(RNODE_IMAGINARY(node))); case NODE_ONCE: return rb_ary_new_from_node_args(ast, 1, RNODE_ONCE(node)->nd_body); case NODE_DSTR: diff --git a/common.mk b/common.mk index 214275aea9..a2746b475e 100644 --- a/common.mk +++ b/common.mk @@ -2200,10 +2200,16 @@ ast.$(OBJEXT): $(hdrdir)/ruby.h ast.$(OBJEXT): $(hdrdir)/ruby/ruby.h ast.$(OBJEXT): $(top_srcdir)/internal/array.h ast.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h +ast.$(OBJEXT): $(top_srcdir)/internal/bignum.h +ast.$(OBJEXT): $(top_srcdir)/internal/bits.h ast.$(OBJEXT): $(top_srcdir)/internal/compilers.h +ast.$(OBJEXT): $(top_srcdir)/internal/complex.h +ast.$(OBJEXT): $(top_srcdir)/internal/fixnum.h ast.$(OBJEXT): $(top_srcdir)/internal/gc.h ast.$(OBJEXT): $(top_srcdir)/internal/imemo.h +ast.$(OBJEXT): $(top_srcdir)/internal/numeric.h ast.$(OBJEXT): $(top_srcdir)/internal/parse.h +ast.$(OBJEXT): $(top_srcdir)/internal/rational.h ast.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h ast.$(OBJEXT): $(top_srcdir)/internal/serial.h ast.$(OBJEXT): $(top_srcdir)/internal/static_assert.h @@ -7416,9 +7422,15 @@ goruby.$(OBJEXT): $(hdrdir)/ruby.h goruby.$(OBJEXT): $(hdrdir)/ruby/ruby.h goruby.$(OBJEXT): $(top_srcdir)/internal/array.h goruby.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h +goruby.$(OBJEXT): $(top_srcdir)/internal/bignum.h +goruby.$(OBJEXT): $(top_srcdir)/internal/bits.h goruby.$(OBJEXT): $(top_srcdir)/internal/compilers.h +goruby.$(OBJEXT): $(top_srcdir)/internal/complex.h +goruby.$(OBJEXT): $(top_srcdir)/internal/fixnum.h goruby.$(OBJEXT): $(top_srcdir)/internal/gc.h goruby.$(OBJEXT): $(top_srcdir)/internal/imemo.h +goruby.$(OBJEXT): $(top_srcdir)/internal/numeric.h +goruby.$(OBJEXT): $(top_srcdir)/internal/rational.h goruby.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h goruby.$(OBJEXT): $(top_srcdir)/internal/serial.h goruby.$(OBJEXT): $(top_srcdir)/internal/static_assert.h @@ -8469,16 +8481,21 @@ iseq.$(OBJEXT): $(hdrdir)/ruby/ruby.h iseq.$(OBJEXT): $(hdrdir)/ruby/version.h iseq.$(OBJEXT): $(top_srcdir)/internal/array.h iseq.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h +iseq.$(OBJEXT): $(top_srcdir)/internal/bignum.h iseq.$(OBJEXT): $(top_srcdir)/internal/bits.h iseq.$(OBJEXT): $(top_srcdir)/internal/class.h iseq.$(OBJEXT): $(top_srcdir)/internal/compile.h iseq.$(OBJEXT): $(top_srcdir)/internal/compilers.h +iseq.$(OBJEXT): $(top_srcdir)/internal/complex.h iseq.$(OBJEXT): $(top_srcdir)/internal/error.h iseq.$(OBJEXT): $(top_srcdir)/internal/file.h +iseq.$(OBJEXT): $(top_srcdir)/internal/fixnum.h iseq.$(OBJEXT): $(top_srcdir)/internal/gc.h iseq.$(OBJEXT): $(top_srcdir)/internal/hash.h iseq.$(OBJEXT): $(top_srcdir)/internal/imemo.h +iseq.$(OBJEXT): $(top_srcdir)/internal/numeric.h iseq.$(OBJEXT): $(top_srcdir)/internal/parse.h +iseq.$(OBJEXT): $(top_srcdir)/internal/rational.h iseq.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h iseq.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h iseq.$(OBJEXT): $(top_srcdir)/internal/serial.h @@ -8719,16 +8736,21 @@ load.$(OBJEXT): $(hdrdir)/ruby/ruby.h load.$(OBJEXT): $(hdrdir)/ruby/version.h load.$(OBJEXT): $(top_srcdir)/internal/array.h load.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h +load.$(OBJEXT): $(top_srcdir)/internal/bignum.h load.$(OBJEXT): $(top_srcdir)/internal/bits.h load.$(OBJEXT): $(top_srcdir)/internal/compilers.h +load.$(OBJEXT): $(top_srcdir)/internal/complex.h load.$(OBJEXT): $(top_srcdir)/internal/dir.h load.$(OBJEXT): $(top_srcdir)/internal/error.h load.$(OBJEXT): $(top_srcdir)/internal/file.h +load.$(OBJEXT): $(top_srcdir)/internal/fixnum.h load.$(OBJEXT): $(top_srcdir)/internal/gc.h load.$(OBJEXT): $(top_srcdir)/internal/hash.h load.$(OBJEXT): $(top_srcdir)/internal/imemo.h load.$(OBJEXT): $(top_srcdir)/internal/load.h +load.$(OBJEXT): $(top_srcdir)/internal/numeric.h load.$(OBJEXT): $(top_srcdir)/internal/parse.h +load.$(OBJEXT): $(top_srcdir)/internal/rational.h load.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h load.$(OBJEXT): $(top_srcdir)/internal/serial.h load.$(OBJEXT): $(top_srcdir)/internal/static_assert.h @@ -10044,9 +10066,15 @@ miniinit.$(OBJEXT): $(hdrdir)/ruby/ruby.h miniinit.$(OBJEXT): $(srcdir)/rjit_c.rb miniinit.$(OBJEXT): $(top_srcdir)/internal/array.h miniinit.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h +miniinit.$(OBJEXT): $(top_srcdir)/internal/bignum.h +miniinit.$(OBJEXT): $(top_srcdir)/internal/bits.h miniinit.$(OBJEXT): $(top_srcdir)/internal/compilers.h +miniinit.$(OBJEXT): $(top_srcdir)/internal/complex.h +miniinit.$(OBJEXT): $(top_srcdir)/internal/fixnum.h miniinit.$(OBJEXT): $(top_srcdir)/internal/gc.h miniinit.$(OBJEXT): $(top_srcdir)/internal/imemo.h +miniinit.$(OBJEXT): $(top_srcdir)/internal/numeric.h +miniinit.$(OBJEXT): $(top_srcdir)/internal/rational.h miniinit.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h miniinit.$(OBJEXT): $(top_srcdir)/internal/serial.h miniinit.$(OBJEXT): $(top_srcdir)/internal/static_assert.h @@ -10492,10 +10520,16 @@ node_dump.$(OBJEXT): $(CCAN_DIR)/str/str.h node_dump.$(OBJEXT): $(hdrdir)/ruby/ruby.h node_dump.$(OBJEXT): $(top_srcdir)/internal/array.h node_dump.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h +node_dump.$(OBJEXT): $(top_srcdir)/internal/bignum.h +node_dump.$(OBJEXT): $(top_srcdir)/internal/bits.h node_dump.$(OBJEXT): $(top_srcdir)/internal/compilers.h +node_dump.$(OBJEXT): $(top_srcdir)/internal/complex.h +node_dump.$(OBJEXT): $(top_srcdir)/internal/fixnum.h node_dump.$(OBJEXT): $(top_srcdir)/internal/gc.h node_dump.$(OBJEXT): $(top_srcdir)/internal/hash.h node_dump.$(OBJEXT): $(top_srcdir)/internal/imemo.h +node_dump.$(OBJEXT): $(top_srcdir)/internal/numeric.h +node_dump.$(OBJEXT): $(top_srcdir)/internal/rational.h node_dump.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h node_dump.$(OBJEXT): $(top_srcdir)/internal/serial.h node_dump.$(OBJEXT): $(top_srcdir)/internal/static_assert.h @@ -15587,12 +15621,16 @@ ruby.$(OBJEXT): $(hdrdir)/ruby/ruby.h ruby.$(OBJEXT): $(hdrdir)/ruby/version.h ruby.$(OBJEXT): $(top_srcdir)/internal/array.h ruby.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h +ruby.$(OBJEXT): $(top_srcdir)/internal/bignum.h +ruby.$(OBJEXT): $(top_srcdir)/internal/bits.h ruby.$(OBJEXT): $(top_srcdir)/internal/class.h ruby.$(OBJEXT): $(top_srcdir)/internal/cmdlineopt.h ruby.$(OBJEXT): $(top_srcdir)/internal/compilers.h +ruby.$(OBJEXT): $(top_srcdir)/internal/complex.h ruby.$(OBJEXT): $(top_srcdir)/internal/cont.h ruby.$(OBJEXT): $(top_srcdir)/internal/error.h ruby.$(OBJEXT): $(top_srcdir)/internal/file.h +ruby.$(OBJEXT): $(top_srcdir)/internal/fixnum.h ruby.$(OBJEXT): $(top_srcdir)/internal/gc.h ruby.$(OBJEXT): $(top_srcdir)/internal/imemo.h ruby.$(OBJEXT): $(top_srcdir)/internal/inits.h @@ -15600,8 +15638,10 @@ ruby.$(OBJEXT): $(top_srcdir)/internal/io.h ruby.$(OBJEXT): $(top_srcdir)/internal/load.h ruby.$(OBJEXT): $(top_srcdir)/internal/loadpath.h ruby.$(OBJEXT): $(top_srcdir)/internal/missing.h +ruby.$(OBJEXT): $(top_srcdir)/internal/numeric.h ruby.$(OBJEXT): $(top_srcdir)/internal/object.h ruby.$(OBJEXT): $(top_srcdir)/internal/parse.h +ruby.$(OBJEXT): $(top_srcdir)/internal/rational.h ruby.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h ruby.$(OBJEXT): $(top_srcdir)/internal/serial.h ruby.$(OBJEXT): $(top_srcdir)/internal/static_assert.h @@ -15828,7 +15868,14 @@ ruby.$(OBJEXT): {$(VPATH)}vm_opts.h ruby.$(OBJEXT): {$(VPATH)}yjit.h ruby_parser.$(OBJEXT): $(hdrdir)/ruby/ruby.h ruby_parser.$(OBJEXT): $(top_srcdir)/internal/array.h +ruby_parser.$(OBJEXT): $(top_srcdir)/internal/bignum.h +ruby_parser.$(OBJEXT): $(top_srcdir)/internal/bits.h +ruby_parser.$(OBJEXT): $(top_srcdir)/internal/compilers.h +ruby_parser.$(OBJEXT): $(top_srcdir)/internal/complex.h +ruby_parser.$(OBJEXT): $(top_srcdir)/internal/fixnum.h ruby_parser.$(OBJEXT): $(top_srcdir)/internal/imemo.h +ruby_parser.$(OBJEXT): $(top_srcdir)/internal/numeric.h +ruby_parser.$(OBJEXT): $(top_srcdir)/internal/rational.h ruby_parser.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h ruby_parser.$(OBJEXT): $(top_srcdir)/internal/serial.h ruby_parser.$(OBJEXT): $(top_srcdir)/internal/static_assert.h @@ -15837,6 +15884,7 @@ ruby_parser.$(OBJEXT): {$(VPATH)}assert.h ruby_parser.$(OBJEXT): {$(VPATH)}backward/2/assume.h ruby_parser.$(OBJEXT): {$(VPATH)}backward/2/attributes.h ruby_parser.$(OBJEXT): {$(VPATH)}backward/2/bool.h +ruby_parser.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h ruby_parser.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h ruby_parser.$(OBJEXT): {$(VPATH)}backward/2/limits.h ruby_parser.$(OBJEXT): {$(VPATH)}backward/2/long_long.h @@ -15998,6 +16046,7 @@ ruby_parser.$(OBJEXT): {$(VPATH)}internal/xmalloc.h ruby_parser.$(OBJEXT): {$(VPATH)}missing.h ruby_parser.$(OBJEXT): {$(VPATH)}onigmo.h ruby_parser.$(OBJEXT): {$(VPATH)}oniguruma.h +ruby_parser.$(OBJEXT): {$(VPATH)}ruby_assert.h ruby_parser.$(OBJEXT): {$(VPATH)}ruby_parser.c ruby_parser.$(OBJEXT): {$(VPATH)}rubyparser.h ruby_parser.$(OBJEXT): {$(VPATH)}st.h @@ -19259,6 +19308,7 @@ vm.$(OBJEXT): $(top_srcdir)/internal/class.h vm.$(OBJEXT): $(top_srcdir)/internal/compar.h vm.$(OBJEXT): $(top_srcdir)/internal/compile.h vm.$(OBJEXT): $(top_srcdir)/internal/compilers.h +vm.$(OBJEXT): $(top_srcdir)/internal/complex.h vm.$(OBJEXT): $(top_srcdir)/internal/cont.h vm.$(OBJEXT): $(top_srcdir)/internal/encoding.h vm.$(OBJEXT): $(top_srcdir)/internal/error.h @@ -19273,6 +19323,7 @@ vm.$(OBJEXT): $(top_srcdir)/internal/object.h vm.$(OBJEXT): $(top_srcdir)/internal/parse.h vm.$(OBJEXT): $(top_srcdir)/internal/proc.h vm.$(OBJEXT): $(top_srcdir)/internal/random.h +vm.$(OBJEXT): $(top_srcdir)/internal/rational.h vm.$(OBJEXT): $(top_srcdir)/internal/re.h vm.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h vm.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h diff --git a/compile.c b/compile.c index 39239934c5..5bda334c6e 100644 --- a/compile.c +++ b/compile.c @@ -1944,6 +1944,17 @@ iseq_set_arguments_keywords(rb_iseq_t *iseq, LINK_ANCHOR *const optargs, break; case NODE_LINE: dv = rb_node_line_lineno_val(val_node);; + case NODE_INTEGER: + dv = rb_node_integer_literal_val(RNODE_INTEGER(val_node)); + break; + case NODE_FLOAT: + dv = rb_node_float_literal_val(RNODE_FLOAT(val_node)); + break; + case NODE_RATIONAL: + dv = rb_node_rational_literal_val(RNODE_RATIONAL(val_node)); + break; + case NODE_IMAGINARY: + dv = rb_node_imaginary_literal_val(RNODE_IMAGINARY(val_node)); break; case NODE_NIL: dv = Qnil; @@ -4506,6 +4517,10 @@ compile_branch_condition(rb_iseq_t *iseq, LINK_ANCHOR *ret, const NODE *cond, case NODE_LIT: /* NODE_LIT is always true */ case NODE_LINE: case NODE_FILE: + case NODE_INTEGER: /* NODE_INTEGER is always true */ + case NODE_FLOAT: /* NODE_FLOAT is always true */ + case NODE_RATIONAL: /* NODE_RATIONAL is always true */ + case NODE_IMAGINARY: /* NODE_IMAGINARY is always true */ case NODE_TRUE: case NODE_STR: case NODE_ZLIST: @@ -4666,6 +4681,10 @@ static_literal_node_p(const NODE *node, const rb_iseq_t *iseq) switch (nd_type(node)) { case NODE_LIT: case NODE_LINE: + case NODE_INTEGER: + case NODE_FLOAT: + case NODE_RATIONAL: + case NODE_IMAGINARY: case NODE_NIL: case NODE_TRUE: case NODE_FALSE: @@ -4682,6 +4701,14 @@ static inline VALUE static_literal_value(const NODE *node, rb_iseq_t *iseq) { switch (nd_type(node)) { + case NODE_INTEGER: + return rb_node_integer_literal_val(RNODE_INTEGER(node)); + case NODE_FLOAT: + return rb_node_float_literal_val(RNODE_FLOAT(node)); + case NODE_RATIONAL: + return rb_node_rational_literal_val(RNODE_RATIONAL(node)); + case NODE_IMAGINARY: + return rb_node_imaginary_literal_val(RNODE_IMAGINARY(node)); case NODE_NIL: return Qnil; case NODE_TRUE: @@ -5059,19 +5086,25 @@ rb_node_case_when_optimizable_literal(const NODE *const node) switch (nd_type(node)) { case NODE_LIT: { VALUE v = RNODE_LIT(node)->nd_lit; - double ival; - if (RB_FLOAT_TYPE_P(v) && - modf(RFLOAT_VALUE(v), &ival) == 0.0) { - return FIXABLE(ival) ? LONG2FIX((long)ival) : rb_dbl2big(ival); - } - if (RB_TYPE_P(v, T_RATIONAL) || RB_TYPE_P(v, T_COMPLEX)) { - return Qundef; - } - if (SYMBOL_P(v) || rb_obj_is_kind_of(v, rb_cNumeric)) { + if (SYMBOL_P(v)) { return v; } break; } + case NODE_INTEGER: + return rb_node_integer_literal_val(RNODE_INTEGER(node)); + case NODE_FLOAT: { + VALUE v = rb_node_float_literal_val(RNODE_FLOAT(node)); + double ival; + + if (modf(RFLOAT_VALUE(v), &ival) == 0.0) { + return FIXABLE(ival) ? LONG2FIX((long)ival) : rb_dbl2big(ival); + } + return v; + } + case NODE_RATIONAL: + case NODE_IMAGINARY: + return Qundef; case NODE_NIL: return Qnil; case NODE_TRUE: @@ -5710,6 +5743,10 @@ defined_expr0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, case NODE_LIT: case NODE_LINE: case NODE_FILE: + case NODE_INTEGER: + case NODE_FLOAT: + case NODE_RATIONAL: + case NODE_IMAGINARY: case NODE_ZLIST: case NODE_AND: case NODE_OR: @@ -6286,6 +6323,8 @@ optimizable_range_item_p(const NODE *n) return RB_INTEGER_TYPE_P(RNODE_LIT(n)->nd_lit); case NODE_LINE: return TRUE; + case NODE_INTEGER: + return TRUE; case NODE_NIL: return TRUE; default: @@ -6301,6 +6340,14 @@ optimized_range_item(const NODE *n) return RNODE_LIT(n)->nd_lit; case NODE_LINE: return rb_node_line_lineno_val(n); + case NODE_INTEGER: + return rb_node_integer_literal_val(RNODE_INTEGER(n)); + case NODE_FLOAT: + return rb_node_float_literal_val(RNODE_FLOAT(n)); + case NODE_RATIONAL: + return rb_node_rational_literal_val(RNODE_RATIONAL(n)); + case NODE_IMAGINARY: + return rb_node_imaginary_literal_val(RNODE_IMAGINARY(n)); case NODE_NIL: return Qnil; default: @@ -7123,6 +7170,10 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c } case NODE_LIT: case NODE_LINE: + case NODE_INTEGER: + case NODE_FLOAT: + case NODE_RATIONAL: + case NODE_IMAGINARY: case NODE_FILE: case NODE_STR: case NODE_XSTR: @@ -9679,6 +9730,10 @@ compile_kw_arg(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, } else if (nd_type_p(default_value, NODE_LIT) || nd_type_p(default_value, NODE_LINE) || + nd_type_p(default_value, NODE_INTEGER) || + nd_type_p(default_value, NODE_FLOAT) || + nd_type_p(default_value, NODE_RATIONAL) || + nd_type_p(default_value, NODE_IMAGINARY) || nd_type_p(default_value, NODE_NIL) || nd_type_p(default_value, NODE_TRUE) || nd_type_p(default_value, NODE_FALSE)) { @@ -10154,6 +10209,42 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no } break; } + case NODE_INTEGER:{ + VALUE lit = rb_node_integer_literal_val(RNODE_INTEGER(node)); + debugp_param("integer", lit); + if (!popped) { + ADD_INSN1(ret, node, putobject, lit); + RB_OBJ_WRITTEN(iseq, Qundef, lit); + } + break; + } + case NODE_FLOAT:{ + VALUE lit = rb_node_float_literal_val(RNODE_FLOAT(node)); + debugp_param("float", lit); + if (!popped) { + ADD_INSN1(ret, node, putobject, lit); + RB_OBJ_WRITTEN(iseq, Qundef, lit); + } + break; + } + case NODE_RATIONAL:{ + VALUE lit = rb_node_rational_literal_val(RNODE_RATIONAL(node)); + debugp_param("rational", lit); + if (!popped) { + ADD_INSN1(ret, node, putobject, lit); + RB_OBJ_WRITTEN(iseq, Qundef, lit); + } + break; + } + case NODE_IMAGINARY:{ + VALUE lit = rb_node_imaginary_literal_val(RNODE_IMAGINARY(node)); + debugp_param("imaginary", lit); + if (!popped) { + ADD_INSN1(ret, node, putobject, lit); + RB_OBJ_WRITTEN(iseq, Qundef, lit); + } + break; + } case NODE_FILE: case NODE_STR:{ debugp_param("nd_lit", get_string_value(node)); diff --git a/ext/ripper/depend b/ext/ripper/depend index a18b67abe3..a07825fd40 100644 --- a/ext/ripper/depend +++ b/ext/ripper/depend @@ -634,6 +634,7 @@ ripper_init.o: $(hdrdir)/ruby/backward.h ripper_init.o: $(hdrdir)/ruby/backward/2/assume.h ripper_init.o: $(hdrdir)/ruby/backward/2/attributes.h ripper_init.o: $(hdrdir)/ruby/backward/2/bool.h +ripper_init.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h ripper_init.o: $(hdrdir)/ruby/backward/2/inttypes.h ripper_init.o: $(hdrdir)/ruby/backward/2/limits.h ripper_init.o: $(hdrdir)/ruby/backward/2/long_long.h @@ -798,13 +799,21 @@ ripper_init.o: $(hdrdir)/ruby/st.h ripper_init.o: $(hdrdir)/ruby/subst.h ripper_init.o: $(top_srcdir)/internal.h ripper_init.o: $(top_srcdir)/internal/array.h +ripper_init.o: $(top_srcdir)/internal/bignum.h +ripper_init.o: $(top_srcdir)/internal/bits.h +ripper_init.o: $(top_srcdir)/internal/compilers.h +ripper_init.o: $(top_srcdir)/internal/complex.h +ripper_init.o: $(top_srcdir)/internal/fixnum.h ripper_init.o: $(top_srcdir)/internal/imemo.h +ripper_init.o: $(top_srcdir)/internal/numeric.h ripper_init.o: $(top_srcdir)/internal/parse.h +ripper_init.o: $(top_srcdir)/internal/rational.h ripper_init.o: $(top_srcdir)/internal/ruby_parser.h ripper_init.o: $(top_srcdir)/internal/serial.h ripper_init.o: $(top_srcdir)/internal/static_assert.h ripper_init.o: $(top_srcdir)/internal/vm.h ripper_init.o: $(top_srcdir)/node.h +ripper_init.o: $(top_srcdir)/ruby_assert.h ripper_init.o: $(top_srcdir)/rubyparser.h ripper_init.o: eventids1.h ripper_init.o: eventids2.h diff --git a/internal/ruby_parser.h b/internal/ruby_parser.h index 2c2134024b..9efc04b70b 100644 --- a/internal/ruby_parser.h +++ b/internal/ruby_parser.h @@ -2,7 +2,11 @@ #define INTERNAL_RUBY_PARSE_H #include "internal.h" +#include "internal/bignum.h" +#include "internal/compilers.h" +#include "internal/complex.h" #include "internal/imemo.h" +#include "internal/rational.h" #include "rubyparser.h" #include "vm.h" @@ -69,4 +73,10 @@ enum lex_state_e { VALUE rb_node_line_lineno_val(const NODE *); VALUE rb_node_file_path_val(const NODE *); + +VALUE rb_node_integer_literal_val(rb_node_integer_t* node); +VALUE rb_node_float_literal_val(rb_node_float_t* node); +VALUE rb_node_rational_literal_val(rb_node_rational_t* node); +VALUE rb_node_imaginary_literal_val(rb_node_imaginary_t* node); + #endif /* INTERNAL_RUBY_PARSE_H */ diff --git a/node.c b/node.c index 6798701a7a..6c42690503 100644 --- a/node.c +++ b/node.c @@ -182,6 +182,18 @@ free_ast_value(rb_ast_t *ast, void *ctx, NODE *node) case NODE_FILE: parser_string_free(ast, RNODE_FILE(node)->path); break; + case NODE_INTEGER: + xfree(RNODE_INTEGER(node)->val); + break; + case NODE_FLOAT: + xfree(RNODE_FLOAT(node)->val); + break; + case NODE_RATIONAL: + xfree(RNODE_RATIONAL(node)->val); + break; + case NODE_IMAGINARY: + xfree(RNODE_IMAGINARY(node)->val); + break; default: break; } diff --git a/node_dump.c b/node_dump.c index c42a02e3b3..8060984391 100644 --- a/node_dump.c +++ b/node_dump.c @@ -706,7 +706,7 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node) case NODE_LIT: ANN("literal"); ANN("format: [nd_lit]"); - ANN("example: 1, /foo/"); + ANN("example: :sym, /foo/"); goto lit; case NODE_STR: ANN("string literal"); @@ -721,6 +721,34 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node) F_LIT(nd_lit, RNODE_LIT, "literal"); return; + case NODE_INTEGER: + ANN("integer literal"); + ANN("format: [val]"); + ANN("example: 1"); + F_VALUE(val, rb_node_integer_literal_val(RNODE_INTEGER(node)), "val"); + return; + + case NODE_FLOAT: + ANN("float literal"); + ANN("format: [val]"); + ANN("example: 1.2"); + F_VALUE(val, rb_node_float_literal_val(RNODE_FLOAT(node)), "val"); + return; + + case NODE_RATIONAL: + ANN("rational number literal"); + ANN("format: [val]"); + ANN("example: 1r"); + F_VALUE(val, rb_node_rational_literal_val(RNODE_RATIONAL(node)), "val"); + return; + + case NODE_IMAGINARY: + ANN("complex number literal"); + ANN("format: [val]"); + ANN("example: 1i"); + F_VALUE(val, rb_node_imaginary_literal_val(RNODE_IMAGINARY(node)), "val"); + return; + case NODE_ONCE: ANN("once evaluation"); ANN("format: [nd_body]"); diff --git a/parse.y b/parse.y index 7e714ccb2c..a8f094271f 100644 --- a/parse.y +++ b/parse.y @@ -912,6 +912,10 @@ static rb_node_back_ref_t *rb_node_back_ref_new(struct parser_params *p, long nd 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); +static rb_node_imaginary_t * rb_node_imaginary_new(struct parser_params *p, char* val, int base, int seen_point, enum rb_numeric_type, const YYLTYPE *loc); static rb_node_str_t *rb_node_str_new(struct parser_params *p, VALUE nd_lit, const YYLTYPE *loc); static rb_node_dstr_t *rb_node_dstr_new0(struct parser_params *p, VALUE nd_lit, long nd_alen, NODE *nd_next, const YYLTYPE *loc); static rb_node_dstr_t *rb_node_dstr_new(struct parser_params *p, VALUE nd_lit, const YYLTYPE *loc); @@ -1015,6 +1019,10 @@ static rb_node_error_t *rb_node_error_new(struct parser_params *p, const YYLTYPE #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) +#define NEW_IMAGINARY(val,base,seen_point,numeric_type,loc) (NODE *)rb_node_imaginary_new(p,val,base,seen_point,numeric_type,loc) #define NEW_STR(s,loc) (NODE *)rb_node_str_new(p,s,loc) #define NEW_DSTR0(s,l,n,loc) (NODE *)rb_node_dstr_new0(p,s,l,n,loc) #define NEW_DSTR(s,loc) (NODE *)rb_node_dstr_new(p,s,loc) @@ -1230,7 +1238,7 @@ static NODE *new_hash_pattern_tail(struct parser_params *p, NODE *kw_args, ID kw static rb_node_kw_arg_t *new_kw_arg(struct parser_params *p, NODE *k, const YYLTYPE *loc); static rb_node_args_t *args_with_numbered(struct parser_params*,rb_node_args_t*,int,ID); -static VALUE negate_lit(struct parser_params*, VALUE); +static NODE* negate_lit(struct parser_params*, NODE*); static NODE *ret_args(struct parser_params*,NODE*); static NODE *arg_blk_pass(NODE*,rb_node_block_pass_t*); static NODE *new_yield(struct parser_params*,NODE*,const YYLTYPE*); @@ -6074,7 +6082,7 @@ numeric : simple_numeric { /*%%%*/ $$ = $2; - RB_OBJ_WRITE(p->ast, &RNODE_LIT($$)->nd_lit, negate_lit(p, RNODE_LIT($$)->nd_lit)); + negate_lit(p, $$); /*% %*/ /*% ripper: unary!(ID2VAL(idUMinus), $2) %*/ } @@ -6652,6 +6660,10 @@ singleton : var_ref case NODE_LIT: case NODE_LINE: case NODE_FILE: + case NODE_INTEGER: + case NODE_FLOAT: + case NODE_RATIONAL: + case NODE_IMAGINARY: case NODE_DSYM: case NODE_LIST: case NODE_ZLIST: @@ -8990,29 +9002,42 @@ number_literal_suffix(struct parser_params *p, int mask) } static enum yytokentype -set_number_literal(struct parser_params *p, VALUE v, - enum yytokentype type, int suffix) +set_number_literal(struct parser_params *p, enum yytokentype type, int suffix, int base, int seen_point) { + enum rb_numeric_type numeric_type = integer_literal; + + if (type == tFLOAT) { + numeric_type = float_literal; + } + + if (suffix & NUM_SUFFIX_R) { + type = tRATIONAL; + numeric_type = rational_literal; + } if (suffix & NUM_SUFFIX_I) { - v = rb_complex_raw(INT2FIX(0), v); type = tIMAGINARY; } - set_yylval_literal(v); + + switch (type) { + case tINTEGER: + set_yylval_node(NEW_INTEGER(strdup(tok(p)), base, &_cur_loc)); + break; + case tFLOAT: + set_yylval_node(NEW_FLOAT(strdup(tok(p)), &_cur_loc)); + break; + case tRATIONAL: + set_yylval_node(NEW_RATIONAL(strdup(tok(p)), base, seen_point, &_cur_loc)); + break; + case tIMAGINARY: + set_yylval_node(NEW_IMAGINARY(strdup(tok(p)), base, seen_point, numeric_type, &_cur_loc)); + break; + default: + rb_bug("unexpected token: %d", type); + } SET_LEX_STATE(EXPR_END); return type; } -static enum yytokentype -set_integer_literal(struct parser_params *p, VALUE v, int suffix) -{ - enum yytokentype type = tINTEGER; - if (suffix & NUM_SUFFIX_R) { - v = rb_rational_raw1(v); - type = tRATIONAL; - } - return set_number_literal(p, v, type, suffix); -} - #ifdef RIPPER static void dispatch_heredoc_end(struct parser_params *p) @@ -9690,24 +9715,13 @@ parser_prepare(struct parser_params *p) (ambiguous_operator(tok, op, syn), 0)), \ (enum yytokentype)(tok)) -static VALUE -parse_rational(struct parser_params *p, char *str, int len, int seen_point) -{ - VALUE v; - char *point = &str[seen_point]; - size_t fraclen = len-seen_point-1; - memmove(point, point+1, fraclen+1); - v = rb_cstr_to_inum(str, 10, FALSE); - return rb_rational_new(v, rb_int_positive_pow(10, fraclen)); -} - static enum yytokentype no_digits(struct parser_params *p) { yyerror0("numeric literal without digits"); if (peek(p, '_')) nextc(p); /* dummy 0, for tUMINUS_NUM at numeric */ - return set_integer_literal(p, INT2FIX(0), 0); + return set_number_literal(p, tINTEGER, 0, 10, 0); } static enum yytokentype @@ -9748,7 +9762,7 @@ parse_numeric(struct parser_params *p, int c) } else if (nondigit) goto trailing_uc; suffix = number_literal_suffix(p, NUM_SUFFIX_ALL); - return set_integer_literal(p, rb_cstr_to_inum(tok(p), 16, FALSE), suffix); + return set_number_literal(p, tINTEGER, suffix, 16, 0); } if (c == 'b' || c == 'B') { /* binary */ @@ -9772,7 +9786,7 @@ parse_numeric(struct parser_params *p, int c) } else if (nondigit) goto trailing_uc; suffix = number_literal_suffix(p, NUM_SUFFIX_ALL); - return set_integer_literal(p, rb_cstr_to_inum(tok(p), 2, FALSE), suffix); + return set_number_literal(p, tINTEGER, suffix, 2, 0); } if (c == 'd' || c == 'D') { /* decimal */ @@ -9796,7 +9810,7 @@ parse_numeric(struct parser_params *p, int c) } else if (nondigit) goto trailing_uc; suffix = number_literal_suffix(p, NUM_SUFFIX_ALL); - return set_integer_literal(p, rb_cstr_to_inum(tok(p), 10, FALSE), suffix); + return set_number_literal(p, tINTEGER, suffix, 10, 0); } if (c == '_') { /* 0_0 */ @@ -9828,7 +9842,7 @@ parse_numeric(struct parser_params *p, int c) tokfix(p); if (nondigit) goto trailing_uc; suffix = number_literal_suffix(p, NUM_SUFFIX_ALL); - return set_integer_literal(p, rb_cstr_to_inum(tok(p), 8, FALSE), suffix); + return set_number_literal(p, tINTEGER, suffix, 8, 0); } if (nondigit) { pushback(p, c); @@ -9844,8 +9858,9 @@ parse_numeric(struct parser_params *p, int c) } else { pushback(p, c); + tokfix(p); suffix = number_literal_suffix(p, NUM_SUFFIX_ALL); - return set_integer_literal(p, INT2FIX(0), suffix); + return set_number_literal(p, tINTEGER, suffix, 10, 0); } } @@ -9925,25 +9940,22 @@ parse_numeric(struct parser_params *p, int c) tokfix(p); if (is_float) { enum yytokentype type = tFLOAT; - VALUE v; suffix = number_literal_suffix(p, seen_e ? NUM_SUFFIX_I : NUM_SUFFIX_ALL); if (suffix & NUM_SUFFIX_R) { type = tRATIONAL; - v = parse_rational(p, tok(p), toklen(p), seen_point); } else { - double d = strtod(tok(p), 0); + strtod(tok(p), 0); if (errno == ERANGE) { rb_warning1("Float %s out of range", WARN_S(tok(p))); errno = 0; } - v = DBL2NUM(d); } - return set_number_literal(p, v, type, suffix); + return set_number_literal(p, type, suffix, 0, seen_point); } suffix = number_literal_suffix(p, NUM_SUFFIX_ALL); - return set_integer_literal(p, rb_cstr_to_inum(tok(p), 10, FALSE), suffix); + return set_number_literal(p, tINTEGER, suffix, 10, 0); } static enum yytokentype @@ -11913,6 +11925,48 @@ rb_node_lit_new(struct parser_params *p, VALUE nd_lit, const YYLTYPE *loc) return n; } +static rb_node_integer_t * +rb_node_integer_new(struct parser_params *p, char* val, int base, const YYLTYPE *loc) { + rb_node_integer_t *n = NODE_NEWNODE(NODE_INTEGER, rb_node_integer_t, loc); + n->val = val; + n->minus = FALSE; + n->base = base; + + return n; +} + +static rb_node_float_t * +rb_node_float_new(struct parser_params *p, char* val, const YYLTYPE *loc) { + rb_node_float_t *n = NODE_NEWNODE(NODE_FLOAT, rb_node_float_t, loc); + n->val = val; + n->minus = FALSE; + + return n; +} + +static rb_node_rational_t * +rb_node_rational_new(struct parser_params *p, char* val, int base, int seen_point, const YYLTYPE *loc) { + rb_node_rational_t *n = NODE_NEWNODE(NODE_RATIONAL, rb_node_rational_t, loc); + n->val = val; + n->minus = FALSE; + n->base = base; + n->seen_point = seen_point; + + return n; +} + +static rb_node_imaginary_t * +rb_node_imaginary_new(struct parser_params *p, char* val, int base, int seen_point, enum rb_numeric_type numeric_type, const YYLTYPE *loc) { + rb_node_imaginary_t *n = NODE_NEWNODE(NODE_IMAGINARY, rb_node_imaginary_t, loc); + n->val = val; + n->minus = FALSE; + n->base = base; + n->seen_point = seen_point; + n->type = numeric_type; + + return n; +} + static rb_node_str_t * rb_node_str_new(struct parser_params *p, VALUE nd_lit, const YYLTYPE *loc) { @@ -13709,6 +13763,14 @@ shareable_literal_value(struct parser_params *p, NODE *node) return Qnil; case NODE_LINE: return rb_node_line_lineno_val(node); + case NODE_INTEGER: + return rb_node_integer_literal_val(RNODE_INTEGER(node)); + case NODE_FLOAT: + return rb_node_float_literal_val(RNODE_FLOAT(node)); + case NODE_RATIONAL: + return rb_node_rational_literal_val(RNODE_RATIONAL(node)); + case NODE_IMAGINARY: + return rb_node_imaginary_literal_val(RNODE_IMAGINARY(node)); case NODE_LIT: return RNODE_LIT(node)->nd_lit; default: @@ -13736,6 +13798,10 @@ shareable_literal_constant(struct parser_params *p, enum shareability shareable, case NODE_NIL: case NODE_LIT: case NODE_LINE: + case NODE_INTEGER: + case NODE_FLOAT: + case NODE_RATIONAL: + case NODE_IMAGINARY: return value; case NODE_DSTR: @@ -14051,6 +14117,10 @@ void_expr(struct parser_params *p, NODE *node) case NODE_LIT: case NODE_LINE: case NODE_FILE: + case NODE_INTEGER: + case NODE_FLOAT: + case NODE_RATIONAL: + case NODE_IMAGINARY: case NODE_STR: case NODE_DSTR: case NODE_DREGX: @@ -14190,6 +14260,10 @@ is_static_content(NODE *node) case NODE_LIT: case NODE_LINE: case NODE_FILE: + case NODE_INTEGER: + case NODE_FLOAT: + case NODE_RATIONAL: + case NODE_IMAGINARY: case NODE_STR: case NODE_NIL: case NODE_TRUE: @@ -14252,7 +14326,7 @@ range_op(struct parser_params *p, NODE *node, const YYLTYPE *loc) type = nd_type(node); value_expr(node); - if (type == NODE_LIT && FIXNUM_P(RNODE_LIT(node)->nd_lit)) { + if (type == NODE_INTEGER) { if (!e_option_supplied(p)) parser_warn(p, node, "integer literal in flip-flop"); ID lineno = rb_intern("$."); return NEW_CALL(node, tEQ, NEW_LIST(NEW_GVAR(lineno, loc), loc), loc); @@ -14334,6 +14408,13 @@ cond0(struct parser_params *p, NODE *node, enum cond_type type, const YYLTYPE *l SWITCH_BY_COND_TYPE(type, warning, ""); break; + case NODE_INTEGER: + case NODE_FLOAT: + case NODE_RATIONAL: + case NODE_IMAGINARY: + SWITCH_BY_COND_TYPE(type, warning, ""); + break; + default: break; } @@ -14431,42 +14512,24 @@ new_yield(struct parser_params *p, NODE *node, const YYLTYPE *loc) return NEW_YIELD(node, loc); } -static VALUE -negate_lit(struct parser_params *p, VALUE lit) +static NODE* +negate_lit(struct parser_params *p, NODE* node) { - if (FIXNUM_P(lit)) { - return LONG2FIX(-FIX2LONG(lit)); - } - if (SPECIAL_CONST_P(lit)) { -#if USE_FLONUM - if (FLONUM_P(lit)) { - return DBL2NUM(-RFLOAT_VALUE(lit)); - } -#endif - goto unknown; - } - switch (BUILTIN_TYPE(lit)) { - case T_BIGNUM: - bignum_negate(lit); - lit = rb_big_norm(lit); + switch (nd_type(node)) { + case NODE_INTEGER: + RNODE_INTEGER(node)->minus = TRUE; break; - case T_RATIONAL: - rational_set_num(lit, negate_lit(p, rational_get_num(lit))); + case NODE_FLOAT: + RNODE_FLOAT(node)->minus = TRUE; break; - case T_COMPLEX: - rcomplex_set_real(lit, negate_lit(p, rcomplex_get_real(lit))); - rcomplex_set_imag(lit, negate_lit(p, rcomplex_get_imag(lit))); + case NODE_RATIONAL: + RNODE_RATIONAL(node)->minus = TRUE; break; - case T_FLOAT: - lit = DBL2NUM(-RFLOAT_VALUE(lit)); - break; - unknown: - default: - rb_parser_fatal(p, "unknown literal type (%s) passed to negate_lit", - rb_builtin_class_name(lit)); + case NODE_IMAGINARY: + RNODE_IMAGINARY(node)->minus = TRUE; break; } - return lit; + return node; } static NODE * @@ -14754,8 +14817,60 @@ remove_duplicate_keys(struct parser_params *p, NODE *hash) RNODE_LIST(last_expr)->nd_head = block_append(p, RNODE_LIST(dup_value)->nd_head, RNODE_LIST(last_expr)->nd_head); } } + else if (nd_type_p(head, NODE_INTEGER) && + st_delete(literal_keys, (key = (st_data_t)rb_node_integer_literal_val(RNODE_INTEGER(head)), &key), &data)) { + NODE *dup_value = (RNODE_LIST((NODE *)data))->nd_next; + rb_compile_warn(p->ruby_sourcefile, nd_line((NODE *)data), + "key %+"PRIsVALUE" is duplicated and overwritten on line %d", + rb_node_integer_literal_val(RNODE_INTEGER(head)), nd_line(head)); + if (dup_value == last_expr) { + RNODE_LIST(value)->nd_head = block_append(p, RNODE_LIST(dup_value)->nd_head, RNODE_LIST(value)->nd_head); + } + else { + RNODE_LIST(last_expr)->nd_head = block_append(p, RNODE_LIST(dup_value)->nd_head, RNODE_LIST(last_expr)->nd_head); + } + } + else if (nd_type_p(head, NODE_FLOAT) && + st_delete(literal_keys, (key = (st_data_t)rb_node_float_literal_val(RNODE_FLOAT(head)), &key), &data)) { + NODE *dup_value = (RNODE_LIST((NODE *)data))->nd_next; + rb_compile_warn(p->ruby_sourcefile, nd_line((NODE *)data), + "key %+"PRIsVALUE" is duplicated and overwritten on line %d", + rb_node_float_literal_val(RNODE_FLOAT(head)), nd_line(head)); + if (dup_value == last_expr) { + RNODE_LIST(value)->nd_head = block_append(p, RNODE_LIST(dup_value)->nd_head, RNODE_LIST(value)->nd_head); + } + else { + RNODE_LIST(last_expr)->nd_head = block_append(p, RNODE_LIST(dup_value)->nd_head, RNODE_LIST(last_expr)->nd_head); + } + } + else if (nd_type_p(head, NODE_RATIONAL) && + st_delete(literal_keys, (key = (st_data_t)rb_node_rational_literal_val(RNODE_RATIONAL(head)), &key), &data)) { + NODE *dup_value = (RNODE_LIST((NODE *)data))->nd_next; + rb_compile_warn(p->ruby_sourcefile, nd_line((NODE *)data), + "key %+"PRIsVALUE" is duplicated and overwritten on line %d", + rb_node_rational_literal_val(RNODE_RATIONAL(head)), nd_line(head)); + if (dup_value == last_expr) { + RNODE_LIST(value)->nd_head = block_append(p, RNODE_LIST(dup_value)->nd_head, RNODE_LIST(value)->nd_head); + } + else { + RNODE_LIST(last_expr)->nd_head = block_append(p, RNODE_LIST(dup_value)->nd_head, RNODE_LIST(last_expr)->nd_head); + } + } + else if (nd_type_p(head, NODE_IMAGINARY) && + st_delete(literal_keys, (key = (st_data_t)rb_node_imaginary_literal_val(RNODE_IMAGINARY(head)), &key), &data)) { + NODE *dup_value = (RNODE_LIST((NODE *)data))->nd_next; + rb_compile_warn(p->ruby_sourcefile, nd_line((NODE *)data), + "key %+"PRIsVALUE" is duplicated and overwritten on line %d", + rb_node_imaginary_literal_val(RNODE_IMAGINARY(head)), nd_line(head)); + if (dup_value == last_expr) { + RNODE_LIST(value)->nd_head = block_append(p, RNODE_LIST(dup_value)->nd_head, RNODE_LIST(value)->nd_head); + } + else { + RNODE_LIST(last_expr)->nd_head = block_append(p, RNODE_LIST(dup_value)->nd_head, RNODE_LIST(last_expr)->nd_head); + } + } st_insert(literal_keys, (st_data_t)key, (st_data_t)hash); - last_expr = !head || nd_type_p(head, NODE_LIT) ? value : head; + last_expr = !head || (nd_type_p(head, NODE_LIT) || nd_type_p(head, NODE_INTEGER) || nd_type_p(head, NODE_FLOAT) || nd_type_p(head, NODE_RATIONAL) || nd_type_p(head, NODE_IMAGINARY)) ? value : head; hash = next; } st_foreach(literal_keys, append_literal_keys, (st_data_t)&result); diff --git a/ruby_parser.c b/ruby_parser.c index 94209b9aba..800b59f637 100644 --- a/ruby_parser.c +++ b/ruby_parser.c @@ -4,6 +4,135 @@ #include "rubyparser.h" +static VALUE +compile_negative_numeric(VALUE val) +{ + if (FIXNUM_P(val)) { + return LONG2FIX(-FIX2LONG(val)); + } + if (SPECIAL_CONST_P(val)) { +#if USE_FLONUM + if (FLONUM_P(val)) { + return DBL2NUM(-RFLOAT_VALUE(val)); + } +#endif + } + switch (OBJ_BUILTIN_TYPE(val)) + { + case T_BIGNUM: + BIGNUM_NEGATE(val); + val = rb_big_norm(val); + break; + case T_RATIONAL: + RATIONAL_SET_NUM(val, compile_negative_numeric(RRATIONAL(val)->num)); + break; + case T_COMPLEX: + RCOMPLEX_SET_REAL(val, compile_negative_numeric(RCOMPLEX(val)->real)); + RCOMPLEX_SET_IMAG(val, compile_negative_numeric(RCOMPLEX(val)->imag)); + break; + case T_FLOAT: + val = DBL2NUM(-RFLOAT_VALUE(val)); + break; + default: + val = LONG2FIX(-FIX2LONG(val)); + break; + } + return val; +} + +static VALUE +compile_numeric_literal(char* val, int base) +{ + return rb_cstr_to_inum(val, base, FALSE); +} + +VALUE +rb_node_integer_literal_val(rb_node_integer_t* node) +{ + VALUE val = compile_numeric_literal(node->val, node->base); + if (node->minus) { + val = compile_negative_numeric(val); + } + return val; +} + +VALUE +rb_node_float_literal_val(rb_node_float_t* node) +{ + double d = strtod(node->val, 0); + if (node->minus) { + d = -d; + } + VALUE val = DBL2NUM(d); + return val; +} + +static VALUE +compile_rational_literal(char* node_val, int base, int seen_point) +{ + VALUE lit; + char* val = strdup(node_val); + if (seen_point > 0) { + int len = (int)(strlen(val)); + char *point = &val[seen_point]; + size_t fraclen = len-seen_point-1; + memmove(point, point+1, fraclen+1); + + lit = rb_rational_new(compile_numeric_literal(val, base), rb_int_positive_pow(10, fraclen)); + } else { + lit = rb_rational_raw1(compile_numeric_literal(val, base)); + } + + free(val); + + return lit; +} + +VALUE +rb_node_rational_literal_val(rb_node_rational_t* node) +{ + VALUE lit; + + lit = compile_rational_literal(node->val, node->base, node->seen_point); + + if (node->minus) { + lit = compile_negative_numeric(lit); + } + + return lit; +} + +VALUE +rb_node_imaginary_literal_val(rb_node_imaginary_t* node) +{ + VALUE lit; + + enum rb_numeric_type type = node->type; + + switch (type) { + case integer_literal: + lit = compile_numeric_literal(node->val, node->base); + break; + case float_literal:{ + double d = strtod(node->val, 0); + lit = DBL2NUM(d); + break; + } + case rational_literal: + lit = compile_rational_literal(node->val, node->base, node->seen_point); + break; + default: + rb_bug("unreachable"); + } + + lit = rb_complex_raw(INT2FIX(0), lit); + + if (node->minus) { + lit = compile_negative_numeric(lit); + } + return lit; +} + #ifdef UNIVERSAL_PARSER #include "internal.h" diff --git a/rubyparser.h b/rubyparser.h index b7608285bb..5ec2d74047 100644 --- a/rubyparser.h +++ b/rubyparser.h @@ -109,6 +109,10 @@ enum node_type { NODE_MATCH2, NODE_MATCH3, NODE_LIT, + NODE_INTEGER, + NODE_FLOAT, + NODE_RATIONAL, + NODE_IMAGINARY, NODE_STR, NODE_DSTR, NODE_XSTR, @@ -628,6 +632,46 @@ typedef struct RNode_LIT { VALUE nd_lit; } rb_node_lit_t; +typedef struct RNode_INTEGER { + NODE node; + + char* val; + int minus; + int base; +} rb_node_integer_t; + +typedef struct RNode_FLOAT { + NODE node; + + char* val; + int minus; +} rb_node_float_t; + +typedef struct RNode_RATIONAL { + NODE node; + + char* val; + int minus; + int base; + int seen_point; +} rb_node_rational_t; + +enum rb_numeric_type { + integer_literal, + float_literal, + rational_literal +}; + +typedef struct RNode_IMAGINARY { + NODE node; + + char* val; + int minus; + int base; + int seen_point; + enum rb_numeric_type type; +} rb_node_imaginary_t; + typedef struct RNode_STR { NODE node; @@ -1020,6 +1064,10 @@ typedef struct RNode_ERROR { #define RNODE_MATCH2(node) ((struct RNode_MATCH2 *)(node)) #define RNODE_MATCH3(node) ((struct RNode_MATCH3 *)(node)) #define RNODE_LIT(node) ((struct RNode_LIT *)(node)) +#define RNODE_INTEGER(node) ((struct RNode_INTEGER *)(node)) +#define RNODE_FLOAT(node) ((struct RNode_FLOAT *)(node)) +#define RNODE_RATIONAL(node) ((struct RNode_RATIONAL *)(node)) +#define RNODE_IMAGINARY(node) ((struct RNode_IMAGINARY *)(node)) #define RNODE_STR(node) ((struct RNode_STR *)(node)) #define RNODE_DSTR(node) ((struct RNode_DSTR *)(node)) #define RNODE_XSTR(node) ((struct RNode_XSTR *)(node)) diff --git a/test/ruby/test_ast.rb b/test/ruby/test_ast.rb index 234c7af219..5f4a440976 100644 --- a/test/ruby/test_ast.rb +++ b/test/ruby/test_ast.rb @@ -589,7 +589,7 @@ class TestAst < Test::Unit::TestCase assert_equal("foo", head) assert_equal(:EVSTR, body.type) body, = body.children - assert_equal(:LIT, body.type) + assert_equal(:INTEGER, body.type) assert_equal([1], body.children) end @@ -885,7 +885,7 @@ dummy begin a = 1 STR - (SCOPE@1:0-2:7 tbl: [:a] args: nil body: (LASGN@2:2-2:7 :a (LIT@2:6-2:7 1))) + (SCOPE@1:0-2:7 tbl: [:a] args: nil body: (LASGN@2:2-2:7 :a (INTEGER@2:6-2:7 1))) EXP end @@ -898,7 +898,8 @@ dummy tbl: [:a] args: nil body: - (IF@1:0-2:7 (VCALL@1:3-1:7 :cond) (LASGN@2:2-2:7 :a (LIT@2:6-2:7 1)) nil)) + (IF@1:0-2:7 (VCALL@1:3-1:7 :cond) (LASGN@2:2-2:7 :a (INTEGER@2:6-2:7 1)) + nil)) EXP assert_error_tolerant(<<~STR, <<~EXP) @@ -910,7 +911,7 @@ dummy tbl: [:a] args: nil body: - (IF@1:0-3:4 (VCALL@1:3-1:7 :cond) (LASGN@2:2-2:7 :a (LIT@2:6-2:7 1)) + (IF@1:0-3:4 (VCALL@1:3-1:7 :cond) (LASGN@2:2-2:7 :a (INTEGER@2:6-2:7 1)) (BEGIN@3:4-3:4 nil))) EXP end @@ -924,7 +925,7 @@ dummy tbl: [:a] args: nil body: - (UNLESS@1:0-2:7 (VCALL@1:7-1:11 :cond) (LASGN@2:2-2:7 :a (LIT@2:6-2:7 1)) + (UNLESS@1:0-2:7 (VCALL@1:7-1:11 :cond) (LASGN@2:2-2:7 :a (INTEGER@2:6-2:7 1)) nil)) EXP @@ -937,7 +938,7 @@ dummy tbl: [:a] args: nil body: - (UNLESS@1:0-3:4 (VCALL@1:7-1:11 :cond) (LASGN@2:2-2:7 :a (LIT@2:6-2:7 1)) + (UNLESS@1:0-3:4 (VCALL@1:7-1:11 :cond) (LASGN@2:2-2:7 :a (INTEGER@2:6-2:7 1)) (BEGIN@3:4-3:4 nil))) EXP end @@ -976,7 +977,7 @@ dummy args: nil body: (CASE@1:0-2:6 (VCALL@1:5-1:6 :a) - (WHEN@2:0-2:6 (LIST@2:5-2:6 (LIT@2:5-2:6 1) nil) (BEGIN@2:6-2:6 nil) + (WHEN@2:0-2:6 (LIST@2:5-2:6 (INTEGER@2:5-2:6 1) nil) (BEGIN@2:6-2:6 nil) nil))) EXP @@ -993,7 +994,7 @@ dummy (WHEN@2:0-2:11 (LIST@2:5-2:11 (OPCALL@2:5-2:11 (VCALL@2:5-2:6 :a) :== - (LIST@2:10-2:11 (LIT@2:10-2:11 1) nil)) nil) + (LIST@2:10-2:11 (INTEGER@2:10-2:11 1) nil)) nil) (BEGIN@2:11-2:11 nil) nil))) EXP @@ -1094,7 +1095,7 @@ dummy tbl: [] args: nil body: - (ITER@1:0-2:3 (FCALL@1:0-1:3 :m (LIST@1:2-1:3 (LIT@1:2-1:3 1) nil)) + (ITER@1:0-2:3 (FCALL@1:0-1:3 :m (LIST@1:2-1:3 (INTEGER@1:2-1:3 1) nil)) (SCOPE@1:4-2:3 tbl: [] args: nil body: (VCALL@2:2-2:3 :a)))) EXP end diff --git a/test/test_pp.rb b/test/test_pp.rb index bb2299a3fa..f6c2f65df2 100644 --- a/test/test_pp.rb +++ b/test/test_pp.rb @@ -228,7 +228,7 @@ if defined?(RubyVM) AST = RubyVM::AbstractSyntaxTree def test_lasgn_literal ast = AST.parse("_=1") - expected = "(SCOPE@1:0-1:3 tbl: [:_] args: nil body: (LASGN@1:0-1:3 :_ (LIT@1:2-1:3 1)))" + expected = "(SCOPE@1:0-1:3 tbl: [:_] args: nil body: (LASGN@1:0-1:3 :_ (INTEGER@1:2-1:3 1)))" assert_equal(expected, PP.singleline_pp(ast, ''.dup), ast) end end diff --git a/universal_parser.c b/universal_parser.c index 61acaf7e05..c3775d8f4d 100644 --- a/universal_parser.c +++ b/universal_parser.c @@ -226,6 +226,7 @@ struct rb_imemo_tmpbuf_struct { #define rb_big_norm p->config->big_norm #define rb_cstr_to_inum p->config->cstr_to_inum +#undef rb_float_new #define rb_float_new p->config->float_new #undef RFLOAT_VALUE #define RFLOAT_VALUE p->config->float_value