Skip to content

Commit

Permalink
Introduce NODE_LINE
Browse files Browse the repository at this point in the history
`__LINE__` was managed by `NODE_LIT` with `Integer` object.
This commit introduces `NODE_LINE` so that

1. `__LINE__` is detectable from AST Node
2. Reduce dependency ruby object
  • Loading branch information
yui-knk committed Dec 29, 2023
1 parent 6f33e3c commit 1ade170
Show file tree
Hide file tree
Showing 8 changed files with 259 additions and 11 deletions.
2 changes: 2 additions & 0 deletions ast.c
Expand Up @@ -692,6 +692,8 @@ node_children(rb_ast_t *ast, const NODE *node)
NEW_CHILD(ast, RNODE_HSHPTN(node)->nd_pkwargs),
kwrest);
}
case NODE_LINE:
return rb_ary_new_from_args(1, rb_node_line_lineno_val(node));
case NODE_ERROR:
return rb_ary_new_from_node_args(ast, 0);
case NODE_ARGS_AUX:
Expand Down
176 changes: 176 additions & 0 deletions common.mk
Expand Up @@ -3264,6 +3264,7 @@ compile.$(OBJEXT): $(top_srcdir)/internal/numeric.h
compile.$(OBJEXT): $(top_srcdir)/internal/object.h
compile.$(OBJEXT): $(top_srcdir)/internal/rational.h
compile.$(OBJEXT): $(top_srcdir)/internal/re.h
compile.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h
compile.$(OBJEXT): $(top_srcdir)/internal/serial.h
compile.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
compile.$(OBJEXT): $(top_srcdir)/internal/string.h
Expand Down Expand Up @@ -15820,7 +15821,182 @@ ruby.$(OBJEXT): {$(VPATH)}util.h
ruby.$(OBJEXT): {$(VPATH)}vm_core.h
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/imemo.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
ruby_parser.$(OBJEXT): $(top_srcdir)/internal/vm.h
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/inttypes.h
ruby_parser.$(OBJEXT): {$(VPATH)}backward/2/limits.h
ruby_parser.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
ruby_parser.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
ruby_parser.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
ruby_parser.$(OBJEXT): {$(VPATH)}config.h
ruby_parser.$(OBJEXT): {$(VPATH)}defines.h
ruby_parser.$(OBJEXT): {$(VPATH)}encoding.h
ruby_parser.$(OBJEXT): {$(VPATH)}intern.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/abi.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/anyargs.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/assume.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/const.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/error.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/format.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/cast.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/config.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/constant_p.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/core.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/core/robject.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/ctype.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/dllexport.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/dosish.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/error.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/eval.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/event.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/fl_type.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/gc.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/glob.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/globals.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/has/extension.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/has/feature.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/has/warning.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/array.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/class.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/error.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/file.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/io.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/load.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/object.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/process.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/random.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/range.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/re.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/select.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/string.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/time.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/interpreter.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/iterator.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/memory.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/method.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/module.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/newobj.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/scan_args.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/special_consts.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/static_assert.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/stdalign.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/stdbool.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/symbol.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/value.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/value_type.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/variable.h
ruby_parser.$(OBJEXT): {$(VPATH)}internal/warning_push.h
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_parser.c
ruby_parser.$(OBJEXT): {$(VPATH)}rubyparser.h
ruby_parser.$(OBJEXT): {$(VPATH)}st.h
ruby_parser.$(OBJEXT): {$(VPATH)}subst.h
scheduler.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
scheduler.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
scheduler.$(OBJEXT): $(CCAN_DIR)/list/list.h
Expand Down
40 changes: 38 additions & 2 deletions compile.c
Expand Up @@ -30,6 +30,7 @@
#include "internal/object.h"
#include "internal/rational.h"
#include "internal/re.h"
#include "internal/ruby_parser.h"
#include "internal/symbol.h"
#include "internal/thread.h"
#include "internal/variable.h"
Expand Down Expand Up @@ -1929,6 +1930,9 @@ iseq_set_arguments_keywords(rb_iseq_t *iseq, LINK_ANCHOR *const optargs,
case NODE_LIT:
dv = RNODE_LIT(val_node)->nd_lit;
break;
case NODE_LINE:
dv = rb_node_line_lineno_val(val_node);;
break;
case NODE_NIL:
dv = Qnil;
break;
Expand Down Expand Up @@ -4488,6 +4492,7 @@ compile_branch_condition(rb_iseq_t *iseq, LINK_ANCHOR *ret, const NODE *cond,
}
goto again;
case NODE_LIT: /* NODE_LIT is always true */
case NODE_LINE:
case NODE_TRUE:
case NODE_STR:
case NODE_ZLIST:
Expand Down Expand Up @@ -4647,6 +4652,7 @@ static_literal_node_p(const NODE *node, const rb_iseq_t *iseq)
{
switch (nd_type(node)) {
case NODE_LIT:
case NODE_LINE:
case NODE_NIL:
case NODE_TRUE:
case NODE_FALSE:
Expand All @@ -4668,6 +4674,8 @@ static_literal_value(const NODE *node, rb_iseq_t *iseq)
return Qtrue;
case NODE_FALSE:
return Qfalse;
case NODE_LINE:
return rb_node_line_lineno_val(node);
case NODE_STR:
if (ISEQ_COMPILE_DATA(iseq)->option->debug_frozen_string_literal || RTEST(ruby_debug)) {
VALUE lit;
Expand Down Expand Up @@ -5055,6 +5063,8 @@ rb_node_case_when_optimizable_literal(const NODE *const node)
return Qtrue;
case NODE_FALSE:
return Qfalse;
case NODE_LINE:
return rb_node_line_lineno_val(node);
case NODE_STR:
return rb_fstring(RNODE_STR(node)->nd_lit);
}
Expand Down Expand Up @@ -5681,6 +5691,7 @@ defined_expr0(rb_iseq_t *iseq, LINK_ANCHOR *const ret,
/* fall through */
case NODE_STR:
case NODE_LIT:
case NODE_LINE:
case NODE_ZLIST:
case NODE_AND:
case NODE_OR:
Expand Down Expand Up @@ -6255,13 +6266,30 @@ optimizable_range_item_p(const NODE *n)
switch (nd_type(n)) {
case NODE_LIT:
return RB_INTEGER_TYPE_P(RNODE_LIT(n)->nd_lit);
case NODE_LINE:
return TRUE;
case NODE_NIL:
return TRUE;
default:
return FALSE;
}
}

static VALUE
optimized_range_item(const NODE *n)
{
switch (nd_type(n)) {
case NODE_LIT:
return RNODE_LIT(n)->nd_lit;
case NODE_LINE:
return rb_node_line_lineno_val(n);
case NODE_NIL:
return Qnil;
default:
rb_bug("unexpected node: %s", ruby_node_name(nd_type(n)));
}
}

static int
compile_if(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped, const enum node_type type)
{
Expand Down Expand Up @@ -7076,6 +7104,7 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c
break;
}
case NODE_LIT:
case NODE_LINE:
case NODE_STR:
case NODE_XSTR:
case NODE_DSTR:
Expand Down Expand Up @@ -9571,8 +9600,8 @@ compile_dots(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in

if (optimizable_range_item_p(b) && optimizable_range_item_p(e)) {
if (!popped) {
VALUE bv = nd_type_p(b, NODE_LIT) ? RNODE_LIT(b)->nd_lit : Qnil;
VALUE ev = nd_type_p(e, NODE_LIT) ? RNODE_LIT(e)->nd_lit : Qnil;
VALUE bv = optimized_range_item(b);
VALUE ev = optimized_range_item(e);
VALUE val = rb_range_new(bv, ev, excl);
ADD_INSN1(ret, node, putobject, val);
RB_OBJ_WRITTEN(iseq, Qundef, val);
Expand Down Expand Up @@ -9629,6 +9658,7 @@ compile_kw_arg(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node,
return COMPILE_NG;
}
else if (nd_type_p(default_value, NODE_LIT) ||
nd_type_p(default_value, NODE_LINE) ||
nd_type_p(default_value, NODE_NIL) ||
nd_type_p(default_value, NODE_TRUE) ||
nd_type_p(default_value, NODE_FALSE)) {
Expand Down Expand Up @@ -10098,6 +10128,12 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
}
break;
}
case NODE_LINE:{
if (!popped) {
ADD_INSN1(ret, node, putobject, rb_node_line_lineno_val(node));
}
break;
}
case NODE_STR:{
debugp_param("nd_lit", RNODE_STR(node)->nd_lit);
if (!popped) {
Expand Down
2 changes: 2 additions & 0 deletions internal/ruby_parser.h
Expand Up @@ -66,4 +66,6 @@ enum lex_state_e {
EXPR_END_ANY = (EXPR_END | EXPR_ENDARG | EXPR_ENDFN),
EXPR_NONE = 0
};

VALUE rb_node_line_lineno_val(const NODE *);
#endif /* INTERNAL_RUBY_PARSE_H */
7 changes: 7 additions & 0 deletions node_dump.c
Expand Up @@ -1098,6 +1098,13 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
F_NODE(nd_pkwrestarg, RNODE_HSHPTN, "keyword rest argument");
}
return;

case NODE_LINE:
ANN("line");
ANN("format: [lineno]");
ANN("example: __LINE__");
return;

case NODE_ERROR:
ANN("Broken input recovered by Error Tolerant mode");
return;
Expand Down

0 comments on commit 1ade170

Please sign in to comment.