aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/ubuntu.yml2
-rw-r--r--.gitignore2
-rw-r--r--ast.c2
-rw-r--r--common.mk488
-rw-r--r--ext/coverage/depend13
-rw-r--r--ext/objspace/depend20
-rw-r--r--ext/ripper/depend532
-rw-r--r--ext/ripper/eventids2.c12
-rw-r--r--ext/ripper/eventids2.h8
-rw-r--r--ext/ripper/extconf.rb4
-rw-r--r--ext/ripper/ripper_init.c.tmpl650
-rw-r--r--ext/ripper/ripper_init.h8
-rw-r--r--ext/ripper/tools/generate.rb39
-rw-r--r--ext/ripper/tools/preproc.rb33
-rw-r--r--ext/socket/depend15
-rw-r--r--internal/gc.h12
-rw-r--r--internal/parse.h123
-rw-r--r--internal/ruby_parser.h68
-rw-r--r--iseq.c2
-rw-r--r--load.c2
-rw-r--r--node.c1275
-rw-r--r--node.h537
-rw-r--r--node_dump.c1122
-rw-r--r--parse.y1383
-rw-r--r--parser_bits.h564
-rw-r--r--parser_node.h133
-rw-r--r--parser_st.c2118
-rw-r--r--parser_st.h165
-rw-r--r--parser_value.h106
-rw-r--r--ruby.c2
-rw-r--r--ruby_parser.c983
-rw-r--r--rubyparser.h642
-rw-r--r--template/prelude.c.tmpl1
-rwxr-xr-xtool/update-deps1
-rw-r--r--universal_parser.c400
-rw-r--r--vm.c2
36 files changed, 9038 insertions, 2431 deletions
diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml
index f77c2633f9..9e2a441bc8 100644
--- a/.github/workflows/ubuntu.yml
+++ b/.github/workflows/ubuntu.yml
@@ -43,6 +43,8 @@ jobs:
- test_task: check
configure: '--enable-shared --enable-load-relative'
- test_task: test-all TESTS=--repeat-count=2
+ - test_task: test-all TESTS=--repeat-count=2
+ configure: 'cppflags=-DUNIVERSAL_PARSER'
- test_task: test-bundler-parallel
- test_task: test-bundled-gems
fail-fast: false
diff --git a/.gitignore b/.gitignore
index ca1783479d..60e4af0716 100644
--- a/.gitignore
+++ b/.gitignore
@@ -205,8 +205,10 @@ lcov*.info
# /ext/ripper/
/ext/ripper/eventids1.c
+/ext/ripper/eventids1.h
/ext/ripper/.eventids2-check
/ext/ripper/eventids2table.c
+/ext/ripper/ripper_init.c
/ext/ripper/ripper.*
/ext/ripper/ids1
/ext/ripper/ids2
diff --git a/ast.c b/ast.c
index d60e5d3fcf..d3e217dafc 100644
--- a/ast.c
+++ b/ast.c
@@ -1,6 +1,6 @@
/* indent-tabs-mode: nil */
#include "internal.h"
-#include "internal/parse.h"
+#include "internal/ruby_parser.h"
#include "internal/symbol.h"
#include "internal/warnings.h"
#include "iseq.h"
diff --git a/common.mk b/common.mk
index fc9612defe..8c96489237 100644
--- a/common.mk
+++ b/common.mk
@@ -113,10 +113,12 @@ COMMONOBJS = array.$(OBJEXT) \
rjit.$(OBJEXT) \
rjit_c.$(OBJEXT) \
node.$(OBJEXT) \
+ node_dump.$(OBJEXT) \
numeric.$(OBJEXT) \
object.$(OBJEXT) \
pack.$(OBJEXT) \
parse.$(OBJEXT) \
+ parser_st.$(OBJEXT) \
proc.$(OBJEXT) \
process.$(OBJEXT) \
ractor.$(OBJEXT) \
@@ -131,6 +133,7 @@ COMMONOBJS = array.$(OBJEXT) \
regparse.$(OBJEXT) \
regsyntax.$(OBJEXT) \
ruby.$(OBJEXT) \
+ ruby_parser.$(OBJEXT) \
scheduler.$(OBJEXT) \
shape.$(OBJEXT) \
signal.$(OBJEXT) \
@@ -1129,9 +1132,9 @@ id.c: $(tooldir)/generic_erb.rb $(srcdir)/template/id.c.tmpl $(srcdir)/defs/id.d
$(Q) $(BASERUBY) $(tooldir)/generic_erb.rb --output=$@ \
$(srcdir)/template/id.c.tmpl
-node_name.inc: $(tooldir)/node_name.rb $(srcdir)/node.h
+node_name.inc: $(tooldir)/node_name.rb $(srcdir)/rubyparser.h
$(ECHO) generating $@
- $(Q) $(BASERUBY) -n $(tooldir)/node_name.rb < $(srcdir)/node.h > $@
+ $(Q) $(BASERUBY) -n $(tooldir)/node_name.rb < $(srcdir)/rubyparser.h > $@
encdb.h: $(RBCONFIG) $(tooldir)/generic_erb.rb $(srcdir)/template/encdb.h.tmpl
$(ECHO) generating $@
@@ -2036,6 +2039,7 @@ array.$(OBJEXT): {$(VPATH)}probes.dmyh
array.$(OBJEXT): {$(VPATH)}probes.h
array.$(OBJEXT): {$(VPATH)}ruby_assert.h
array.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+array.$(OBJEXT): {$(VPATH)}rubyparser.h
array.$(OBJEXT): {$(VPATH)}shape.h
array.$(OBJEXT): {$(VPATH)}st.h
array.$(OBJEXT): {$(VPATH)}subst.h
@@ -2057,6 +2061,7 @@ ast.$(OBJEXT): $(top_srcdir)/internal/compilers.h
ast.$(OBJEXT): $(top_srcdir)/internal/gc.h
ast.$(OBJEXT): $(top_srcdir)/internal/imemo.h
ast.$(OBJEXT): $(top_srcdir)/internal/parse.h
+ast.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h
ast.$(OBJEXT): $(top_srcdir)/internal/serial.h
ast.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
ast.$(OBJEXT): $(top_srcdir)/internal/symbol.h
@@ -2241,6 +2246,7 @@ ast.$(OBJEXT): {$(VPATH)}onigmo.h
ast.$(OBJEXT): {$(VPATH)}oniguruma.h
ast.$(OBJEXT): {$(VPATH)}ruby_assert.h
ast.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+ast.$(OBJEXT): {$(VPATH)}rubyparser.h
ast.$(OBJEXT): {$(VPATH)}shape.h
ast.$(OBJEXT): {$(VPATH)}st.h
ast.$(OBJEXT): {$(VPATH)}subst.h
@@ -2287,6 +2293,7 @@ bignum.$(OBJEXT): {$(VPATH)}bignum.c
bignum.$(OBJEXT): {$(VPATH)}config.h
bignum.$(OBJEXT): {$(VPATH)}constant.h
bignum.$(OBJEXT): {$(VPATH)}defines.h
+bignum.$(OBJEXT): {$(VPATH)}encoding.h
bignum.$(OBJEXT): {$(VPATH)}id.h
bignum.$(OBJEXT): {$(VPATH)}id_table.h
bignum.$(OBJEXT): {$(VPATH)}intern.h
@@ -2362,6 +2369,15 @@ bignum.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
bignum.$(OBJEXT): {$(VPATH)}internal/ctype.h
bignum.$(OBJEXT): {$(VPATH)}internal/dllexport.h
bignum.$(OBJEXT): {$(VPATH)}internal/dosish.h
+bignum.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+bignum.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+bignum.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+bignum.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+bignum.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+bignum.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+bignum.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+bignum.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+bignum.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
bignum.$(OBJEXT): {$(VPATH)}internal/error.h
bignum.$(OBJEXT): {$(VPATH)}internal/eval.h
bignum.$(OBJEXT): {$(VPATH)}internal/event.h
@@ -2433,8 +2449,11 @@ bignum.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
bignum.$(OBJEXT): {$(VPATH)}method.h
bignum.$(OBJEXT): {$(VPATH)}missing.h
bignum.$(OBJEXT): {$(VPATH)}node.h
+bignum.$(OBJEXT): {$(VPATH)}onigmo.h
+bignum.$(OBJEXT): {$(VPATH)}oniguruma.h
bignum.$(OBJEXT): {$(VPATH)}ruby_assert.h
bignum.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+bignum.$(OBJEXT): {$(VPATH)}rubyparser.h
bignum.$(OBJEXT): {$(VPATH)}shape.h
bignum.$(OBJEXT): {$(VPATH)}st.h
bignum.$(OBJEXT): {$(VPATH)}subst.h
@@ -2476,6 +2495,7 @@ builtin.$(OBJEXT): {$(VPATH)}builtin_binary.inc
builtin.$(OBJEXT): {$(VPATH)}config.h
builtin.$(OBJEXT): {$(VPATH)}constant.h
builtin.$(OBJEXT): {$(VPATH)}defines.h
+builtin.$(OBJEXT): {$(VPATH)}encoding.h
builtin.$(OBJEXT): {$(VPATH)}id.h
builtin.$(OBJEXT): {$(VPATH)}id_table.h
builtin.$(OBJEXT): {$(VPATH)}intern.h
@@ -2551,6 +2571,15 @@ builtin.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
builtin.$(OBJEXT): {$(VPATH)}internal/ctype.h
builtin.$(OBJEXT): {$(VPATH)}internal/dllexport.h
builtin.$(OBJEXT): {$(VPATH)}internal/dosish.h
+builtin.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+builtin.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+builtin.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+builtin.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+builtin.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+builtin.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+builtin.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+builtin.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+builtin.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
builtin.$(OBJEXT): {$(VPATH)}internal/error.h
builtin.$(OBJEXT): {$(VPATH)}internal/eval.h
builtin.$(OBJEXT): {$(VPATH)}internal/event.h
@@ -2623,8 +2652,11 @@ builtin.$(OBJEXT): {$(VPATH)}iseq.h
builtin.$(OBJEXT): {$(VPATH)}method.h
builtin.$(OBJEXT): {$(VPATH)}missing.h
builtin.$(OBJEXT): {$(VPATH)}node.h
+builtin.$(OBJEXT): {$(VPATH)}onigmo.h
+builtin.$(OBJEXT): {$(VPATH)}oniguruma.h
builtin.$(OBJEXT): {$(VPATH)}ruby_assert.h
builtin.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+builtin.$(OBJEXT): {$(VPATH)}rubyparser.h
builtin.$(OBJEXT): {$(VPATH)}shape.h
builtin.$(OBJEXT): {$(VPATH)}st.h
builtin.$(OBJEXT): {$(VPATH)}subst.h
@@ -2828,6 +2860,7 @@ class.$(OBJEXT): {$(VPATH)}onigmo.h
class.$(OBJEXT): {$(VPATH)}oniguruma.h
class.$(OBJEXT): {$(VPATH)}ruby_assert.h
class.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+class.$(OBJEXT): {$(VPATH)}rubyparser.h
class.$(OBJEXT): {$(VPATH)}shape.h
class.$(OBJEXT): {$(VPATH)}st.h
class.$(OBJEXT): {$(VPATH)}subst.h
@@ -3231,6 +3264,7 @@ compile.$(OBJEXT): {$(VPATH)}re.h
compile.$(OBJEXT): {$(VPATH)}regex.h
compile.$(OBJEXT): {$(VPATH)}ruby_assert.h
compile.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+compile.$(OBJEXT): {$(VPATH)}rubyparser.h
compile.$(OBJEXT): {$(VPATH)}shape.h
compile.$(OBJEXT): {$(VPATH)}st.h
compile.$(OBJEXT): {$(VPATH)}subst.h
@@ -3280,6 +3314,7 @@ complex.$(OBJEXT): {$(VPATH)}complex.c
complex.$(OBJEXT): {$(VPATH)}config.h
complex.$(OBJEXT): {$(VPATH)}constant.h
complex.$(OBJEXT): {$(VPATH)}defines.h
+complex.$(OBJEXT): {$(VPATH)}encoding.h
complex.$(OBJEXT): {$(VPATH)}id.h
complex.$(OBJEXT): {$(VPATH)}id_table.h
complex.$(OBJEXT): {$(VPATH)}intern.h
@@ -3355,6 +3390,15 @@ complex.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
complex.$(OBJEXT): {$(VPATH)}internal/ctype.h
complex.$(OBJEXT): {$(VPATH)}internal/dllexport.h
complex.$(OBJEXT): {$(VPATH)}internal/dosish.h
+complex.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+complex.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+complex.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+complex.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+complex.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+complex.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+complex.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+complex.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+complex.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
complex.$(OBJEXT): {$(VPATH)}internal/error.h
complex.$(OBJEXT): {$(VPATH)}internal/eval.h
complex.$(OBJEXT): {$(VPATH)}internal/event.h
@@ -3426,8 +3470,11 @@ complex.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
complex.$(OBJEXT): {$(VPATH)}method.h
complex.$(OBJEXT): {$(VPATH)}missing.h
complex.$(OBJEXT): {$(VPATH)}node.h
+complex.$(OBJEXT): {$(VPATH)}onigmo.h
+complex.$(OBJEXT): {$(VPATH)}oniguruma.h
complex.$(OBJEXT): {$(VPATH)}ruby_assert.h
complex.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+complex.$(OBJEXT): {$(VPATH)}rubyparser.h
complex.$(OBJEXT): {$(VPATH)}shape.h
complex.$(OBJEXT): {$(VPATH)}st.h
complex.$(OBJEXT): {$(VPATH)}subst.h
@@ -3640,6 +3687,7 @@ cont.$(OBJEXT): {$(VPATH)}ractor_core.h
cont.$(OBJEXT): {$(VPATH)}rjit.h
cont.$(OBJEXT): {$(VPATH)}ruby_assert.h
cont.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+cont.$(OBJEXT): {$(VPATH)}rubyparser.h
cont.$(OBJEXT): {$(VPATH)}shape.h
cont.$(OBJEXT): {$(VPATH)}st.h
cont.$(OBJEXT): {$(VPATH)}subst.h
@@ -3848,6 +3896,7 @@ debug.$(OBJEXT): {$(VPATH)}ractor.h
debug.$(OBJEXT): {$(VPATH)}ractor_core.h
debug.$(OBJEXT): {$(VPATH)}ruby_assert.h
debug.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+debug.$(OBJEXT): {$(VPATH)}rubyparser.h
debug.$(OBJEXT): {$(VPATH)}shape.h
debug.$(OBJEXT): {$(VPATH)}st.h
debug.$(OBJEXT): {$(VPATH)}subst.h
@@ -4220,6 +4269,7 @@ dir.$(OBJEXT): {$(VPATH)}onigmo.h
dir.$(OBJEXT): {$(VPATH)}oniguruma.h
dir.$(OBJEXT): {$(VPATH)}ruby_assert.h
dir.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+dir.$(OBJEXT): {$(VPATH)}rubyparser.h
dir.$(OBJEXT): {$(VPATH)}shape.h
dir.$(OBJEXT): {$(VPATH)}st.h
dir.$(OBJEXT): {$(VPATH)}subst.h
@@ -6120,6 +6170,7 @@ enumerator.$(OBJEXT): {$(VPATH)}onigmo.h
enumerator.$(OBJEXT): {$(VPATH)}oniguruma.h
enumerator.$(OBJEXT): {$(VPATH)}ruby_assert.h
enumerator.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+enumerator.$(OBJEXT): {$(VPATH)}rubyparser.h
enumerator.$(OBJEXT): {$(VPATH)}shape.h
enumerator.$(OBJEXT): {$(VPATH)}st.h
enumerator.$(OBJEXT): {$(VPATH)}subst.h
@@ -6330,6 +6381,7 @@ error.$(OBJEXT): {$(VPATH)}onigmo.h
error.$(OBJEXT): {$(VPATH)}oniguruma.h
error.$(OBJEXT): {$(VPATH)}ruby_assert.h
error.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+error.$(OBJEXT): {$(VPATH)}rubyparser.h
error.$(OBJEXT): {$(VPATH)}shape.h
error.$(OBJEXT): {$(VPATH)}st.h
error.$(OBJEXT): {$(VPATH)}subst.h
@@ -6552,6 +6604,7 @@ eval.$(OBJEXT): {$(VPATH)}ractor_core.h
eval.$(OBJEXT): {$(VPATH)}rjit.h
eval.$(OBJEXT): {$(VPATH)}ruby_assert.h
eval.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+eval.$(OBJEXT): {$(VPATH)}rubyparser.h
eval.$(OBJEXT): {$(VPATH)}shape.h
eval.$(OBJEXT): {$(VPATH)}st.h
eval.$(OBJEXT): {$(VPATH)}subst.h
@@ -7007,6 +7060,7 @@ gc.$(OBJEXT): {$(VPATH)}regint.h
gc.$(OBJEXT): {$(VPATH)}rjit.h
gc.$(OBJEXT): {$(VPATH)}ruby_assert.h
gc.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+gc.$(OBJEXT): {$(VPATH)}rubyparser.h
gc.$(OBJEXT): {$(VPATH)}shape.h
gc.$(OBJEXT): {$(VPATH)}st.h
gc.$(OBJEXT): {$(VPATH)}subst.h
@@ -7032,6 +7086,7 @@ goruby.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
goruby.$(OBJEXT): $(top_srcdir)/internal/compilers.h
goruby.$(OBJEXT): $(top_srcdir)/internal/gc.h
goruby.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+goruby.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h
goruby.$(OBJEXT): $(top_srcdir)/internal/serial.h
goruby.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
goruby.$(OBJEXT): $(top_srcdir)/internal/variable.h
@@ -7052,6 +7107,7 @@ goruby.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
goruby.$(OBJEXT): {$(VPATH)}config.h
goruby.$(OBJEXT): {$(VPATH)}constant.h
goruby.$(OBJEXT): {$(VPATH)}defines.h
+goruby.$(OBJEXT): {$(VPATH)}encoding.h
goruby.$(OBJEXT): {$(VPATH)}golf_prelude.c
goruby.$(OBJEXT): {$(VPATH)}goruby.c
goruby.$(OBJEXT): {$(VPATH)}id.h
@@ -7129,6 +7185,15 @@ goruby.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
goruby.$(OBJEXT): {$(VPATH)}internal/ctype.h
goruby.$(OBJEXT): {$(VPATH)}internal/dllexport.h
goruby.$(OBJEXT): {$(VPATH)}internal/dosish.h
+goruby.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+goruby.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+goruby.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+goruby.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+goruby.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+goruby.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+goruby.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+goruby.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+goruby.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
goruby.$(OBJEXT): {$(VPATH)}internal/error.h
goruby.$(OBJEXT): {$(VPATH)}internal/eval.h
goruby.$(OBJEXT): {$(VPATH)}internal/event.h
@@ -7202,8 +7267,11 @@ goruby.$(OBJEXT): {$(VPATH)}main.c
goruby.$(OBJEXT): {$(VPATH)}method.h
goruby.$(OBJEXT): {$(VPATH)}missing.h
goruby.$(OBJEXT): {$(VPATH)}node.h
+goruby.$(OBJEXT): {$(VPATH)}onigmo.h
+goruby.$(OBJEXT): {$(VPATH)}oniguruma.h
goruby.$(OBJEXT): {$(VPATH)}ruby_assert.h
goruby.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+goruby.$(OBJEXT): {$(VPATH)}rubyparser.h
goruby.$(OBJEXT): {$(VPATH)}shape.h
goruby.$(OBJEXT): {$(VPATH)}st.h
goruby.$(OBJEXT): {$(VPATH)}subst.h
@@ -7419,6 +7487,7 @@ hash.$(OBJEXT): {$(VPATH)}probes.h
hash.$(OBJEXT): {$(VPATH)}ractor.h
hash.$(OBJEXT): {$(VPATH)}ruby_assert.h
hash.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+hash.$(OBJEXT): {$(VPATH)}rubyparser.h
hash.$(OBJEXT): {$(VPATH)}shape.h
hash.$(OBJEXT): {$(VPATH)}st.h
hash.$(OBJEXT): {$(VPATH)}subst.h
@@ -7806,6 +7875,7 @@ io.$(OBJEXT): {$(VPATH)}oniguruma.h
io.$(OBJEXT): {$(VPATH)}ractor.h
io.$(OBJEXT): {$(VPATH)}ruby_assert.h
io.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+io.$(OBJEXT): {$(VPATH)}rubyparser.h
io.$(OBJEXT): {$(VPATH)}shape.h
io.$(OBJEXT): {$(VPATH)}st.h
io.$(OBJEXT): {$(VPATH)}subst.h
@@ -8023,6 +8093,7 @@ 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/parse.h
+iseq.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h
iseq.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
iseq.$(OBJEXT): $(top_srcdir)/internal/serial.h
iseq.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
@@ -8216,6 +8287,7 @@ iseq.$(OBJEXT): {$(VPATH)}ractor.h
iseq.$(OBJEXT): {$(VPATH)}rjit.h
iseq.$(OBJEXT): {$(VPATH)}ruby_assert.h
iseq.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+iseq.$(OBJEXT): {$(VPATH)}rubyparser.h
iseq.$(OBJEXT): {$(VPATH)}shape.h
iseq.$(OBJEXT): {$(VPATH)}st.h
iseq.$(OBJEXT): {$(VPATH)}subst.h
@@ -8241,6 +8313,7 @@ load.$(OBJEXT): $(top_srcdir)/internal/gc.h
load.$(OBJEXT): $(top_srcdir)/internal/imemo.h
load.$(OBJEXT): $(top_srcdir)/internal/load.h
load.$(OBJEXT): $(top_srcdir)/internal/parse.h
+load.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h
load.$(OBJEXT): $(top_srcdir)/internal/serial.h
load.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
load.$(OBJEXT): $(top_srcdir)/internal/string.h
@@ -8429,6 +8502,7 @@ load.$(OBJEXT): {$(VPATH)}probes.dmyh
load.$(OBJEXT): {$(VPATH)}probes.h
load.$(OBJEXT): {$(VPATH)}ruby_assert.h
load.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+load.$(OBJEXT): {$(VPATH)}rubyparser.h
load.$(OBJEXT): {$(VPATH)}shape.h
load.$(OBJEXT): {$(VPATH)}st.h
load.$(OBJEXT): {$(VPATH)}subst.h
@@ -9132,6 +9206,7 @@ marshal.$(OBJEXT): {$(VPATH)}onigmo.h
marshal.$(OBJEXT): {$(VPATH)}oniguruma.h
marshal.$(OBJEXT): {$(VPATH)}ruby_assert.h
marshal.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+marshal.$(OBJEXT): {$(VPATH)}rubyparser.h
marshal.$(OBJEXT): {$(VPATH)}shape.h
marshal.$(OBJEXT): {$(VPATH)}st.h
marshal.$(OBJEXT): {$(VPATH)}subst.h
@@ -9344,6 +9419,7 @@ memory_view.$(OBJEXT): {$(VPATH)}config.h
memory_view.$(OBJEXT): {$(VPATH)}constant.h
memory_view.$(OBJEXT): {$(VPATH)}debug_counter.h
memory_view.$(OBJEXT): {$(VPATH)}defines.h
+memory_view.$(OBJEXT): {$(VPATH)}encoding.h
memory_view.$(OBJEXT): {$(VPATH)}id.h
memory_view.$(OBJEXT): {$(VPATH)}id_table.h
memory_view.$(OBJEXT): {$(VPATH)}intern.h
@@ -9419,6 +9495,15 @@ memory_view.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
memory_view.$(OBJEXT): {$(VPATH)}internal/ctype.h
memory_view.$(OBJEXT): {$(VPATH)}internal/dllexport.h
memory_view.$(OBJEXT): {$(VPATH)}internal/dosish.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
memory_view.$(OBJEXT): {$(VPATH)}internal/error.h
memory_view.$(OBJEXT): {$(VPATH)}internal/eval.h
memory_view.$(OBJEXT): {$(VPATH)}internal/event.h
@@ -9492,8 +9577,11 @@ memory_view.$(OBJEXT): {$(VPATH)}memory_view.h
memory_view.$(OBJEXT): {$(VPATH)}method.h
memory_view.$(OBJEXT): {$(VPATH)}missing.h
memory_view.$(OBJEXT): {$(VPATH)}node.h
+memory_view.$(OBJEXT): {$(VPATH)}onigmo.h
+memory_view.$(OBJEXT): {$(VPATH)}oniguruma.h
memory_view.$(OBJEXT): {$(VPATH)}ruby_assert.h
memory_view.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+memory_view.$(OBJEXT): {$(VPATH)}rubyparser.h
memory_view.$(OBJEXT): {$(VPATH)}shape.h
memory_view.$(OBJEXT): {$(VPATH)}st.h
memory_view.$(OBJEXT): {$(VPATH)}subst.h
@@ -9515,6 +9603,7 @@ miniinit.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
miniinit.$(OBJEXT): $(top_srcdir)/internal/compilers.h
miniinit.$(OBJEXT): $(top_srcdir)/internal/gc.h
miniinit.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+miniinit.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h
miniinit.$(OBJEXT): $(top_srcdir)/internal/serial.h
miniinit.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
miniinit.$(OBJEXT): $(top_srcdir)/internal/variable.h
@@ -9714,6 +9803,7 @@ miniinit.$(OBJEXT): {$(VPATH)}rjit.rb
miniinit.$(OBJEXT): {$(VPATH)}rjit_c.rb
miniinit.$(OBJEXT): {$(VPATH)}ruby_assert.h
miniinit.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+miniinit.$(OBJEXT): {$(VPATH)}rubyparser.h
miniinit.$(OBJEXT): {$(VPATH)}shape.h
miniinit.$(OBJEXT): {$(VPATH)}st.h
miniinit.$(OBJEXT): {$(VPATH)}subst.h
@@ -9757,6 +9847,7 @@ node.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
node.$(OBJEXT): {$(VPATH)}config.h
node.$(OBJEXT): {$(VPATH)}constant.h
node.$(OBJEXT): {$(VPATH)}defines.h
+node.$(OBJEXT): {$(VPATH)}encoding.h
node.$(OBJEXT): {$(VPATH)}id.h
node.$(OBJEXT): {$(VPATH)}id_table.h
node.$(OBJEXT): {$(VPATH)}intern.h
@@ -9832,6 +9923,15 @@ node.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
node.$(OBJEXT): {$(VPATH)}internal/ctype.h
node.$(OBJEXT): {$(VPATH)}internal/dllexport.h
node.$(OBJEXT): {$(VPATH)}internal/dosish.h
+node.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+node.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+node.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+node.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+node.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+node.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+node.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+node.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+node.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
node.$(OBJEXT): {$(VPATH)}internal/error.h
node.$(OBJEXT): {$(VPATH)}internal/eval.h
node.$(OBJEXT): {$(VPATH)}internal/event.h
@@ -9905,8 +10005,11 @@ node.$(OBJEXT): {$(VPATH)}missing.h
node.$(OBJEXT): {$(VPATH)}node.c
node.$(OBJEXT): {$(VPATH)}node.h
node.$(OBJEXT): {$(VPATH)}node_name.inc
+node.$(OBJEXT): {$(VPATH)}onigmo.h
+node.$(OBJEXT): {$(VPATH)}oniguruma.h
node.$(OBJEXT): {$(VPATH)}ruby_assert.h
node.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+node.$(OBJEXT): {$(VPATH)}rubyparser.h
node.$(OBJEXT): {$(VPATH)}shape.h
node.$(OBJEXT): {$(VPATH)}st.h
node.$(OBJEXT): {$(VPATH)}subst.h
@@ -9914,6 +10017,205 @@ node.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
node.$(OBJEXT): {$(VPATH)}thread_native.h
node.$(OBJEXT): {$(VPATH)}vm_core.h
node.$(OBJEXT): {$(VPATH)}vm_opts.h
+node_dump.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
+node_dump.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
+node_dump.$(OBJEXT): $(CCAN_DIR)/list/list.h
+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/compilers.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/serial.h
+node_dump.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+node_dump.$(OBJEXT): $(top_srcdir)/internal/variable.h
+node_dump.$(OBJEXT): $(top_srcdir)/internal/vm.h
+node_dump.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+node_dump.$(OBJEXT): {$(VPATH)}assert.h
+node_dump.$(OBJEXT): {$(VPATH)}atomic.h
+node_dump.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+node_dump.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+node_dump.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+node_dump.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+node_dump.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+node_dump.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+node_dump.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+node_dump.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+node_dump.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
+node_dump.$(OBJEXT): {$(VPATH)}config.h
+node_dump.$(OBJEXT): {$(VPATH)}constant.h
+node_dump.$(OBJEXT): {$(VPATH)}defines.h
+node_dump.$(OBJEXT): {$(VPATH)}encoding.h
+node_dump.$(OBJEXT): {$(VPATH)}id.h
+node_dump.$(OBJEXT): {$(VPATH)}id_table.h
+node_dump.$(OBJEXT): {$(VPATH)}intern.h
+node_dump.$(OBJEXT): {$(VPATH)}internal.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/abi.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/assume.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/cast.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/config.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/core.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/ctype.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/dosish.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/error.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/eval.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/event.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/gc.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/glob.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/globals.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/iterator.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/memory.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/method.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/module.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/newobj.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/symbol.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/value.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/value_type.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/variable.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
+node_dump.$(OBJEXT): {$(VPATH)}method.h
+node_dump.$(OBJEXT): {$(VPATH)}missing.h
+node_dump.$(OBJEXT): {$(VPATH)}node.h
+node_dump.$(OBJEXT): {$(VPATH)}node_dump.c
+node_dump.$(OBJEXT): {$(VPATH)}onigmo.h
+node_dump.$(OBJEXT): {$(VPATH)}oniguruma.h
+node_dump.$(OBJEXT): {$(VPATH)}ruby_assert.h
+node_dump.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+node_dump.$(OBJEXT): {$(VPATH)}rubyparser.h
+node_dump.$(OBJEXT): {$(VPATH)}shape.h
+node_dump.$(OBJEXT): {$(VPATH)}st.h
+node_dump.$(OBJEXT): {$(VPATH)}subst.h
+node_dump.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+node_dump.$(OBJEXT): {$(VPATH)}thread_native.h
+node_dump.$(OBJEXT): {$(VPATH)}vm_core.h
+node_dump.$(OBJEXT): {$(VPATH)}vm_opts.h
numeric.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
numeric.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
numeric.$(OBJEXT): $(CCAN_DIR)/list/list.h
@@ -10118,6 +10420,7 @@ numeric.$(OBJEXT): {$(VPATH)}onigmo.h
numeric.$(OBJEXT): {$(VPATH)}oniguruma.h
numeric.$(OBJEXT): {$(VPATH)}ruby_assert.h
numeric.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+numeric.$(OBJEXT): {$(VPATH)}rubyparser.h
numeric.$(OBJEXT): {$(VPATH)}shape.h
numeric.$(OBJEXT): {$(VPATH)}st.h
numeric.$(OBJEXT): {$(VPATH)}subst.h
@@ -10333,6 +10636,7 @@ object.$(OBJEXT): {$(VPATH)}probes.dmyh
object.$(OBJEXT): {$(VPATH)}probes.h
object.$(OBJEXT): {$(VPATH)}ruby_assert.h
object.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+object.$(OBJEXT): {$(VPATH)}rubyparser.h
object.$(OBJEXT): {$(VPATH)}shape.h
object.$(OBJEXT): {$(VPATH)}st.h
object.$(OBJEXT): {$(VPATH)}subst.h
@@ -10537,6 +10841,7 @@ pack.$(OBJEXT): {$(VPATH)}pack.c
pack.$(OBJEXT): {$(VPATH)}pack.rbinc
pack.$(OBJEXT): {$(VPATH)}ruby_assert.h
pack.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+pack.$(OBJEXT): {$(VPATH)}rubyparser.h
pack.$(OBJEXT): {$(VPATH)}shape.h
pack.$(OBJEXT): {$(VPATH)}st.h
pack.$(OBJEXT): {$(VPATH)}subst.h
@@ -10569,6 +10874,7 @@ parse.$(OBJEXT): $(top_srcdir)/internal/numeric.h
parse.$(OBJEXT): $(top_srcdir)/internal/parse.h
parse.$(OBJEXT): $(top_srcdir)/internal/rational.h
parse.$(OBJEXT): $(top_srcdir)/internal/re.h
+parse.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h
parse.$(OBJEXT): $(top_srcdir)/internal/serial.h
parse.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
parse.$(OBJEXT): $(top_srcdir)/internal/string.h
@@ -10755,6 +11061,7 @@ parse.$(OBJEXT): {$(VPATH)}oniguruma.h
parse.$(OBJEXT): {$(VPATH)}parse.c
parse.$(OBJEXT): {$(VPATH)}parse.h
parse.$(OBJEXT): {$(VPATH)}parse.y
+parse.$(OBJEXT): {$(VPATH)}parser_node.h
parse.$(OBJEXT): {$(VPATH)}probes.dmyh
parse.$(OBJEXT): {$(VPATH)}probes.h
parse.$(OBJEXT): {$(VPATH)}ractor.h
@@ -10762,6 +11069,7 @@ parse.$(OBJEXT): {$(VPATH)}regenc.h
parse.$(OBJEXT): {$(VPATH)}regex.h
parse.$(OBJEXT): {$(VPATH)}ruby_assert.h
parse.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+parse.$(OBJEXT): {$(VPATH)}rubyparser.h
parse.$(OBJEXT): {$(VPATH)}shape.h
parse.$(OBJEXT): {$(VPATH)}st.h
parse.$(OBJEXT): {$(VPATH)}subst.h
@@ -10771,6 +11079,68 @@ parse.$(OBJEXT): {$(VPATH)}thread_native.h
parse.$(OBJEXT): {$(VPATH)}util.h
parse.$(OBJEXT): {$(VPATH)}vm_core.h
parse.$(OBJEXT): {$(VPATH)}vm_opts.h
+parser_st.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+parser_st.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+parser_st.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+parser_st.$(OBJEXT): {$(VPATH)}assert.h
+parser_st.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+parser_st.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+parser_st.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+parser_st.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+parser_st.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+parser_st.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+parser_st.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
+parser_st.$(OBJEXT): {$(VPATH)}config.h
+parser_st.$(OBJEXT): {$(VPATH)}defines.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/assume.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/cast.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/config.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/dosish.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
+parser_st.$(OBJEXT): {$(VPATH)}missing.h
+parser_st.$(OBJEXT): {$(VPATH)}parser_bits.h
+parser_st.$(OBJEXT): {$(VPATH)}parser_st.c
+parser_st.$(OBJEXT): {$(VPATH)}parser_st.h
+parser_st.$(OBJEXT): {$(VPATH)}parser_value.h
proc.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
proc.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
proc.$(OBJEXT): $(CCAN_DIR)/list/list.h
@@ -10970,6 +11340,7 @@ proc.$(OBJEXT): {$(VPATH)}oniguruma.h
proc.$(OBJEXT): {$(VPATH)}proc.c
proc.$(OBJEXT): {$(VPATH)}ruby_assert.h
proc.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+proc.$(OBJEXT): {$(VPATH)}rubyparser.h
proc.$(OBJEXT): {$(VPATH)}shape.h
proc.$(OBJEXT): {$(VPATH)}st.h
proc.$(OBJEXT): {$(VPATH)}subst.h
@@ -11191,6 +11562,7 @@ process.$(OBJEXT): {$(VPATH)}ractor.h
process.$(OBJEXT): {$(VPATH)}rjit.h
process.$(OBJEXT): {$(VPATH)}ruby_assert.h
process.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+process.$(OBJEXT): {$(VPATH)}rubyparser.h
process.$(OBJEXT): {$(VPATH)}shape.h
process.$(OBJEXT): {$(VPATH)}st.h
process.$(OBJEXT): {$(VPATH)}subst.h
@@ -11409,6 +11781,7 @@ ractor.$(OBJEXT): {$(VPATH)}ractor_core.h
ractor.$(OBJEXT): {$(VPATH)}rjit.h
ractor.$(OBJEXT): {$(VPATH)}ruby_assert.h
ractor.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+ractor.$(OBJEXT): {$(VPATH)}rubyparser.h
ractor.$(OBJEXT): {$(VPATH)}shape.h
ractor.$(OBJEXT): {$(VPATH)}st.h
ractor.$(OBJEXT): {$(VPATH)}subst.h
@@ -11457,6 +11830,7 @@ random.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
random.$(OBJEXT): {$(VPATH)}config.h
random.$(OBJEXT): {$(VPATH)}constant.h
random.$(OBJEXT): {$(VPATH)}defines.h
+random.$(OBJEXT): {$(VPATH)}encoding.h
random.$(OBJEXT): {$(VPATH)}id.h
random.$(OBJEXT): {$(VPATH)}id_table.h
random.$(OBJEXT): {$(VPATH)}intern.h
@@ -11532,6 +11906,15 @@ random.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
random.$(OBJEXT): {$(VPATH)}internal/ctype.h
random.$(OBJEXT): {$(VPATH)}internal/dllexport.h
random.$(OBJEXT): {$(VPATH)}internal/dosish.h
+random.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+random.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+random.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+random.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+random.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+random.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+random.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+random.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+random.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
random.$(OBJEXT): {$(VPATH)}internal/error.h
random.$(OBJEXT): {$(VPATH)}internal/eval.h
random.$(OBJEXT): {$(VPATH)}internal/event.h
@@ -11604,11 +11987,14 @@ random.$(OBJEXT): {$(VPATH)}method.h
random.$(OBJEXT): {$(VPATH)}missing.h
random.$(OBJEXT): {$(VPATH)}mt19937.c
random.$(OBJEXT): {$(VPATH)}node.h
+random.$(OBJEXT): {$(VPATH)}onigmo.h
+random.$(OBJEXT): {$(VPATH)}oniguruma.h
random.$(OBJEXT): {$(VPATH)}ractor.h
random.$(OBJEXT): {$(VPATH)}random.c
random.$(OBJEXT): {$(VPATH)}random.h
random.$(OBJEXT): {$(VPATH)}ruby_assert.h
random.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+random.$(OBJEXT): {$(VPATH)}rubyparser.h
random.$(OBJEXT): {$(VPATH)}shape.h
random.$(OBJEXT): {$(VPATH)}siphash.c
random.$(OBJEXT): {$(VPATH)}siphash.h
@@ -11846,6 +12232,7 @@ rational.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
rational.$(OBJEXT): {$(VPATH)}config.h
rational.$(OBJEXT): {$(VPATH)}constant.h
rational.$(OBJEXT): {$(VPATH)}defines.h
+rational.$(OBJEXT): {$(VPATH)}encoding.h
rational.$(OBJEXT): {$(VPATH)}id.h
rational.$(OBJEXT): {$(VPATH)}id_table.h
rational.$(OBJEXT): {$(VPATH)}intern.h
@@ -11921,6 +12308,15 @@ rational.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
rational.$(OBJEXT): {$(VPATH)}internal/ctype.h
rational.$(OBJEXT): {$(VPATH)}internal/dllexport.h
rational.$(OBJEXT): {$(VPATH)}internal/dosish.h
+rational.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+rational.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+rational.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+rational.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+rational.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+rational.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+rational.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+rational.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+rational.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
rational.$(OBJEXT): {$(VPATH)}internal/error.h
rational.$(OBJEXT): {$(VPATH)}internal/eval.h
rational.$(OBJEXT): {$(VPATH)}internal/event.h
@@ -11992,9 +12388,12 @@ rational.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
rational.$(OBJEXT): {$(VPATH)}method.h
rational.$(OBJEXT): {$(VPATH)}missing.h
rational.$(OBJEXT): {$(VPATH)}node.h
+rational.$(OBJEXT): {$(VPATH)}onigmo.h
+rational.$(OBJEXT): {$(VPATH)}oniguruma.h
rational.$(OBJEXT): {$(VPATH)}rational.c
rational.$(OBJEXT): {$(VPATH)}ruby_assert.h
rational.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+rational.$(OBJEXT): {$(VPATH)}rubyparser.h
rational.$(OBJEXT): {$(VPATH)}shape.h
rational.$(OBJEXT): {$(VPATH)}st.h
rational.$(OBJEXT): {$(VPATH)}subst.h
@@ -12209,6 +12608,7 @@ re.$(OBJEXT): {$(VPATH)}regex.h
re.$(OBJEXT): {$(VPATH)}regint.h
re.$(OBJEXT): {$(VPATH)}ruby_assert.h
re.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+re.$(OBJEXT): {$(VPATH)}rubyparser.h
re.$(OBJEXT): {$(VPATH)}shape.h
re.$(OBJEXT): {$(VPATH)}st.h
re.$(OBJEXT): {$(VPATH)}subst.h
@@ -13397,6 +13797,7 @@ rjit.$(OBJEXT): {$(VPATH)}rjit.rbinc
rjit.$(OBJEXT): {$(VPATH)}rjit_c.h
rjit.$(OBJEXT): {$(VPATH)}ruby_assert.h
rjit.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+rjit.$(OBJEXT): {$(VPATH)}rubyparser.h
rjit.$(OBJEXT): {$(VPATH)}shape.h
rjit.$(OBJEXT): {$(VPATH)}st.h
rjit.$(OBJEXT): {$(VPATH)}subst.h
@@ -13625,6 +14026,7 @@ rjit_c.$(OBJEXT): {$(VPATH)}rjit_c.rb
rjit_c.$(OBJEXT): {$(VPATH)}rjit_c.rbinc
rjit_c.$(OBJEXT): {$(VPATH)}ruby_assert.h
rjit_c.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+rjit_c.$(OBJEXT): {$(VPATH)}rubyparser.h
rjit_c.$(OBJEXT): {$(VPATH)}shape.h
rjit_c.$(OBJEXT): {$(VPATH)}st.h
rjit_c.$(OBJEXT): {$(VPATH)}subst.h
@@ -13672,6 +14074,7 @@ ruby.$(OBJEXT): $(top_srcdir)/internal/loadpath.h
ruby.$(OBJEXT): $(top_srcdir)/internal/missing.h
ruby.$(OBJEXT): $(top_srcdir)/internal/object.h
ruby.$(OBJEXT): $(top_srcdir)/internal/parse.h
+ruby.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h
ruby.$(OBJEXT): $(top_srcdir)/internal/serial.h
ruby.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
ruby.$(OBJEXT): $(top_srcdir)/internal/string.h
@@ -13859,6 +14262,7 @@ ruby.$(OBJEXT): {$(VPATH)}rjit.h
ruby.$(OBJEXT): {$(VPATH)}ruby.c
ruby.$(OBJEXT): {$(VPATH)}ruby_assert.h
ruby.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+ruby.$(OBJEXT): {$(VPATH)}rubyparser.h
ruby.$(OBJEXT): {$(VPATH)}shape.h
ruby.$(OBJEXT): {$(VPATH)}st.h
ruby.$(OBJEXT): {$(VPATH)}subst.h
@@ -13869,6 +14273,7 @@ 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): {$(VPATH)}ruby_parser.c
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
@@ -14062,6 +14467,7 @@ scheduler.$(OBJEXT): {$(VPATH)}onigmo.h
scheduler.$(OBJEXT): {$(VPATH)}oniguruma.h
scheduler.$(OBJEXT): {$(VPATH)}ruby_assert.h
scheduler.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+scheduler.$(OBJEXT): {$(VPATH)}rubyparser.h
scheduler.$(OBJEXT): {$(VPATH)}scheduler.c
scheduler.$(OBJEXT): {$(VPATH)}shape.h
scheduler.$(OBJEXT): {$(VPATH)}st.h
@@ -14422,6 +14828,7 @@ shape.$(OBJEXT): {$(VPATH)}onigmo.h
shape.$(OBJEXT): {$(VPATH)}oniguruma.h
shape.$(OBJEXT): {$(VPATH)}ruby_assert.h
shape.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+shape.$(OBJEXT): {$(VPATH)}rubyparser.h
shape.$(OBJEXT): {$(VPATH)}shape.c
shape.$(OBJEXT): {$(VPATH)}shape.h
shape.$(OBJEXT): {$(VPATH)}st.h
@@ -14633,6 +15040,7 @@ signal.$(OBJEXT): {$(VPATH)}ractor.h
signal.$(OBJEXT): {$(VPATH)}ractor_core.h
signal.$(OBJEXT): {$(VPATH)}ruby_assert.h
signal.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+signal.$(OBJEXT): {$(VPATH)}rubyparser.h
signal.$(OBJEXT): {$(VPATH)}shape.h
signal.$(OBJEXT): {$(VPATH)}signal.c
signal.$(OBJEXT): {$(VPATH)}st.h
@@ -15391,6 +15799,7 @@ string.$(OBJEXT): {$(VPATH)}re.h
string.$(OBJEXT): {$(VPATH)}regex.h
string.$(OBJEXT): {$(VPATH)}ruby_assert.h
string.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+string.$(OBJEXT): {$(VPATH)}rubyparser.h
string.$(OBJEXT): {$(VPATH)}shape.h
string.$(OBJEXT): {$(VPATH)}st.h
string.$(OBJEXT): {$(VPATH)}string.c
@@ -15630,6 +16039,7 @@ struct.$(OBJEXT): {$(VPATH)}onigmo.h
struct.$(OBJEXT): {$(VPATH)}oniguruma.h
struct.$(OBJEXT): {$(VPATH)}ruby_assert.h
struct.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+struct.$(OBJEXT): {$(VPATH)}rubyparser.h
struct.$(OBJEXT): {$(VPATH)}shape.h
struct.$(OBJEXT): {$(VPATH)}st.h
struct.$(OBJEXT): {$(VPATH)}struct.c
@@ -15840,6 +16250,7 @@ symbol.$(OBJEXT): {$(VPATH)}probes.dmyh
symbol.$(OBJEXT): {$(VPATH)}probes.h
symbol.$(OBJEXT): {$(VPATH)}ruby_assert.h
symbol.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+symbol.$(OBJEXT): {$(VPATH)}rubyparser.h
symbol.$(OBJEXT): {$(VPATH)}shape.h
symbol.$(OBJEXT): {$(VPATH)}st.h
symbol.$(OBJEXT): {$(VPATH)}subst.h
@@ -16066,6 +16477,7 @@ thread.$(OBJEXT): {$(VPATH)}ractor_core.h
thread.$(OBJEXT): {$(VPATH)}rjit.h
thread.$(OBJEXT): {$(VPATH)}ruby_assert.h
thread.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+thread.$(OBJEXT): {$(VPATH)}rubyparser.h
thread.$(OBJEXT): {$(VPATH)}shape.h
thread.$(OBJEXT): {$(VPATH)}st.h
thread.$(OBJEXT): {$(VPATH)}subst.h
@@ -16280,6 +16692,7 @@ time.$(OBJEXT): {$(VPATH)}onigmo.h
time.$(OBJEXT): {$(VPATH)}oniguruma.h
time.$(OBJEXT): {$(VPATH)}ruby_assert.h
time.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+time.$(OBJEXT): {$(VPATH)}rubyparser.h
time.$(OBJEXT): {$(VPATH)}shape.h
time.$(OBJEXT): {$(VPATH)}st.h
time.$(OBJEXT): {$(VPATH)}subst.h
@@ -16510,6 +16923,7 @@ transient_heap.$(OBJEXT): {$(VPATH)}constant.h
transient_heap.$(OBJEXT): {$(VPATH)}debug.h
transient_heap.$(OBJEXT): {$(VPATH)}debug_counter.h
transient_heap.$(OBJEXT): {$(VPATH)}defines.h
+transient_heap.$(OBJEXT): {$(VPATH)}encoding.h
transient_heap.$(OBJEXT): {$(VPATH)}id.h
transient_heap.$(OBJEXT): {$(VPATH)}id_table.h
transient_heap.$(OBJEXT): {$(VPATH)}intern.h
@@ -16585,6 +16999,15 @@ transient_heap.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
transient_heap.$(OBJEXT): {$(VPATH)}internal/ctype.h
transient_heap.$(OBJEXT): {$(VPATH)}internal/dllexport.h
transient_heap.$(OBJEXT): {$(VPATH)}internal/dosish.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
transient_heap.$(OBJEXT): {$(VPATH)}internal/error.h
transient_heap.$(OBJEXT): {$(VPATH)}internal/eval.h
transient_heap.$(OBJEXT): {$(VPATH)}internal/event.h
@@ -16656,8 +17079,11 @@ transient_heap.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
transient_heap.$(OBJEXT): {$(VPATH)}method.h
transient_heap.$(OBJEXT): {$(VPATH)}missing.h
transient_heap.$(OBJEXT): {$(VPATH)}node.h
+transient_heap.$(OBJEXT): {$(VPATH)}onigmo.h
+transient_heap.$(OBJEXT): {$(VPATH)}oniguruma.h
transient_heap.$(OBJEXT): {$(VPATH)}ruby_assert.h
transient_heap.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+transient_heap.$(OBJEXT): {$(VPATH)}rubyparser.h
transient_heap.$(OBJEXT): {$(VPATH)}shape.h
transient_heap.$(OBJEXT): {$(VPATH)}st.h
transient_heap.$(OBJEXT): {$(VPATH)}subst.h
@@ -17036,6 +17462,7 @@ variable.$(OBJEXT): {$(VPATH)}ractor.h
variable.$(OBJEXT): {$(VPATH)}ractor_core.h
variable.$(OBJEXT): {$(VPATH)}ruby_assert.h
variable.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+variable.$(OBJEXT): {$(VPATH)}rubyparser.h
variable.$(OBJEXT): {$(VPATH)}shape.h
variable.$(OBJEXT): {$(VPATH)}st.h
variable.$(OBJEXT): {$(VPATH)}subst.h
@@ -17083,6 +17510,7 @@ version.$(OBJEXT): {$(VPATH)}config.h
version.$(OBJEXT): {$(VPATH)}constant.h
version.$(OBJEXT): {$(VPATH)}debug_counter.h
version.$(OBJEXT): {$(VPATH)}defines.h
+version.$(OBJEXT): {$(VPATH)}encoding.h
version.$(OBJEXT): {$(VPATH)}id.h
version.$(OBJEXT): {$(VPATH)}id_table.h
version.$(OBJEXT): {$(VPATH)}intern.h
@@ -17158,6 +17586,15 @@ version.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
version.$(OBJEXT): {$(VPATH)}internal/ctype.h
version.$(OBJEXT): {$(VPATH)}internal/dllexport.h
version.$(OBJEXT): {$(VPATH)}internal/dosish.h
+version.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+version.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+version.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+version.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+version.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+version.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+version.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+version.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+version.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
version.$(OBJEXT): {$(VPATH)}internal/error.h
version.$(OBJEXT): {$(VPATH)}internal/eval.h
version.$(OBJEXT): {$(VPATH)}internal/event.h
@@ -17229,10 +17666,13 @@ version.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
version.$(OBJEXT): {$(VPATH)}method.h
version.$(OBJEXT): {$(VPATH)}missing.h
version.$(OBJEXT): {$(VPATH)}node.h
+version.$(OBJEXT): {$(VPATH)}onigmo.h
+version.$(OBJEXT): {$(VPATH)}oniguruma.h
version.$(OBJEXT): {$(VPATH)}revision.h
version.$(OBJEXT): {$(VPATH)}rjit.h
version.$(OBJEXT): {$(VPATH)}ruby_assert.h
version.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+version.$(OBJEXT): {$(VPATH)}rubyparser.h
version.$(OBJEXT): {$(VPATH)}shape.h
version.$(OBJEXT): {$(VPATH)}st.h
version.$(OBJEXT): {$(VPATH)}subst.h
@@ -17270,6 +17710,7 @@ 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/re.h
+vm.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h
vm.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
vm.$(OBJEXT): $(top_srcdir)/internal/serial.h
vm.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
@@ -17468,6 +17909,7 @@ vm.$(OBJEXT): {$(VPATH)}ractor_core.h
vm.$(OBJEXT): {$(VPATH)}rjit.h
vm.$(OBJEXT): {$(VPATH)}ruby_assert.h
vm.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+vm.$(OBJEXT): {$(VPATH)}rubyparser.h
vm.$(OBJEXT): {$(VPATH)}shape.h
vm.$(OBJEXT): {$(VPATH)}st.h
vm.$(OBJEXT): {$(VPATH)}subst.h
@@ -17687,6 +18129,7 @@ vm_backtrace.$(OBJEXT): {$(VPATH)}onigmo.h
vm_backtrace.$(OBJEXT): {$(VPATH)}oniguruma.h
vm_backtrace.$(OBJEXT): {$(VPATH)}ruby_assert.h
vm_backtrace.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}rubyparser.h
vm_backtrace.$(OBJEXT): {$(VPATH)}shape.h
vm_backtrace.$(OBJEXT): {$(VPATH)}st.h
vm_backtrace.$(OBJEXT): {$(VPATH)}subst.h
@@ -17725,6 +18168,7 @@ vm_dump.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
vm_dump.$(OBJEXT): {$(VPATH)}config.h
vm_dump.$(OBJEXT): {$(VPATH)}constant.h
vm_dump.$(OBJEXT): {$(VPATH)}defines.h
+vm_dump.$(OBJEXT): {$(VPATH)}encoding.h
vm_dump.$(OBJEXT): {$(VPATH)}id.h
vm_dump.$(OBJEXT): {$(VPATH)}id_table.h
vm_dump.$(OBJEXT): {$(VPATH)}intern.h
@@ -17800,6 +18244,15 @@ vm_dump.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
vm_dump.$(OBJEXT): {$(VPATH)}internal/ctype.h
vm_dump.$(OBJEXT): {$(VPATH)}internal/dllexport.h
vm_dump.$(OBJEXT): {$(VPATH)}internal/dosish.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
vm_dump.$(OBJEXT): {$(VPATH)}internal/error.h
vm_dump.$(OBJEXT): {$(VPATH)}internal/eval.h
vm_dump.$(OBJEXT): {$(VPATH)}internal/event.h
@@ -17872,11 +18325,14 @@ vm_dump.$(OBJEXT): {$(VPATH)}iseq.h
vm_dump.$(OBJEXT): {$(VPATH)}method.h
vm_dump.$(OBJEXT): {$(VPATH)}missing.h
vm_dump.$(OBJEXT): {$(VPATH)}node.h
+vm_dump.$(OBJEXT): {$(VPATH)}onigmo.h
+vm_dump.$(OBJEXT): {$(VPATH)}oniguruma.h
vm_dump.$(OBJEXT): {$(VPATH)}procstat_vm.c
vm_dump.$(OBJEXT): {$(VPATH)}ractor.h
vm_dump.$(OBJEXT): {$(VPATH)}ractor_core.h
vm_dump.$(OBJEXT): {$(VPATH)}ruby_assert.h
vm_dump.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+vm_dump.$(OBJEXT): {$(VPATH)}rubyparser.h
vm_dump.$(OBJEXT): {$(VPATH)}shape.h
vm_dump.$(OBJEXT): {$(VPATH)}st.h
vm_dump.$(OBJEXT): {$(VPATH)}subst.h
@@ -17917,6 +18373,7 @@ vm_sync.$(OBJEXT): {$(VPATH)}config.h
vm_sync.$(OBJEXT): {$(VPATH)}constant.h
vm_sync.$(OBJEXT): {$(VPATH)}debug_counter.h
vm_sync.$(OBJEXT): {$(VPATH)}defines.h
+vm_sync.$(OBJEXT): {$(VPATH)}encoding.h
vm_sync.$(OBJEXT): {$(VPATH)}id.h
vm_sync.$(OBJEXT): {$(VPATH)}id_table.h
vm_sync.$(OBJEXT): {$(VPATH)}intern.h
@@ -17992,6 +18449,15 @@ vm_sync.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
vm_sync.$(OBJEXT): {$(VPATH)}internal/ctype.h
vm_sync.$(OBJEXT): {$(VPATH)}internal/dllexport.h
vm_sync.$(OBJEXT): {$(VPATH)}internal/dosish.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
vm_sync.$(OBJEXT): {$(VPATH)}internal/error.h
vm_sync.$(OBJEXT): {$(VPATH)}internal/eval.h
vm_sync.$(OBJEXT): {$(VPATH)}internal/event.h
@@ -18063,10 +18529,13 @@ vm_sync.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
vm_sync.$(OBJEXT): {$(VPATH)}method.h
vm_sync.$(OBJEXT): {$(VPATH)}missing.h
vm_sync.$(OBJEXT): {$(VPATH)}node.h
+vm_sync.$(OBJEXT): {$(VPATH)}onigmo.h
+vm_sync.$(OBJEXT): {$(VPATH)}oniguruma.h
vm_sync.$(OBJEXT): {$(VPATH)}ractor.h
vm_sync.$(OBJEXT): {$(VPATH)}ractor_core.h
vm_sync.$(OBJEXT): {$(VPATH)}ruby_assert.h
vm_sync.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+vm_sync.$(OBJEXT): {$(VPATH)}rubyparser.h
vm_sync.$(OBJEXT): {$(VPATH)}shape.h
vm_sync.$(OBJEXT): {$(VPATH)}st.h
vm_sync.$(OBJEXT): {$(VPATH)}subst.h
@@ -18277,6 +18746,7 @@ vm_trace.$(OBJEXT): {$(VPATH)}ractor.h
vm_trace.$(OBJEXT): {$(VPATH)}rjit.h
vm_trace.$(OBJEXT): {$(VPATH)}ruby_assert.h
vm_trace.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+vm_trace.$(OBJEXT): {$(VPATH)}rubyparser.h
vm_trace.$(OBJEXT): {$(VPATH)}shape.h
vm_trace.$(OBJEXT): {$(VPATH)}st.h
vm_trace.$(OBJEXT): {$(VPATH)}subst.h
@@ -18317,6 +18787,7 @@ weakmap.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
weakmap.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
weakmap.$(OBJEXT): {$(VPATH)}config.h
weakmap.$(OBJEXT): {$(VPATH)}defines.h
+weakmap.$(OBJEXT): {$(VPATH)}encoding.h
weakmap.$(OBJEXT): {$(VPATH)}id.h
weakmap.$(OBJEXT): {$(VPATH)}intern.h
weakmap.$(OBJEXT): {$(VPATH)}internal.h
@@ -18391,6 +18862,15 @@ weakmap.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
weakmap.$(OBJEXT): {$(VPATH)}internal/ctype.h
weakmap.$(OBJEXT): {$(VPATH)}internal/dllexport.h
weakmap.$(OBJEXT): {$(VPATH)}internal/dosish.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
weakmap.$(OBJEXT): {$(VPATH)}internal/error.h
weakmap.$(OBJEXT): {$(VPATH)}internal/eval.h
weakmap.$(OBJEXT): {$(VPATH)}internal/event.h
@@ -18462,8 +18942,11 @@ weakmap.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
weakmap.$(OBJEXT): {$(VPATH)}method.h
weakmap.$(OBJEXT): {$(VPATH)}missing.h
weakmap.$(OBJEXT): {$(VPATH)}node.h
+weakmap.$(OBJEXT): {$(VPATH)}onigmo.h
+weakmap.$(OBJEXT): {$(VPATH)}oniguruma.h
weakmap.$(OBJEXT): {$(VPATH)}ruby_assert.h
weakmap.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+weakmap.$(OBJEXT): {$(VPATH)}rubyparser.h
weakmap.$(OBJEXT): {$(VPATH)}st.h
weakmap.$(OBJEXT): {$(VPATH)}subst.h
weakmap.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
@@ -18681,6 +19164,7 @@ yjit.$(OBJEXT): {$(VPATH)}probes.h
yjit.$(OBJEXT): {$(VPATH)}probes_helper.h
yjit.$(OBJEXT): {$(VPATH)}ruby_assert.h
yjit.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+yjit.$(OBJEXT): {$(VPATH)}rubyparser.h
yjit.$(OBJEXT): {$(VPATH)}shape.h
yjit.$(OBJEXT): {$(VPATH)}st.h
yjit.$(OBJEXT): {$(VPATH)}subst.h
diff --git a/ext/coverage/depend b/ext/coverage/depend
index cd7ef43a43..0a6c61d5c6 100644
--- a/ext/coverage/depend
+++ b/ext/coverage/depend
@@ -15,6 +15,7 @@ coverage.o: $(hdrdir)/ruby/backward/2/long_long.h
coverage.o: $(hdrdir)/ruby/backward/2/stdalign.h
coverage.o: $(hdrdir)/ruby/backward/2/stdarg.h
coverage.o: $(hdrdir)/ruby/defines.h
+coverage.o: $(hdrdir)/ruby/encoding.h
coverage.o: $(hdrdir)/ruby/intern.h
coverage.o: $(hdrdir)/ruby/internal/abi.h
coverage.o: $(hdrdir)/ruby/internal/anyargs.h
@@ -87,6 +88,15 @@ coverage.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
coverage.o: $(hdrdir)/ruby/internal/ctype.h
coverage.o: $(hdrdir)/ruby/internal/dllexport.h
coverage.o: $(hdrdir)/ruby/internal/dosish.h
+coverage.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+coverage.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+coverage.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+coverage.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+coverage.o: $(hdrdir)/ruby/internal/encoding/re.h
+coverage.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+coverage.o: $(hdrdir)/ruby/internal/encoding/string.h
+coverage.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+coverage.o: $(hdrdir)/ruby/internal/encoding/transcode.h
coverage.o: $(hdrdir)/ruby/internal/error.h
coverage.o: $(hdrdir)/ruby/internal/eval.h
coverage.o: $(hdrdir)/ruby/internal/event.h
@@ -156,6 +166,8 @@ coverage.o: $(hdrdir)/ruby/internal/variable.h
coverage.o: $(hdrdir)/ruby/internal/warning_push.h
coverage.o: $(hdrdir)/ruby/internal/xmalloc.h
coverage.o: $(hdrdir)/ruby/missing.h
+coverage.o: $(hdrdir)/ruby/onigmo.h
+coverage.o: $(hdrdir)/ruby/oniguruma.h
coverage.o: $(hdrdir)/ruby/ruby.h
coverage.o: $(hdrdir)/ruby/st.h
coverage.o: $(hdrdir)/ruby/subst.h
@@ -184,6 +196,7 @@ coverage.o: $(top_srcdir)/method.h
coverage.o: $(top_srcdir)/node.h
coverage.o: $(top_srcdir)/ruby_assert.h
coverage.o: $(top_srcdir)/ruby_atomic.h
+coverage.o: $(top_srcdir)/rubyparser.h
coverage.o: $(top_srcdir)/shape.h
coverage.o: $(top_srcdir)/thread_pthread.h
coverage.o: $(top_srcdir)/vm_core.h
diff --git a/ext/objspace/depend b/ext/objspace/depend
index f0e1f928cd..9e9cce0fc2 100644
--- a/ext/objspace/depend
+++ b/ext/objspace/depend
@@ -15,6 +15,7 @@ object_tracing.o: $(hdrdir)/ruby/backward/2/stdalign.h
object_tracing.o: $(hdrdir)/ruby/backward/2/stdarg.h
object_tracing.o: $(hdrdir)/ruby/debug.h
object_tracing.o: $(hdrdir)/ruby/defines.h
+object_tracing.o: $(hdrdir)/ruby/encoding.h
object_tracing.o: $(hdrdir)/ruby/intern.h
object_tracing.o: $(hdrdir)/ruby/internal/abi.h
object_tracing.o: $(hdrdir)/ruby/internal/anyargs.h
@@ -87,6 +88,15 @@ object_tracing.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
object_tracing.o: $(hdrdir)/ruby/internal/ctype.h
object_tracing.o: $(hdrdir)/ruby/internal/dllexport.h
object_tracing.o: $(hdrdir)/ruby/internal/dosish.h
+object_tracing.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+object_tracing.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+object_tracing.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+object_tracing.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+object_tracing.o: $(hdrdir)/ruby/internal/encoding/re.h
+object_tracing.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+object_tracing.o: $(hdrdir)/ruby/internal/encoding/string.h
+object_tracing.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+object_tracing.o: $(hdrdir)/ruby/internal/encoding/transcode.h
object_tracing.o: $(hdrdir)/ruby/internal/error.h
object_tracing.o: $(hdrdir)/ruby/internal/eval.h
object_tracing.o: $(hdrdir)/ruby/internal/event.h
@@ -156,6 +166,8 @@ object_tracing.o: $(hdrdir)/ruby/internal/variable.h
object_tracing.o: $(hdrdir)/ruby/internal/warning_push.h
object_tracing.o: $(hdrdir)/ruby/internal/xmalloc.h
object_tracing.o: $(hdrdir)/ruby/missing.h
+object_tracing.o: $(hdrdir)/ruby/onigmo.h
+object_tracing.o: $(hdrdir)/ruby/oniguruma.h
object_tracing.o: $(hdrdir)/ruby/ruby.h
object_tracing.o: $(hdrdir)/ruby/st.h
object_tracing.o: $(hdrdir)/ruby/subst.h
@@ -178,6 +190,7 @@ object_tracing.o: $(top_srcdir)/method.h
object_tracing.o: $(top_srcdir)/node.h
object_tracing.o: $(top_srcdir)/ruby_assert.h
object_tracing.o: $(top_srcdir)/ruby_atomic.h
+object_tracing.o: $(top_srcdir)/rubyparser.h
object_tracing.o: $(top_srcdir)/thread_pthread.h
object_tracing.o: $(top_srcdir)/vm_core.h
object_tracing.o: $(top_srcdir)/vm_opts.h
@@ -365,11 +378,6 @@ objspace.o: $(top_srcdir)/ccan/container_of/container_of.h
objspace.o: $(top_srcdir)/ccan/list/list.h
objspace.o: $(top_srcdir)/ccan/str/str.h
objspace.o: $(top_srcdir)/constant.h
-objspace.o: $(hdrdir)/ruby/thread_native.h
-objspace.o: $(top_srcdir)/ccan/check_type/check_type.h
-objspace.o: $(top_srcdir)/ccan/container_of/container_of.h
-objspace.o: $(top_srcdir)/ccan/list/list.h
-objspace.o: $(top_srcdir)/ccan/str/str.h
objspace.o: $(top_srcdir)/id_table.h
objspace.o: $(top_srcdir)/internal.h
objspace.o: $(top_srcdir)/internal/array.h
@@ -389,6 +397,7 @@ objspace.o: $(top_srcdir)/method.h
objspace.o: $(top_srcdir)/node.h
objspace.o: $(top_srcdir)/ruby_assert.h
objspace.o: $(top_srcdir)/ruby_atomic.h
+objspace.o: $(top_srcdir)/rubyparser.h
objspace.o: $(top_srcdir)/shape.h
objspace.o: $(top_srcdir)/symbol.h
objspace.o: $(top_srcdir)/thread_pthread.h
@@ -597,6 +606,7 @@ objspace_dump.o: $(top_srcdir)/method.h
objspace_dump.o: $(top_srcdir)/node.h
objspace_dump.o: $(top_srcdir)/ruby_assert.h
objspace_dump.o: $(top_srcdir)/ruby_atomic.h
+objspace_dump.o: $(top_srcdir)/rubyparser.h
objspace_dump.o: $(top_srcdir)/shape.h
objspace_dump.o: $(top_srcdir)/symbol.h
objspace_dump.o: $(top_srcdir)/thread_pthread.h
diff --git a/ext/ripper/depend b/ext/ripper/depend
index da1bf58da7..8fb32f48f0 100644
--- a/ext/ripper/depend
+++ b/ext/ripper/depend
@@ -28,6 +28,10 @@ check: .eventids2-check
$(Q) $(RUBY) $(GEN) --mode=check --ids1src=$(SRC1) --ids2src=$(SRC2)
@exit > $@
+eventids1.h: $(GEN) $(srcdir)/tools/dsl.rb $(SRC1)
+ $(ECHO) generating $@ from $(SRC1)
+ $(Q) $(RUBY) $(GEN) --mode=eventids1_h --ids1src=$(SRC1) --output=$@
+
eventids1.c: $(GEN) $(srcdir)/tools/dsl.rb $(SRC1)
$(ECHO) generating $@ from $(SRC1)
$(Q) $(RUBY) $(GEN) --mode=eventids1 --ids1src=$(SRC1) --output=$@
@@ -36,6 +40,10 @@ eventids2table.c: $(GEN) $(srcdir)/tools/dsl.rb $(SRC2)
$(ECHO) generating $@ from $(SRC2)
$(Q) $(RUBY) $(GEN) --mode=eventids2table --ids2src=$(SRC2) --output=$@
+ripper_init.c: $(srcdir)/ripper_init.c.tmpl ripper.y $(srcdir)/tools/preproc.rb $(top_srcdir)/internal/ruby_parser.h
+ $(ECHO) generating $@ from $(srcdir)/ripper_init.c.tmpl
+ $(Q) $(RUBY) $(srcdir)/tools/preproc.rb --output=$@ --template=$(srcdir)/ripper_init.c.tmpl $(top_srcdir)/internal/ruby_parser.h
+
# Entries for Ripper maintainer
preproc: ripper.E
@@ -44,6 +52,342 @@ ripper.E: ripper.c
$(Q) $(CC) -E $(INCFLAGS) $(CPPFLAGS) $< | $(RUBY) $(srcdir)/tools/strip.rb > $@
# AUTOGENERATED DEPENDENCIES START
+eventids1.o: $(RUBY_EXTCONF_H)
+eventids1.o: $(arch_hdrdir)/ruby/config.h
+eventids1.o: $(hdrdir)/ruby/assert.h
+eventids1.o: $(hdrdir)/ruby/backward.h
+eventids1.o: $(hdrdir)/ruby/backward/2/assume.h
+eventids1.o: $(hdrdir)/ruby/backward/2/attributes.h
+eventids1.o: $(hdrdir)/ruby/backward/2/bool.h
+eventids1.o: $(hdrdir)/ruby/backward/2/inttypes.h
+eventids1.o: $(hdrdir)/ruby/backward/2/limits.h
+eventids1.o: $(hdrdir)/ruby/backward/2/long_long.h
+eventids1.o: $(hdrdir)/ruby/backward/2/stdalign.h
+eventids1.o: $(hdrdir)/ruby/backward/2/stdarg.h
+eventids1.o: $(hdrdir)/ruby/defines.h
+eventids1.o: $(hdrdir)/ruby/intern.h
+eventids1.o: $(hdrdir)/ruby/internal/abi.h
+eventids1.o: $(hdrdir)/ruby/internal/anyargs.h
+eventids1.o: $(hdrdir)/ruby/internal/arithmetic.h
+eventids1.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+eventids1.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+eventids1.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+eventids1.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+eventids1.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+eventids1.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+eventids1.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+eventids1.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+eventids1.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+eventids1.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+eventids1.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+eventids1.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+eventids1.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+eventids1.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+eventids1.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+eventids1.o: $(hdrdir)/ruby/internal/assume.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/artificial.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/cold.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/const.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/error.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/format.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/noalias.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/noinline.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/pure.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/restrict.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/warning.h
+eventids1.o: $(hdrdir)/ruby/internal/attr/weakref.h
+eventids1.o: $(hdrdir)/ruby/internal/cast.h
+eventids1.o: $(hdrdir)/ruby/internal/compiler_is.h
+eventids1.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+eventids1.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+eventids1.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+eventids1.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+eventids1.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+eventids1.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+eventids1.o: $(hdrdir)/ruby/internal/compiler_since.h
+eventids1.o: $(hdrdir)/ruby/internal/config.h
+eventids1.o: $(hdrdir)/ruby/internal/constant_p.h
+eventids1.o: $(hdrdir)/ruby/internal/core.h
+eventids1.o: $(hdrdir)/ruby/internal/core/rarray.h
+eventids1.o: $(hdrdir)/ruby/internal/core/rbasic.h
+eventids1.o: $(hdrdir)/ruby/internal/core/rbignum.h
+eventids1.o: $(hdrdir)/ruby/internal/core/rclass.h
+eventids1.o: $(hdrdir)/ruby/internal/core/rdata.h
+eventids1.o: $(hdrdir)/ruby/internal/core/rfile.h
+eventids1.o: $(hdrdir)/ruby/internal/core/rhash.h
+eventids1.o: $(hdrdir)/ruby/internal/core/robject.h
+eventids1.o: $(hdrdir)/ruby/internal/core/rregexp.h
+eventids1.o: $(hdrdir)/ruby/internal/core/rstring.h
+eventids1.o: $(hdrdir)/ruby/internal/core/rstruct.h
+eventids1.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+eventids1.o: $(hdrdir)/ruby/internal/ctype.h
+eventids1.o: $(hdrdir)/ruby/internal/dllexport.h
+eventids1.o: $(hdrdir)/ruby/internal/dosish.h
+eventids1.o: $(hdrdir)/ruby/internal/error.h
+eventids1.o: $(hdrdir)/ruby/internal/eval.h
+eventids1.o: $(hdrdir)/ruby/internal/event.h
+eventids1.o: $(hdrdir)/ruby/internal/fl_type.h
+eventids1.o: $(hdrdir)/ruby/internal/gc.h
+eventids1.o: $(hdrdir)/ruby/internal/glob.h
+eventids1.o: $(hdrdir)/ruby/internal/globals.h
+eventids1.o: $(hdrdir)/ruby/internal/has/attribute.h
+eventids1.o: $(hdrdir)/ruby/internal/has/builtin.h
+eventids1.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+eventids1.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+eventids1.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+eventids1.o: $(hdrdir)/ruby/internal/has/extension.h
+eventids1.o: $(hdrdir)/ruby/internal/has/feature.h
+eventids1.o: $(hdrdir)/ruby/internal/has/warning.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/array.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/bignum.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/class.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/compar.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/complex.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/cont.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/dir.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/enum.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/error.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/eval.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/file.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/hash.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/io.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/load.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/marshal.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/numeric.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/object.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/parse.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/proc.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/process.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/random.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/range.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/rational.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/re.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/ruby.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/select.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/signal.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/string.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/struct.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/thread.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/time.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/variable.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/vm.h
+eventids1.o: $(hdrdir)/ruby/internal/interpreter.h
+eventids1.o: $(hdrdir)/ruby/internal/iterator.h
+eventids1.o: $(hdrdir)/ruby/internal/memory.h
+eventids1.o: $(hdrdir)/ruby/internal/method.h
+eventids1.o: $(hdrdir)/ruby/internal/module.h
+eventids1.o: $(hdrdir)/ruby/internal/newobj.h
+eventids1.o: $(hdrdir)/ruby/internal/scan_args.h
+eventids1.o: $(hdrdir)/ruby/internal/special_consts.h
+eventids1.o: $(hdrdir)/ruby/internal/static_assert.h
+eventids1.o: $(hdrdir)/ruby/internal/stdalign.h
+eventids1.o: $(hdrdir)/ruby/internal/stdbool.h
+eventids1.o: $(hdrdir)/ruby/internal/symbol.h
+eventids1.o: $(hdrdir)/ruby/internal/value.h
+eventids1.o: $(hdrdir)/ruby/internal/value_type.h
+eventids1.o: $(hdrdir)/ruby/internal/variable.h
+eventids1.o: $(hdrdir)/ruby/internal/warning_push.h
+eventids1.o: $(hdrdir)/ruby/internal/xmalloc.h
+eventids1.o: $(hdrdir)/ruby/missing.h
+eventids1.o: $(hdrdir)/ruby/ruby.h
+eventids1.o: $(hdrdir)/ruby/st.h
+eventids1.o: $(hdrdir)/ruby/subst.h
+eventids1.o: eventids1.h
+eventids1.o: {$(VPATH)}eventids1.c
+eventids1.o: {$(VPATH)}eventids1.h
+eventids2.o: $(RUBY_EXTCONF_H)
+eventids2.o: $(arch_hdrdir)/ruby/config.h
+eventids2.o: $(hdrdir)/ruby/assert.h
+eventids2.o: $(hdrdir)/ruby/backward.h
+eventids2.o: $(hdrdir)/ruby/backward/2/assume.h
+eventids2.o: $(hdrdir)/ruby/backward/2/attributes.h
+eventids2.o: $(hdrdir)/ruby/backward/2/bool.h
+eventids2.o: $(hdrdir)/ruby/backward/2/inttypes.h
+eventids2.o: $(hdrdir)/ruby/backward/2/limits.h
+eventids2.o: $(hdrdir)/ruby/backward/2/long_long.h
+eventids2.o: $(hdrdir)/ruby/backward/2/stdalign.h
+eventids2.o: $(hdrdir)/ruby/backward/2/stdarg.h
+eventids2.o: $(hdrdir)/ruby/defines.h
+eventids2.o: $(hdrdir)/ruby/encoding.h
+eventids2.o: $(hdrdir)/ruby/intern.h
+eventids2.o: $(hdrdir)/ruby/internal/abi.h
+eventids2.o: $(hdrdir)/ruby/internal/anyargs.h
+eventids2.o: $(hdrdir)/ruby/internal/arithmetic.h
+eventids2.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+eventids2.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+eventids2.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+eventids2.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+eventids2.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+eventids2.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+eventids2.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+eventids2.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+eventids2.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+eventids2.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+eventids2.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+eventids2.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+eventids2.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+eventids2.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+eventids2.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+eventids2.o: $(hdrdir)/ruby/internal/assume.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/artificial.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/cold.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/const.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/error.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/format.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/noalias.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/noinline.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/pure.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/restrict.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/warning.h
+eventids2.o: $(hdrdir)/ruby/internal/attr/weakref.h
+eventids2.o: $(hdrdir)/ruby/internal/cast.h
+eventids2.o: $(hdrdir)/ruby/internal/compiler_is.h
+eventids2.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+eventids2.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+eventids2.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+eventids2.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+eventids2.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+eventids2.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+eventids2.o: $(hdrdir)/ruby/internal/compiler_since.h
+eventids2.o: $(hdrdir)/ruby/internal/config.h
+eventids2.o: $(hdrdir)/ruby/internal/constant_p.h
+eventids2.o: $(hdrdir)/ruby/internal/core.h
+eventids2.o: $(hdrdir)/ruby/internal/core/rarray.h
+eventids2.o: $(hdrdir)/ruby/internal/core/rbasic.h
+eventids2.o: $(hdrdir)/ruby/internal/core/rbignum.h
+eventids2.o: $(hdrdir)/ruby/internal/core/rclass.h
+eventids2.o: $(hdrdir)/ruby/internal/core/rdata.h
+eventids2.o: $(hdrdir)/ruby/internal/core/rfile.h
+eventids2.o: $(hdrdir)/ruby/internal/core/rhash.h
+eventids2.o: $(hdrdir)/ruby/internal/core/robject.h
+eventids2.o: $(hdrdir)/ruby/internal/core/rregexp.h
+eventids2.o: $(hdrdir)/ruby/internal/core/rstring.h
+eventids2.o: $(hdrdir)/ruby/internal/core/rstruct.h
+eventids2.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+eventids2.o: $(hdrdir)/ruby/internal/ctype.h
+eventids2.o: $(hdrdir)/ruby/internal/dllexport.h
+eventids2.o: $(hdrdir)/ruby/internal/dosish.h
+eventids2.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+eventids2.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+eventids2.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+eventids2.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+eventids2.o: $(hdrdir)/ruby/internal/encoding/re.h
+eventids2.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+eventids2.o: $(hdrdir)/ruby/internal/encoding/string.h
+eventids2.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+eventids2.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+eventids2.o: $(hdrdir)/ruby/internal/error.h
+eventids2.o: $(hdrdir)/ruby/internal/eval.h
+eventids2.o: $(hdrdir)/ruby/internal/event.h
+eventids2.o: $(hdrdir)/ruby/internal/fl_type.h
+eventids2.o: $(hdrdir)/ruby/internal/gc.h
+eventids2.o: $(hdrdir)/ruby/internal/glob.h
+eventids2.o: $(hdrdir)/ruby/internal/globals.h
+eventids2.o: $(hdrdir)/ruby/internal/has/attribute.h
+eventids2.o: $(hdrdir)/ruby/internal/has/builtin.h
+eventids2.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+eventids2.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+eventids2.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+eventids2.o: $(hdrdir)/ruby/internal/has/extension.h
+eventids2.o: $(hdrdir)/ruby/internal/has/feature.h
+eventids2.o: $(hdrdir)/ruby/internal/has/warning.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/array.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/bignum.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/class.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/compar.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/complex.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/cont.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/dir.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/enum.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/error.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/eval.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/file.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/hash.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/io.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/load.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/marshal.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/numeric.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/object.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/parse.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/proc.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/process.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/random.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/range.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/rational.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/re.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/ruby.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/select.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/signal.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/string.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/struct.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/thread.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/time.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/variable.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/vm.h
+eventids2.o: $(hdrdir)/ruby/internal/interpreter.h
+eventids2.o: $(hdrdir)/ruby/internal/iterator.h
+eventids2.o: $(hdrdir)/ruby/internal/memory.h
+eventids2.o: $(hdrdir)/ruby/internal/method.h
+eventids2.o: $(hdrdir)/ruby/internal/module.h
+eventids2.o: $(hdrdir)/ruby/internal/newobj.h
+eventids2.o: $(hdrdir)/ruby/internal/scan_args.h
+eventids2.o: $(hdrdir)/ruby/internal/special_consts.h
+eventids2.o: $(hdrdir)/ruby/internal/static_assert.h
+eventids2.o: $(hdrdir)/ruby/internal/stdalign.h
+eventids2.o: $(hdrdir)/ruby/internal/stdbool.h
+eventids2.o: $(hdrdir)/ruby/internal/symbol.h
+eventids2.o: $(hdrdir)/ruby/internal/value.h
+eventids2.o: $(hdrdir)/ruby/internal/value_type.h
+eventids2.o: $(hdrdir)/ruby/internal/variable.h
+eventids2.o: $(hdrdir)/ruby/internal/warning_push.h
+eventids2.o: $(hdrdir)/ruby/internal/xmalloc.h
+eventids2.o: $(hdrdir)/ruby/missing.h
+eventids2.o: $(hdrdir)/ruby/onigmo.h
+eventids2.o: $(hdrdir)/ruby/oniguruma.h
+eventids2.o: $(hdrdir)/ruby/ruby.h
+eventids2.o: $(hdrdir)/ruby/st.h
+eventids2.o: $(hdrdir)/ruby/subst.h
+eventids2.o: $(top_srcdir)/internal.h
+eventids2.o: $(top_srcdir)/internal/static_assert.h
+eventids2.o: $(top_srcdir)/rubyparser.h
+eventids2.o: eventids2.c
+eventids2.o: eventids2.h
+eventids2.o: {$(VPATH)}eventids2table.c
+eventids2.o: {$(VPATH)}parse.h
ripper.o: $(RUBY_EXTCONF_H)
ripper.o: $(arch_hdrdir)/ruby/config.h
ripper.o: $(hdrdir)/ruby.h
@@ -246,6 +590,7 @@ ripper.o: $(top_srcdir)/internal/numeric.h
ripper.o: $(top_srcdir)/internal/parse.h
ripper.o: $(top_srcdir)/internal/rational.h
ripper.o: $(top_srcdir)/internal/re.h
+ripper.o: $(top_srcdir)/internal/ruby_parser.h
ripper.o: $(top_srcdir)/internal/serial.h
ripper.o: $(top_srcdir)/internal/static_assert.h
ripper.o: $(top_srcdir)/internal/string.h
@@ -256,17 +601,22 @@ ripper.o: $(top_srcdir)/internal/vm.h
ripper.o: $(top_srcdir)/internal/warnings.h
ripper.o: $(top_srcdir)/method.h
ripper.o: $(top_srcdir)/node.h
+ripper.o: $(top_srcdir)/parser_node.h
ripper.o: $(top_srcdir)/regenc.h
ripper.o: $(top_srcdir)/ruby_assert.h
ripper.o: $(top_srcdir)/ruby_atomic.h
+ripper.o: $(top_srcdir)/rubyparser.h
ripper.o: $(top_srcdir)/shape.h
ripper.o: $(top_srcdir)/symbol.h
ripper.o: $(top_srcdir)/thread_pthread.h
ripper.o: $(top_srcdir)/vm_core.h
ripper.o: $(top_srcdir)/vm_opts.h
ripper.o: ../../probes.h
+ripper.o: eventids1.h
ripper.o: eventids2.c
+ripper.o: eventids2.h
ripper.o: ripper.y
+ripper.o: ripper_init.h
ripper.o: {$(VPATH)}eventids1.c
ripper.o: {$(VPATH)}eventids2table.c
ripper.o: {$(VPATH)}id.h
@@ -274,4 +624,186 @@ ripper.o: {$(VPATH)}lex.c
ripper.o: {$(VPATH)}parse.h
ripper.o: {$(VPATH)}probes.dmyh
ripper.o: {$(VPATH)}ripper.c
+ripper_init.o: $(RUBY_EXTCONF_H)
+ripper_init.o: $(arch_hdrdir)/ruby/config.h
+ripper_init.o: $(hdrdir)/ruby/assert.h
+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/inttypes.h
+ripper_init.o: $(hdrdir)/ruby/backward/2/limits.h
+ripper_init.o: $(hdrdir)/ruby/backward/2/long_long.h
+ripper_init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ripper_init.o: $(hdrdir)/ruby/backward/2/stdarg.h
+ripper_init.o: $(hdrdir)/ruby/defines.h
+ripper_init.o: $(hdrdir)/ruby/encoding.h
+ripper_init.o: $(hdrdir)/ruby/intern.h
+ripper_init.o: $(hdrdir)/ruby/internal/abi.h
+ripper_init.o: $(hdrdir)/ruby/internal/anyargs.h
+ripper_init.o: $(hdrdir)/ruby/internal/arithmetic.h
+ripper_init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ripper_init.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ripper_init.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ripper_init.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ripper_init.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ripper_init.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ripper_init.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ripper_init.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ripper_init.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ripper_init.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ripper_init.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ripper_init.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ripper_init.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ripper_init.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ripper_init.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ripper_init.o: $(hdrdir)/ruby/internal/assume.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/cold.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/const.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/error.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/format.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/pure.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/warning.h
+ripper_init.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ripper_init.o: $(hdrdir)/ruby/internal/cast.h
+ripper_init.o: $(hdrdir)/ruby/internal/compiler_is.h
+ripper_init.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ripper_init.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ripper_init.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ripper_init.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ripper_init.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ripper_init.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ripper_init.o: $(hdrdir)/ruby/internal/compiler_since.h
+ripper_init.o: $(hdrdir)/ruby/internal/config.h
+ripper_init.o: $(hdrdir)/ruby/internal/constant_p.h
+ripper_init.o: $(hdrdir)/ruby/internal/core.h
+ripper_init.o: $(hdrdir)/ruby/internal/core/rarray.h
+ripper_init.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ripper_init.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ripper_init.o: $(hdrdir)/ruby/internal/core/rclass.h
+ripper_init.o: $(hdrdir)/ruby/internal/core/rdata.h
+ripper_init.o: $(hdrdir)/ruby/internal/core/rfile.h
+ripper_init.o: $(hdrdir)/ruby/internal/core/rhash.h
+ripper_init.o: $(hdrdir)/ruby/internal/core/robject.h
+ripper_init.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ripper_init.o: $(hdrdir)/ruby/internal/core/rstring.h
+ripper_init.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ripper_init.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ripper_init.o: $(hdrdir)/ruby/internal/ctype.h
+ripper_init.o: $(hdrdir)/ruby/internal/dllexport.h
+ripper_init.o: $(hdrdir)/ruby/internal/dosish.h
+ripper_init.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+ripper_init.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+ripper_init.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+ripper_init.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+ripper_init.o: $(hdrdir)/ruby/internal/encoding/re.h
+ripper_init.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+ripper_init.o: $(hdrdir)/ruby/internal/encoding/string.h
+ripper_init.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+ripper_init.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+ripper_init.o: $(hdrdir)/ruby/internal/error.h
+ripper_init.o: $(hdrdir)/ruby/internal/eval.h
+ripper_init.o: $(hdrdir)/ruby/internal/event.h
+ripper_init.o: $(hdrdir)/ruby/internal/fl_type.h
+ripper_init.o: $(hdrdir)/ruby/internal/gc.h
+ripper_init.o: $(hdrdir)/ruby/internal/glob.h
+ripper_init.o: $(hdrdir)/ruby/internal/globals.h
+ripper_init.o: $(hdrdir)/ruby/internal/has/attribute.h
+ripper_init.o: $(hdrdir)/ruby/internal/has/builtin.h
+ripper_init.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ripper_init.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ripper_init.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ripper_init.o: $(hdrdir)/ruby/internal/has/extension.h
+ripper_init.o: $(hdrdir)/ruby/internal/has/feature.h
+ripper_init.o: $(hdrdir)/ruby/internal/has/warning.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/array.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/class.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/compar.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/complex.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/cont.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/dir.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/enum.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/error.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/eval.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/file.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/hash.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/io.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/load.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/object.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/parse.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/proc.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/process.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/random.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/range.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/rational.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/re.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/select.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/signal.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/string.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/struct.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/thread.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/time.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/variable.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/vm.h
+ripper_init.o: $(hdrdir)/ruby/internal/interpreter.h
+ripper_init.o: $(hdrdir)/ruby/internal/iterator.h
+ripper_init.o: $(hdrdir)/ruby/internal/memory.h
+ripper_init.o: $(hdrdir)/ruby/internal/method.h
+ripper_init.o: $(hdrdir)/ruby/internal/module.h
+ripper_init.o: $(hdrdir)/ruby/internal/newobj.h
+ripper_init.o: $(hdrdir)/ruby/internal/scan_args.h
+ripper_init.o: $(hdrdir)/ruby/internal/special_consts.h
+ripper_init.o: $(hdrdir)/ruby/internal/static_assert.h
+ripper_init.o: $(hdrdir)/ruby/internal/stdalign.h
+ripper_init.o: $(hdrdir)/ruby/internal/stdbool.h
+ripper_init.o: $(hdrdir)/ruby/internal/symbol.h
+ripper_init.o: $(hdrdir)/ruby/internal/value.h
+ripper_init.o: $(hdrdir)/ruby/internal/value_type.h
+ripper_init.o: $(hdrdir)/ruby/internal/variable.h
+ripper_init.o: $(hdrdir)/ruby/internal/warning_push.h
+ripper_init.o: $(hdrdir)/ruby/internal/xmalloc.h
+ripper_init.o: $(hdrdir)/ruby/missing.h
+ripper_init.o: $(hdrdir)/ruby/onigmo.h
+ripper_init.o: $(hdrdir)/ruby/oniguruma.h
+ripper_init.o: $(hdrdir)/ruby/ruby.h
+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/parse.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)/rubyparser.h
+ripper_init.o: eventids1.h
+ripper_init.o: eventids2.h
+ripper_init.o: ripper_init.h
+ripper_init.o: {$(VPATH)}parse.h
+ripper_init.o: {$(VPATH)}ripper_init.c
# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/ripper/eventids2.c b/ext/ripper/eventids2.c
index 05687497ac..ac54955857 100644
--- a/ext/ripper/eventids2.c
+++ b/ext/ripper/eventids2.c
@@ -1,3 +1,11 @@
+#include "ruby/ruby.h"
+#include "rubyparser.h"
+#define YYSTYPE_IS_DECLARED
+#include "parse.h"
+#include "eventids2.h"
+#include "internal.h"
+#include "internal/static_assert.h"
+
typedef struct {
ID ripper_id_backref;
ID ripper_id_backtick;
@@ -57,7 +65,7 @@ static ripper_scanner_ids_t ripper_scanner_ids;
#include "eventids2table.c"
-static void
+void
ripper_init_eventids2(void)
{
#define set_id2(name) ripper_scanner_ids.ripper_id_##name = rb_intern_const("on_"#name)
@@ -118,7 +126,7 @@ ripper_init_eventids2(void)
STATIC_ASSERT(k__END___range, k__END__ < SHRT_MAX);
STATIC_ASSERT(ripper_scanner_ids_size, sizeof(ripper_scanner_ids) < SHRT_MAX);
-static ID
+ID
ripper_token2eventid(enum yytokentype tok)
{
#define O(member) (int)offsetof(ripper_scanner_ids_t, ripper_id_##member)+1
diff --git a/ext/ripper/eventids2.h b/ext/ripper/eventids2.h
new file mode 100644
index 0000000000..49e46432b9
--- /dev/null
+++ b/ext/ripper/eventids2.h
@@ -0,0 +1,8 @@
+#ifndef RIPPER_EVENTIDS2
+#define RIPPER_EVENTIDS2
+
+void ripper_init_eventids2(void);
+void ripper_init_eventids2_table(VALUE self);
+ID ripper_token2eventid(enum yytokentype tok);
+
+#endif /* RIPPER_EVENTIDS2 */
diff --git a/ext/ripper/extconf.rb b/ext/ripper/extconf.rb
index 24bf8c063f..c3c56c27c5 100644
--- a/ext/ripper/extconf.rb
+++ b/ext/ripper/extconf.rb
@@ -5,8 +5,8 @@ require 'mkmf'
require 'rbconfig'
def main
- $objs = %w(ripper.o)
- $distcleanfiles.concat %w(ripper.y ripper.c eventids1.c eventids2table.c)
+ $objs = %w(eventids1.o eventids2.o ripper.o ripper_init.o)
+ $distcleanfiles.concat %w(ripper.y ripper.c eventids1.c eventids1.h eventids2table.c ripper_init.c)
$cleanfiles.concat %w(ripper.E ripper.output y.output .eventids2-check)
$defs << '-DRIPPER'
$defs << '-DRIPPER_DEBUG' if $debug
diff --git a/ext/ripper/ripper_init.c.tmpl b/ext/ripper/ripper_init.c.tmpl
new file mode 100644
index 0000000000..db58d64fe6
--- /dev/null
+++ b/ext/ripper/ripper_init.c.tmpl
@@ -0,0 +1,650 @@
+#include "ruby/ruby.h"
+#include "ruby/encoding.h"
+#include "internal.h"
+#include "internal/parse.h"
+#include "internal/ruby_parser.h"
+#include "node.h"
+#include "rubyparser.h"
+#include "eventids1.h"
+#define YYSTYPE_IS_DECLARED
+#include "parse.h"
+#include "eventids2.h"
+#include "ripper_init.h"
+
+#define STR_NEW2(ptr) rb_enc_str_new((ptr),strlen(ptr),rb_ruby_parser_enc(p))
+#define NODE_RIPPER NODE_CDECL
+#define RIPPER_VERSION "0.1.0"
+
+ID id_warn, id_warning, id_gets, id_assoc;
+
+struct ripper {
+ rb_parser_t *p;
+};
+
+static void
+ripper_parser_mark2(void *ptr)
+{
+ struct ripper *r = (struct ripper*)ptr;
+ ripper_parser_mark(r->p);
+}
+
+static void
+ripper_parser_free2(void *ptr)
+{
+ struct ripper *r = (struct ripper*)ptr;
+ ripper_parser_free(r->p);
+}
+
+static size_t
+ripper_parser_memsize2(const void *ptr)
+{
+ struct ripper *r = (struct ripper*)ptr;
+ return ripper_parser_memsize(r->p);
+}
+
+static const rb_data_type_t parser_data_type = {
+ "ripper",
+ {
+ ripper_parser_mark2,
+ ripper_parser_free2,
+ ripper_parser_memsize2,
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
+};
+
+ID
+ripper_get_id(VALUE v)
+{
+ NODE *nd;
+ if (!RB_TYPE_P(v, T_NODE)) return 0;
+ nd = (NODE *)v;
+ if (!nd_type_p(nd, NODE_RIPPER)) return 0;
+ return nd->nd_vid;
+}
+
+VALUE
+ripper_get_value(VALUE v)
+{
+ NODE *nd;
+ if (UNDEF_P(v)) return Qnil;
+ if (!RB_TYPE_P(v, T_NODE)) return v;
+ nd = (NODE *)v;
+ if (!nd_type_p(nd, NODE_RIPPER)) return Qnil;
+ return nd->nd_rval;
+}
+
+static VALUE
+ripper_lex_get_generic(struct parser_params *p, VALUE src)
+{
+ VALUE line = rb_funcallv_public(src, id_gets, 0, 0);
+ if (!NIL_P(line) && !RB_TYPE_P(line, T_STRING)) {
+ rb_raise(rb_eTypeError,
+ "gets returned %"PRIsVALUE" (expected String or nil)",
+ rb_obj_class(line));
+ }
+ return line;
+}
+
+void
+ripper_compile_error(struct parser_params *p, const char *fmt, ...)
+{
+ VALUE str;
+ va_list args;
+
+ va_start(args, fmt);
+ str = rb_vsprintf(fmt, args);
+ va_end(args);
+ rb_funcall(ripper_value(p), rb_intern("compile_error"), 1, str);
+ ripper_error(p);
+}
+
+static VALUE
+ripper_lex_io_get(struct parser_params *p, VALUE src)
+{
+ return rb_io_gets(src);
+}
+
+static VALUE
+ripper_s_allocate(VALUE klass)
+{
+ struct ripper *r;
+
+ VALUE self = TypedData_Make_Struct(klass, struct ripper,
+ &parser_data_type, r);
+
+#ifdef UNIVERSAL_PARSER
+ rb_parser_config_t *config;
+ config = rb_ruby_parser_config_new(ruby_xmalloc);
+ rb_parser_config_initialize(config);
+ r->p = rb_ruby_parser_allocate(config);
+#else
+ r->p = rb_ruby_ripper_parser_allocate();
+#endif
+ rb_ruby_parser_set_value(r->p, self);
+ return self;
+}
+
+/*
+ * call-seq:
+ * ripper.error? -> Boolean
+ *
+ * Return true if parsed source has errors.
+ */
+static VALUE
+ripper_error_p(VALUE vparser)
+{
+ struct ripper *r;
+
+ TypedData_Get_Struct(vparser, struct ripper, &parser_data_type, r);
+ return RBOOL(rb_ruby_parser_error_p(r->p));
+}
+
+/*
+ * call-seq:
+ * ripper.end_seen? -> Boolean
+ *
+ * Return true if parsed source ended by +\_\_END\_\_+.
+ */
+static VALUE
+ripper_parser_end_seen_p(VALUE vparser)
+{
+ struct ripper *r;
+
+ TypedData_Get_Struct(vparser, struct ripper, &parser_data_type, r);
+ return RBOOL(rb_ruby_parser_end_seen_p(r->p));
+}
+
+/*
+ * call-seq:
+ * ripper.encoding -> encoding
+ *
+ * Return encoding of the source.
+ */
+static VALUE
+ripper_parser_encoding(VALUE vparser)
+{
+ struct ripper *r;
+
+ TypedData_Get_Struct(vparser, struct ripper, &parser_data_type, r);
+ return rb_ruby_parser_encoding(r->p);
+}
+
+/*
+ * call-seq:
+ * ripper.yydebug -> true or false
+ *
+ * Get yydebug.
+ */
+static VALUE
+ripper_parser_get_yydebug(VALUE self)
+{
+ struct ripper *r;
+
+ TypedData_Get_Struct(self, struct ripper, &parser_data_type, r);
+ return RBOOL(rb_ruby_parser_get_yydebug(r->p));
+}
+
+/*
+ * call-seq:
+ * ripper.yydebug = flag
+ *
+ * Set yydebug.
+ */
+static VALUE
+ripper_parser_set_yydebug(VALUE self, VALUE flag)
+{
+ struct ripper *r;
+
+ TypedData_Get_Struct(self, struct ripper, &parser_data_type, r);
+ rb_ruby_parser_set_yydebug(r->p, RTEST(flag));
+ return flag;
+}
+
+/*
+ * call-seq:
+ * ripper.debug_output -> obj
+ *
+ * Get debug output.
+ */
+static VALUE
+ripper_parser_get_debug_output(VALUE self)
+{
+ struct ripper *r;
+
+ TypedData_Get_Struct(self, struct ripper, &parser_data_type, r);
+ return rb_ruby_parser_debug_output(r->p);
+}
+
+/*
+ * call-seq:
+ * ripper.debug_output = obj
+ *
+ * Set debug output.
+ */
+static VALUE
+ripper_parser_set_debug_output(VALUE self, VALUE output)
+{
+ struct ripper *r;
+
+ TypedData_Get_Struct(self, struct ripper, &parser_data_type, r);
+ rb_ruby_parser_set_debug_output(r->p, output);
+ return output;
+}
+
+#ifdef UNIVERSAL_PARSER
+struct dedent_string_arg {
+ struct parser_params *p;
+ VALUE input;
+ VALUE width;
+};
+
+static VALUE
+parser_dedent_string0(VALUE a)
+{
+ struct dedent_string_arg *arg = (void *)a;
+ int wid, col;
+
+ StringValue(arg->input);
+ wid = NUM2UINT(arg->width);
+ col = rb_ruby_ripper_dedent_string(arg->p, arg->input, wid);
+ return INT2NUM(col);
+}
+
+static VALUE
+parser_config_free(VALUE a)
+{
+ rb_parser_config_t *config = (void *)a;
+
+ rb_ruby_parser_config_free(config);
+ return Qnil;
+}
+#endif
+
+/*
+ * call-seq:
+ * Ripper.dedent_string(input, width) -> Integer
+ *
+ * USE OF RIPPER LIBRARY ONLY.
+ *
+ * Strips up to +width+ leading whitespaces from +input+,
+ * and returns the stripped column width.
+ */
+#ifdef UNIVERSAL_PARSER
+static VALUE
+parser_dedent_string(VALUE self, VALUE input, VALUE width)
+{
+ struct parser_params *p;
+ rb_parser_config_t *config;
+ struct dedent_string_arg args;
+
+ config = rb_ruby_parser_config_new(ruby_xmalloc);
+ rb_parser_config_initialize(config);
+ p = rb_ruby_parser_new(config);
+
+ args.p = p;
+ args.input = input;
+ args.width = width;
+ return rb_ensure(parser_dedent_string0, (VALUE)&args, parser_config_free, (VALUE)config);
+}
+#else
+static VALUE
+parser_dedent_string(VALUE self, VALUE input, VALUE width)
+{
+ int wid, col;
+
+ StringValue(input);
+ wid = NUM2UINT(width);
+ col = rb_ruby_ripper_dedent_string(0, input, wid);
+ return INT2NUM(col);
+}
+#endif
+
+/*
+ * call-seq:
+ * Ripper.new(src, filename="(ripper)", lineno=1) -> ripper
+ *
+ * Create a new Ripper object.
+ * _src_ must be a String, an IO, or an Object which has #gets method.
+ *
+ * This method does not starts parsing.
+ * See also Ripper#parse and Ripper.parse.
+ */
+static VALUE
+ripper_initialize(int argc, VALUE *argv, VALUE self)
+{
+ struct ripper *r;
+ struct parser_params *p;
+ VALUE src, fname, lineno;
+ VALUE (*gets)(struct parser_params*,VALUE);
+ VALUE input, sourcefile_string;
+ const char *sourcefile;
+ int sourceline;
+
+ TypedData_Get_Struct(self, struct ripper, &parser_data_type, r);
+ p = r->p;
+ rb_scan_args(argc, argv, "12", &src, &fname, &lineno);
+ if (RB_TYPE_P(src, T_FILE)) {
+ gets = ripper_lex_io_get;
+ }
+ else if (rb_respond_to(src, id_gets)) {
+ gets = ripper_lex_get_generic;
+ }
+ else {
+ StringValue(src);
+ gets = rb_ruby_ripper_lex_get_str;
+ }
+ input = src;
+ if (NIL_P(fname)) {
+ fname = STR_NEW2("(ripper)");
+ OBJ_FREEZE(fname);
+ }
+ else {
+ StringValueCStr(fname);
+ fname = rb_str_new_frozen(fname);
+ }
+ rb_ruby_ripper_parser_initialize(p);
+
+ sourcefile_string = fname;
+ sourcefile = RSTRING_PTR(fname);
+ sourceline = NIL_P(lineno) ? 0 : NUM2INT(lineno) - 1;
+
+ rb_ruby_parser_ripper_initialize(p, gets, input, sourcefile_string, sourcefile, sourceline);
+
+ return Qnil;
+}
+
+static VALUE
+ripper_parse0(VALUE vparser)
+{
+ struct ripper *r;
+ struct parser_params *p;
+
+ TypedData_Get_Struct(vparser, struct ripper, &parser_data_type, r);
+ p = r->p;
+ // RB_GC_GUARD(vparser);
+ rb_ruby_ripper_parse0(p);
+ return rb_ruby_parser_result(p);
+}
+
+static VALUE
+ripper_ensure(VALUE vparser)
+{
+ struct ripper *r;
+
+ TypedData_Get_Struct(vparser, struct ripper, &parser_data_type, r);
+ rb_ruby_parser_set_parsing_thread(r->p, Qnil);
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * ripper.parse
+ *
+ * Start parsing and returns the value of the root action.
+ */
+static VALUE
+ripper_parse(VALUE self)
+{
+ struct ripper *r;
+ struct parser_params *p;
+
+ TypedData_Get_Struct(self, struct ripper, &parser_data_type, r);
+ p = r->p;
+ if (!rb_ruby_ripper_initialized_p(p)) {
+ rb_raise(rb_eArgError, "method called for uninitialized object");
+ }
+ if (!NIL_P(rb_ruby_parser_parsing_thread(p))) {
+ if (rb_ruby_parser_parsing_thread(p) == rb_thread_current())
+ rb_raise(rb_eArgError, "Ripper#parse is not reentrant");
+ else
+ rb_raise(rb_eArgError, "Ripper#parse is not multithread-safe");
+ }
+ rb_ruby_parser_set_parsing_thread(p, rb_thread_current());
+ rb_ensure(ripper_parse0, self, ripper_ensure, self);
+
+ return rb_ruby_parser_result(p);
+}
+
+/*
+ * call-seq:
+ * ripper.column -> Integer
+ *
+ * Return column number of current parsing line.
+ * This number starts from 0.
+ */
+static VALUE
+ripper_column(VALUE self)
+{
+ struct ripper *r;
+ struct parser_params *p;
+ long col;
+
+ TypedData_Get_Struct(self, struct ripper, &parser_data_type, r);
+ p = r->p;
+ if (!rb_ruby_ripper_initialized_p(p)) {
+ rb_raise(rb_eArgError, "method called for uninitialized object");
+ }
+ if (NIL_P(rb_ruby_parser_parsing_thread(p))) return Qnil;
+ col = rb_ruby_ripper_column(p);
+ return LONG2NUM(col);
+}
+
+/*
+ * call-seq:
+ * ripper.filename -> String
+ *
+ * Return current parsing filename.
+ */
+static VALUE
+ripper_filename(VALUE self)
+{
+ struct ripper *r;
+ struct parser_params *p;
+
+ TypedData_Get_Struct(self, struct ripper, &parser_data_type, r);
+ p = r->p;
+ if (!rb_ruby_ripper_initialized_p(p)) {
+ rb_raise(rb_eArgError, "method called for uninitialized object");
+ }
+ return rb_ruby_parser_ruby_sourcefile_string(p);
+}
+
+/*
+ * call-seq:
+ * ripper.lineno -> Integer
+ *
+ * Return line number of current parsing line.
+ * This number starts from 1.
+ */
+static VALUE
+ripper_lineno(VALUE self)
+{
+ struct ripper *r;
+ struct parser_params *p;
+
+ TypedData_Get_Struct(self, struct ripper, &parser_data_type, r);
+ p = r->p;
+ if (!rb_ruby_ripper_initialized_p(p)) {
+ rb_raise(rb_eArgError, "method called for uninitialized object");
+ }
+ if (NIL_P(rb_ruby_parser_parsing_thread(p))) return Qnil;
+ return INT2NUM(rb_ruby_parser_ruby_sourceline(p));
+}
+
+/*
+ * call-seq:
+ * ripper.state -> Integer
+ *
+ * Return scanner state of current token.
+ */
+static VALUE
+ripper_state(VALUE self)
+{
+ struct ripper *r;
+ struct parser_params *p;
+
+ TypedData_Get_Struct(self, struct ripper, &parser_data_type, r);
+ p = r->p;
+ if (!rb_ruby_ripper_initialized_p(p)) {
+ rb_raise(rb_eArgError, "method called for uninitialized object");
+ }
+ if (NIL_P(rb_ruby_parser_parsing_thread(p))) return Qnil;
+ return INT2NUM(rb_ruby_parser_lex_state(p));
+}
+
+/*
+ * call-seq:
+ * ripper.token -> String
+ *
+ * Return the current token string.
+ */
+static VALUE
+ripper_token(VALUE self)
+{
+ struct ripper *r;
+ struct parser_params *p;
+ long pos, len;
+
+ TypedData_Get_Struct(self, struct ripper, &parser_data_type, r);
+ p = r->p;
+ if (!rb_ruby_ripper_initialized_p(p)) {
+ rb_raise(rb_eArgError, "method called for uninitialized object");
+ }
+ if (NIL_P(rb_ruby_parser_parsing_thread(p))) return Qnil;
+ pos = rb_ruby_ripper_column(p);
+ len = rb_ruby_ripper_token_len(p);
+ return rb_str_subseq(rb_ruby_ripper_lex_lastline(p), pos, len);
+}
+
+#ifdef RIPPER_DEBUG
+/* :nodoc: */
+static VALUE
+ripper_assert_Qundef(VALUE self, VALUE obj, VALUE msg)
+{
+ StringValue(msg);
+ if (UNDEF_P(obj)) {
+ rb_raise(rb_eArgError, "%"PRIsVALUE, msg);
+ }
+ return Qnil;
+}
+
+/* :nodoc: */
+static VALUE
+ripper_raw_value(VALUE self, VALUE obj)
+{
+ return ULONG2NUM(obj);
+}
+#endif
+
+#ifdef UNIVERSAL_PARSER
+struct lex_state_name_arg {
+ struct parser_params *p;
+ VALUE state;
+};
+
+static VALUE
+lex_state_name0(VALUE a)
+{
+ struct lex_state_name_arg *arg = (void *)a;
+
+ return rb_ruby_ripper_lex_state_name(arg->p, NUM2INT(arg->state));
+}
+#endif
+
+/*
+ * call-seq:
+ * Ripper.lex_state_name(integer) -> string
+ *
+ * Returns a string representation of lex_state.
+ */
+#ifdef UNIVERSAL_PARSER
+static VALUE
+ripper_lex_state_name(VALUE self, VALUE state)
+{
+ struct parser_params *p;
+ rb_parser_config_t *config;
+ struct lex_state_name_arg args;
+
+ config = rb_ruby_parser_config_new(ruby_xmalloc);
+ rb_parser_config_initialize(config);
+ p = rb_ruby_parser_new(config);
+
+ args.p = p;
+ args.state = state;
+
+ return rb_ensure(lex_state_name0, (VALUE)&args, parser_config_free, (VALUE)config);
+}
+#else
+static VALUE
+ripper_lex_state_name(VALUE self, VALUE state)
+{
+ return rb_ruby_ripper_lex_state_name(0, NUM2INT(state));
+}
+#endif
+
+void
+Init_ripper(void)
+{
+ ripper_init_eventids1();
+ ripper_init_eventids2();
+ id_warn = rb_intern_const("warn");
+ id_warning = rb_intern_const("warning");
+ id_gets = rb_intern_const("gets");
+ id_assoc = rb_intern_const("=>");
+
+ InitVM(ripper);
+}
+
+void
+InitVM_ripper(void)
+{
+ VALUE Ripper;
+
+ Ripper = rb_define_class("Ripper", rb_cObject);
+ /* version of Ripper */
+ rb_define_const(Ripper, "Version", rb_usascii_str_new2(RIPPER_VERSION));
+ rb_define_alloc_func(Ripper, ripper_s_allocate);
+ rb_define_method(Ripper, "initialize", ripper_initialize, -1);
+ rb_define_method(Ripper, "parse", ripper_parse, 0);
+ rb_define_method(Ripper, "column", ripper_column, 0);
+ rb_define_method(Ripper, "filename", ripper_filename, 0);
+ rb_define_method(Ripper, "lineno", ripper_lineno, 0);
+ rb_define_method(Ripper, "state", ripper_state, 0);
+ rb_define_method(Ripper, "token", ripper_token, 0);
+ rb_define_method(Ripper, "end_seen?", ripper_parser_end_seen_p, 0);
+ rb_define_method(Ripper, "encoding", ripper_parser_encoding, 0);
+ rb_define_method(Ripper, "yydebug", ripper_parser_get_yydebug, 0);
+ rb_define_method(Ripper, "yydebug=", ripper_parser_set_yydebug, 1);
+ rb_define_method(Ripper, "debug_output", ripper_parser_get_debug_output, 0);
+ rb_define_method(Ripper, "debug_output=", ripper_parser_set_debug_output, 1);
+ rb_define_method(Ripper, "error?", ripper_error_p, 0);
+#ifdef RIPPER_DEBUG
+ rb_define_method(Ripper, "assert_Qundef", ripper_assert_Qundef, 2);
+ rb_define_method(Ripper, "rawVALUE", ripper_raw_value, 1);
+ rb_define_method(Ripper, "validate_object", ripper_validate_object, 1);
+#endif
+
+ rb_define_singleton_method(Ripper, "dedent_string", parser_dedent_string, 2);
+ rb_define_private_method(Ripper, "dedent_string", parser_dedent_string, 2);
+
+ rb_define_singleton_method(Ripper, "lex_state_name", ripper_lex_state_name, 1);
+
+<% @exprs.each do |expr, desc| -%>
+ /* <%=desc%> */
+ rb_define_const(Ripper, "<%=expr%>", INT2NUM(<%=expr%>));
+<% end %>
+ ripper_init_eventids1_table(Ripper);
+ ripper_init_eventids2_table(Ripper);
+
+# if 0
+ /* Hack to let RDoc document SCRIPT_LINES__ */
+
+ /*
+ * When a Hash is assigned to +SCRIPT_LINES__+ the contents of files loaded
+ * after the assignment will be added as an Array of lines with the file
+ * name as the key.
+ */
+ rb_define_global_const("SCRIPT_LINES__", Qnil);
+#endif
+
+}
diff --git a/ext/ripper/ripper_init.h b/ext/ripper/ripper_init.h
new file mode 100644
index 0000000000..82ff13b95f
--- /dev/null
+++ b/ext/ripper/ripper_init.h
@@ -0,0 +1,8 @@
+#ifndef RIPPER_INIT_H
+#define RIPPER_INIT_H
+
+VALUE ripper_get_value(VALUE v);
+ID ripper_get_id(VALUE v);
+PRINTF_ARGS(void ripper_compile_error(struct parser_params*, const char *fmt, ...), 2, 3);
+
+#endif /* RIPPER_INIT_H */
diff --git a/ext/ripper/tools/generate.rb b/ext/ripper/tools/generate.rb
index 883e6ef2df..bb64d2fe8b 100644
--- a/ext/ripper/tools/generate.rb
+++ b/ext/ripper/tools/generate.rb
@@ -11,7 +11,7 @@ def main
parser = @parser = OptionParser.new
parser.banner = "Usage: #{File.basename($0)} --mode=MODE [--ids1src=PATH] [--ids2src=PATH] [--output=PATH]"
- parser.on('--mode=MODE', 'check, eventids1, or eventids2table.') {|m|
+ parser.on('--mode=MODE', 'check, eventids1_h, eventids1, or eventids2table.') {|m|
mode = m
}
parser.on('--ids1src=PATH', 'A source file of event-IDs 1 (parse.y).') {|path|
@@ -45,6 +45,9 @@ def main
abort "event crash: #{common.join(' ')}"
end
exit 0
+ when 'eventids1_h'
+ usage 'no --ids1src' unless ids1src
+ result = generate_eventids1_h(read_ids1(ids1src))
when 'eventids1'
usage 'no --ids1src' unless ids1src
result = generate_eventids1(read_ids1(ids1src))
@@ -67,19 +70,35 @@ def usage(msg)
exit false
end
-def generate_eventids1(ids)
+def generate_eventids1_h(ids)
buf = "".dup
- buf << %Q[static struct {\n]
+ buf << %Q[#ifndef RIPPER_EVENTIDS1\n]
+ buf << %Q[#define RIPPER_EVENTIDS1\n]
+ buf << %Q[\n]
+ buf << %Q[void ripper_init_eventids1(void);\n]
+ buf << %Q[void ripper_init_eventids1_table(VALUE self);\n]
+ buf << %Q[\n]
+ buf << %Q[struct ripper_parser_ids {\n]
ids.each do |id, arity|
buf << %Q[ ID id_#{id};\n]
end
- buf << %Q[} ripper_parser_ids;\n]
+ buf << %Q[};\n]
buf << %Q[\n]
ids.each do |id, arity|
buf << %Q[#define ripper_id_#{id} ripper_parser_ids.id_#{id}\n]
end
+ buf << %Q[#endif /* RIPPER_EVENTIDS1 */\n]
buf << %Q[\n]
- buf << %Q[static void\n]
+end
+
+def generate_eventids1(ids)
+ buf = "".dup
+ buf << %Q[#include "ruby/ruby.h"\n]
+ buf << %Q[#include "eventids1.h"\n]
+ buf << %Q[\n]
+ buf << %Q[struct ripper_parser_ids ripper_parser_ids;\n]
+ buf << %Q[\n]
+ buf << %Q[void\n]
buf << %Q[ripper_init_eventids1(void)\n]
buf << %Q[{\n]
buf << %Q[#define set_id1(name) ripper_id_##name = rb_intern_const("on_"#name)\n]
@@ -88,7 +107,9 @@ def generate_eventids1(ids)
end
buf << %Q[}\n]
buf << %Q[\n]
- buf << %Q[static void\n]
+ buf << %Q[#define intern_sym(name) ID2SYM(rb_intern_const(name))\n]
+ buf << %Q[\n]
+ buf << %Q[void\n]
buf << %Q[ripper_init_eventids1_table(VALUE self)\n]
buf << %Q[{\n]
buf << %Q[ VALUE h = rb_hash_new();\n]
@@ -102,7 +123,11 @@ end
def generate_eventids2_table(ids)
buf = "".dup
- buf << %Q[static void\n]
+ buf << %Q[#include "ruby/ruby.h"\n]
+ buf << %Q[\n]
+ buf << %Q[#define intern_sym(name) ID2SYM(rb_intern_const(name))\n]
+ buf << %Q[\n]
+ buf << %Q[void\n]
buf << %Q[ripper_init_eventids2_table(VALUE self)\n]
buf << %Q[{\n]
buf << %Q[ VALUE h = rb_hash_new();\n]
diff --git a/ext/ripper/tools/preproc.rb b/ext/ripper/tools/preproc.rb
index f419fc3dbe..07ef627cf3 100644
--- a/ext/ripper/tools/preproc.rb
+++ b/ext/ripper/tools/preproc.rb
@@ -5,11 +5,15 @@ require 'optparse'
def main
output = nil
+ template = nil
parser = OptionParser.new
- parser.banner = "Usage: #{File.basename($0)} [--output=PATH] <parse.y>"
+ parser.banner = "Usage: #{File.basename($0)} [--output=PATH] [--template=PATH] <parse.y>"
parser.on('--output=PATH', 'An output file.') {|path|
output = path
}
+ parser.on('--template=PATH', 'An template file.') {|path|
+ template = path
+ }
parser.on('--help', 'Prints this message and quit.') {
puts parser.help
exit true
@@ -25,13 +29,13 @@ def main
unless ARGV.size == 2
abort "wrong number of arguments (#{ARGV.size} for 2)"
end
- process STDIN, out, ARGV[1]
+ process STDIN, out, ARGV[1], template
else
unless ARGV.size == 1
abort "wrong number of arguments (#{ARGV.size} for 1)"
end
File.open(ARGV[0]) {|f|
- process f, out, ARGV[0]
+ process f, out, ARGV[0], template
}
end
if output
@@ -41,10 +45,10 @@ def main
end
end
-def process(f, out, path)
+def process(f, out, path, template)
prelude f, out
grammar f, out
- usercode f, out, path
+ usercode f, out, path, template
end
def prelude(f, out)
@@ -103,12 +107,25 @@ def grammar(f, out)
end
end
-def usercode(f, out, path)
+def usercode(f, out, path, template)
require 'erb'
+ lineno = nil
+ src = nil
compiler = ERB::Compiler.new('%-')
compiler.put_cmd = compiler.insert_cmd = "out.<<"
- lineno = f.lineno
- src, = compiler.compile(f.read)
+
+ if template
+ File.open(template) do |f|
+ out.clear
+ lineno = f.lineno
+ src, = compiler.compile(f.read)
+ path = template
+ end
+ else
+ lineno = f.lineno
+ src, = compiler.compile(f.read)
+ end
+
eval(src, binding, path, lineno)
end
diff --git a/ext/socket/depend b/ext/socket/depend
index 016b6cfc90..675520c0b5 100644
--- a/ext/socket/depend
+++ b/ext/socket/depend
@@ -208,6 +208,7 @@ ancdata.o: $(top_srcdir)/method.h
ancdata.o: $(top_srcdir)/node.h
ancdata.o: $(top_srcdir)/ruby_assert.h
ancdata.o: $(top_srcdir)/ruby_atomic.h
+ancdata.o: $(top_srcdir)/rubyparser.h
ancdata.o: $(top_srcdir)/shape.h
ancdata.o: $(top_srcdir)/thread_pthread.h
ancdata.o: $(top_srcdir)/vm_core.h
@@ -415,6 +416,7 @@ basicsocket.o: $(top_srcdir)/method.h
basicsocket.o: $(top_srcdir)/node.h
basicsocket.o: $(top_srcdir)/ruby_assert.h
basicsocket.o: $(top_srcdir)/ruby_atomic.h
+basicsocket.o: $(top_srcdir)/rubyparser.h
basicsocket.o: $(top_srcdir)/shape.h
basicsocket.o: $(top_srcdir)/thread_pthread.h
basicsocket.o: $(top_srcdir)/vm_core.h
@@ -622,6 +624,7 @@ constants.o: $(top_srcdir)/method.h
constants.o: $(top_srcdir)/node.h
constants.o: $(top_srcdir)/ruby_assert.h
constants.o: $(top_srcdir)/ruby_atomic.h
+constants.o: $(top_srcdir)/rubyparser.h
constants.o: $(top_srcdir)/shape.h
constants.o: $(top_srcdir)/thread_pthread.h
constants.o: $(top_srcdir)/vm_core.h
@@ -830,6 +833,7 @@ ifaddr.o: $(top_srcdir)/method.h
ifaddr.o: $(top_srcdir)/node.h
ifaddr.o: $(top_srcdir)/ruby_assert.h
ifaddr.o: $(top_srcdir)/ruby_atomic.h
+ifaddr.o: $(top_srcdir)/rubyparser.h
ifaddr.o: $(top_srcdir)/shape.h
ifaddr.o: $(top_srcdir)/thread_pthread.h
ifaddr.o: $(top_srcdir)/vm_core.h
@@ -1037,6 +1041,7 @@ init.o: $(top_srcdir)/method.h
init.o: $(top_srcdir)/node.h
init.o: $(top_srcdir)/ruby_assert.h
init.o: $(top_srcdir)/ruby_atomic.h
+init.o: $(top_srcdir)/rubyparser.h
init.o: $(top_srcdir)/shape.h
init.o: $(top_srcdir)/thread_pthread.h
init.o: $(top_srcdir)/vm_core.h
@@ -1244,6 +1249,7 @@ ipsocket.o: $(top_srcdir)/method.h
ipsocket.o: $(top_srcdir)/node.h
ipsocket.o: $(top_srcdir)/ruby_assert.h
ipsocket.o: $(top_srcdir)/ruby_atomic.h
+ipsocket.o: $(top_srcdir)/rubyparser.h
ipsocket.o: $(top_srcdir)/shape.h
ipsocket.o: $(top_srcdir)/thread_pthread.h
ipsocket.o: $(top_srcdir)/vm_core.h
@@ -1451,6 +1457,7 @@ option.o: $(top_srcdir)/method.h
option.o: $(top_srcdir)/node.h
option.o: $(top_srcdir)/ruby_assert.h
option.o: $(top_srcdir)/ruby_atomic.h
+option.o: $(top_srcdir)/rubyparser.h
option.o: $(top_srcdir)/shape.h
option.o: $(top_srcdir)/thread_pthread.h
option.o: $(top_srcdir)/vm_core.h
@@ -1658,6 +1665,7 @@ raddrinfo.o: $(top_srcdir)/method.h
raddrinfo.o: $(top_srcdir)/node.h
raddrinfo.o: $(top_srcdir)/ruby_assert.h
raddrinfo.o: $(top_srcdir)/ruby_atomic.h
+raddrinfo.o: $(top_srcdir)/rubyparser.h
raddrinfo.o: $(top_srcdir)/shape.h
raddrinfo.o: $(top_srcdir)/thread_pthread.h
raddrinfo.o: $(top_srcdir)/vm_core.h
@@ -1865,6 +1873,7 @@ socket.o: $(top_srcdir)/method.h
socket.o: $(top_srcdir)/node.h
socket.o: $(top_srcdir)/ruby_assert.h
socket.o: $(top_srcdir)/ruby_atomic.h
+socket.o: $(top_srcdir)/rubyparser.h
socket.o: $(top_srcdir)/shape.h
socket.o: $(top_srcdir)/thread_pthread.h
socket.o: $(top_srcdir)/vm_core.h
@@ -2072,6 +2081,7 @@ sockssocket.o: $(top_srcdir)/method.h
sockssocket.o: $(top_srcdir)/node.h
sockssocket.o: $(top_srcdir)/ruby_assert.h
sockssocket.o: $(top_srcdir)/ruby_atomic.h
+sockssocket.o: $(top_srcdir)/rubyparser.h
sockssocket.o: $(top_srcdir)/shape.h
sockssocket.o: $(top_srcdir)/thread_pthread.h
sockssocket.o: $(top_srcdir)/vm_core.h
@@ -2279,6 +2289,7 @@ tcpserver.o: $(top_srcdir)/method.h
tcpserver.o: $(top_srcdir)/node.h
tcpserver.o: $(top_srcdir)/ruby_assert.h
tcpserver.o: $(top_srcdir)/ruby_atomic.h
+tcpserver.o: $(top_srcdir)/rubyparser.h
tcpserver.o: $(top_srcdir)/shape.h
tcpserver.o: $(top_srcdir)/thread_pthread.h
tcpserver.o: $(top_srcdir)/vm_core.h
@@ -2486,6 +2497,7 @@ tcpsocket.o: $(top_srcdir)/method.h
tcpsocket.o: $(top_srcdir)/node.h
tcpsocket.o: $(top_srcdir)/ruby_assert.h
tcpsocket.o: $(top_srcdir)/ruby_atomic.h
+tcpsocket.o: $(top_srcdir)/rubyparser.h
tcpsocket.o: $(top_srcdir)/shape.h
tcpsocket.o: $(top_srcdir)/thread_pthread.h
tcpsocket.o: $(top_srcdir)/vm_core.h
@@ -2693,6 +2705,7 @@ udpsocket.o: $(top_srcdir)/method.h
udpsocket.o: $(top_srcdir)/node.h
udpsocket.o: $(top_srcdir)/ruby_assert.h
udpsocket.o: $(top_srcdir)/ruby_atomic.h
+udpsocket.o: $(top_srcdir)/rubyparser.h
udpsocket.o: $(top_srcdir)/shape.h
udpsocket.o: $(top_srcdir)/thread_pthread.h
udpsocket.o: $(top_srcdir)/vm_core.h
@@ -2900,6 +2913,7 @@ unixserver.o: $(top_srcdir)/method.h
unixserver.o: $(top_srcdir)/node.h
unixserver.o: $(top_srcdir)/ruby_assert.h
unixserver.o: $(top_srcdir)/ruby_atomic.h
+unixserver.o: $(top_srcdir)/rubyparser.h
unixserver.o: $(top_srcdir)/shape.h
unixserver.o: $(top_srcdir)/thread_pthread.h
unixserver.o: $(top_srcdir)/vm_core.h
@@ -3107,6 +3121,7 @@ unixsocket.o: $(top_srcdir)/method.h
unixsocket.o: $(top_srcdir)/node.h
unixsocket.o: $(top_srcdir)/ruby_assert.h
unixsocket.o: $(top_srcdir)/ruby_atomic.h
+unixsocket.o: $(top_srcdir)/rubyparser.h
unixsocket.o: $(top_srcdir)/shape.h
unixsocket.o: $(top_srcdir)/thread_pthread.h
unixsocket.o: $(top_srcdir)/vm_core.h
diff --git a/internal/gc.h b/internal/gc.h
index d19b09f6fc..e345f20cb6 100644
--- a/internal/gc.h
+++ b/internal/gc.h
@@ -302,6 +302,12 @@ ruby_sized_xfree_inlined(void *ptr, size_t size)
# define SIZED_REALLOC_N(x, y, z, w) REALLOC_N(x, y, z)
+static inline void *
+ruby_sized_realloc_n(void *ptr, size_t new_count, size_t element_size, size_t old_count)
+{
+ return ruby_xrealloc2(ptr, new_count, element_size);
+}
+
#else
static inline void *
@@ -325,6 +331,12 @@ ruby_sized_xfree_inlined(void *ptr, size_t size)
# define SIZED_REALLOC_N(v, T, m, n) \
((v) = (T *)ruby_sized_xrealloc2((void *)(v), (m), sizeof(T), (n)))
+static inline void *
+ruby_sized_realloc_n(void *ptr, size_t new_count, size_t element_size, size_t old_count)
+{
+ return ruby_sized_xrealloc2(ptr, new_count, element_size, old_count);
+}
+
#endif /* HAVE_MALLOC_USABLE_SIZE */
#define ruby_sized_xrealloc ruby_sized_xrealloc_inlined
diff --git a/internal/parse.h b/internal/parse.h
index f242c384ad..9e257cf39d 100644
--- a/internal/parse.h
+++ b/internal/parse.h
@@ -8,18 +8,121 @@
* file COPYING are met. Consult the file for details.
* @brief Internal header for the parser.
*/
-#include "ruby/ruby.h" /* for VALUE */
+#include <limits.h>
+#include "rubyparser.h"
+#include "internal/static_assert.h"
+
+#ifdef UNIVERSAL_PARSER
+#define rb_encoding void
+#endif
+
struct rb_iseq_struct; /* in vm_core.h */
+#define STRTERM_HEREDOC IMEMO_FL_USER0
+
+/* structs for managing terminator of string literal and heredocment */
+typedef struct rb_strterm_literal_struct {
+ union {
+ VALUE dummy;
+ long nest;
+ } u0;
+ union {
+ VALUE dummy;
+ long func; /* STR_FUNC_* (e.g., STR_FUNC_ESCAPE and STR_FUNC_EXPAND) */
+ } u1;
+ union {
+ VALUE dummy;
+ long paren; /* '(' of `%q(...)` */
+ } u2;
+ union {
+ VALUE dummy;
+ long term; /* ')' of `%q(...)` */
+ } u3;
+} rb_strterm_literal_t;
+
+#define HERETERM_LENGTH_BITS ((SIZEOF_VALUE - 1) * CHAR_BIT - 1)
+
+typedef struct rb_strterm_heredoc_struct {
+ VALUE lastline; /* the string of line that contains `<<"END"` */
+ long offset; /* the column of END in `<<"END"` */
+ int sourceline; /* lineno of the line that contains `<<"END"` */
+ unsigned length /* the length of END in `<<"END"` */
+#if HERETERM_LENGTH_BITS < SIZEOF_INT * CHAR_BIT
+ : HERETERM_LENGTH_BITS
+# define HERETERM_LENGTH_MAX ((1U << HERETERM_LENGTH_BITS) - 1)
+#else
+# define HERETERM_LENGTH_MAX UINT_MAX
+#endif
+ ;
+#if HERETERM_LENGTH_BITS < SIZEOF_INT * CHAR_BIT
+ unsigned quote: 1;
+ unsigned func: 8;
+#else
+ uint8_t quote;
+ uint8_t func;
+#endif
+} rb_strterm_heredoc_t;
+STATIC_ASSERT(rb_strterm_heredoc_t, sizeof(rb_strterm_heredoc_t) <= 4 * SIZEOF_VALUE);
+
+typedef struct rb_strterm_struct {
+ VALUE flags;
+ union {
+ rb_strterm_literal_t literal;
+ rb_strterm_heredoc_t heredoc;
+ } u;
+} rb_strterm_t;
+
/* parse.y */
-VALUE rb_parser_set_yydebug(VALUE, VALUE);
-void *rb_parser_load_file(VALUE parser, VALUE name);
-void rb_parser_keep_script_lines(VALUE vparser);
-void rb_parser_error_tolerant(VALUE vparser);
-void rb_parser_keep_tokens(VALUE vparser);
-
-RUBY_SYMBOL_EXPORT_BEGIN
-VALUE rb_parser_set_context(VALUE, const struct rb_iseq_struct *, int);
-RUBY_SYMBOL_EXPORT_END
+void rb_ruby_parser_mark(void *ptr);
+size_t rb_ruby_parser_memsize(const void *ptr);
+
+void rb_ruby_parser_set_options(rb_parser_t *p, int print, int loop, int chomp, int split);
+rb_parser_t *rb_ruby_parser_set_context(rb_parser_t *p, const struct rb_iseq_struct *base, int main);
+void rb_ruby_parser_keep_script_lines(rb_parser_t *p);
+void rb_ruby_parser_error_tolerant(rb_parser_t *p);
+rb_ast_t* rb_ruby_parser_compile_file_path(rb_parser_t *p, VALUE fname, VALUE file, int start);
+void rb_ruby_parser_keep_tokens(rb_parser_t *p);
+rb_ast_t* rb_ruby_parser_compile_generic(rb_parser_t *p, VALUE (*lex_gets)(VALUE, int), VALUE fname, VALUE input, int start);
+rb_ast_t* rb_ruby_parser_compile_string_path(rb_parser_t *p, VALUE f, VALUE s, int line);
+VALUE rb_ruby_parser_encoding(rb_parser_t *p);
+int rb_ruby_parser_end_seen_p(rb_parser_t *p);
+int rb_ruby_parser_set_yydebug(rb_parser_t *p, int flag);
+
+int rb_reg_named_capture_assign_iter_impl(struct parser_params *p, const char *s, long len, rb_encoding *enc, NODE **succ_block, const rb_code_location_t *loc);
+
+#ifdef RIPPER
+void ripper_parser_mark(void *ptr);
+void ripper_parser_free(void *ptr);
+size_t ripper_parser_memsize(const void *ptr);
+void ripper_error(struct parser_params *p);
+VALUE ripper_value(struct parser_params *p);
+int rb_ruby_parser_get_yydebug(rb_parser_t *p);
+void rb_ruby_parser_set_value(rb_parser_t *p, VALUE value);
+int rb_ruby_parser_error_p(rb_parser_t *p);
+VALUE rb_ruby_parser_debug_output(rb_parser_t *p);
+void rb_ruby_parser_set_debug_output(rb_parser_t *p, VALUE output);
+VALUE rb_ruby_parser_parsing_thread(rb_parser_t *p);
+void rb_ruby_parser_set_parsing_thread(rb_parser_t *p, VALUE parsing_thread);
+void rb_ruby_parser_ripper_initialize(rb_parser_t *p, VALUE (*gets)(struct parser_params*,VALUE), VALUE input, VALUE sourcefile_string, const char *sourcefile, int sourceline);
+VALUE rb_ruby_parser_result(rb_parser_t *p);
+rb_encoding *rb_ruby_parser_enc(rb_parser_t *p);
+VALUE rb_ruby_parser_ruby_sourcefile_string(rb_parser_t *p);
+int rb_ruby_parser_ruby_sourceline(rb_parser_t *p);
+int rb_ruby_parser_lex_state(rb_parser_t *p);
+void rb_ruby_ripper_parse0(rb_parser_t *p);
+int rb_ruby_ripper_dedent_string(rb_parser_t *p, VALUE string, int width);
+VALUE rb_ruby_ripper_lex_get_str(rb_parser_t *p, VALUE s);
+int rb_ruby_ripper_initialized_p(rb_parser_t *p);
+void rb_ruby_ripper_parser_initialize(rb_parser_t *p);
+long rb_ruby_ripper_column(rb_parser_t *p);
+long rb_ruby_ripper_token_len(rb_parser_t *p);
+VALUE rb_ruby_ripper_lex_lastline(rb_parser_t *p);
+VALUE rb_ruby_ripper_lex_state_name(struct parser_params *p, int state);
+struct parser_params *rb_ruby_ripper_parser_allocate(void);
+#endif
+
+#ifdef UNIVERSAL_PARSER
+#undef rb_encoding
+#endif
#endif /* INTERNAL_PARSE_H */
diff --git a/internal/ruby_parser.h b/internal/ruby_parser.h
new file mode 100644
index 0000000000..97ac49dd3b
--- /dev/null
+++ b/internal/ruby_parser.h
@@ -0,0 +1,68 @@
+#ifndef INTERNAL_RUBY_PARSE_H
+#define INTERNAL_RUBY_PARSE_H
+
+#include "rubyparser.h"
+#include "internal.h"
+#include "vm.h"
+
+RUBY_SYMBOL_EXPORT_BEGIN
+#ifdef UNIVERSAL_PARSER
+void rb_parser_config_initialize(rb_parser_config_t *config);
+#endif
+VALUE rb_parser_set_context(VALUE, const struct rb_iseq_struct *, int);
+RUBY_SYMBOL_EXPORT_END
+
+VALUE rb_parser_new(void);
+VALUE rb_parser_end_seen_p(VALUE);
+VALUE rb_parser_encoding(VALUE);
+VALUE rb_parser_set_yydebug(VALUE, VALUE);
+void rb_parser_set_options(VALUE, int, int, int, int);
+void *rb_parser_load_file(VALUE parser, VALUE name);
+void rb_parser_keep_script_lines(VALUE vparser);
+void rb_parser_error_tolerant(VALUE vparser);
+void rb_parser_keep_tokens(VALUE vparser);
+
+rb_ast_t *rb_parser_compile_string(VALUE, const char*, VALUE, int);
+rb_ast_t *rb_parser_compile_string_path(VALUE vparser, VALUE fname, VALUE src, int line);
+rb_ast_t *rb_parser_compile_file_path(VALUE vparser, VALUE fname, VALUE input, int line);
+rb_ast_t *rb_parser_compile_generic(VALUE vparser, VALUE (*lex_gets)(VALUE, int), VALUE fname, VALUE input, int line);
+
+enum lex_state_bits {
+ EXPR_BEG_bit, /* ignore newline, +/- is a sign. */
+ EXPR_END_bit, /* newline significant, +/- is an operator. */
+ EXPR_ENDARG_bit, /* ditto, and unbound braces. */
+ EXPR_ENDFN_bit, /* ditto, and unbound braces. */
+ EXPR_ARG_bit, /* newline significant, +/- is an operator. */
+ EXPR_CMDARG_bit, /* newline significant, +/- is an operator. */
+ EXPR_MID_bit, /* newline significant, +/- is an operator. */
+ EXPR_FNAME_bit, /* ignore newline, no reserved words. */
+ EXPR_DOT_bit, /* right after `.', `&.' or `::', no reserved words. */
+ EXPR_CLASS_bit, /* immediate after `class', no here document. */
+ EXPR_LABEL_bit, /* flag bit, label is allowed. */
+ EXPR_LABELED_bit, /* flag bit, just after a label. */
+ EXPR_FITEM_bit, /* symbol literal as FNAME. */
+ EXPR_MAX_STATE
+};
+/* examine combinations */
+enum lex_state_e {
+#define DEF_EXPR(n) EXPR_##n = (1 << EXPR_##n##_bit)
+ DEF_EXPR(BEG),
+ DEF_EXPR(END),
+ DEF_EXPR(ENDARG),
+ DEF_EXPR(ENDFN),
+ DEF_EXPR(ARG),
+ DEF_EXPR(CMDARG),
+ DEF_EXPR(MID),
+ DEF_EXPR(FNAME),
+ DEF_EXPR(DOT),
+ DEF_EXPR(CLASS),
+ DEF_EXPR(LABEL),
+ DEF_EXPR(LABELED),
+ DEF_EXPR(FITEM),
+ EXPR_VALUE = EXPR_BEG,
+ EXPR_BEG_ANY = (EXPR_BEG | EXPR_MID | EXPR_CLASS),
+ EXPR_ARG_ANY = (EXPR_ARG | EXPR_CMDARG),
+ EXPR_END_ANY = (EXPR_END | EXPR_ENDARG | EXPR_ENDFN),
+ EXPR_NONE = 0
+};
+#endif /* INTERNAL_RUBY_PARSE_H */
diff --git a/iseq.c b/iseq.c
index bbeb537053..6d8596528e 100644
--- a/iseq.c
+++ b/iseq.c
@@ -28,7 +28,7 @@
#include "internal/file.h"
#include "internal/gc.h"
#include "internal/hash.h"
-#include "internal/parse.h"
+#include "internal/ruby_parser.h"
#include "internal/sanitizers.h"
#include "internal/symbol.h"
#include "internal/thread.h"
diff --git a/load.c b/load.c
index da81becfc1..debc544038 100644
--- a/load.c
+++ b/load.c
@@ -9,7 +9,7 @@
#include "internal/error.h"
#include "internal/file.h"
#include "internal/load.h"
-#include "internal/parse.h"
+#include "internal/ruby_parser.h"
#include "internal/thread.h"
#include "internal/variable.h"
#include "iseq.h"
diff --git a/node.c b/node.c
index 027b00ed06..1d3b7b75e4 100644
--- a/node.c
+++ b/node.c
@@ -9,1119 +9,40 @@
**********************************************************************/
+#ifdef UNIVERSAL_PARSER
+
+#include <stddef.h>
+#include "node.h"
+#include "rubyparser.h"
+#include "internal/parse.h"
+#define T_NODE 0x1b
+
+#define ruby_xmalloc ast->node_buffer->config->malloc
+#undef xfree
+#define xfree ast->node_buffer->config->free
+#define rb_ident_hash_new ast->node_buffer->config->ident_hash_new
+#define rb_xmalloc_mul_add ast->node_buffer->config->xmalloc_mul_add
+#define ruby_xrealloc(var,size) (ast->node_buffer->config->realloc_n((void *)var, 1, size))
+#define rb_gc_mark ast->node_buffer->config->gc_mark
+#define rb_gc_location ast->node_buffer->config->gc_location
+#define rb_gc_mark_movable ast->node_buffer->config->gc_mark_movable
+#define Qnil ast->node_buffer->config->qnil
+#define Qtrue ast->node_buffer->config->qtrue
+#define NIL_P ast->node_buffer->config->nil_p
+#define rb_hash_aset ast->node_buffer->config->hash_aset
+#define RB_OBJ_WRITE(old, slot, young) ast->node_buffer->config->obj_write((VALUE)(old), (VALUE *)(slot), (VALUE)(young))
+
+#else
+
#include "internal.h"
#include "internal/hash.h"
#include "internal/variable.h"
#include "ruby/ruby.h"
#include "vm_core.h"
-#define NODE_BUF_DEFAULT_LEN 16
-
-#define A(str) rb_str_cat2(buf, (str))
-#define AR(str) rb_str_concat(buf, (str))
-
-#define A_INDENT add_indent(buf, indent)
-#define D_INDENT rb_str_cat2(indent, next_indent)
-#define D_DEDENT rb_str_resize(indent, RSTRING_LEN(indent) - 4)
-#define A_ID(id) add_id(buf, (id))
-#define A_INT(val) rb_str_catf(buf, "%d", (val))
-#define A_LONG(val) rb_str_catf(buf, "%ld", (val))
-#define A_LIT(lit) AR(rb_dump_literal(lit))
-#define A_NODE_HEADER(node, term) \
- rb_str_catf(buf, "@ %s (id: %d, line: %d, location: (%d,%d)-(%d,%d))%s"term, \
- ruby_node_name(nd_type(node)), nd_node_id(node), nd_line(node), \
- nd_first_lineno(node), nd_first_column(node), \
- nd_last_lineno(node), nd_last_column(node), \
- (node->flags & NODE_FL_NEWLINE ? "*" : ""))
-#define A_FIELD_HEADER(len, name, term) \
- rb_str_catf(buf, "+- %.*s:"term, (len), (name))
-#define D_FIELD_HEADER(len, name, term) (A_INDENT, A_FIELD_HEADER(len, name, term))
-
-#define D_NULL_NODE (A_INDENT, A("(null node)\n"))
-#define D_NODE_HEADER(node) (A_INDENT, A_NODE_HEADER(node, "\n"))
-
-#define COMPOUND_FIELD(len, name) \
- FIELD_BLOCK((D_FIELD_HEADER((len), (name), "\n"), D_INDENT), D_DEDENT)
-
-#define COMPOUND_FIELD1(name, ann) \
- COMPOUND_FIELD(FIELD_NAME_LEN(name, ann), \
- FIELD_NAME_DESC(name, ann))
-
-#define FIELD_NAME_DESC(name, ann) name " (" ann ")"
-#define FIELD_NAME_LEN(name, ann) (int)( \
- comment ? \
- rb_strlen_lit(FIELD_NAME_DESC(name, ann)) : \
- rb_strlen_lit(name))
-#define SIMPLE_FIELD(len, name) \
- FIELD_BLOCK(D_FIELD_HEADER((len), (name), " "), A("\n"))
-
-#define FIELD_BLOCK(init, reset) \
- for (init, field_flag = 1; \
- field_flag; /* should be optimized away */ \
- reset, field_flag = 0)
-
-#define SIMPLE_FIELD1(name, ann) SIMPLE_FIELD(FIELD_NAME_LEN(name, ann), FIELD_NAME_DESC(name, ann))
-#define F_CUSTOM1(name, ann) SIMPLE_FIELD1(#name, ann)
-#define F_ID(name, ann) SIMPLE_FIELD1(#name, ann) A_ID(node->name)
-#define F_GENTRY(name, ann) SIMPLE_FIELD1(#name, ann) A_ID(node->name)
-#define F_INT(name, ann) SIMPLE_FIELD1(#name, ann) A_INT(node->name)
-#define F_LONG(name, ann) SIMPLE_FIELD1(#name, ann) A_LONG(node->name)
-#define F_LIT(name, ann) SIMPLE_FIELD1(#name, ann) A_LIT(node->name)
-#define F_MSG(name, ann, desc) SIMPLE_FIELD1(#name, ann) A(desc)
-
-#define F_NODE(name, ann) \
- COMPOUND_FIELD1(#name, ann) {dump_node(buf, indent, comment, node->name);}
-
-#define ANN(ann) \
- if (comment) { \
- A_INDENT; A("| # " ann "\n"); \
- }
-
-#define LAST_NODE (next_indent = " ")
-
-VALUE
-rb_dump_literal(VALUE lit)
-{
- if (!RB_SPECIAL_CONST_P(lit)) {
- VALUE str;
- switch (RB_BUILTIN_TYPE(lit)) {
- case T_CLASS: case T_MODULE: case T_ICLASS:
- str = rb_class_path(lit);
- if (FL_TEST(lit, FL_SINGLETON)) {
- str = rb_sprintf("<%"PRIsVALUE">", str);
- }
- return str;
- default:
- break;
- }
- }
- return rb_inspect(lit);
-}
-
-static void
-add_indent(VALUE buf, VALUE indent)
-{
- AR(indent);
-}
-
-static void
-add_id(VALUE buf, ID id)
-{
- if (id == 0) {
- A("(null)");
- }
- else {
- VALUE str = rb_id2str(id);
- if (str) {
- A(":"); AR(str);
- }
- else {
- rb_str_catf(buf, "(internal variable: 0x%"PRIsVALUE")", id);
- }
- }
-}
-
-struct add_option_arg {
- VALUE buf, indent;
- st_index_t count;
-};
-
-static void dump_node(VALUE, VALUE, int, const NODE *);
-static const char default_indent[] = "| ";
-
-static void
-dump_array(VALUE buf, VALUE indent, int comment, const NODE *node)
-{
- int field_flag;
- const char *next_indent = default_indent;
- F_LONG(nd_alen, "length");
- F_NODE(nd_head, "element");
- while (node->nd_next && nd_type_p(node->nd_next, NODE_LIST)) {
- node = node->nd_next;
- F_NODE(nd_head, "element");
- }
- LAST_NODE;
- F_NODE(nd_next, "next element");
-}
-
-static void
-dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
-{
- int field_flag;
- int i;
- const char *next_indent = default_indent;
- enum node_type type;
-
- if (!node) {
- D_NULL_NODE;
- return;
- }
-
- D_NODE_HEADER(node);
-
- type = nd_type(node);
- switch (type) {
- case NODE_BLOCK:
- ANN("statement sequence");
- ANN("format: [nd_head]; ...; [nd_next]");
- ANN("example: foo; bar");
- i = 0;
- do {
- A_INDENT;
- rb_str_catf(buf, "+- nd_head (%s%d):\n",
- comment ? "statement #" : "", ++i);
- if (!node->nd_next) LAST_NODE;
- D_INDENT;
- dump_node(buf, indent, comment, node->nd_head);
- D_DEDENT;
- } while (node->nd_next &&
- nd_type_p(node->nd_next, NODE_BLOCK) &&
- (node = node->nd_next, 1));
- if (node->nd_next) {
- LAST_NODE;
- F_NODE(nd_next, "next block");
- }
- return;
-
- case NODE_IF:
- ANN("if statement");
- ANN("format: if [nd_cond] then [nd_body] else [nd_else] end");
- ANN("example: if x == 1 then foo else bar end");
- F_NODE(nd_cond, "condition expr");
- F_NODE(nd_body, "then clause");
- LAST_NODE;
- F_NODE(nd_else, "else clause");
- return;
-
- case NODE_UNLESS:
- ANN("unless statement");
- ANN("format: unless [nd_cond] then [nd_body] else [nd_else] end");
- ANN("example: unless x == 1 then foo else bar end");
- F_NODE(nd_cond, "condition expr");
- F_NODE(nd_body, "then clause");
- LAST_NODE;
- F_NODE(nd_else, "else clause");
- return;
-
- case NODE_CASE:
- ANN("case statement");
- ANN("format: case [nd_head]; [nd_body]; end");
- ANN("example: case x; when 1; foo; when 2; bar; else baz; end");
- F_NODE(nd_head, "case expr");
- LAST_NODE;
- F_NODE(nd_body, "when clauses");
- return;
- case NODE_CASE2:
- ANN("case statement with no head");
- ANN("format: case; [nd_body]; end");
- ANN("example: case; when 1; foo; when 2; bar; else baz; end");
- F_NODE(nd_head, "case expr");
- LAST_NODE;
- F_NODE(nd_body, "when clauses");
- return;
- case NODE_CASE3:
- ANN("case statement (pattern matching)");
- ANN("format: case [nd_head]; [nd_body]; end");
- ANN("example: case x; in 1; foo; in 2; bar; else baz; end");
- F_NODE(nd_head, "case expr");
- LAST_NODE;
- F_NODE(nd_body, "in clauses");
- return;
-
- case NODE_WHEN:
- ANN("when clause");
- ANN("format: when [nd_head]; [nd_body]; (when or else) [nd_next]");
- ANN("example: case x; when 1; foo; when 2; bar; else baz; end");
- F_NODE(nd_head, "when value");
- F_NODE(nd_body, "when body");
- LAST_NODE;
- F_NODE(nd_next, "next when clause");
- return;
-
- case NODE_IN:
- ANN("in clause");
- ANN("format: in [nd_head]; [nd_body]; (in or else) [nd_next]");
- ANN("example: case x; in 1; foo; in 2; bar; else baz; end");
- F_NODE(nd_head, "in pattern");
- F_NODE(nd_body, "in body");
- LAST_NODE;
- F_NODE(nd_next, "next in clause");
- return;
-
- case NODE_WHILE:
- ANN("while statement");
- ANN("format: while [nd_cond]; [nd_body]; end");
- ANN("example: while x == 1; foo; end");
- goto loop;
- case NODE_UNTIL:
- ANN("until statement");
- ANN("format: until [nd_cond]; [nd_body]; end");
- ANN("example: until x == 1; foo; end");
- loop:
- F_CUSTOM1(nd_state, "begin-end-while?") {
- A_INT((int)node->nd_state);
- A((node->nd_state == 1) ? " (while-end)" : " (begin-end-while)");
- }
- F_NODE(nd_cond, "condition");
- LAST_NODE;
- F_NODE(nd_body, "body");
- return;
-
- case NODE_ITER:
- ANN("method call with block");
- ANN("format: [nd_iter] { [nd_body] }");
- ANN("example: 3.times { foo }");
- goto iter;
- case NODE_FOR:
- ANN("for statement");
- ANN("format: for * in [nd_iter] do [nd_body] end");
- ANN("example: for i in 1..3 do foo end");
- iter:
- F_NODE(nd_iter, "iteration receiver");
- LAST_NODE;
- F_NODE(nd_body, "body");
- return;
-
- case NODE_FOR_MASGN:
- ANN("vars of for statement with masgn");
- ANN("format: for [nd_var] in ... do ... end");
- ANN("example: for x, y in 1..3 do foo end");
- LAST_NODE;
- F_NODE(nd_var, "var");
- return;
-
- case NODE_BREAK:
- ANN("break statement");
- ANN("format: break [nd_stts]");
- ANN("example: break 1");
- goto jump;
- case NODE_NEXT:
- ANN("next statement");
- ANN("format: next [nd_stts]");
- ANN("example: next 1");
- goto jump;
- case NODE_RETURN:
- ANN("return statement");
- ANN("format: return [nd_stts]");
- ANN("example: return 1");
- jump:
- LAST_NODE;
- F_NODE(nd_stts, "value");
- return;
-
- case NODE_REDO:
- ANN("redo statement");
- ANN("format: redo");
- ANN("example: redo");
- return;
-
- case NODE_RETRY:
- ANN("retry statement");
- ANN("format: retry");
- ANN("example: retry");
- return;
-
- case NODE_BEGIN:
- ANN("begin statement");
- ANN("format: begin; [nd_body]; end");
- ANN("example: begin; 1; end");
- LAST_NODE;
- F_NODE(nd_body, "body");
- return;
-
- case NODE_RESCUE:
- ANN("rescue clause");
- ANN("format: begin; [nd_body]; (rescue) [nd_resq]; else [nd_else]; end");
- ANN("example: begin; foo; rescue; bar; else; baz; end");
- F_NODE(nd_head, "body");
- F_NODE(nd_resq, "rescue clause list");
- LAST_NODE;
- F_NODE(nd_else, "rescue else clause");
- return;
-
- case NODE_RESBODY:
- ANN("rescue clause (cont'd)");
- ANN("format: rescue [nd_args]; [nd_body]; (rescue) [nd_head]");
- ANN("example: begin; foo; rescue; bar; else; baz; end");
- F_NODE(nd_args, "rescue exceptions");
- F_NODE(nd_body, "rescue clause");
- LAST_NODE;
- F_NODE(nd_head, "next rescue clause");
- return;
-
- case NODE_ENSURE:
- ANN("ensure clause");
- ANN("format: begin; [nd_head]; ensure; [nd_ensr]; end");
- ANN("example: begin; foo; ensure; bar; end");
- F_NODE(nd_head, "body");
- LAST_NODE;
- F_NODE(nd_ensr, "ensure clause");
- return;
-
- case NODE_AND:
- ANN("&& operator");
- ANN("format: [nd_1st] && [nd_2nd]");
- ANN("example: foo && bar");
- goto andor;
- case NODE_OR:
- ANN("|| operator");
- ANN("format: [nd_1st] || [nd_2nd]");
- ANN("example: foo || bar");
- andor:
- while (1) {
- F_NODE(nd_1st, "left expr");
- if (!node->nd_2nd || !nd_type_p(node->nd_2nd, type))
- break;
- node = node->nd_2nd;
- }
- LAST_NODE;
- F_NODE(nd_2nd, "right expr");
- return;
-
- case NODE_MASGN:
- ANN("multiple assignment");
- ANN("format: [nd_head], [nd_args] = [nd_value]");
- ANN("example: a, b = foo");
- F_NODE(nd_value, "rhsn");
- F_NODE(nd_head, "lhsn");
- if (NODE_NAMED_REST_P(node->nd_args)) {
- LAST_NODE;
- F_NODE(nd_args, "splatn");
- }
- else {
- F_MSG(nd_args, "splatn", "NODE_SPECIAL_NO_NAME_REST (rest argument without name)");
- }
- return;
-
- case NODE_LASGN:
- ANN("local variable assignment");
- ANN("format: [nd_vid](lvar) = [nd_value]");
- ANN("example: x = foo");
- F_ID(nd_vid, "local variable");
- if (NODE_REQUIRED_KEYWORD_P(node)) {
- F_MSG(nd_value, "rvalue", "NODE_SPECIAL_REQUIRED_KEYWORD (required keyword argument)");
- }
- else {
- LAST_NODE;
- F_NODE(nd_value, "rvalue");
- }
- return;
- case NODE_DASGN:
- ANN("dynamic variable assignment");
- ANN("format: [nd_vid](dvar) = [nd_value]");
- ANN("example: x = nil; 1.times { x = foo }");
- ANN("example: 1.times { x = foo }");
- F_ID(nd_vid, "local variable");
- if (NODE_REQUIRED_KEYWORD_P(node)) {
- F_MSG(nd_value, "rvalue", "NODE_SPECIAL_REQUIRED_KEYWORD (required keyword argument)");
- }
- else {
- LAST_NODE;
- F_NODE(nd_value, "rvalue");
- }
- return;
- case NODE_IASGN:
- ANN("instance variable assignment");
- ANN("format: [nd_vid](ivar) = [nd_value]");
- ANN("example: @x = foo");
- F_ID(nd_vid, "instance variable");
- LAST_NODE;
- F_NODE(nd_value, "rvalue");
- return;
- case NODE_CVASGN:
- ANN("class variable assignment");
- ANN("format: [nd_vid](cvar) = [nd_value]");
- ANN("example: @@x = foo");
- F_ID(nd_vid, "class variable");
- LAST_NODE;
- F_NODE(nd_value, "rvalue");
- return;
- case NODE_GASGN:
- ANN("global variable assignment");
- ANN("format: [nd_entry](gvar) = [nd_value]");
- ANN("example: $x = foo");
- F_GENTRY(nd_entry, "global variable");
- LAST_NODE;
- F_NODE(nd_value, "rvalue");
- return;
-
- case NODE_CDECL:
- ANN("constant declaration");
- ANN("format: [nd_else]::[nd_vid](constant) = [nd_value]");
- ANN("example: X = foo");
- if (node->nd_vid) {
- F_ID(nd_vid, "constant");
- F_MSG(nd_else, "extension", "not used");
- }
- else {
- F_MSG(nd_vid, "constant", "0 (see extension field)");
- F_NODE(nd_else, "extension");
- }
- LAST_NODE;
- F_NODE(nd_value, "rvalue");
- return;
-
- case NODE_OP_ASGN1:
- ANN("array assignment with operator");
- ANN("format: [nd_recv] [ [nd_args->nd_head] ] [nd_mid]= [nd_args->nd_body]");
- ANN("example: ary[1] += foo");
- F_NODE(nd_recv, "receiver");
- F_ID(nd_mid, "operator");
- F_NODE(nd_args->nd_head, "index");
- LAST_NODE;
- F_NODE(nd_args->nd_body, "rvalue");
- return;
-
- case NODE_OP_ASGN2:
- ANN("attr assignment with operator");
- ANN("format: [nd_recv].[attr] [nd_next->nd_mid]= [nd_value]");
- ANN(" where [attr]: [nd_next->nd_vid]");
- ANN("example: struct.field += foo");
- F_NODE(nd_recv, "receiver");
- F_CUSTOM1(nd_next->nd_vid, "attr") {
- if (node->nd_next->nd_aid) A("? ");
- A_ID(node->nd_next->nd_vid);
- }
- F_ID(nd_next->nd_mid, "operator");
- LAST_NODE;
- F_NODE(nd_value, "rvalue");
- return;
-
- case NODE_OP_ASGN_AND:
- ANN("assignment with && operator");
- ANN("format: [nd_head] &&= [nd_value]");
- ANN("example: foo &&= bar");
- goto asgn_andor;
- case NODE_OP_ASGN_OR:
- ANN("assignment with || operator");
- ANN("format: [nd_head] ||= [nd_value]");
- ANN("example: foo ||= bar");
- asgn_andor:
- F_NODE(nd_head, "variable");
- LAST_NODE;
- F_NODE(nd_value, "rvalue");
- return;
-
- case NODE_OP_CDECL:
- ANN("constant declaration with operator");
- ANN("format: [nd_head](constant) [nd_aid]= [nd_value]");
- ANN("example: A::B ||= 1");
- F_NODE(nd_head, "constant");
- F_ID(nd_aid, "operator");
- LAST_NODE;
- F_NODE(nd_value, "rvalue");
- return;
-
- case NODE_CALL:
- ANN("method invocation");
- ANN("format: [nd_recv].[nd_mid]([nd_args])");
- ANN("example: obj.foo(1)");
- F_ID(nd_mid, "method id");
- F_NODE(nd_recv, "receiver");
- LAST_NODE;
- F_NODE(nd_args, "arguments");
- return;
-
- case NODE_OPCALL:
- ANN("method invocation");
- ANN("format: [nd_recv] [nd_mid] [nd_args]");
- ANN("example: foo + bar");
- F_ID(nd_mid, "method id");
- F_NODE(nd_recv, "receiver");
- LAST_NODE;
- F_NODE(nd_args, "arguments");
- return;
-
- case NODE_FCALL:
- ANN("function call");
- ANN("format: [nd_mid]([nd_args])");
- ANN("example: foo(1)");
- F_ID(nd_mid, "method id");
- LAST_NODE;
- F_NODE(nd_args, "arguments");
- return;
-
- case NODE_VCALL:
- ANN("function call with no argument");
- ANN("format: [nd_mid]");
- ANN("example: foo");
- F_ID(nd_mid, "method id");
- return;
-
- case NODE_QCALL:
- ANN("safe method invocation");
- ANN("format: [nd_recv]&.[nd_mid]([nd_args])");
- ANN("example: obj&.foo(1)");
- F_ID(nd_mid, "method id");
- F_NODE(nd_recv, "receiver");
- LAST_NODE;
- F_NODE(nd_args, "arguments");
- return;
-
- case NODE_SUPER:
- ANN("super invocation");
- ANN("format: super [nd_args]");
- ANN("example: super 1");
- LAST_NODE;
- F_NODE(nd_args, "arguments");
- return;
-
- case NODE_ZSUPER:
- ANN("super invocation with no argument");
- ANN("format: super");
- ANN("example: super");
- return;
-
- case NODE_LIST:
- ANN("list constructor");
- ANN("format: [ [nd_head], [nd_next].. ] (length: [nd_alen])");
- ANN("example: [1, 2, 3]");
- goto ary;
- case NODE_VALUES:
- ANN("return arguments");
- ANN("format: [ [nd_head], [nd_next].. ] (length: [nd_alen])");
- ANN("example: return 1, 2, 3");
- ary:
- dump_array(buf, indent, comment, node);
- return;
-
- case NODE_ZLIST:
- ANN("empty list constructor");
- ANN("format: []");
- ANN("example: []");
- return;
-
- case NODE_HASH:
- if (!node->nd_brace) {
- ANN("keyword arguments");
- ANN("format: nd_head");
- ANN("example: a: 1, b: 2");
- }
- else {
- ANN("hash constructor");
- ANN("format: { [nd_head] }");
- ANN("example: { 1 => 2, 3 => 4 }");
- }
- F_CUSTOM1(nd_brace, "keyword arguments or hash literal") {
- switch (node->nd_brace) {
- case 0: A("0 (keyword argument)"); break;
- case 1: A("1 (hash literal)"); break;
- }
- }
- LAST_NODE;
- F_NODE(nd_head, "contents");
- return;
-
- case NODE_YIELD:
- ANN("yield invocation");
- ANN("format: yield [nd_head]");
- ANN("example: yield 1");
- LAST_NODE;
- F_NODE(nd_head, "arguments");
- return;
-
- case NODE_LVAR:
- ANN("local variable reference");
- ANN("format: [nd_vid](lvar)");
- ANN("example: x");
- F_ID(nd_vid, "local variable");
- return;
- case NODE_DVAR:
- ANN("dynamic variable reference");
- ANN("format: [nd_vid](dvar)");
- ANN("example: 1.times { x = 1; x }");
- F_ID(nd_vid, "local variable");
- return;
- case NODE_IVAR:
- ANN("instance variable reference");
- ANN("format: [nd_vid](ivar)");
- ANN("example: @x");
- F_ID(nd_vid, "instance variable");
- return;
- case NODE_CONST:
- ANN("constant reference");
- ANN("format: [nd_vid](constant)");
- ANN("example: X");
- F_ID(nd_vid, "constant");
- return;
- case NODE_CVAR:
- ANN("class variable reference");
- ANN("format: [nd_vid](cvar)");
- ANN("example: @@x");
- F_ID(nd_vid, "class variable");
- return;
-
- case NODE_GVAR:
- ANN("global variable reference");
- ANN("format: [nd_entry](gvar)");
- ANN("example: $x");
- F_GENTRY(nd_entry, "global variable");
- return;
-
- case NODE_NTH_REF:
- ANN("nth special variable reference");
- ANN("format: $[nd_nth]");
- ANN("example: $1, $2, ..");
- F_CUSTOM1(nd_nth, "variable") { A("$"); A_LONG(node->nd_nth); }
- return;
-
- case NODE_BACK_REF:
- ANN("back special variable reference");
- ANN("format: $[nd_nth]");
- ANN("example: $&, $`, $', $+");
- F_CUSTOM1(nd_nth, "variable") {
- char name[3] = "$ ";
- name[1] = (char)node->nd_nth;
- A(name);
- }
- return;
-
- case NODE_MATCH:
- ANN("match expression (against $_ implicitly)");
- ANN("format: [nd_lit] (in condition)");
- ANN("example: if /foo/; foo; end");
- F_LIT(nd_lit, "regexp");
- return;
-
- case NODE_MATCH2:
- ANN("match expression (regexp first)");
- ANN("format: [nd_recv] =~ [nd_value]");
- ANN("example: /foo/ =~ 'foo'");
- F_NODE(nd_recv, "regexp (receiver)");
- if (!node->nd_args) LAST_NODE;
- F_NODE(nd_value, "string (argument)");
- if (node->nd_args) {
- LAST_NODE;
- F_NODE(nd_args, "named captures");
- }
- return;
+#endif
- case NODE_MATCH3:
- ANN("match expression (regexp second)");
- ANN("format: [nd_recv] =~ [nd_value]");
- ANN("example: 'foo' =~ /foo/");
- F_NODE(nd_recv, "string (receiver)");
- LAST_NODE;
- F_NODE(nd_value, "regexp (argument)");
- return;
-
- case NODE_LIT:
- ANN("literal");
- ANN("format: [nd_lit]");
- ANN("example: 1, /foo/");
- goto lit;
- case NODE_STR:
- ANN("string literal");
- ANN("format: [nd_lit]");
- ANN("example: 'foo'");
- goto lit;
- case NODE_XSTR:
- ANN("xstring literal");
- ANN("format: [nd_lit]");
- ANN("example: `foo`");
- lit:
- F_LIT(nd_lit, "literal");
- return;
-
- case NODE_ONCE:
- ANN("once evaluation");
- ANN("format: [nd_body]");
- ANN("example: /foo#{ bar }baz/o");
- LAST_NODE;
- F_NODE(nd_body, "body");
- return;
- case NODE_DSTR:
- ANN("string literal with interpolation");
- ANN("format: [nd_lit]");
- ANN("example: \"foo#{ bar }baz\"");
- goto dlit;
- case NODE_DXSTR:
- ANN("xstring literal with interpolation");
- ANN("format: [nd_lit]");
- ANN("example: `foo#{ bar }baz`");
- goto dlit;
- case NODE_DREGX:
- ANN("regexp literal with interpolation");
- ANN("format: [nd_lit]");
- ANN("example: /foo#{ bar }baz/");
- goto dlit;
- case NODE_DSYM:
- ANN("symbol literal with interpolation");
- ANN("format: [nd_lit]");
- ANN("example: :\"foo#{ bar }baz\"");
- dlit:
- F_LIT(nd_lit, "preceding string");
- if (!node->nd_next) return;
- F_NODE(nd_next->nd_head, "interpolation");
- LAST_NODE;
- F_NODE(nd_next->nd_next, "tailing strings");
- return;
-
- case NODE_EVSTR:
- ANN("interpolation expression");
- ANN("format: \"..#{ [nd_lit] }..\"");
- ANN("example: \"foo#{ bar }baz\"");
- LAST_NODE;
- F_NODE(nd_body, "body");
- return;
-
- case NODE_ARGSCAT:
- ANN("splat argument following arguments");
- ANN("format: ..(*[nd_head], [nd_body..])");
- ANN("example: foo(*ary, post_arg1, post_arg2)");
- F_NODE(nd_head, "preceding array");
- LAST_NODE;
- F_NODE(nd_body, "following array");
- return;
-
- case NODE_ARGSPUSH:
- ANN("splat argument following one argument");
- ANN("format: ..(*[nd_head], [nd_body])");
- ANN("example: foo(*ary, post_arg)");
- F_NODE(nd_head, "preceding array");
- LAST_NODE;
- F_NODE(nd_body, "following element");
- return;
-
- case NODE_SPLAT:
- ANN("splat argument");
- ANN("format: *[nd_head]");
- ANN("example: foo(*ary)");
- LAST_NODE;
- F_NODE(nd_head, "splat'ed array");
- return;
-
- case NODE_BLOCK_PASS:
- ANN("arguments with block argument");
- ANN("format: ..([nd_head], &[nd_body])");
- ANN("example: foo(x, &blk)");
- F_NODE(nd_head, "other arguments");
- LAST_NODE;
- F_NODE(nd_body, "block argument");
- return;
-
- case NODE_DEFN:
- ANN("method definition");
- ANN("format: def [nd_mid] [nd_defn]; end");
- ANN("example: def foo; bar; end");
- F_ID(nd_mid, "method name");
- LAST_NODE;
- F_NODE(nd_defn, "method definition");
- return;
-
- case NODE_DEFS:
- ANN("singleton method definition");
- ANN("format: def [nd_recv].[nd_mid] [nd_defn]; end");
- ANN("example: def obj.foo; bar; end");
- F_NODE(nd_recv, "receiver");
- F_ID(nd_mid, "method name");
- LAST_NODE;
- F_NODE(nd_defn, "method definition");
- return;
-
- case NODE_ALIAS:
- ANN("method alias statement");
- ANN("format: alias [nd_1st] [nd_2nd]");
- ANN("example: alias bar foo");
- F_NODE(nd_1st, "new name");
- LAST_NODE;
- F_NODE(nd_2nd, "old name");
- return;
-
- case NODE_VALIAS:
- ANN("global variable alias statement");
- ANN("format: alias [nd_alias](gvar) [nd_orig](gvar)");
- ANN("example: alias $y $x");
- F_ID(nd_alias, "new name");
- F_ID(nd_orig, "old name");
- return;
-
- case NODE_UNDEF:
- ANN("method undef statement");
- ANN("format: undef [nd_undef]");
- ANN("example: undef foo");
- LAST_NODE;
- F_NODE(nd_undef, "old name");
- return;
-
- case NODE_CLASS:
- ANN("class definition");
- ANN("format: class [nd_cpath] < [nd_super]; [nd_body]; end");
- ANN("example: class C2 < C; ..; end");
- F_NODE(nd_cpath, "class path");
- F_NODE(nd_super, "superclass");
- LAST_NODE;
- F_NODE(nd_body, "class definition");
- return;
-
- case NODE_MODULE:
- ANN("module definition");
- ANN("format: module [nd_cpath]; [nd_body]; end");
- ANN("example: module M; ..; end");
- F_NODE(nd_cpath, "module path");
- LAST_NODE;
- F_NODE(nd_body, "module definition");
- return;
-
- case NODE_SCLASS:
- ANN("singleton class definition");
- ANN("format: class << [nd_recv]; [nd_body]; end");
- ANN("example: class << obj; ..; end");
- F_NODE(nd_recv, "receiver");
- LAST_NODE;
- F_NODE(nd_body, "singleton class definition");
- return;
-
- case NODE_COLON2:
- ANN("scoped constant reference");
- ANN("format: [nd_head]::[nd_mid]");
- ANN("example: M::C");
- F_ID(nd_mid, "constant name");
- LAST_NODE;
- F_NODE(nd_head, "receiver");
- return;
-
- case NODE_COLON3:
- ANN("top-level constant reference");
- ANN("format: ::[nd_mid]");
- ANN("example: ::Object");
- F_ID(nd_mid, "constant name");
- return;
-
- case NODE_DOT2:
- ANN("range constructor (incl.)");
- ANN("format: [nd_beg]..[nd_end]");
- ANN("example: 1..5");
- goto dot;
- case NODE_DOT3:
- ANN("range constructor (excl.)");
- ANN("format: [nd_beg]...[nd_end]");
- ANN("example: 1...5");
- goto dot;
- case NODE_FLIP2:
- ANN("flip-flop condition (incl.)");
- ANN("format: [nd_beg]..[nd_end]");
- ANN("example: if (x==1)..(x==5); foo; end");
- goto dot;
- case NODE_FLIP3:
- ANN("flip-flop condition (excl.)");
- ANN("format: [nd_beg]...[nd_end]");
- ANN("example: if (x==1)...(x==5); foo; end");
- dot:
- F_NODE(nd_beg, "begin");
- LAST_NODE;
- F_NODE(nd_end, "end");
- return;
-
- case NODE_SELF:
- ANN("self");
- ANN("format: self");
- ANN("example: self");
- return;
-
- case NODE_NIL:
- ANN("nil");
- ANN("format: nil");
- ANN("example: nil");
- return;
-
- case NODE_TRUE:
- ANN("true");
- ANN("format: true");
- ANN("example: true");
- return;
-
- case NODE_FALSE:
- ANN("false");
- ANN("format: false");
- ANN("example: false");
- return;
-
- case NODE_ERRINFO:
- ANN("virtual reference to $!");
- ANN("format: rescue => id");
- ANN("example: rescue => id");
- return;
-
- case NODE_DEFINED:
- ANN("defined? expression");
- ANN("format: defined?([nd_head])");
- ANN("example: defined?(foo)");
- F_NODE(nd_head, "expr");
- return;
-
- case NODE_POSTEXE:
- ANN("post-execution");
- ANN("format: END { [nd_body] }");
- ANN("example: END { foo }");
- LAST_NODE;
- F_NODE(nd_body, "END clause");
- return;
-
- case NODE_ATTRASGN:
- ANN("attr assignment");
- ANN("format: [nd_recv].[nd_mid] = [nd_args]");
- ANN("example: struct.field = foo");
- F_NODE(nd_recv, "receiver");
- F_ID(nd_mid, "method name");
- LAST_NODE;
- F_NODE(nd_args, "arguments");
- return;
-
- case NODE_LAMBDA:
- ANN("lambda expression");
- ANN("format: -> [nd_body]");
- ANN("example: -> { foo }");
- LAST_NODE;
- F_NODE(nd_body, "lambda clause");
- return;
-
- case NODE_OPT_ARG:
- ANN("optional arguments");
- ANN("format: def method_name([nd_body=some], [nd_next..])");
- ANN("example: def foo(a, b=1, c); end");
- F_NODE(nd_body, "body");
- LAST_NODE;
- F_NODE(nd_next, "next");
- return;
-
- case NODE_KW_ARG:
- ANN("keyword arguments");
- ANN("format: def method_name([nd_body=some], [nd_next..])");
- ANN("example: def foo(a:1, b:2); end");
- F_NODE(nd_body, "body");
- LAST_NODE;
- F_NODE(nd_next, "next");
- return;
-
- case NODE_POSTARG:
- ANN("post arguments");
- ANN("format: *[nd_1st], [nd_2nd..] = ..");
- ANN("example: a, *rest, z = foo");
- if (NODE_NAMED_REST_P(node->nd_1st)) {
- F_NODE(nd_1st, "rest argument");
- }
- else {
- F_MSG(nd_1st, "rest argument", "NODE_SPECIAL_NO_NAME_REST (rest argument without name)");
- }
- LAST_NODE;
- F_NODE(nd_2nd, "post arguments");
- return;
-
- case NODE_ARGS:
- ANN("method parameters");
- ANN("format: def method_name(.., [nd_ainfo->nd_optargs], *[nd_ainfo->rest_arg], [nd_ainfo->first_post_arg], .., [nd_ainfo->kw_args], **[nd_ainfo->kw_rest_arg], &[nd_ainfo->block_arg])");
- ANN("example: def foo(a, b, opt1=1, opt2=2, *rest, y, z, kw: 1, **kwrest, &blk); end");
- F_INT(nd_ainfo->pre_args_num, "count of mandatory (pre-)arguments");
- F_NODE(nd_ainfo->pre_init, "initialization of (pre-)arguments");
- F_INT(nd_ainfo->post_args_num, "count of mandatory post-arguments");
- F_NODE(nd_ainfo->post_init, "initialization of post-arguments");
- F_ID(nd_ainfo->first_post_arg, "first post argument");
- F_CUSTOM1(nd_ainfo->rest_arg, "rest argument") {
- if (node->nd_ainfo->rest_arg == NODE_SPECIAL_EXCESSIVE_COMMA) {
- A("1 (excessed comma)");
- }
- else {
- A_ID(node->nd_ainfo->rest_arg);
- }
- }
- F_ID(nd_ainfo->block_arg, "block argument");
- F_NODE(nd_ainfo->opt_args, "optional arguments");
- F_NODE(nd_ainfo->kw_args, "keyword arguments");
- LAST_NODE;
- F_NODE(nd_ainfo->kw_rest_arg, "keyword rest argument");
- return;
-
- case NODE_SCOPE:
- ANN("new scope");
- ANN("format: [nd_tbl]: local table, [nd_args]: arguments, [nd_body]: body");
- F_CUSTOM1(nd_tbl, "local table") {
- rb_ast_id_table_t *tbl = node->nd_tbl;
- int i;
- int size = tbl ? tbl->size : 0;
- if (size == 0) A("(empty)");
- for (i = 0; i < size; i++) {
- A_ID(tbl->ids[i]); if (i < size - 1) A(",");
- }
- }
- F_NODE(nd_args, "arguments");
- LAST_NODE;
- F_NODE(nd_body, "body");
- return;
-
- case NODE_ARYPTN:
- ANN("array pattern");
- ANN("format: [nd_pconst]([pre_args], ..., *[rest_arg], [post_args], ...)");
- F_NODE(nd_pconst, "constant");
- F_NODE(nd_apinfo->pre_args, "pre arguments");
- if (NODE_NAMED_REST_P(node->nd_apinfo->rest_arg)) {
- F_NODE(nd_apinfo->rest_arg, "rest argument");
- }
- else {
- F_MSG(nd_apinfo->rest_arg, "rest argument", "NODE_SPECIAL_NO_NAME_REST (rest argument without name)");
- }
- LAST_NODE;
- F_NODE(nd_apinfo->post_args, "post arguments");
- return;
-
- case NODE_FNDPTN:
- ANN("find pattern");
- ANN("format: [nd_pconst](*[pre_rest_arg], args, ..., *[post_rest_arg])");
- F_NODE(nd_pconst, "constant");
- if (NODE_NAMED_REST_P(node->nd_fpinfo->pre_rest_arg)) {
- F_NODE(nd_fpinfo->pre_rest_arg, "pre rest argument");
- }
- else {
- F_MSG(nd_fpinfo->pre_rest_arg, "pre rest argument", "NODE_SPECIAL_NO_NAME_REST (rest argument without name)");
- }
- F_NODE(nd_fpinfo->args, "arguments");
-
- LAST_NODE;
- if (NODE_NAMED_REST_P(node->nd_fpinfo->post_rest_arg)) {
- F_NODE(nd_fpinfo->post_rest_arg, "post rest argument");
- }
- else {
- F_MSG(nd_fpinfo->post_rest_arg, "post rest argument", "NODE_SPECIAL_NO_NAME_REST (rest argument without name)");
- }
- return;
-
- case NODE_HSHPTN:
- ANN("hash pattern");
- ANN("format: [nd_pconst]([nd_pkwargs], ..., **[nd_pkwrestarg])");
- F_NODE(nd_pconst, "constant");
- F_NODE(nd_pkwargs, "keyword arguments");
- LAST_NODE;
- if (node->nd_pkwrestarg == NODE_SPECIAL_NO_REST_KEYWORD) {
- F_MSG(nd_pkwrestarg, "keyword rest argument", "NODE_SPECIAL_NO_REST_KEYWORD (**nil)");
- }
- else {
- F_NODE(nd_pkwrestarg, "keyword rest argument");
- }
- return;
- case NODE_ERROR:
- ANN("Broken input recovered by Error Tolerant mode");
- return;
-
- case NODE_ARGS_AUX:
- case NODE_LAST:
- break;
- }
-
- rb_bug("dump_node: unknown node: %s", ruby_node_name(nd_type(node)));
-}
-
-VALUE
-rb_parser_dump_tree(const NODE *node, int comment)
-{
- VALUE buf = rb_str_new_cstr(
- "###########################################################\n"
- "## Do NOT use this node dump for any purpose other than ##\n"
- "## debug and research. Compatibility is not guaranteed. ##\n"
- "###########################################################\n\n"
- );
- dump_node(buf, rb_str_new_cstr("# "), comment, node);
- return buf;
-}
+#define NODE_BUF_DEFAULT_LEN 16
/* Setup NODE structure.
* NODE is not an object managed by GC, but it imitates an object
@@ -1145,40 +66,31 @@ rb_node_init(NODE *n, enum node_type type, VALUE a0, VALUE a1, VALUE a2)
}
const char *
-ruby_node_name(int node)
+rb_node_name(int node)
{
switch (node) {
#include "node_name.inc"
default:
- rb_bug("unknown node: %d", node);
return 0;
}
}
-typedef struct node_buffer_elem_struct {
- struct node_buffer_elem_struct *next;
- long len;
- NODE buf[FLEX_ARY_LEN];
-} node_buffer_elem_t;
-
-typedef struct {
- long idx, len;
- node_buffer_elem_t *head;
- node_buffer_elem_t *last;
-} node_buffer_list_t;
+#ifdef UNIVERSAL_PARSER
+const char *
+ruby_node_name(int node)
+{
+ return rb_node_name(node);
+}
+#else
+const char *
+ruby_node_name(int node)
+{
+ const char *name = rb_node_name(node);
-struct node_buffer_struct {
- node_buffer_list_t unmarkable;
- node_buffer_list_t markable;
- struct rb_ast_local_table_link *local_tables;
- VALUE mark_hash;
- // - id (sequence number)
- // - token_type
- // - text of token
- // - location info
- // Array, whose entry is array
- VALUE tokens;
-};
+ if (!name) rb_bug("unknown node: %d", node);
+ return name;
+}
+#endif
static void
init_node_buffer_list(node_buffer_list_t * nb, node_buffer_elem_t *head)
@@ -1190,6 +102,26 @@ init_node_buffer_list(node_buffer_list_t * nb, node_buffer_elem_t *head)
nb->head->next = NULL;
}
+#ifdef UNIVERSAL_PARSER
+static node_buffer_t *
+rb_node_buffer_new(rb_parser_config_t *config)
+{
+ const size_t bucket_size = offsetof(node_buffer_elem_t, buf) + NODE_BUF_DEFAULT_LEN * sizeof(NODE);
+ const size_t alloc_size = sizeof(node_buffer_t) + (bucket_size * 2);
+ STATIC_ASSERT(
+ integer_overflow,
+ offsetof(node_buffer_elem_t, buf) + NODE_BUF_DEFAULT_LEN * sizeof(NODE)
+ > sizeof(node_buffer_t) + 2 * sizeof(node_buffer_elem_t));
+ node_buffer_t *nb = config->malloc(alloc_size);
+ init_node_buffer_list(&nb->unmarkable, (node_buffer_elem_t*)&nb[1]);
+ init_node_buffer_list(&nb->markable, (node_buffer_elem_t*)((size_t)nb->unmarkable.head + bucket_size));
+ nb->local_tables = 0;
+ nb->mark_hash = config->qnil;
+ nb->tokens = config->qnil;
+ nb->config = config;
+ return nb;
+}
+#else
static node_buffer_t *
rb_node_buffer_new(void)
{
@@ -1207,9 +139,10 @@ rb_node_buffer_new(void)
nb->tokens = Qnil;
return nb;
}
+#endif
static void
-node_buffer_list_free(node_buffer_list_t * nb)
+node_buffer_list_free(rb_ast_t *ast, node_buffer_list_t * nb)
{
node_buffer_elem_t *nbe = nb->head;
@@ -1229,10 +162,10 @@ struct rb_ast_local_table_link {
};
static void
-rb_node_buffer_free(node_buffer_t *nb)
+rb_node_buffer_free(rb_ast_t *ast, node_buffer_t *nb)
{
- node_buffer_list_free(&nb->unmarkable);
- node_buffer_list_free(&nb->markable);
+ node_buffer_list_free(ast, &nb->unmarkable);
+ node_buffer_list_free(ast, &nb->markable);
struct rb_ast_local_table_link *local_table = nb->local_tables;
while (local_table) {
struct rb_ast_local_table_link *next_table = local_table->next;
@@ -1243,7 +176,7 @@ rb_node_buffer_free(node_buffer_t *nb)
}
static NODE *
-ast_newnode_in_bucket(node_buffer_list_t *nb)
+ast_newnode_in_bucket(rb_ast_t *ast, node_buffer_list_t *nb)
{
if (nb->idx >= nb->len) {
long n = nb->len * 2;
@@ -1286,9 +219,10 @@ rb_ast_newnode(rb_ast_t *ast, enum node_type type)
node_buffer_t *nb = ast->node_buffer;
node_buffer_list_t *bucket =
(nodetype_markable_p(type) ? &nb->markable : &nb->unmarkable);
- return ast_newnode_in_bucket(bucket);
+ return ast_newnode_in_bucket(ast, bucket);
}
+#if RUBY_DEBUG
void
rb_ast_node_type_change(NODE *n, enum node_type type)
{
@@ -1298,6 +232,7 @@ rb_ast_node_type_change(NODE *n, enum node_type type)
ruby_node_name(old_type), ruby_node_name(type));
}
}
+#endif
rb_ast_id_table_t *
rb_ast_new_local_table(rb_ast_t *ast, int size)
@@ -1331,6 +266,15 @@ rb_ast_delete_node(rb_ast_t *ast, NODE *n)
/* should we implement freelist? */
}
+#ifdef UNIVERSAL_PARSER
+rb_ast_t *
+rb_ast_new(rb_parser_config_t *config)
+{
+ node_buffer_t *nb = rb_node_buffer_new(config);
+ config->counter++;
+ return config->ast_new((VALUE)nb);
+}
+#else
rb_ast_t *
rb_ast_new(void)
{
@@ -1338,36 +282,41 @@ rb_ast_new(void)
rb_ast_t *ast = (rb_ast_t *)rb_imemo_new(imemo_ast, 0, 0, 0, (VALUE)nb);
return ast;
}
+#endif
-typedef void node_itr_t(void *ctx, NODE * node);
+typedef void node_itr_t(rb_ast_t *ast, void *ctx, NODE * node);
static void
-iterate_buffer_elements(node_buffer_elem_t *nbe, long len, node_itr_t *func, void *ctx)
+iterate_buffer_elements(rb_ast_t *ast, node_buffer_elem_t *nbe, long len, node_itr_t *func, void *ctx)
{
long cursor;
for (cursor = 0; cursor < len; cursor++) {
- func(ctx, &nbe->buf[cursor]);
+ func(ast, ctx, &nbe->buf[cursor]);
}
}
static void
-iterate_node_values(node_buffer_list_t *nb, node_itr_t * func, void *ctx)
+iterate_node_values(rb_ast_t *ast, node_buffer_list_t *nb, node_itr_t * func, void *ctx)
{
node_buffer_elem_t *nbe = nb->head;
/* iterate over the head first because it's not full */
- iterate_buffer_elements(nbe, nb->idx, func, ctx);
+ iterate_buffer_elements(ast, nbe, nb->idx, func, ctx);
nbe = nbe->next;
while (nbe) {
- iterate_buffer_elements(nbe, nbe->len, func, ctx);
+ iterate_buffer_elements(ast, nbe, nbe->len, func, ctx);
nbe = nbe->next;
}
}
static void
-mark_ast_value(void *ctx, NODE * node)
+mark_ast_value(rb_ast_t *ast, void *ctx, NODE * node)
{
+#ifdef UNIVERSAL_PARSER
+ bug_report_func rb_bug = ast->node_buffer->config->bug;
+#endif
+
switch (nd_type(node)) {
case NODE_ARGS:
{
@@ -1395,8 +344,12 @@ mark_ast_value(void *ctx, NODE * node)
}
static void
-update_ast_value(void *ctx, NODE * node)
+update_ast_value(rb_ast_t *ast, void *ctx, NODE * node)
{
+#ifdef UNIVERSAL_PARSER
+ bug_report_func rb_bug = ast->node_buffer->config->bug;
+#endif
+
switch (nd_type(node)) {
case NODE_ARGS:
{
@@ -1429,7 +382,7 @@ rb_ast_update_references(rb_ast_t *ast)
if (ast->node_buffer) {
node_buffer_t *nb = ast->node_buffer;
- iterate_node_values(&nb->markable, update_ast_value, NULL);
+ iterate_node_values(ast, &nb->markable, update_ast_value, NULL);
}
}
@@ -1439,22 +392,29 @@ rb_ast_mark(rb_ast_t *ast)
if (ast->node_buffer) {
rb_gc_mark(ast->node_buffer->mark_hash);
rb_gc_mark(ast->node_buffer->tokens);
- }
- if (ast->body.compile_option) rb_gc_mark(ast->body.compile_option);
- if (ast->node_buffer) {
+ if (ast->body.compile_option) rb_gc_mark(ast->body.compile_option);
node_buffer_t *nb = ast->node_buffer;
-
- iterate_node_values(&nb->markable, mark_ast_value, NULL);
+ iterate_node_values(ast, &nb->markable, mark_ast_value, NULL);
+ if (ast->body.script_lines) rb_gc_mark(ast->body.script_lines);
}
- if (ast->body.script_lines) rb_gc_mark(ast->body.script_lines);
}
void
rb_ast_free(rb_ast_t *ast)
{
if (ast->node_buffer) {
- rb_node_buffer_free(ast->node_buffer);
+#ifdef UNIVERSAL_PARSER
+ rb_parser_config_t *config = ast->node_buffer->config;
+#endif
+
+ rb_node_buffer_free(ast, ast->node_buffer);
ast->node_buffer = 0;
+#ifdef UNIVERSAL_PARSER
+ config->counter--;
+ if (config->counter <= 0) {
+ rb_ruby_parser_config_free(config);
+ }
+#endif
}
}
@@ -1510,3 +470,12 @@ rb_ast_set_tokens(rb_ast_t *ast, VALUE tokens)
{
RB_OBJ_WRITE(ast, &ast->node_buffer->tokens, tokens);
}
+
+VALUE
+rb_node_set_type(NODE *n, enum node_type t)
+{
+#if RUBY_DEBUG
+ rb_ast_node_type_change(n, t);
+#endif
+ return nd_init_type(n, t);
+}
diff --git a/node.h b/node.h
index befb1328fb..69f73fc798 100644
--- a/node.h
+++ b/node.h
@@ -11,199 +11,99 @@
**********************************************************************/
-#include "internal/compilers.h"
-
-#if defined(__cplusplus)
-extern "C" {
-#if 0
-} /* satisfy cc-mode */
-#endif
+#include <stdbool.h>
+#include "rubyparser.h"
+#include "ruby/backward/2/attributes.h"
+
+typedef void (*bug_report_func)(const char *fmt, ...);
+
+typedef struct node_buffer_elem_struct {
+ struct node_buffer_elem_struct *next;
+ long len;
+ NODE buf[FLEX_ARY_LEN];
+} node_buffer_elem_t;
+
+typedef struct {
+ long idx, len;
+ node_buffer_elem_t *head;
+ node_buffer_elem_t *last;
+} node_buffer_list_t;
+
+#ifdef UNIVERSAL_PARSER
+typedef struct rb_parser_config_struct rb_parser_config_t;
#endif
-enum node_type {
- NODE_SCOPE,
- NODE_BLOCK,
- NODE_IF,
- NODE_UNLESS,
- NODE_CASE,
- NODE_CASE2,
- NODE_CASE3,
- NODE_WHEN,
- NODE_IN,
- NODE_WHILE,
- NODE_UNTIL,
- NODE_ITER,
- NODE_FOR,
- NODE_FOR_MASGN,
- NODE_BREAK,
- NODE_NEXT,
- NODE_REDO,
- NODE_RETRY,
- NODE_BEGIN,
- NODE_RESCUE,
- NODE_RESBODY,
- NODE_ENSURE,
- NODE_AND,
- NODE_OR,
- NODE_MASGN,
- NODE_LASGN,
- NODE_DASGN,
- NODE_GASGN,
- NODE_IASGN,
- NODE_CDECL,
- NODE_CVASGN,
- NODE_OP_ASGN1,
- NODE_OP_ASGN2,
- NODE_OP_ASGN_AND,
- NODE_OP_ASGN_OR,
- NODE_OP_CDECL,
- NODE_CALL,
- NODE_OPCALL,
- NODE_FCALL,
- NODE_VCALL,
- NODE_QCALL,
- NODE_SUPER,
- NODE_ZSUPER,
- NODE_LIST,
- NODE_ZLIST,
- NODE_VALUES,
- NODE_HASH,
- NODE_RETURN,
- NODE_YIELD,
- NODE_LVAR,
- NODE_DVAR,
- NODE_GVAR,
- NODE_IVAR,
- NODE_CONST,
- NODE_CVAR,
- NODE_NTH_REF,
- NODE_BACK_REF,
- NODE_MATCH,
- NODE_MATCH2,
- NODE_MATCH3,
- NODE_LIT,
- NODE_STR,
- NODE_DSTR,
- NODE_XSTR,
- NODE_DXSTR,
- NODE_EVSTR,
- NODE_DREGX,
- NODE_ONCE,
- NODE_ARGS,
- NODE_ARGS_AUX,
- NODE_OPT_ARG,
- NODE_KW_ARG,
- NODE_POSTARG,
- NODE_ARGSCAT,
- NODE_ARGSPUSH,
- NODE_SPLAT,
- NODE_BLOCK_PASS,
- NODE_DEFN,
- NODE_DEFS,
- NODE_ALIAS,
- NODE_VALIAS,
- NODE_UNDEF,
- NODE_CLASS,
- NODE_MODULE,
- NODE_SCLASS,
- NODE_COLON2,
- NODE_COLON3,
- NODE_DOT2,
- NODE_DOT3,
- NODE_FLIP2,
- NODE_FLIP3,
- NODE_SELF,
- NODE_NIL,
- NODE_TRUE,
- NODE_FALSE,
- NODE_ERRINFO,
- NODE_DEFINED,
- NODE_POSTEXE,
- NODE_DSYM,
- NODE_ATTRASGN,
- NODE_LAMBDA,
- NODE_ARYPTN,
- NODE_HSHPTN,
- NODE_FNDPTN,
- NODE_ERROR,
- NODE_LAST
+struct node_buffer_struct {
+ node_buffer_list_t unmarkable;
+ node_buffer_list_t markable;
+ struct rb_ast_local_table_link *local_tables;
+ VALUE mark_hash;
+ // - id (sequence number)
+ // - token_type
+ // - text of token
+ // - location info
+ // Array, whose entry is array
+ VALUE tokens;
+#ifdef UNIVERSAL_PARSER
+ rb_parser_config_t *config;
+#endif
};
-typedef struct rb_code_position_struct {
- int lineno;
- int column;
-} rb_code_position_t;
-
-typedef struct rb_code_location_struct {
- rb_code_position_t beg_pos;
- rb_code_position_t end_pos;
-} rb_code_location_t;
-
-static inline rb_code_location_t
-code_loc_gen(const rb_code_location_t *loc1, const rb_code_location_t *loc2)
-{
- rb_code_location_t loc;
- loc.beg_pos = loc1->beg_pos;
- loc.end_pos = loc2->end_pos;
- return loc;
-}
+RUBY_SYMBOL_EXPORT_BEGIN
-typedef struct rb_ast_id_table {
- int size;
- ID ids[FLEX_ARY_LEN];
-} rb_ast_id_table_t;
+#ifdef UNIVERSAL_PARSER
+rb_ast_t *rb_ast_new(rb_parser_config_t *config);
+#else
+rb_ast_t *rb_ast_new();
+#endif
+size_t rb_ast_memsize(const rb_ast_t*);
+void rb_ast_dispose(rb_ast_t*);
+VALUE rb_ast_tokens(rb_ast_t *ast);
+#if RUBY_DEBUG
+void rb_ast_node_type_change(NODE *n, enum node_type type);
+#endif
+const char *ruby_node_name(int node);
+void rb_node_init(NODE *n, enum node_type type, VALUE a0, VALUE a1, VALUE a2);
-typedef struct RNode {
- VALUE flags;
- union {
- struct RNode *node;
- ID id;
- VALUE value;
- rb_ast_id_table_t *tbl;
- } u1;
- union {
- struct RNode *node;
- ID id;
- long argc;
- VALUE value;
- } u2;
- union {
- struct RNode *node;
- ID id;
- long state;
- struct rb_args_info *args;
- struct rb_ary_pattern_info *apinfo;
- struct rb_fnd_pattern_info *fpinfo;
- VALUE value;
- } u3;
- rb_code_location_t nd_loc;
- int node_id;
-} NODE;
+void rb_ast_mark(rb_ast_t*);
+void rb_ast_update_references(rb_ast_t*);
+void rb_ast_free(rb_ast_t*);
+void rb_ast_add_mark_object(rb_ast_t*, VALUE);
+void rb_ast_set_tokens(rb_ast_t*, VALUE);
+NODE *rb_ast_newnode(rb_ast_t*, enum node_type type);
+void rb_ast_delete_node(rb_ast_t*, NODE *n);
+rb_ast_id_table_t *rb_ast_new_local_table(rb_ast_t*, int);
+rb_ast_id_table_t *rb_ast_resize_latest_local_table(rb_ast_t*, int);
-#define RNODE(obj) ((struct RNode *)(obj))
+VALUE rb_parser_dump_tree(const NODE *node, int comment);
-/* FL : 0..4: T_TYPES, 5: KEEP_WB, 6: PROMOTED, 7: FINALIZE, 8: UNUSED, 9: UNUSED, 10: EXIVAR, 11: FREEZE */
-/* NODE_FL: 0..4: T_TYPES, 5: KEEP_WB, 6: PROMOTED, 7: NODE_FL_NEWLINE,
- * 8..14: nd_type,
- * 15..: nd_line
- */
-#define NODE_FL_NEWLINE (((VALUE)1)<<7)
+const struct kwtable *rb_reserved_word(const char *, unsigned int);
-#define NODE_TYPESHIFT 8
-#define NODE_TYPEMASK (((VALUE)0x7f)<<NODE_TYPESHIFT)
+struct parser_params;
+void *rb_parser_malloc(struct parser_params *, size_t);
+void *rb_parser_realloc(struct parser_params *, void *, size_t);
+void *rb_parser_calloc(struct parser_params *, size_t, size_t);
+void rb_parser_free(struct parser_params *, void *);
+PRINTF_ARGS(void rb_parser_printf(struct parser_params *parser, const char *fmt, ...), 2, 3);
+VALUE rb_node_set_type(NODE *n, enum node_type t);
-#define nd_type(n) ((int) (((n)->flags & NODE_TYPEMASK)>>NODE_TYPESHIFT))
-#define nd_set_type(n,t) \
- rb_node_set_type(n, t)
-#define nd_init_type(n,t) \
- (n)->flags=(((n)->flags&~NODE_TYPEMASK)|((((unsigned long)(t))<<NODE_TYPESHIFT)&NODE_TYPEMASK))
+RUBY_SYMBOL_EXPORT_END
#define NODE_LSHIFT (NODE_TYPESHIFT+7)
#define NODE_LMASK (((SIGNED_VALUE)1<<(sizeof(VALUE)*CHAR_BIT-NODE_LSHIFT))-1)
+
#define nd_line(n) (int)(((SIGNED_VALUE)(n)->flags)>>NODE_LSHIFT)
#define nd_set_line(n,l) \
(n)->flags=(((n)->flags&~((VALUE)(-1)<<NODE_LSHIFT))|((VALUE)((l)&NODE_LMASK)<<NODE_LSHIFT))
+
+#define NODE_SPECIAL_REQUIRED_KEYWORD ((NODE *)-1)
+#define NODE_REQUIRED_KEYWORD_P(node) ((node)->nd_value == NODE_SPECIAL_REQUIRED_KEYWORD)
+#define NODE_SPECIAL_NO_NAME_REST ((NODE *)-1)
+#define NODE_NAMED_REST_P(node) ((node) != NODE_SPECIAL_NO_NAME_REST)
+#define NODE_SPECIAL_EXCESSIVE_COMMA ((ID)1)
+#define NODE_SPECIAL_NO_REST_KEYWORD ((NODE *)-1)
+
#define nd_first_column(n) ((int)((n)->nd_loc.beg_pos.column))
#define nd_set_first_column(n, v) ((n)->nd_loc.beg_pos.column = (v))
#define nd_first_lineno(n) ((int)((n)->nd_loc.beg_pos.lineno))
@@ -220,295 +120,10 @@ typedef struct RNode {
#define nd_node_id(n) ((n)->node_id)
#define nd_set_node_id(n,id) ((n)->node_id = (id))
-#define nd_head u1.node
-#define nd_alen u2.argc
-#define nd_next u3.node
-
-#define nd_cond u1.node
-#define nd_body u2.node
-#define nd_else u3.node
-
-#define nd_resq u2.node
-#define nd_ensr u3.node
-
-#define nd_1st u1.node
-#define nd_2nd u2.node
-
-#define nd_stts u1.node
-
-#define nd_entry u3.id
-#define nd_vid u1.id
-
-#define nd_var u1.node
-#define nd_iter u3.node
-
-#define nd_value u2.node
-#define nd_aid u3.id
-
-#define nd_lit u1.value
-
-#define nd_recv u1.node
-#define nd_mid u2.id
-#define nd_args u3.node
-#define nd_ainfo u3.args
-
-#define nd_defn u3.node
-
-#define nd_cpath u1.node
-#define nd_super u3.node
-
-#define nd_beg u1.node
-#define nd_end u2.node
-#define nd_state u3.state
-
-#define nd_nth u2.argc
-
-#define nd_alias u1.id
-#define nd_orig u2.id
-#define nd_undef u2.node
-
-#define nd_brace u2.argc
-
-#define nd_pconst u1.node
-#define nd_pkwargs u2.node
-#define nd_pkwrestarg u3.node
-
-#define nd_apinfo u3.apinfo
-
-#define nd_fpinfo u3.fpinfo
-
-// for NODE_SCOPE
-#define nd_tbl u1.tbl
-
-// for NODE_ARGS_AUX
-#define nd_pid u1.id
-#define nd_plen u2.argc
-#define nd_cflag u2.id
-
-// for ripper
-#define nd_cval u3.value
-#define nd_rval u2.value
-#define nd_tag u1.id
-
-#define NEW_NODE(t,a0,a1,a2,loc) rb_node_newnode((t),(VALUE)(a0),(VALUE)(a1),(VALUE)(a2),loc)
-#define NEW_NODE_WITH_LOCALS(t,a1,a2,loc) node_newnode_with_locals(p, (t),(VALUE)(a1),(VALUE)(a2),loc)
-
-#define NEW_DEFN(i,a,d,loc) NEW_NODE(NODE_DEFN,0,i,NEW_SCOPE(a,d,loc),loc)
-#define NEW_DEFS(r,i,a,d,loc) NEW_NODE(NODE_DEFS,r,i,NEW_SCOPE(a,d,loc),loc)
-#define NEW_SCOPE(a,b,loc) NEW_NODE_WITH_LOCALS(NODE_SCOPE,b,a,loc)
-#define NEW_BLOCK(a,loc) NEW_NODE(NODE_BLOCK,a,0,0,loc)
-#define NEW_IF(c,t,e,loc) NEW_NODE(NODE_IF,c,t,e,loc)
-#define NEW_UNLESS(c,t,e,loc) NEW_NODE(NODE_UNLESS,c,t,e,loc)
-#define NEW_CASE(h,b,loc) NEW_NODE(NODE_CASE,h,b,0,loc)
-#define NEW_CASE2(b,loc) NEW_NODE(NODE_CASE2,0,b,0,loc)
-#define NEW_CASE3(h,b,loc) NEW_NODE(NODE_CASE3,h,b,0,loc)
-#define NEW_WHEN(c,t,e,loc) NEW_NODE(NODE_WHEN,c,t,e,loc)
-#define NEW_IN(c,t,e,loc) NEW_NODE(NODE_IN,c,t,e,loc)
-#define NEW_WHILE(c,b,n,loc) NEW_NODE(NODE_WHILE,c,b,n,loc)
-#define NEW_UNTIL(c,b,n,loc) NEW_NODE(NODE_UNTIL,c,b,n,loc)
-#define NEW_FOR(i,b,loc) NEW_NODE(NODE_FOR,0,b,i,loc)
-#define NEW_FOR_MASGN(v,loc) NEW_NODE(NODE_FOR_MASGN,v,0,0,loc)
-#define NEW_ITER(a,b,loc) NEW_NODE(NODE_ITER,0,NEW_SCOPE(a,b,loc),0,loc)
-#define NEW_LAMBDA(a,b,loc) NEW_NODE(NODE_LAMBDA,0,NEW_SCOPE(a,b,loc),0,loc)
-#define NEW_BREAK(s,loc) NEW_NODE(NODE_BREAK,s,0,0,loc)
-#define NEW_NEXT(s,loc) NEW_NODE(NODE_NEXT,s,0,0,loc)
-#define NEW_REDO(loc) NEW_NODE(NODE_REDO,0,0,0,loc)
-#define NEW_RETRY(loc) NEW_NODE(NODE_RETRY,0,0,0,loc)
-#define NEW_BEGIN(b,loc) NEW_NODE(NODE_BEGIN,0,b,0,loc)
-#define NEW_RESCUE(b,res,e,loc) NEW_NODE(NODE_RESCUE,b,res,e,loc)
-#define NEW_RESBODY(a,ex,n,loc) NEW_NODE(NODE_RESBODY,n,ex,a,loc)
-#define NEW_ENSURE(b,en,loc) NEW_NODE(NODE_ENSURE,b,0,en,loc)
-#define NEW_RETURN(s,loc) NEW_NODE(NODE_RETURN,s,0,0,loc)
-#define NEW_YIELD(a,loc) NEW_NODE(NODE_YIELD,a,0,0,loc)
-#define NEW_LIST(a,loc) NEW_NODE(NODE_LIST,a,1,0,loc)
-#define NEW_ZLIST(loc) NEW_NODE(NODE_ZLIST,0,0,0,loc)
-#define NEW_HASH(a,loc) NEW_NODE(NODE_HASH,a,0,0,loc)
-#define NEW_MASGN(l,r,loc) NEW_NODE(NODE_MASGN,l,0,r,loc)
-#define NEW_GASGN(v,val,loc) NEW_NODE(NODE_GASGN,v,val,v,loc)
-#define NEW_LASGN(v,val,loc) NEW_NODE(NODE_LASGN,v,val,0,loc)
-#define NEW_DASGN(v,val,loc) NEW_NODE(NODE_DASGN,v,val,0,loc)
-#define NEW_IASGN(v,val,loc) NEW_NODE(NODE_IASGN,v,val,0,loc)
-#define NEW_CDECL(v,val,path,loc) NEW_NODE(NODE_CDECL,v,val,path,loc)
-#define NEW_CVASGN(v,val,loc) NEW_NODE(NODE_CVASGN,v,val,0,loc)
-#define NEW_OP_ASGN1(p,id,a,loc) NEW_NODE(NODE_OP_ASGN1,p,id,a,loc)
-#define NEW_OP_ASGN2(r,t,i,o,val,loc) NEW_NODE(NODE_OP_ASGN2,r,val,NEW_OP_ASGN22(i,o,t,loc),loc)
-#define NEW_OP_ASGN22(i,o,t,loc) NEW_NODE(NODE_OP_ASGN2,i,o,t,loc)
-#define NEW_OP_ASGN_OR(i,val,loc) NEW_NODE(NODE_OP_ASGN_OR,i,val,0,loc)
-#define NEW_OP_ASGN_AND(i,val,loc) NEW_NODE(NODE_OP_ASGN_AND,i,val,0,loc)
-#define NEW_OP_CDECL(v,op,val,loc) NEW_NODE(NODE_OP_CDECL,v,val,op,loc)
-#define NEW_GVAR(v,loc) NEW_NODE(NODE_GVAR,v,0,v,loc)
-#define NEW_LVAR(v,loc) NEW_NODE(NODE_LVAR,v,0,0,loc)
-#define NEW_DVAR(v,loc) NEW_NODE(NODE_DVAR,v,0,0,loc)
-#define NEW_IVAR(v,loc) NEW_NODE(NODE_IVAR,v,0,0,loc)
-#define NEW_CONST(v,loc) NEW_NODE(NODE_CONST,v,0,0,loc)
-#define NEW_CVAR(v,loc) NEW_NODE(NODE_CVAR,v,0,0,loc)
-#define NEW_NTH_REF(n,loc) NEW_NODE(NODE_NTH_REF,0,n,0,loc)
-#define NEW_BACK_REF(n,loc) NEW_NODE(NODE_BACK_REF,0,n,0,loc)
-#define NEW_MATCH(c,loc) NEW_NODE(NODE_MATCH,c,0,0,loc)
-#define NEW_MATCH2(n1,n2,loc) NEW_NODE(NODE_MATCH2,n1,n2,0,loc)
-#define NEW_MATCH3(r,n2,loc) NEW_NODE(NODE_MATCH3,r,n2,0,loc)
-#define NEW_LIT(l,loc) NEW_NODE(NODE_LIT,l,0,0,loc)
-#define NEW_STR(s,loc) NEW_NODE(NODE_STR,s,0,0,loc)
-#define NEW_DSTR(s,loc) NEW_NODE(NODE_DSTR,s,1,0,loc)
-#define NEW_XSTR(s,loc) NEW_NODE(NODE_XSTR,s,0,0,loc)
-#define NEW_DXSTR(s,loc) NEW_NODE(NODE_DXSTR,s,0,0,loc)
-#define NEW_DSYM(s,loc) NEW_NODE(NODE_DSYM,s,0,0,loc)
-#define NEW_EVSTR(n,loc) NEW_NODE(NODE_EVSTR,0,(n),0,loc)
-#define NEW_CALL(r,m,a,loc) NEW_NODE(NODE_CALL,r,m,a,loc)
-#define NEW_OPCALL(r,m,a,loc) NEW_NODE(NODE_OPCALL,r,m,a,loc)
-#define NEW_FCALL(m,a,loc) NEW_NODE(NODE_FCALL,0,m,a,loc)
-#define NEW_VCALL(m,loc) NEW_NODE(NODE_VCALL,0,m,0,loc)
-#define NEW_SUPER(a,loc) NEW_NODE(NODE_SUPER,0,0,a,loc)
-#define NEW_ZSUPER(loc) NEW_NODE(NODE_ZSUPER,0,0,0,loc)
-#define NEW_ARGS_AUX(r,b,loc) NEW_NODE(NODE_ARGS_AUX,r,b,0,loc)
-#define NEW_OPT_ARG(i,v,loc) NEW_NODE(NODE_OPT_ARG,i,v,0,loc)
-#define NEW_KW_ARG(i,v,loc) NEW_NODE(NODE_KW_ARG,i,v,0,loc)
-#define NEW_POSTARG(i,v,loc) NEW_NODE(NODE_POSTARG,i,v,0,loc)
-#define NEW_ARGSCAT(a,b,loc) NEW_NODE(NODE_ARGSCAT,a,b,0,loc)
-#define NEW_ARGSPUSH(a,b,loc) NEW_NODE(NODE_ARGSPUSH,a,b,0,loc)
-#define NEW_SPLAT(a,loc) NEW_NODE(NODE_SPLAT,a,0,0,loc)
-#define NEW_BLOCK_PASS(b,loc) NEW_NODE(NODE_BLOCK_PASS,0,b,0,loc)
-#define NEW_ALIAS(n,o,loc) NEW_NODE(NODE_ALIAS,n,o,0,loc)
-#define NEW_VALIAS(n,o,loc) NEW_NODE(NODE_VALIAS,n,o,0,loc)
-#define NEW_UNDEF(i,loc) NEW_NODE(NODE_UNDEF,0,i,0,loc)
-#define NEW_CLASS(n,b,s,loc) NEW_NODE(NODE_CLASS,n,NEW_SCOPE(0,b,loc),(s),loc)
-#define NEW_SCLASS(r,b,loc) NEW_NODE(NODE_SCLASS,r,NEW_SCOPE(0,b,loc),0,loc)
-#define NEW_MODULE(n,b,loc) NEW_NODE(NODE_MODULE,n,NEW_SCOPE(0,b,loc),0,loc)
-#define NEW_COLON2(c,i,loc) NEW_NODE(NODE_COLON2,c,i,0,loc)
-#define NEW_COLON3(i,loc) NEW_NODE(NODE_COLON3,0,i,0,loc)
-#define NEW_DOT2(b,e,loc) NEW_NODE(NODE_DOT2,b,e,0,loc)
-#define NEW_DOT3(b,e,loc) NEW_NODE(NODE_DOT3,b,e,0,loc)
-#define NEW_SELF(loc) NEW_NODE(NODE_SELF,0,0,1,loc)
-#define NEW_NIL(loc) NEW_NODE(NODE_NIL,0,0,0,loc)
-#define NEW_TRUE(loc) NEW_NODE(NODE_TRUE,0,0,0,loc)
-#define NEW_FALSE(loc) NEW_NODE(NODE_FALSE,0,0,0,loc)
-#define NEW_ERRINFO(loc) NEW_NODE(NODE_ERRINFO,0,0,0,loc)
-#define NEW_DEFINED(e,loc) NEW_NODE(NODE_DEFINED,e,0,0,loc)
-#define NEW_POSTEXE(b,loc) NEW_NODE(NODE_POSTEXE,0,b,0,loc)
-#define NEW_ATTRASGN(r,m,a,loc) NEW_NODE(NODE_ATTRASGN,r,m,a,loc)
-#define NEW_ERROR(loc) NEW_NODE(NODE_ERROR,0,0,0,loc)
-
-#define NODE_SPECIAL_REQUIRED_KEYWORD ((NODE *)-1)
-#define NODE_REQUIRED_KEYWORD_P(node) ((node)->nd_value == NODE_SPECIAL_REQUIRED_KEYWORD)
-#define NODE_SPECIAL_NO_NAME_REST ((NODE *)-1)
-#define NODE_NAMED_REST_P(node) ((node) != NODE_SPECIAL_NO_NAME_REST)
-#define NODE_SPECIAL_EXCESSIVE_COMMA ((ID)1)
-#define NODE_SPECIAL_NO_REST_KEYWORD ((NODE *)-1)
-
-VALUE rb_node_case_when_optimizable_literal(const NODE *const node);
-
-RUBY_SYMBOL_EXPORT_BEGIN
-
-typedef struct node_buffer_struct node_buffer_t;
-/* T_IMEMO/ast */
-typedef struct rb_ast_body_struct {
- const NODE *root;
- VALUE compile_option;
- VALUE script_lines;
- // script_lines is either:
- // - a Fixnum that represents the line count of the original source, or
- // - an Array that contains the lines of the original source
-} rb_ast_body_t;
-typedef struct rb_ast_struct {
- VALUE flags;
- node_buffer_t *node_buffer;
- rb_ast_body_t body;
-} rb_ast_t;
-rb_ast_t *rb_ast_new(void);
-void rb_ast_mark(rb_ast_t*);
-void rb_ast_update_references(rb_ast_t*);
-void rb_ast_dispose(rb_ast_t*);
-void rb_ast_free(rb_ast_t*);
-size_t rb_ast_memsize(const rb_ast_t*);
-void rb_ast_add_mark_object(rb_ast_t*, VALUE);
-void rb_ast_set_tokens(rb_ast_t*, VALUE);
-VALUE rb_ast_tokens(rb_ast_t *ast);
-NODE *rb_ast_newnode(rb_ast_t*, enum node_type type);
-void rb_ast_delete_node(rb_ast_t*, NODE *n);
-rb_ast_id_table_t *rb_ast_new_local_table(rb_ast_t*, int);
-rb_ast_id_table_t *rb_ast_resize_latest_local_table(rb_ast_t*, int);
-
-VALUE rb_parser_new(void);
-VALUE rb_parser_end_seen_p(VALUE);
-VALUE rb_parser_encoding(VALUE);
-VALUE rb_parser_set_yydebug(VALUE, VALUE);
-VALUE rb_parser_dump_tree(const NODE *node, int comment);
-void rb_parser_set_options(VALUE, int, int, int, int);
-
-rb_ast_t *rb_parser_compile_string(VALUE, const char*, VALUE, int);
-rb_ast_t *rb_parser_compile_string_path(VALUE vparser, VALUE fname, VALUE src, int line);
-rb_ast_t *rb_parser_compile_file_path(VALUE vparser, VALUE fname, VALUE input, int line);
-rb_ast_t *rb_parser_compile_generic(VALUE vparser, VALUE (*lex_gets)(VALUE, int), VALUE fname, VALUE input, int line);
-
-void rb_node_init(NODE *n, enum node_type type, VALUE a0, VALUE a1, VALUE a2);
-const char *ruby_node_name(int node);
-
-const struct kwtable *rb_reserved_word(const char *, unsigned int);
-
-struct rb_args_info {
- NODE *pre_init;
- NODE *post_init;
-
- int pre_args_num; /* count of mandatory pre-arguments */
- int post_args_num; /* count of mandatory post-arguments */
-
- ID first_post_arg;
-
- ID rest_arg;
- ID block_arg;
-
- NODE *kw_args;
- NODE *kw_rest_arg;
-
- NODE *opt_args;
- unsigned int no_kwarg: 1;
- unsigned int ruby2_keywords: 1;
- unsigned int forwarding: 1;
-
- VALUE imemo;
-};
-
-struct rb_ary_pattern_info {
- NODE *pre_args;
- NODE *rest_arg;
- NODE *post_args;
-};
-
-struct rb_fnd_pattern_info {
- NODE *pre_rest_arg;
- NODE *args;
- NODE *post_rest_arg;
-};
-
-struct parser_params;
-void *rb_parser_malloc(struct parser_params *, size_t);
-void *rb_parser_realloc(struct parser_params *, void *, size_t);
-void *rb_parser_calloc(struct parser_params *, size_t, size_t);
-void rb_parser_free(struct parser_params *, void *);
-PRINTF_ARGS(void rb_parser_printf(struct parser_params *parser, const char *fmt, ...), 2, 3);
-void rb_ast_node_type_change(NODE *n, enum node_type type);
-
-RUBY_SYMBOL_EXPORT_END
-
-static inline VALUE
-rb_node_set_type(NODE *n, enum node_type t)
-{
-#if RUBY_DEBUG
- rb_ast_node_type_change(n, t);
-#endif
- return nd_init_type(n, t);
-}
-
static inline bool
nd_type_p(const NODE *n, enum node_type t)
{
return (enum node_type)nd_type(n) == t;
}
-#if defined(__cplusplus)
-#if 0
-{ /* satisfy cc-mode */
-#endif
-} /* extern "C" { */
-#endif
#endif /* RUBY_NODE_H */
diff --git a/node_dump.c b/node_dump.c
new file mode 100644
index 0000000000..331ea4da52
--- /dev/null
+++ b/node_dump.c
@@ -0,0 +1,1122 @@
+/**********************************************************************
+
+ node_dump.c - dump ruby node tree
+
+ $Author: mame $
+ created at: 09/12/06 21:23:44 JST
+
+ Copyright (C) 2009 Yusuke Endoh
+
+**********************************************************************/
+
+#include "internal.h"
+#include "internal/hash.h"
+#include "internal/variable.h"
+#include "ruby/ruby.h"
+#include "vm_core.h"
+
+#define A(str) rb_str_cat2(buf, (str))
+#define AR(str) rb_str_concat(buf, (str))
+
+#define A_INDENT add_indent(buf, indent)
+#define D_INDENT rb_str_cat2(indent, next_indent)
+#define D_DEDENT rb_str_resize(indent, RSTRING_LEN(indent) - 4)
+#define A_ID(id) add_id(buf, (id))
+#define A_INT(val) rb_str_catf(buf, "%d", (val))
+#define A_LONG(val) rb_str_catf(buf, "%ld", (val))
+#define A_LIT(lit) AR(rb_dump_literal(lit))
+#define A_NODE_HEADER(node, term) \
+ rb_str_catf(buf, "@ %s (id: %d, line: %d, location: (%d,%d)-(%d,%d))%s"term, \
+ ruby_node_name(nd_type(node)), nd_node_id(node), nd_line(node), \
+ nd_first_lineno(node), nd_first_column(node), \
+ nd_last_lineno(node), nd_last_column(node), \
+ (node->flags & NODE_FL_NEWLINE ? "*" : ""))
+#define A_FIELD_HEADER(len, name, term) \
+ rb_str_catf(buf, "+- %.*s:"term, (len), (name))
+#define D_FIELD_HEADER(len, name, term) (A_INDENT, A_FIELD_HEADER(len, name, term))
+
+#define D_NULL_NODE (A_INDENT, A("(null node)\n"))
+#define D_NODE_HEADER(node) (A_INDENT, A_NODE_HEADER(node, "\n"))
+
+#define COMPOUND_FIELD(len, name) \
+ FIELD_BLOCK((D_FIELD_HEADER((len), (name), "\n"), D_INDENT), D_DEDENT)
+
+#define COMPOUND_FIELD1(name, ann) \
+ COMPOUND_FIELD(FIELD_NAME_LEN(name, ann), \
+ FIELD_NAME_DESC(name, ann))
+
+#define FIELD_NAME_DESC(name, ann) name " (" ann ")"
+#define FIELD_NAME_LEN(name, ann) (int)( \
+ comment ? \
+ rb_strlen_lit(FIELD_NAME_DESC(name, ann)) : \
+ rb_strlen_lit(name))
+#define SIMPLE_FIELD(len, name) \
+ FIELD_BLOCK(D_FIELD_HEADER((len), (name), " "), A("\n"))
+
+#define FIELD_BLOCK(init, reset) \
+ for (init, field_flag = 1; \
+ field_flag; /* should be optimized away */ \
+ reset, field_flag = 0)
+
+#define SIMPLE_FIELD1(name, ann) SIMPLE_FIELD(FIELD_NAME_LEN(name, ann), FIELD_NAME_DESC(name, ann))
+#define F_CUSTOM1(name, ann) SIMPLE_FIELD1(#name, ann)
+#define F_ID(name, ann) SIMPLE_FIELD1(#name, ann) A_ID(node->name)
+#define F_GENTRY(name, ann) SIMPLE_FIELD1(#name, ann) A_ID(node->name)
+#define F_INT(name, ann) SIMPLE_FIELD1(#name, ann) A_INT(node->name)
+#define F_LONG(name, ann) SIMPLE_FIELD1(#name, ann) A_LONG(node->name)
+#define F_LIT(name, ann) SIMPLE_FIELD1(#name, ann) A_LIT(node->name)
+#define F_MSG(name, ann, desc) SIMPLE_FIELD1(#name, ann) A(desc)
+
+#define F_NODE(name, ann) \
+ COMPOUND_FIELD1(#name, ann) {dump_node(buf, indent, comment, node->name);}
+
+#define ANN(ann) \
+ if (comment) { \
+ A_INDENT; A("| # " ann "\n"); \
+ }
+
+#define LAST_NODE (next_indent = " ")
+
+VALUE
+rb_dump_literal(VALUE lit)
+{
+ if (!RB_SPECIAL_CONST_P(lit)) {
+ VALUE str;
+ switch (RB_BUILTIN_TYPE(lit)) {
+ case T_CLASS: case T_MODULE: case T_ICLASS:
+ str = rb_class_path(lit);
+ if (FL_TEST(lit, FL_SINGLETON)) {
+ str = rb_sprintf("<%"PRIsVALUE">", str);
+ }
+ return str;
+ default:
+ break;
+ }
+ }
+ return rb_inspect(lit);
+}
+
+static void
+add_indent(VALUE buf, VALUE indent)
+{
+ AR(indent);
+}
+
+static void
+add_id(VALUE buf, ID id)
+{
+ if (id == 0) {
+ A("(null)");
+ }
+ else {
+ VALUE str = rb_id2str(id);
+ if (str) {
+ A(":"); AR(str);
+ }
+ else {
+ rb_str_catf(buf, "(internal variable: 0x%"PRIsVALUE")", id);
+ }
+ }
+}
+
+struct add_option_arg {
+ VALUE buf, indent;
+ st_index_t count;
+};
+
+static void dump_node(VALUE, VALUE, int, const NODE *);
+static const char default_indent[] = "| ";
+
+static void
+dump_array(VALUE buf, VALUE indent, int comment, const NODE *node)
+{
+ int field_flag;
+ const char *next_indent = default_indent;
+ F_LONG(nd_alen, "length");
+ F_NODE(nd_head, "element");
+ while (node->nd_next && nd_type_p(node->nd_next, NODE_LIST)) {
+ node = node->nd_next;
+ F_NODE(nd_head, "element");
+ }
+ LAST_NODE;
+ F_NODE(nd_next, "next element");
+}
+
+static void
+dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
+{
+ int field_flag;
+ int i;
+ const char *next_indent = default_indent;
+ enum node_type type;
+
+ if (!node) {
+ D_NULL_NODE;
+ return;
+ }
+
+ D_NODE_HEADER(node);
+
+ type = nd_type(node);
+ switch (type) {
+ case NODE_BLOCK:
+ ANN("statement sequence");
+ ANN("format: [nd_head]; ...; [nd_next]");
+ ANN("example: foo; bar");
+ i = 0;
+ do {
+ A_INDENT;
+ rb_str_catf(buf, "+- nd_head (%s%d):\n",
+ comment ? "statement #" : "", ++i);
+ if (!node->nd_next) LAST_NODE;
+ D_INDENT;
+ dump_node(buf, indent, comment, node->nd_head);
+ D_DEDENT;
+ } while (node->nd_next &&
+ nd_type_p(node->nd_next, NODE_BLOCK) &&
+ (node = node->nd_next, 1));
+ if (node->nd_next) {
+ LAST_NODE;
+ F_NODE(nd_next, "next block");
+ }
+ return;
+
+ case NODE_IF:
+ ANN("if statement");
+ ANN("format: if [nd_cond] then [nd_body] else [nd_else] end");
+ ANN("example: if x == 1 then foo else bar end");
+ F_NODE(nd_cond, "condition expr");
+ F_NODE(nd_body, "then clause");
+ LAST_NODE;
+ F_NODE(nd_else, "else clause");
+ return;
+
+ case NODE_UNLESS:
+ ANN("unless statement");
+ ANN("format: unless [nd_cond] then [nd_body] else [nd_else] end");
+ ANN("example: unless x == 1 then foo else bar end");
+ F_NODE(nd_cond, "condition expr");
+ F_NODE(nd_body, "then clause");
+ LAST_NODE;
+ F_NODE(nd_else, "else clause");
+ return;
+
+ case NODE_CASE:
+ ANN("case statement");
+ ANN("format: case [nd_head]; [nd_body]; end");
+ ANN("example: case x; when 1; foo; when 2; bar; else baz; end");
+ F_NODE(nd_head, "case expr");
+ LAST_NODE;
+ F_NODE(nd_body, "when clauses");
+ return;
+ case NODE_CASE2:
+ ANN("case statement with no head");
+ ANN("format: case; [nd_body]; end");
+ ANN("example: case; when 1; foo; when 2; bar; else baz; end");
+ F_NODE(nd_head, "case expr");
+ LAST_NODE;
+ F_NODE(nd_body, "when clauses");
+ return;
+ case NODE_CASE3:
+ ANN("case statement (pattern matching)");
+ ANN("format: case [nd_head]; [nd_body]; end");
+ ANN("example: case x; in 1; foo; in 2; bar; else baz; end");
+ F_NODE(nd_head, "case expr");
+ LAST_NODE;
+ F_NODE(nd_body, "in clauses");
+ return;
+
+ case NODE_WHEN:
+ ANN("when clause");
+ ANN("format: when [nd_head]; [nd_body]; (when or else) [nd_next]");
+ ANN("example: case x; when 1; foo; when 2; bar; else baz; end");
+ F_NODE(nd_head, "when value");
+ F_NODE(nd_body, "when body");
+ LAST_NODE;
+ F_NODE(nd_next, "next when clause");
+ return;
+
+ case NODE_IN:
+ ANN("in clause");
+ ANN("format: in [nd_head]; [nd_body]; (in or else) [nd_next]");
+ ANN("example: case x; in 1; foo; in 2; bar; else baz; end");
+ F_NODE(nd_head, "in pattern");
+ F_NODE(nd_body, "in body");
+ LAST_NODE;
+ F_NODE(nd_next, "next in clause");
+ return;
+
+ case NODE_WHILE:
+ ANN("while statement");
+ ANN("format: while [nd_cond]; [nd_body]; end");
+ ANN("example: while x == 1; foo; end");
+ goto loop;
+ case NODE_UNTIL:
+ ANN("until statement");
+ ANN("format: until [nd_cond]; [nd_body]; end");
+ ANN("example: until x == 1; foo; end");
+ loop:
+ F_CUSTOM1(nd_state, "begin-end-while?") {
+ A_INT((int)node->nd_state);
+ A((node->nd_state == 1) ? " (while-end)" : " (begin-end-while)");
+ }
+ F_NODE(nd_cond, "condition");
+ LAST_NODE;
+ F_NODE(nd_body, "body");
+ return;
+
+ case NODE_ITER:
+ ANN("method call with block");
+ ANN("format: [nd_iter] { [nd_body] }");
+ ANN("example: 3.times { foo }");
+ goto iter;
+ case NODE_FOR:
+ ANN("for statement");
+ ANN("format: for * in [nd_iter] do [nd_body] end");
+ ANN("example: for i in 1..3 do foo end");
+ iter:
+ F_NODE(nd_iter, "iteration receiver");
+ LAST_NODE;
+ F_NODE(nd_body, "body");
+ return;
+
+ case NODE_FOR_MASGN:
+ ANN("vars of for statement with masgn");
+ ANN("format: for [nd_var] in ... do ... end");
+ ANN("example: for x, y in 1..3 do foo end");
+ LAST_NODE;
+ F_NODE(nd_var, "var");
+ return;
+
+ case NODE_BREAK:
+ ANN("break statement");
+ ANN("format: break [nd_stts]");
+ ANN("example: break 1");
+ goto jump;
+ case NODE_NEXT:
+ ANN("next statement");
+ ANN("format: next [nd_stts]");
+ ANN("example: next 1");
+ goto jump;
+ case NODE_RETURN:
+ ANN("return statement");
+ ANN("format: return [nd_stts]");
+ ANN("example: return 1");
+ jump:
+ LAST_NODE;
+ F_NODE(nd_stts, "value");
+ return;
+
+ case NODE_REDO:
+ ANN("redo statement");
+ ANN("format: redo");
+ ANN("example: redo");
+ return;
+
+ case NODE_RETRY:
+ ANN("retry statement");
+ ANN("format: retry");
+ ANN("example: retry");
+ return;
+
+ case NODE_BEGIN:
+ ANN("begin statement");
+ ANN("format: begin; [nd_body]; end");
+ ANN("example: begin; 1; end");
+ LAST_NODE;
+ F_NODE(nd_body, "body");
+ return;
+
+ case NODE_RESCUE:
+ ANN("rescue clause");
+ ANN("format: begin; [nd_body]; (rescue) [nd_resq]; else [nd_else]; end");
+ ANN("example: begin; foo; rescue; bar; else; baz; end");
+ F_NODE(nd_head, "body");
+ F_NODE(nd_resq, "rescue clause list");
+ LAST_NODE;
+ F_NODE(nd_else, "rescue else clause");
+ return;
+
+ case NODE_RESBODY:
+ ANN("rescue clause (cont'd)");
+ ANN("format: rescue [nd_args]; [nd_body]; (rescue) [nd_head]");
+ ANN("example: begin; foo; rescue; bar; else; baz; end");
+ F_NODE(nd_args, "rescue exceptions");
+ F_NODE(nd_body, "rescue clause");
+ LAST_NODE;
+ F_NODE(nd_head, "next rescue clause");
+ return;
+
+ case NODE_ENSURE:
+ ANN("ensure clause");
+ ANN("format: begin; [nd_head]; ensure; [nd_ensr]; end");
+ ANN("example: begin; foo; ensure; bar; end");
+ F_NODE(nd_head, "body");
+ LAST_NODE;
+ F_NODE(nd_ensr, "ensure clause");
+ return;
+
+ case NODE_AND:
+ ANN("&& operator");
+ ANN("format: [nd_1st] && [nd_2nd]");
+ ANN("example: foo && bar");
+ goto andor;
+ case NODE_OR:
+ ANN("|| operator");
+ ANN("format: [nd_1st] || [nd_2nd]");
+ ANN("example: foo || bar");
+ andor:
+ while (1) {
+ F_NODE(nd_1st, "left expr");
+ if (!node->nd_2nd || !nd_type_p(node->nd_2nd, type))
+ break;
+ node = node->nd_2nd;
+ }
+ LAST_NODE;
+ F_NODE(nd_2nd, "right expr");
+ return;
+
+ case NODE_MASGN:
+ ANN("multiple assignment");
+ ANN("format: [nd_head], [nd_args] = [nd_value]");
+ ANN("example: a, b = foo");
+ F_NODE(nd_value, "rhsn");
+ F_NODE(nd_head, "lhsn");
+ if (NODE_NAMED_REST_P(node->nd_args)) {
+ LAST_NODE;
+ F_NODE(nd_args, "splatn");
+ }
+ else {
+ F_MSG(nd_args, "splatn", "NODE_SPECIAL_NO_NAME_REST (rest argument without name)");
+ }
+ return;
+
+ case NODE_LASGN:
+ ANN("local variable assignment");
+ ANN("format: [nd_vid](lvar) = [nd_value]");
+ ANN("example: x = foo");
+ F_ID(nd_vid, "local variable");
+ if (NODE_REQUIRED_KEYWORD_P(node)) {
+ F_MSG(nd_value, "rvalue", "NODE_SPECIAL_REQUIRED_KEYWORD (required keyword argument)");
+ }
+ else {
+ LAST_NODE;
+ F_NODE(nd_value, "rvalue");
+ }
+ return;
+ case NODE_DASGN:
+ ANN("dynamic variable assignment");
+ ANN("format: [nd_vid](dvar) = [nd_value]");
+ ANN("example: x = nil; 1.times { x = foo }");
+ ANN("example: 1.times { x = foo }");
+ F_ID(nd_vid, "local variable");
+ if (NODE_REQUIRED_KEYWORD_P(node)) {
+ F_MSG(nd_value, "rvalue", "NODE_SPECIAL_REQUIRED_KEYWORD (required keyword argument)");
+ }
+ else {
+ LAST_NODE;
+ F_NODE(nd_value, "rvalue");
+ }
+ return;
+ case NODE_IASGN:
+ ANN("instance variable assignment");
+ ANN("format: [nd_vid](ivar) = [nd_value]");
+ ANN("example: @x = foo");
+ F_ID(nd_vid, "instance variable");
+ LAST_NODE;
+ F_NODE(nd_value, "rvalue");
+ return;
+ case NODE_CVASGN:
+ ANN("class variable assignment");
+ ANN("format: [nd_vid](cvar) = [nd_value]");
+ ANN("example: @@x = foo");
+ F_ID(nd_vid, "class variable");
+ LAST_NODE;
+ F_NODE(nd_value, "rvalue");
+ return;
+ case NODE_GASGN:
+ ANN("global variable assignment");
+ ANN("format: [nd_entry](gvar) = [nd_value]");
+ ANN("example: $x = foo");
+ F_GENTRY(nd_entry, "global variable");
+ LAST_NODE;
+ F_NODE(nd_value, "rvalue");
+ return;
+
+ case NODE_CDECL:
+ ANN("constant declaration");
+ ANN("format: [nd_else]::[nd_vid](constant) = [nd_value]");
+ ANN("example: X = foo");
+ if (node->nd_vid) {
+ F_ID(nd_vid, "constant");
+ F_MSG(nd_else, "extension", "not used");
+ }
+ else {
+ F_MSG(nd_vid, "constant", "0 (see extension field)");
+ F_NODE(nd_else, "extension");
+ }
+ LAST_NODE;
+ F_NODE(nd_value, "rvalue");
+ return;
+
+ case NODE_OP_ASGN1:
+ ANN("array assignment with operator");
+ ANN("format: [nd_recv] [ [nd_args->nd_head] ] [nd_mid]= [nd_args->nd_body]");
+ ANN("example: ary[1] += foo");
+ F_NODE(nd_recv, "receiver");
+ F_ID(nd_mid, "operator");
+ F_NODE(nd_args->nd_head, "index");
+ LAST_NODE;
+ F_NODE(nd_args->nd_body, "rvalue");
+ return;
+
+ case NODE_OP_ASGN2:
+ ANN("attr assignment with operator");
+ ANN("format: [nd_recv].[attr] [nd_next->nd_mid]= [nd_value]");
+ ANN(" where [attr]: [nd_next->nd_vid]");
+ ANN("example: struct.field += foo");
+ F_NODE(nd_recv, "receiver");
+ F_CUSTOM1(nd_next->nd_vid, "attr") {
+ if (node->nd_next->nd_aid) A("? ");
+ A_ID(node->nd_next->nd_vid);
+ }
+ F_ID(nd_next->nd_mid, "operator");
+ LAST_NODE;
+ F_NODE(nd_value, "rvalue");
+ return;
+
+ case NODE_OP_ASGN_AND:
+ ANN("assignment with && operator");
+ ANN("format: [nd_head] &&= [nd_value]");
+ ANN("example: foo &&= bar");
+ goto asgn_andor;
+ case NODE_OP_ASGN_OR:
+ ANN("assignment with || operator");
+ ANN("format: [nd_head] ||= [nd_value]");
+ ANN("example: foo ||= bar");
+ asgn_andor:
+ F_NODE(nd_head, "variable");
+ LAST_NODE;
+ F_NODE(nd_value, "rvalue");
+ return;
+
+ case NODE_OP_CDECL:
+ ANN("constant declaration with operator");
+ ANN("format: [nd_head](constant) [nd_aid]= [nd_value]");
+ ANN("example: A::B ||= 1");
+ F_NODE(nd_head, "constant");
+ F_ID(nd_aid, "operator");
+ LAST_NODE;
+ F_NODE(nd_value, "rvalue");
+ return;
+
+ case NODE_CALL:
+ ANN("method invocation");
+ ANN("format: [nd_recv].[nd_mid]([nd_args])");
+ ANN("example: obj.foo(1)");
+ F_ID(nd_mid, "method id");
+ F_NODE(nd_recv, "receiver");
+ LAST_NODE;
+ F_NODE(nd_args, "arguments");
+ return;
+
+ case NODE_OPCALL:
+ ANN("method invocation");
+ ANN("format: [nd_recv] [nd_mid] [nd_args]");
+ ANN("example: foo + bar");
+ F_ID(nd_mid, "method id");
+ F_NODE(nd_recv, "receiver");
+ LAST_NODE;
+ F_NODE(nd_args, "arguments");
+ return;
+
+ case NODE_FCALL:
+ ANN("function call");
+ ANN("format: [nd_mid]([nd_args])");
+ ANN("example: foo(1)");
+ F_ID(nd_mid, "method id");
+ LAST_NODE;
+ F_NODE(nd_args, "arguments");
+ return;
+
+ case NODE_VCALL:
+ ANN("function call with no argument");
+ ANN("format: [nd_mid]");
+ ANN("example: foo");
+ F_ID(nd_mid, "method id");
+ return;
+
+ case NODE_QCALL:
+ ANN("safe method invocation");
+ ANN("format: [nd_recv]&.[nd_mid]([nd_args])");
+ ANN("example: obj&.foo(1)");
+ F_ID(nd_mid, "method id");
+ F_NODE(nd_recv, "receiver");
+ LAST_NODE;
+ F_NODE(nd_args, "arguments");
+ return;
+
+ case NODE_SUPER:
+ ANN("super invocation");
+ ANN("format: super [nd_args]");
+ ANN("example: super 1");
+ LAST_NODE;
+ F_NODE(nd_args, "arguments");
+ return;
+
+ case NODE_ZSUPER:
+ ANN("super invocation with no argument");
+ ANN("format: super");
+ ANN("example: super");
+ return;
+
+ case NODE_LIST:
+ ANN("list constructor");
+ ANN("format: [ [nd_head], [nd_next].. ] (length: [nd_alen])");
+ ANN("example: [1, 2, 3]");
+ goto ary;
+ case NODE_VALUES:
+ ANN("return arguments");
+ ANN("format: [ [nd_head], [nd_next].. ] (length: [nd_alen])");
+ ANN("example: return 1, 2, 3");
+ ary:
+ dump_array(buf, indent, comment, node);
+ return;
+
+ case NODE_ZLIST:
+ ANN("empty list constructor");
+ ANN("format: []");
+ ANN("example: []");
+ return;
+
+ case NODE_HASH:
+ if (!node->nd_brace) {
+ ANN("keyword arguments");
+ ANN("format: nd_head");
+ ANN("example: a: 1, b: 2");
+ }
+ else {
+ ANN("hash constructor");
+ ANN("format: { [nd_head] }");
+ ANN("example: { 1 => 2, 3 => 4 }");
+ }
+ F_CUSTOM1(nd_brace, "keyword arguments or hash literal") {
+ switch (node->nd_brace) {
+ case 0: A("0 (keyword argument)"); break;
+ case 1: A("1 (hash literal)"); break;
+ }
+ }
+ LAST_NODE;
+ F_NODE(nd_head, "contents");
+ return;
+
+ case NODE_YIELD:
+ ANN("yield invocation");
+ ANN("format: yield [nd_head]");
+ ANN("example: yield 1");
+ LAST_NODE;
+ F_NODE(nd_head, "arguments");
+ return;
+
+ case NODE_LVAR:
+ ANN("local variable reference");
+ ANN("format: [nd_vid](lvar)");
+ ANN("example: x");
+ F_ID(nd_vid, "local variable");
+ return;
+ case NODE_DVAR:
+ ANN("dynamic variable reference");
+ ANN("format: [nd_vid](dvar)");
+ ANN("example: 1.times { x = 1; x }");
+ F_ID(nd_vid, "local variable");
+ return;
+ case NODE_IVAR:
+ ANN("instance variable reference");
+ ANN("format: [nd_vid](ivar)");
+ ANN("example: @x");
+ F_ID(nd_vid, "instance variable");
+ return;
+ case NODE_CONST:
+ ANN("constant reference");
+ ANN("format: [nd_vid](constant)");
+ ANN("example: X");
+ F_ID(nd_vid, "constant");
+ return;
+ case NODE_CVAR:
+ ANN("class variable reference");
+ ANN("format: [nd_vid](cvar)");
+ ANN("example: @@x");
+ F_ID(nd_vid, "class variable");
+ return;
+
+ case NODE_GVAR:
+ ANN("global variable reference");
+ ANN("format: [nd_entry](gvar)");
+ ANN("example: $x");
+ F_GENTRY(nd_entry, "global variable");
+ return;
+
+ case NODE_NTH_REF:
+ ANN("nth special variable reference");
+ ANN("format: $[nd_nth]");
+ ANN("example: $1, $2, ..");
+ F_CUSTOM1(nd_nth, "variable") { A("$"); A_LONG(node->nd_nth); }
+ return;
+
+ case NODE_BACK_REF:
+ ANN("back special variable reference");
+ ANN("format: $[nd_nth]");
+ ANN("example: $&, $`, $', $+");
+ F_CUSTOM1(nd_nth, "variable") {
+ char name[3] = "$ ";
+ name[1] = (char)node->nd_nth;
+ A(name);
+ }
+ return;
+
+ case NODE_MATCH:
+ ANN("match expression (against $_ implicitly)");
+ ANN("format: [nd_lit] (in condition)");
+ ANN("example: if /foo/; foo; end");
+ F_LIT(nd_lit, "regexp");
+ return;
+
+ case NODE_MATCH2:
+ ANN("match expression (regexp first)");
+ ANN("format: [nd_recv] =~ [nd_value]");
+ ANN("example: /foo/ =~ 'foo'");
+ F_NODE(nd_recv, "regexp (receiver)");
+ if (!node->nd_args) LAST_NODE;
+ F_NODE(nd_value, "string (argument)");
+ if (node->nd_args) {
+ LAST_NODE;
+ F_NODE(nd_args, "named captures");
+ }
+ return;
+
+ case NODE_MATCH3:
+ ANN("match expression (regexp second)");
+ ANN("format: [nd_recv] =~ [nd_value]");
+ ANN("example: 'foo' =~ /foo/");
+ F_NODE(nd_recv, "string (receiver)");
+ LAST_NODE;
+ F_NODE(nd_value, "regexp (argument)");
+ return;
+
+ case NODE_LIT:
+ ANN("literal");
+ ANN("format: [nd_lit]");
+ ANN("example: 1, /foo/");
+ goto lit;
+ case NODE_STR:
+ ANN("string literal");
+ ANN("format: [nd_lit]");
+ ANN("example: 'foo'");
+ goto lit;
+ case NODE_XSTR:
+ ANN("xstring literal");
+ ANN("format: [nd_lit]");
+ ANN("example: `foo`");
+ lit:
+ F_LIT(nd_lit, "literal");
+ return;
+
+ case NODE_ONCE:
+ ANN("once evaluation");
+ ANN("format: [nd_body]");
+ ANN("example: /foo#{ bar }baz/o");
+ LAST_NODE;
+ F_NODE(nd_body, "body");
+ return;
+ case NODE_DSTR:
+ ANN("string literal with interpolation");
+ ANN("format: [nd_lit]");
+ ANN("example: \"foo#{ bar }baz\"");
+ goto dlit;
+ case NODE_DXSTR:
+ ANN("xstring literal with interpolation");
+ ANN("format: [nd_lit]");
+ ANN("example: `foo#{ bar }baz`");
+ goto dlit;
+ case NODE_DREGX:
+ ANN("regexp literal with interpolation");
+ ANN("format: [nd_lit]");
+ ANN("example: /foo#{ bar }baz/");
+ goto dlit;
+ case NODE_DSYM:
+ ANN("symbol literal with interpolation");
+ ANN("format: [nd_lit]");
+ ANN("example: :\"foo#{ bar }baz\"");
+ dlit:
+ F_LIT(nd_lit, "preceding string");
+ if (!node->nd_next) return;
+ F_NODE(nd_next->nd_head, "interpolation");
+ LAST_NODE;
+ F_NODE(nd_next->nd_next, "tailing strings");
+ return;
+
+ case NODE_EVSTR:
+ ANN("interpolation expression");
+ ANN("format: \"..#{ [nd_lit] }..\"");
+ ANN("example: \"foo#{ bar }baz\"");
+ LAST_NODE;
+ F_NODE(nd_body, "body");
+ return;
+
+ case NODE_ARGSCAT:
+ ANN("splat argument following arguments");
+ ANN("format: ..(*[nd_head], [nd_body..])");
+ ANN("example: foo(*ary, post_arg1, post_arg2)");
+ F_NODE(nd_head, "preceding array");
+ LAST_NODE;
+ F_NODE(nd_body, "following array");
+ return;
+
+ case NODE_ARGSPUSH:
+ ANN("splat argument following one argument");
+ ANN("format: ..(*[nd_head], [nd_body])");
+ ANN("example: foo(*ary, post_arg)");
+ F_NODE(nd_head, "preceding array");
+ LAST_NODE;
+ F_NODE(nd_body, "following element");
+ return;
+
+ case NODE_SPLAT:
+ ANN("splat argument");
+ ANN("format: *[nd_head]");
+ ANN("example: foo(*ary)");
+ LAST_NODE;
+ F_NODE(nd_head, "splat'ed array");
+ return;
+
+ case NODE_BLOCK_PASS:
+ ANN("arguments with block argument");
+ ANN("format: ..([nd_head], &[nd_body])");
+ ANN("example: foo(x, &blk)");
+ F_NODE(nd_head, "other arguments");
+ LAST_NODE;
+ F_NODE(nd_body, "block argument");
+ return;
+
+ case NODE_DEFN:
+ ANN("method definition");
+ ANN("format: def [nd_mid] [nd_defn]; end");
+ ANN("example: def foo; bar; end");
+ F_ID(nd_mid, "method name");
+ LAST_NODE;
+ F_NODE(nd_defn, "method definition");
+ return;
+
+ case NODE_DEFS:
+ ANN("singleton method definition");
+ ANN("format: def [nd_recv].[nd_mid] [nd_defn]; end");
+ ANN("example: def obj.foo; bar; end");
+ F_NODE(nd_recv, "receiver");
+ F_ID(nd_mid, "method name");
+ LAST_NODE;
+ F_NODE(nd_defn, "method definition");
+ return;
+
+ case NODE_ALIAS:
+ ANN("method alias statement");
+ ANN("format: alias [nd_1st] [nd_2nd]");
+ ANN("example: alias bar foo");
+ F_NODE(nd_1st, "new name");
+ LAST_NODE;
+ F_NODE(nd_2nd, "old name");
+ return;
+
+ case NODE_VALIAS:
+ ANN("global variable alias statement");
+ ANN("format: alias [nd_alias](gvar) [nd_orig](gvar)");
+ ANN("example: alias $y $x");
+ F_ID(nd_alias, "new name");
+ F_ID(nd_orig, "old name");
+ return;
+
+ case NODE_UNDEF:
+ ANN("method undef statement");
+ ANN("format: undef [nd_undef]");
+ ANN("example: undef foo");
+ LAST_NODE;
+ F_NODE(nd_undef, "old name");
+ return;
+
+ case NODE_CLASS:
+ ANN("class definition");
+ ANN("format: class [nd_cpath] < [nd_super]; [nd_body]; end");
+ ANN("example: class C2 < C; ..; end");
+ F_NODE(nd_cpath, "class path");
+ F_NODE(nd_super, "superclass");
+ LAST_NODE;
+ F_NODE(nd_body, "class definition");
+ return;
+
+ case NODE_MODULE:
+ ANN("module definition");
+ ANN("format: module [nd_cpath]; [nd_body]; end");
+ ANN("example: module M; ..; end");
+ F_NODE(nd_cpath, "module path");
+ LAST_NODE;
+ F_NODE(nd_body, "module definition");
+ return;
+
+ case NODE_SCLASS:
+ ANN("singleton class definition");
+ ANN("format: class << [nd_recv]; [nd_body]; end");
+ ANN("example: class << obj; ..; end");
+ F_NODE(nd_recv, "receiver");
+ LAST_NODE;
+ F_NODE(nd_body, "singleton class definition");
+ return;
+
+ case NODE_COLON2:
+ ANN("scoped constant reference");
+ ANN("format: [nd_head]::[nd_mid]");
+ ANN("example: M::C");
+ F_ID(nd_mid, "constant name");
+ LAST_NODE;
+ F_NODE(nd_head, "receiver");
+ return;
+
+ case NODE_COLON3:
+ ANN("top-level constant reference");
+ ANN("format: ::[nd_mid]");
+ ANN("example: ::Object");
+ F_ID(nd_mid, "constant name");
+ return;
+
+ case NODE_DOT2:
+ ANN("range constructor (incl.)");
+ ANN("format: [nd_beg]..[nd_end]");
+ ANN("example: 1..5");
+ goto dot;
+ case NODE_DOT3:
+ ANN("range constructor (excl.)");
+ ANN("format: [nd_beg]...[nd_end]");
+ ANN("example: 1...5");
+ goto dot;
+ case NODE_FLIP2:
+ ANN("flip-flop condition (incl.)");
+ ANN("format: [nd_beg]..[nd_end]");
+ ANN("example: if (x==1)..(x==5); foo; end");
+ goto dot;
+ case NODE_FLIP3:
+ ANN("flip-flop condition (excl.)");
+ ANN("format: [nd_beg]...[nd_end]");
+ ANN("example: if (x==1)...(x==5); foo; end");
+ dot:
+ F_NODE(nd_beg, "begin");
+ LAST_NODE;
+ F_NODE(nd_end, "end");
+ return;
+
+ case NODE_SELF:
+ ANN("self");
+ ANN("format: self");
+ ANN("example: self");
+ return;
+
+ case NODE_NIL:
+ ANN("nil");
+ ANN("format: nil");
+ ANN("example: nil");
+ return;
+
+ case NODE_TRUE:
+ ANN("true");
+ ANN("format: true");
+ ANN("example: true");
+ return;
+
+ case NODE_FALSE:
+ ANN("false");
+ ANN("format: false");
+ ANN("example: false");
+ return;
+
+ case NODE_ERRINFO:
+ ANN("virtual reference to $!");
+ ANN("format: rescue => id");
+ ANN("example: rescue => id");
+ return;
+
+ case NODE_DEFINED:
+ ANN("defined? expression");
+ ANN("format: defined?([nd_head])");
+ ANN("example: defined?(foo)");
+ F_NODE(nd_head, "expr");
+ return;
+
+ case NODE_POSTEXE:
+ ANN("post-execution");
+ ANN("format: END { [nd_body] }");
+ ANN("example: END { foo }");
+ LAST_NODE;
+ F_NODE(nd_body, "END clause");
+ return;
+
+ case NODE_ATTRASGN:
+ ANN("attr assignment");
+ ANN("format: [nd_recv].[nd_mid] = [nd_args]");
+ ANN("example: struct.field = foo");
+ F_NODE(nd_recv, "receiver");
+ F_ID(nd_mid, "method name");
+ LAST_NODE;
+ F_NODE(nd_args, "arguments");
+ return;
+
+ case NODE_LAMBDA:
+ ANN("lambda expression");
+ ANN("format: -> [nd_body]");
+ ANN("example: -> { foo }");
+ LAST_NODE;
+ F_NODE(nd_body, "lambda clause");
+ return;
+
+ case NODE_OPT_ARG:
+ ANN("optional arguments");
+ ANN("format: def method_name([nd_body=some], [nd_next..])");
+ ANN("example: def foo(a, b=1, c); end");
+ F_NODE(nd_body, "body");
+ LAST_NODE;
+ F_NODE(nd_next, "next");
+ return;
+
+ case NODE_KW_ARG:
+ ANN("keyword arguments");
+ ANN("format: def method_name([nd_body=some], [nd_next..])");
+ ANN("example: def foo(a:1, b:2); end");
+ F_NODE(nd_body, "body");
+ LAST_NODE;
+ F_NODE(nd_next, "next");
+ return;
+
+ case NODE_POSTARG:
+ ANN("post arguments");
+ ANN("format: *[nd_1st], [nd_2nd..] = ..");
+ ANN("example: a, *rest, z = foo");
+ if (NODE_NAMED_REST_P(node->nd_1st)) {
+ F_NODE(nd_1st, "rest argument");
+ }
+ else {
+ F_MSG(nd_1st, "rest argument", "NODE_SPECIAL_NO_NAME_REST (rest argument without name)");
+ }
+ LAST_NODE;
+ F_NODE(nd_2nd, "post arguments");
+ return;
+
+ case NODE_ARGS:
+ ANN("method parameters");
+ ANN("format: def method_name(.., [nd_ainfo->nd_optargs], *[nd_ainfo->rest_arg], [nd_ainfo->first_post_arg], .., [nd_ainfo->kw_args], **[nd_ainfo->kw_rest_arg], &[nd_ainfo->block_arg])");
+ ANN("example: def foo(a, b, opt1=1, opt2=2, *rest, y, z, kw: 1, **kwrest, &blk); end");
+ F_INT(nd_ainfo->pre_args_num, "count of mandatory (pre-)arguments");
+ F_NODE(nd_ainfo->pre_init, "initialization of (pre-)arguments");
+ F_INT(nd_ainfo->post_args_num, "count of mandatory post-arguments");
+ F_NODE(nd_ainfo->post_init, "initialization of post-arguments");
+ F_ID(nd_ainfo->first_post_arg, "first post argument");
+ F_CUSTOM1(nd_ainfo->rest_arg, "rest argument") {
+ if (node->nd_ainfo->rest_arg == NODE_SPECIAL_EXCESSIVE_COMMA) {
+ A("1 (excessed comma)");
+ }
+ else {
+ A_ID(node->nd_ainfo->rest_arg);
+ }
+ }
+ F_ID(nd_ainfo->block_arg, "block argument");
+ F_NODE(nd_ainfo->opt_args, "optional arguments");
+ F_NODE(nd_ainfo->kw_args, "keyword arguments");
+ LAST_NODE;
+ F_NODE(nd_ainfo->kw_rest_arg, "keyword rest argument");
+ return;
+
+ case NODE_SCOPE:
+ ANN("new scope");
+ ANN("format: [nd_tbl]: local table, [nd_args]: arguments, [nd_body]: body");
+ F_CUSTOM1(nd_tbl, "local table") {
+ rb_ast_id_table_t *tbl = node->nd_tbl;
+ int i;
+ int size = tbl ? tbl->size : 0;
+ if (size == 0) A("(empty)");
+ for (i = 0; i < size; i++) {
+ A_ID(tbl->ids[i]); if (i < size - 1) A(",");
+ }
+ }
+ F_NODE(nd_args, "arguments");
+ LAST_NODE;
+ F_NODE(nd_body, "body");
+ return;
+
+ case NODE_ARYPTN:
+ ANN("array pattern");
+ ANN("format: [nd_pconst]([pre_args], ..., *[rest_arg], [post_args], ...)");
+ F_NODE(nd_pconst, "constant");
+ F_NODE(nd_apinfo->pre_args, "pre arguments");
+ if (NODE_NAMED_REST_P(node->nd_apinfo->rest_arg)) {
+ F_NODE(nd_apinfo->rest_arg, "rest argument");
+ }
+ else {
+ F_MSG(nd_apinfo->rest_arg, "rest argument", "NODE_SPECIAL_NO_NAME_REST (rest argument without name)");
+ }
+ LAST_NODE;
+ F_NODE(nd_apinfo->post_args, "post arguments");
+ return;
+
+ case NODE_FNDPTN:
+ ANN("find pattern");
+ ANN("format: [nd_pconst](*[pre_rest_arg], args, ..., *[post_rest_arg])");
+ F_NODE(nd_pconst, "constant");
+ if (NODE_NAMED_REST_P(node->nd_fpinfo->pre_rest_arg)) {
+ F_NODE(nd_fpinfo->pre_rest_arg, "pre rest argument");
+ }
+ else {
+ F_MSG(nd_fpinfo->pre_rest_arg, "pre rest argument", "NODE_SPECIAL_NO_NAME_REST (rest argument without name)");
+ }
+ F_NODE(nd_fpinfo->args, "arguments");
+
+ LAST_NODE;
+ if (NODE_NAMED_REST_P(node->nd_fpinfo->post_rest_arg)) {
+ F_NODE(nd_fpinfo->post_rest_arg, "post rest argument");
+ }
+ else {
+ F_MSG(nd_fpinfo->post_rest_arg, "post rest argument", "NODE_SPECIAL_NO_NAME_REST (rest argument without name)");
+ }
+ return;
+
+ case NODE_HSHPTN:
+ ANN("hash pattern");
+ ANN("format: [nd_pconst]([nd_pkwargs], ..., **[nd_pkwrestarg])");
+ F_NODE(nd_pconst, "constant");
+ F_NODE(nd_pkwargs, "keyword arguments");
+ LAST_NODE;
+ if (node->nd_pkwrestarg == NODE_SPECIAL_NO_REST_KEYWORD) {
+ F_MSG(nd_pkwrestarg, "keyword rest argument", "NODE_SPECIAL_NO_REST_KEYWORD (**nil)");
+ }
+ else {
+ F_NODE(nd_pkwrestarg, "keyword rest argument");
+ }
+ return;
+ case NODE_ERROR:
+ ANN("Broken input recovered by Error Tolerant mode");
+ return;
+
+ case NODE_ARGS_AUX:
+ case NODE_LAST:
+ break;
+ }
+
+ rb_bug("dump_node: unknown node: %s", ruby_node_name(nd_type(node)));
+}
+
+VALUE
+rb_parser_dump_tree(const NODE *node, int comment)
+{
+ VALUE buf = rb_str_new_cstr(
+ "###########################################################\n"
+ "## Do NOT use this node dump for any purpose other than ##\n"
+ "## debug and research. Compatibility is not guaranteed. ##\n"
+ "###########################################################\n\n"
+ );
+ dump_node(buf, rb_str_new_cstr("# "), comment, node);
+ return buf;
+}
diff --git a/parse.y b/parse.y
index b331174a1a..82ea9a0750 100644
--- a/parse.y
+++ b/parse.y
@@ -22,6 +22,27 @@
#define YYLTYPE rb_code_location_t
#define YYLTYPE_IS_DECLARED 1
+#ifdef UNIVERSAL_PARSER
+
+/* For Ripper */
+#ifdef RUBY_EXTCONF_H
+# include RUBY_EXTCONF_H
+#endif
+
+#include <errno.h>
+#include "internal/ruby_parser.h"
+#include "parser_node.h"
+#include "universal_parser.c"
+
+#ifdef RIPPER
+#undef T_NODE
+#define T_NODE 0x1b
+#define STATIC_ID2SYM p->config->static_id2sym
+#define rb_str_coderange_scan_restartable p->config->str_coderange_scan_restartable
+#endif
+
+#else
+
#include "ruby/internal/config.h"
#include <ctype.h>
@@ -43,10 +64,12 @@ struct lex_context;
#include "internal/parse.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"
#include "node.h"
+#include "parser_node.h"
#include "probes.h"
#include "regenc.h"
#include "ruby/encoding.h"
@@ -57,6 +80,129 @@ struct lex_context;
#include "ruby/ractor.h"
#include "symbol.h"
+#ifndef RIPPER
+static void
+bignum_negate(VALUE b)
+{
+ BIGNUM_NEGATE(b);
+}
+
+static void
+rational_set_num(VALUE r, VALUE n)
+{
+ RATIONAL_SET_NUM(r, n);
+}
+
+static VALUE
+rational_get_num(VALUE obj)
+{
+ return RRATIONAL(obj)->num;
+}
+
+static void
+rcomplex_set_real(VALUE cmp, VALUE r)
+{
+ RCOMPLEX_SET_REAL(cmp, r);
+}
+
+static VALUE
+rcomplex_get_real(VALUE obj)
+{
+ return RCOMPLEX(obj)->real;
+}
+
+static void
+rcomplex_set_imag(VALUE cmp, VALUE i)
+{
+ RCOMPLEX_SET_IMAG(cmp, i);
+}
+
+static VALUE
+rcomplex_get_imag(VALUE obj)
+{
+ return RCOMPLEX(obj)->imag;
+}
+
+static bool
+hash_literal_key_p(VALUE k)
+{
+ switch (OBJ_BUILTIN_TYPE(k)) {
+ case T_NODE:
+ return false;
+ default:
+ return true;
+ }
+}
+
+static int
+literal_cmp(VALUE val, VALUE lit)
+{
+ if (val == lit) return 0;
+ if (!hash_literal_key_p(val) || !hash_literal_key_p(lit)) return -1;
+ return rb_iseq_cdhash_cmp(val, lit);
+}
+
+static st_index_t
+literal_hash(VALUE a)
+{
+ if (!hash_literal_key_p(a)) return (st_index_t)a;
+ return rb_iseq_cdhash_hash(a);
+}
+
+static int
+script_lines_defined(void)
+{
+ ID script_lines;
+ CONST_ID(script_lines, "SCRIPT_LINES__");
+
+ return rb_const_defined_at(rb_cObject, script_lines);
+}
+
+static VALUE
+script_lines_get(void)
+{
+ ID script_lines;
+ CONST_ID(script_lines, "SCRIPT_LINES__");
+
+ return rb_const_get_at(rb_cObject, script_lines);
+}
+
+static VALUE
+syntax_error_new(void)
+{
+ return rb_class_new_instance(0, 0, rb_eSyntaxError);
+}
+
+static NODE *reg_named_capture_assign(struct parser_params* p, VALUE regexp, const YYLTYPE *loc);
+#endif /* !RIPPER */
+
+#define compile_callback rb_suppress_tracing
+VALUE rb_io_gets_internal(VALUE io);
+
+VALUE rb_node_case_when_optimizable_literal(const NODE *const node);
+
+static int
+strterm_is_heredoc(VALUE strterm)
+{
+ return ((rb_strterm_t *)strterm)->flags & STRTERM_HEREDOC;
+}
+
+static VALUE
+new_strterm(VALUE v1, VALUE v2, VALUE v3, VALUE v0, int heredoc)
+{
+ rb_strterm_t *imemo = (rb_strterm_t *)rb_imemo_new(imemo_parser_strterm, v1, v2, v3, v0);
+ if (heredoc) {
+ imemo->flags |= STRTERM_HEREDOC;
+ }
+
+ return (VALUE)imemo;
+}
+#endif /* !UNIVERSAL_PARSER */
+
+#ifdef RIPPER
+#include "ripper_init.h"
+#endif
+
enum shareability {
shareable_none,
shareable_literal,
@@ -141,44 +287,6 @@ RBIMPL_WARNING_POP()
{p->ruby_sourceline, (int)(p->lex.pcur - p->lex.pbeg)}, \
}
-enum lex_state_bits {
- EXPR_BEG_bit, /* ignore newline, +/- is a sign. */
- EXPR_END_bit, /* newline significant, +/- is an operator. */
- EXPR_ENDARG_bit, /* ditto, and unbound braces. */
- EXPR_ENDFN_bit, /* ditto, and unbound braces. */
- EXPR_ARG_bit, /* newline significant, +/- is an operator. */
- EXPR_CMDARG_bit, /* newline significant, +/- is an operator. */
- EXPR_MID_bit, /* newline significant, +/- is an operator. */
- EXPR_FNAME_bit, /* ignore newline, no reserved words. */
- EXPR_DOT_bit, /* right after `.', `&.' or `::', no reserved words. */
- EXPR_CLASS_bit, /* immediate after `class', no here document. */
- EXPR_LABEL_bit, /* flag bit, label is allowed. */
- EXPR_LABELED_bit, /* flag bit, just after a label. */
- EXPR_FITEM_bit, /* symbol literal as FNAME. */
- EXPR_MAX_STATE
-};
-/* examine combinations */
-enum lex_state_e {
-#define DEF_EXPR(n) EXPR_##n = (1 << EXPR_##n##_bit)
- DEF_EXPR(BEG),
- DEF_EXPR(END),
- DEF_EXPR(ENDARG),
- DEF_EXPR(ENDFN),
- DEF_EXPR(ARG),
- DEF_EXPR(CMDARG),
- DEF_EXPR(MID),
- DEF_EXPR(FNAME),
- DEF_EXPR(DOT),
- DEF_EXPR(CLASS),
- DEF_EXPR(LABEL),
- DEF_EXPR(LABELED),
- DEF_EXPR(FITEM),
- EXPR_VALUE = EXPR_BEG,
- EXPR_BEG_ANY = (EXPR_BEG | EXPR_MID | EXPR_CLASS),
- EXPR_ARG_ANY = (EXPR_ARG | EXPR_CMDARG),
- EXPR_END_ANY = (EXPR_END | EXPR_ENDARG | EXPR_ENDFN),
- EXPR_NONE = 0
-};
#define IS_lex_state_for(x, ls) ((x) & (ls))
#define IS_lex_state_all_for(x, ls) (((x) & (ls)) == (ls))
#define IS_lex_state(ls) IS_lex_state_for(p->lex.state, (ls))
@@ -240,18 +348,6 @@ enum {
NUMPARAM_MAX = 9,
};
-#define NUMPARAM_ID_P(id) numparam_id_p(id)
-#define NUMPARAM_ID_TO_IDX(id) (unsigned int)(((id) >> ID_SCOPE_SHIFT) - (tNUMPARAM_1 - 1))
-#define NUMPARAM_IDX_TO_ID(idx) TOKEN2LOCALID((tNUMPARAM_1 - 1 + (idx)))
-static int
-numparam_id_p(ID id)
-{
- if (!is_local_id(id) || id < (tNUMPARAM_1 << ID_SCOPE_SHIFT)) return 0;
- unsigned int idx = NUMPARAM_ID_TO_IDX(id);
- return idx > 0 && idx <= NUMPARAM_MAX;
-}
-static void numparam_name(struct parser_params *p, ID id);
-
#define DVARS_INHERIT ((void*)1)
#define DVARS_TOPSCOPE NULL
#define DVARS_TERMINAL_P(tbl) ((tbl) == DVARS_INHERIT || (tbl) == DVARS_TOPSCOPE)
@@ -264,8 +360,6 @@ typedef struct token_info {
struct token_info *next;
} token_info;
-typedef struct rb_strterm_struct rb_strterm_t;
-
/*
Structure of Lexer Buffer:
@@ -344,6 +438,10 @@ struct parser_params {
struct lex_context ctxt;
+#ifdef UNIVERSAL_PARSER
+ rb_parser_config_t *config;
+#endif
+
unsigned int command_start:1;
unsigned int eofp: 1;
unsigned int ruby__end__seen: 1;
@@ -388,12 +486,25 @@ struct parser_params {
#endif
};
+#define NUMPARAM_ID_P(id) numparam_id_p(p, id)
+#define NUMPARAM_ID_TO_IDX(id) (unsigned int)(((id) >> ID_SCOPE_SHIFT) - (tNUMPARAM_1 - 1))
+#define NUMPARAM_IDX_TO_ID(idx) TOKEN2LOCALID((tNUMPARAM_1 - 1 + (idx)))
+static int
+numparam_id_p(struct parser_params *p, ID id)
+{
+ if (!is_local_id(id) || id < (tNUMPARAM_1 << ID_SCOPE_SHIFT)) return 0;
+ unsigned int idx = NUMPARAM_ID_TO_IDX(id);
+ return idx > 0 && idx <= NUMPARAM_MAX;
+}
+static void numparam_name(struct parser_params *p, ID id);
+
+
#define intern_cstr(n,l,en) rb_intern3(n,l,en)
#define STR_NEW(ptr,len) rb_enc_str_new((ptr),(len),p->enc)
#define STR_NEW0() rb_enc_str_new(0,0,p->enc)
#define STR_NEW2(ptr) rb_enc_str_new((ptr),strlen(ptr),p->enc)
-#define STR_NEW3(ptr,len,e,func) parser_str_new((ptr),(len),(e),(func),p->enc)
+#define STR_NEW3(ptr,len,e,func) parser_str_new(p, (ptr),(len),(e),(func),p->enc)
#define TOK_INTERN() intern_cstr(tok(p), toklen(p), p->enc)
static st_table *
@@ -463,7 +574,7 @@ peek_end_expect_token_locations(struct parser_params *p)
}
static ID
-parser_token2id(enum yytokentype tok)
+parser_token2id(struct parser_params *p, enum yytokentype tok)
{
switch ((int) tok) {
#define TOKEN2ID(tok) case tok: return rb_intern(#tok);
@@ -830,7 +941,6 @@ static rb_ast_id_table_t *local_tbl(struct parser_params*);
static VALUE reg_compile(struct parser_params*, VALUE, int);
static void reg_fragment_setenc(struct parser_params*, VALUE, int);
static int reg_fragment_check(struct parser_params*, VALUE, int);
-static NODE *reg_named_capture_assign(struct parser_params* p, VALUE regexp, const YYLTYPE *loc);
static int literal_concat0(struct parser_params *p, VALUE head, VALUE tail);
static NODE *heredoc_dedent(struct parser_params*,NODE*);
@@ -846,12 +956,12 @@ static void check_literal_when(struct parser_params *p, NODE *args, const YYLTYP
#define NODE_RIPPER2 NODE_OP_CDECL
#define NEW_RIPPER2(a,b,c,loc) (VALUE)NEW_OP_CDECL(a,c,b,loc)
-static inline int ripper_is_node_yylval(VALUE n);
+static inline int ripper_is_node_yylval(struct parser_params *p, VALUE n);
static inline VALUE
ripper_new_yylval(struct parser_params *p, ID a, VALUE b, VALUE c)
{
- if (ripper_is_node_yylval(c)) c = RNODE(c)->nd_cval;
+ if (ripper_is_node_yylval(p, c)) c = RNODE(c)->nd_cval;
add_mark_object(p, b);
add_mark_object(p, c);
return NEW_RIPPER(a, b, c, &NULL_LOC);
@@ -867,7 +977,7 @@ ripper_new_yylval2(struct parser_params *p, VALUE a, VALUE b, VALUE c)
}
static inline int
-ripper_is_node_yylval(VALUE n)
+ripper_is_node_yylval(struct parser_params *p, VALUE n)
{
return RB_TYPE_P(n, T_NODE) && nd_type_p(RNODE(n), NODE_RIPPER);
}
@@ -875,11 +985,11 @@ ripper_is_node_yylval(VALUE n)
#define value_expr(node) ((void)(node))
#define remove_begin(node) (node)
#define void_stmts(p,x) (x)
+#undef rb_dvar_defined
#define rb_dvar_defined(id, base) 0
+#undef rb_local_defined
#define rb_local_defined(id, base) 0
-static ID ripper_get_id(VALUE);
#define get_id(id) ripper_get_id(id)
-static VALUE ripper_get_value(VALUE);
#define get_value(val) ripper_get_value(val)
#define get_num(num) (int)get_id(num)
static VALUE assignable(struct parser_params*,VALUE);
@@ -905,14 +1015,11 @@ static VALUE parser_reg_compile(struct parser_params*, VALUE, int, VALUE *);
static VALUE backref_error(struct parser_params*, NODE *, VALUE);
#endif /* !RIPPER */
-/* forward declaration */
-typedef struct rb_strterm_heredoc_struct rb_strterm_heredoc_t;
-
RUBY_SYMBOL_EXPORT_BEGIN
VALUE rb_parser_reg_compile(struct parser_params* p, VALUE str, int options);
int rb_reg_fragment_setenc(struct parser_params*, VALUE, int);
enum lex_state_e rb_parser_trace_lex_state(struct parser_params *, enum lex_state_e, enum lex_state_e, int);
-VALUE rb_parser_lex_state_name(enum lex_state_e state);
+VALUE rb_parser_lex_state_name(struct parser_params *p, enum lex_state_e state);
void rb_parser_show_bitstack(struct parser_params *, stack_type, const char *, int);
PRINTF_ARGS(void rb_parser_fatal(struct parser_params *p, const char *fmt, ...), 2, 3);
YYLTYPE *rb_parser_set_location_from_strterm_heredoc(struct parser_params *p, rb_strterm_heredoc_t *here, YYLTYPE *yylloc);
@@ -979,72 +1086,6 @@ static void numparam_pop(struct parser_params *p, NODE *prev_inner);
#define RE_OPTION_MASK 0xff
#define RE_OPTION_ARG_ENCODING_NONE 32
-/* structs for managing terminator of string literal and heredocment */
-typedef struct rb_strterm_literal_struct {
- union {
- VALUE dummy;
- long nest;
- } u0;
- union {
- VALUE dummy;
- long func; /* STR_FUNC_* (e.g., STR_FUNC_ESCAPE and STR_FUNC_EXPAND) */
- } u1;
- union {
- VALUE dummy;
- long paren; /* '(' of `%q(...)` */
- } u2;
- union {
- VALUE dummy;
- long term; /* ')' of `%q(...)` */
- } u3;
-} rb_strterm_literal_t;
-
-#define HERETERM_LENGTH_BITS ((SIZEOF_VALUE - 1) * CHAR_BIT - 1)
-
-struct rb_strterm_heredoc_struct {
- VALUE lastline; /* the string of line that contains `<<"END"` */
- long offset; /* the column of END in `<<"END"` */
- int sourceline; /* lineno of the line that contains `<<"END"` */
- unsigned length /* the length of END in `<<"END"` */
-#if HERETERM_LENGTH_BITS < SIZEOF_INT * CHAR_BIT
- : HERETERM_LENGTH_BITS
-# define HERETERM_LENGTH_MAX ((1U << HERETERM_LENGTH_BITS) - 1)
-#else
-# define HERETERM_LENGTH_MAX UINT_MAX
-#endif
- ;
-#if HERETERM_LENGTH_BITS < SIZEOF_INT * CHAR_BIT
- unsigned quote: 1;
- unsigned func: 8;
-#else
- uint8_t quote;
- uint8_t func;
-#endif
-};
-STATIC_ASSERT(rb_strterm_heredoc_t, sizeof(rb_strterm_heredoc_t) <= 4 * SIZEOF_VALUE);
-
-#define STRTERM_HEREDOC IMEMO_FL_USER0
-
-struct rb_strterm_struct {
- VALUE flags;
- union {
- rb_strterm_literal_t literal;
- rb_strterm_heredoc_t heredoc;
- } u;
-};
-
-#ifndef RIPPER
-void
-rb_strterm_mark(VALUE obj)
-{
- rb_strterm_t *strterm = (rb_strterm_t*)obj;
- if (RBASIC(obj)->flags & STRTERM_HEREDOC) {
- rb_strterm_heredoc_t *heredoc = &strterm->u.heredoc;
- rb_gc_mark(heredoc->lastline);
- }
-}
-#endif
-
#define yytnamerr(yyres, yystr) (YYSIZE_T)rb_yytnamerr(p, yyres, yystr)
size_t rb_yytnamerr(struct parser_params *p, char *yyres, const char *yystr);
@@ -1060,12 +1101,11 @@ size_t rb_yytnamerr(struct parser_params *p, char *yyres, const char *yystr);
/****** Ripper *******/
#ifdef RIPPER
-#define RIPPER_VERSION "0.1.0"
-static inline VALUE intern_sym(const char *name);
+#include "eventids1.h"
+#include "eventids2.h"
-#include "eventids1.c"
-#include "eventids2.c"
+extern const struct ripper_parser_ids ripper_parser_ids;
static VALUE ripper_dispatch0(struct parser_params*,ID);
static VALUE ripper_dispatch1(struct parser_params*,ID,VALUE);
@@ -1074,7 +1114,7 @@ static VALUE ripper_dispatch3(struct parser_params*,ID,VALUE,VALUE,VALUE);
static VALUE ripper_dispatch4(struct parser_params*,ID,VALUE,VALUE,VALUE,VALUE);
static VALUE ripper_dispatch5(struct parser_params*,ID,VALUE,VALUE,VALUE,VALUE,VALUE);
static VALUE ripper_dispatch7(struct parser_params*,ID,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE);
-static void ripper_error(struct parser_params *p);
+void ripper_error(struct parser_params *p);
#define dispatch0(n) ripper_dispatch0(p, TOKEN_PASTE(ripper_id_, n))
#define dispatch1(n,a) ripper_dispatch1(p, TOKEN_PASTE(ripper_id_, n), (a))
@@ -1284,7 +1324,7 @@ endless_method_name(struct parser_params *p, NODE *defn, const YYLTYPE *loc)
# define rb_warning3L(l,fmt,a,b,c) WARNING_CALL(WARNING_ARGS_L(l, fmt, 4), (a), (b), (c))
# define rb_warning4L(l,fmt,a,b,c,d) WARNING_CALL(WARNING_ARGS_L(l, fmt, 5), (a), (b), (c), (d))
#ifdef RIPPER
-static ID id_warn, id_warning, id_gets, id_assoc;
+extern const ID id_warn, id_warning, id_gets, id_assoc;
# define ERR_MESG() STR_NEW2(mesg) /* to bypass Ripper DSL */
# define WARN_S_L(s,l) STR_NEW(s,l)
# define WARN_S(s) STR_NEW2(s)
@@ -1307,7 +1347,6 @@ static ID id_warn, id_warning, id_gets, id_assoc;
# else
# define WARNING_CALL rb_funcall
# endif
-PRINTF_ARGS(static void ripper_compile_error(struct parser_params*, const char *fmt, ...), 2, 3);
# define compile_error ripper_compile_error
#else
# define WARN_S_L(s,l) s
@@ -4754,7 +4793,7 @@ p_kw_label : tLABEL
$$ = SYM2ID(node->nd_lit);
}
/*%
- if (ripper_is_node_yylval($2) && RNODE($2)->nd_cval) {
+ if (ripper_is_node_yylval(p, $2) && RNODE($2)->nd_cval) {
VALUE label = RNODE($2)->nd_cval;
VALUE rval = RNODE($2)->nd_rval;
$$ = ripper_new_yylval(p, rb_intern_str(label), rval, label);
@@ -5173,7 +5212,7 @@ string_contents : /* none */
/*% ripper: string_add!($1, $2) %*/
/*%%%*/
/*%
- if (ripper_is_node_yylval($1) && ripper_is_node_yylval($2) &&
+ if (ripper_is_node_yylval(p, $1) && ripper_is_node_yylval(p, $2) &&
!RNODE($1)->nd_cval) {
RNODE($1)->nd_cval = RNODE($2)->nd_cval;
RNODE($1)->nd_rval = add_mark_object(p, $$);
@@ -5235,11 +5274,11 @@ regexp_contents: /* none */
}
/*%
VALUE s1 = 1, s2 = 0, n1 = $1, n2 = $2;
- if (ripper_is_node_yylval(n1)) {
+ if (ripper_is_node_yylval(p, n1)) {
s1 = RNODE(n1)->nd_cval;
n1 = RNODE(n1)->nd_rval;
}
- if (ripper_is_node_yylval(n2)) {
+ if (ripper_is_node_yylval(p, n2)) {
s2 = RNODE(n2)->nd_cval;
n2 = RNODE(n2)->nd_rval;
}
@@ -6187,7 +6226,7 @@ parser_has_token(struct parser_params *p)
}
static VALUE
-code_loc_to_ary(const rb_code_location_t *loc)
+code_loc_to_ary(struct parser_params *p, const rb_code_location_t *loc)
{
VALUE ary = rb_ary_new_from_args(4,
INT2NUM(loc->beg_pos.lineno), INT2NUM(loc->beg_pos.column),
@@ -6206,9 +6245,9 @@ parser_append_tokens(struct parser_params *p, VALUE str, enum yytokentype t, int
ary = rb_ary_new2(4);
token_id = p->token_id;
rb_ary_push(ary, INT2FIX(token_id));
- rb_ary_push(ary, ID2SYM(parser_token2id(t)));
+ rb_ary_push(ary, ID2SYM(parser_token2id(p, t)));
rb_ary_push(ary, str);
- rb_ary_push(ary, code_loc_to_ary(p->yylloc));
+ rb_ary_push(ary, code_loc_to_ary(p, p->yylloc));
rb_obj_freeze(ary);
rb_ary_push(p->tokens, ary);
p->token_id++;
@@ -6263,13 +6302,6 @@ parser_dispatch_delayed_token(struct parser_params *p, enum yytokentype t, int l
#define yylval_rval (*(RB_TYPE_P(yylval.val, T_NODE) ? &yylval.node->nd_rval : &yylval.val))
-static inline VALUE
-intern_sym(const char *name)
-{
- ID id = rb_intern_const(name);
- return ID2SYM(id);
-}
-
static int
ripper_has_scan_event(struct parser_params *p)
{
@@ -6313,7 +6345,7 @@ ripper_dispatch_delayed_token(struct parser_params *p, enum yytokentype t)
#endif /* RIPPER */
static inline int
-is_identchar(const char *ptr, const char *MAYBE_UNUSED(ptr_end), rb_encoding *enc)
+is_identchar(struct parser_params *p, const char *ptr, const char *MAYBE_UNUSED(ptr_end), rb_encoding *enc)
{
return rb_enc_isalnum((unsigned char)*ptr, enc) || *ptr == '_' || !ISASCII(*ptr);
}
@@ -6321,7 +6353,7 @@ is_identchar(const char *ptr, const char *MAYBE_UNUSED(ptr_end), rb_encoding *en
static inline int
parser_is_identchar(struct parser_params *p)
{
- return !(p)->eofp && is_identchar(p->lex.pcur-1, p->lex.pend, p->enc);
+ return !(p)->eofp && is_identchar(p, p->lex.pcur-1, p->lex.pend, p->enc);
}
static inline int
@@ -6424,7 +6456,7 @@ parser_precise_mbclen(struct parser_params *p, const char *ptr)
}
#ifndef RIPPER
-static void ruby_show_error_line(VALUE errbuf, const YYLTYPE *yylloc, int lineno, VALUE str);
+static void ruby_show_error_line(struct parser_params *p, VALUE errbuf, const YYLTYPE *yylloc, int lineno, VALUE str);
static inline void
parser_show_error_line(struct parser_params *p, const YYLTYPE *yylloc)
@@ -6440,7 +6472,7 @@ parser_show_error_line(struct parser_params *p, const YYLTYPE *yylloc)
else {
return;
}
- ruby_show_error_line(p->error_buffer, yylloc, lineno, str);
+ ruby_show_error_line(p, p->error_buffer, yylloc, lineno, str);
}
static int
@@ -6470,7 +6502,7 @@ parser_yyerror0(struct parser_params *p, const char *msg)
}
static void
-ruby_show_error_line(VALUE errbuf, const YYLTYPE *yylloc, int lineno, VALUE str)
+ruby_show_error_line(struct parser_params *p, VALUE errbuf, const YYLTYPE *yylloc, int lineno, VALUE str)
{
VALUE mesg;
const int max_line_margin = 30;
@@ -6716,12 +6748,10 @@ static void parser_prepare(struct parser_params *p);
static NODE *parser_append_options(struct parser_params *p, NODE *node);
static VALUE
-debug_lines(VALUE fname)
+debug_lines(struct parser_params *p, VALUE fname)
{
- ID script_lines;
- CONST_ID(script_lines, "SCRIPT_LINES__");
- if (rb_const_defined_at(rb_cObject, script_lines)) {
- VALUE hash = rb_const_get_at(rb_cObject, script_lines);
+ if (script_lines_defined()) {
+ VALUE hash = script_lines_get();
if (RB_TYPE_P(hash, T_HASH)) {
VALUE lines = rb_ary_new();
rb_hash_aset(hash, fname, lines);
@@ -6746,7 +6776,7 @@ yycompile0(VALUE arg)
VALUE cov = Qfalse;
if (!compile_for_eval && !NIL_P(p->ruby_sourcefile_string)) {
- p->debug_lines = debug_lines(p->ruby_sourcefile_string);
+ p->debug_lines = debug_lines(p, p->ruby_sourcefile_string);
if (p->debug_lines && p->ruby_sourceline > 0) {
VALUE str = rb_default_rs;
n = p->ruby_sourceline;
@@ -6783,7 +6813,7 @@ yycompile0(VALUE arg)
if (n || p->error_p) {
VALUE mesg = p->error_buffer;
if (!mesg) {
- mesg = rb_class_new_instance(0, 0, rb_eSyntaxError);
+ mesg = syntax_error_new();
}
if (!p->error_tolerant) {
rb_set_errinfo(mesg);
@@ -6815,7 +6845,7 @@ yycompile0(VALUE arg)
}
static rb_ast_t *
-yycompile(VALUE vparser, struct parser_params *p, VALUE fname, int line)
+yycompile(struct parser_params *p, VALUE fname, int line)
{
rb_ast_t *ast;
if (NIL_P(fname)) {
@@ -6831,9 +6861,8 @@ yycompile(VALUE vparser, struct parser_params *p, VALUE fname, int line)
p->lvtbl = NULL;
p->ast = ast = rb_ast_new();
- rb_suppress_tracing(yycompile0, (VALUE)p);
+ compile_callback(yycompile0, (VALUE)p);
p->ast = 0;
- RB_GC_GUARD(vparser); /* prohibit tail call optimization */
while (p->lvtbl) {
local_pop(p);
@@ -6844,7 +6873,7 @@ yycompile(VALUE vparser, struct parser_params *p, VALUE fname, int line)
#endif /* !RIPPER */
static rb_encoding *
-must_be_ascii_compatible(VALUE s)
+must_be_ascii_compatible(struct parser_params *p, VALUE s)
{
rb_encoding *enc = rb_enc_get(s);
if (!rb_enc_asciicompat(enc)) {
@@ -6878,45 +6907,37 @@ lex_getline(struct parser_params *p)
{
VALUE line = (*p->lex.gets)(p, p->lex.input);
if (NIL_P(line)) return line;
- must_be_ascii_compatible(line);
+ must_be_ascii_compatible(p, line);
if (RB_OBJ_FROZEN(line)) line = rb_str_dup(line); // needed for RubyVM::AST.of because script_lines in iseq is deep-frozen
p->line_count++;
return line;
}
-static const rb_data_type_t parser_data_type;
-
#ifndef RIPPER
static rb_ast_t*
-parser_compile_string(VALUE vparser, VALUE fname, VALUE s, int line)
+parser_compile_string(rb_parser_t *p, VALUE fname, VALUE s, int line)
{
- struct parser_params *p;
-
- TypedData_Get_Struct(vparser, struct parser_params, &parser_data_type, p);
-
p->lex.gets = lex_get_str;
p->lex.gets_.ptr = 0;
p->lex.input = rb_str_new_frozen(s);
p->lex.pbeg = p->lex.pcur = p->lex.pend = 0;
- return yycompile(vparser, p, fname, line);
+ return yycompile(p, fname, line);
}
rb_ast_t*
-rb_parser_compile_string(VALUE vparser, const char *f, VALUE s, int line)
+rb_ruby_parser_compile_string_path(rb_parser_t *p, VALUE f, VALUE s, int line)
{
- return rb_parser_compile_string_path(vparser, rb_filesystem_str_new_cstr(f), s, line);
+ must_be_ascii_compatible(p, s);
+ return parser_compile_string(p, f, s, line);
}
rb_ast_t*
-rb_parser_compile_string_path(VALUE vparser, VALUE f, VALUE s, int line)
+rb_ruby_parser_compile_string(rb_parser_t *p, const char *f, VALUE s, int line)
{
- must_be_ascii_compatible(s);
- return parser_compile_string(vparser, f, s, line);
+ return rb_ruby_parser_compile_string_path(p, rb_filesystem_str_new_cstr(f), s, line);
}
-VALUE rb_io_gets_internal(VALUE io);
-
static VALUE
lex_io_gets(struct parser_params *p, VALUE io)
{
@@ -6924,17 +6945,13 @@ lex_io_gets(struct parser_params *p, VALUE io)
}
rb_ast_t*
-rb_parser_compile_file_path(VALUE vparser, VALUE fname, VALUE file, int start)
+rb_ruby_parser_compile_file_path(rb_parser_t *p, VALUE fname, VALUE file, int start)
{
- struct parser_params *p;
-
- TypedData_Get_Struct(vparser, struct parser_params, &parser_data_type, p);
-
p->lex.gets = lex_io_gets;
p->lex.input = file;
p->lex.pbeg = p->lex.pcur = p->lex.pend = 0;
- return yycompile(vparser, p, fname, start);
+ return yycompile(p, fname, start);
}
static VALUE
@@ -6944,18 +6961,14 @@ lex_generic_gets(struct parser_params *p, VALUE input)
}
rb_ast_t*
-rb_parser_compile_generic(VALUE vparser, VALUE (*lex_gets)(VALUE, int), VALUE fname, VALUE input, int start)
+rb_ruby_parser_compile_generic(rb_parser_t *p, VALUE (*lex_gets)(VALUE, int), VALUE fname, VALUE input, int start)
{
- struct parser_params *p;
-
- TypedData_Get_Struct(vparser, struct parser_params, &parser_data_type, p);
-
p->lex.gets = lex_generic_gets;
p->lex.gets_.call = lex_gets;
p->lex.input = input;
p->lex.pbeg = p->lex.pcur = p->lex.pend = 0;
- return yycompile(vparser, p, fname, start);
+ return yycompile(p, fname, start);
}
#endif /* !RIPPER */
@@ -6982,7 +6995,7 @@ enum string_type {
};
static VALUE
-parser_str_new(const char *ptr, long len, rb_encoding *enc, int func, rb_encoding *enc0)
+parser_str_new(struct parser_params *p, const char *ptr, long len, rb_encoding *enc, int func, rb_encoding *enc0)
{
VALUE str;
@@ -6990,7 +7003,7 @@ parser_str_new(const char *ptr, long len, rb_encoding *enc, int func, rb_encodin
if (!(func & STR_FUNC_REGEXP) && rb_enc_asciicompat(enc)) {
if (is_ascii_string(str)) {
}
- else if (rb_is_usascii_enc(enc0) && enc != rb_utf8_encoding()) {
+ else if (rb_is_usascii_enc((void *)enc0) && enc != rb_utf8_encoding()) {
rb_enc_associate(str, rb_ascii8bit_encoding());
}
}
@@ -7174,7 +7187,7 @@ tok_hex(struct parser_params *p, size_t *numlen)
{
int c;
- c = scan_hex(p->lex.pcur, 2, numlen);
+ c = (int)ruby_scan_hex(p->lex.pcur, 2, numlen);
if (!*numlen) {
yyerror0("invalid hex escape");
token_flush(p);
@@ -7221,10 +7234,10 @@ tokadd_codepoint(struct parser_params *p, rb_encoding **encp,
int regexp_literal, int wide)
{
size_t numlen;
- int codepoint = scan_hex(p->lex.pcur, wide ? p->lex.pend - p->lex.pcur : 4, &numlen);
+ int codepoint = (int)ruby_scan_hex(p->lex.pcur, wide ? p->lex.pend - p->lex.pcur : 4, &numlen);
p->lex.pcur += numlen;
if (p->lex.strterm == NULL ||
- (p->lex.strterm->flags & STRTERM_HEREDOC) ||
+ (strterm_is_heredoc((VALUE)p->lex.strterm)) ||
(p->lex.strterm->u.literal.u1.func != str_regexp)) {
if (wide ? (numlen == 0 || numlen > 6) : (numlen < 4)) {
literal_flush(p, p->lex.pcur);
@@ -7363,7 +7376,7 @@ read_escape(struct parser_params *p, int flags, rb_encoding **encp)
case '0': case '1': case '2': case '3': /* octal constant */
case '4': case '5': case '6': case '7':
pushback(p, c);
- c = scan_oct(p->lex.pcur, 3, &numlen);
+ c = (int)ruby_scan_oct(p->lex.pcur, 3, &numlen);
p->lex.pcur += numlen;
return c;
@@ -7773,22 +7786,16 @@ tokadd_string(struct parser_params *p,
return c;
}
-static inline rb_strterm_t *
-new_strterm(VALUE v1, VALUE v2, VALUE v3, VALUE v0)
-{
- return (rb_strterm_t*)rb_imemo_new(imemo_parser_strterm, v1, v2, v3, v0);
-}
-
/* imemo_parser_strterm for literal */
#define NEW_STRTERM(func, term, paren) \
- new_strterm((VALUE)(func), (VALUE)(paren), (VALUE)(term), 0)
+ (rb_strterm_t *)new_strterm((VALUE)(func), (VALUE)(paren), (VALUE)(term), 0, 0)
#ifdef RIPPER
static void
flush_string_content(struct parser_params *p, rb_encoding *enc)
{
VALUE content = yylval.val;
- if (!ripper_is_node_yylval(content))
+ if (!ripper_is_node_yylval(p, content))
content = ripper_new_yylval(p, 0, 0, content);
if (has_delayed_token(p)) {
ptrdiff_t len = p->lex.pcur - p->lex.ptok;
@@ -8058,8 +8065,7 @@ heredoc_identifier(struct parser_params *p)
dispatch_scan_event(p, tHEREDOC_BEG);
lex_goto_eol(p);
- p->lex.strterm = new_strterm(0, 0, 0, p->lex.lastline);
- p->lex.strterm->flags |= STRTERM_HEREDOC;
+ p->lex.strterm = (rb_strterm_t *)new_strterm(0, 0, 0, p->lex.lastline, 1);
rb_strterm_heredoc_t *here = &p->lex.strterm->u.heredoc;
here->offset = offset;
here->sourceline = p->ruby_sourceline;
@@ -8092,7 +8098,7 @@ heredoc_restore(struct parser_params *p, rb_strterm_heredoc_t *here)
}
static int
-dedent_string(VALUE string, int width)
+dedent_string(struct parser_params *p, VALUE string, int width)
{
char *str;
long len;
@@ -8140,7 +8146,7 @@ heredoc_dedent(struct parser_params *p, NODE *root)
while (str_node) {
VALUE lit = str_node->nd_lit;
if (str_node->flags & NODE_FL_NEWLINE) {
- dedent_string(lit, indent);
+ dedent_string(p, lit, indent);
}
if (!prev_lit) {
prev_lit = lit;
@@ -8185,26 +8191,6 @@ heredoc_dedent(struct parser_params *p, VALUE array)
dispatch2(heredoc_dedent, array, INT2NUM(indent));
return array;
}
-
-/*
- * call-seq:
- * Ripper.dedent_string(input, width) -> Integer
- *
- * USE OF RIPPER LIBRARY ONLY.
- *
- * Strips up to +width+ leading whitespaces from +input+,
- * and returns the stripped column width.
- */
-static VALUE
-parser_dedent_string(VALUE self, VALUE input, VALUE width)
-{
- int wid, col;
-
- StringValue(input);
- wid = NUM2UINT(width);
- col = dedent_string(input, wid);
- return INT2NUM(col);
-}
#endif
static int
@@ -9266,14 +9252,14 @@ parse_qmark(struct parser_params *p, int space_seen)
if (tokadd_mbchar(p, c) == -1) return 0;
}
else if ((rb_enc_isalnum(c, p->enc) || c == '_') &&
- p->lex.pcur < p->lex.pend && is_identchar(p->lex.pcur, p->lex.pend, p->enc)) {
+ p->lex.pcur < p->lex.pend && is_identchar(p, p->lex.pcur, p->lex.pend, p->enc)) {
if (space_seen) {
const char *start = p->lex.pcur - 1, *ptr = start;
do {
int n = parser_precise_mbclen(p, ptr);
if (n < 0) return -1;
ptr += n;
- } while (ptr < p->lex.pend && is_identchar(ptr, p->lex.pend, p->enc));
+ } while (ptr < p->lex.pend && is_identchar(p, ptr, p->lex.pend, p->enc));
rb_warn2("`?' just followed by `%.*s' is interpreted as" \
" a conditional operator, put a space after `?'",
WARN_I((int)(ptr - start)), WARN_S_L(start, (ptr - start)));
@@ -9777,7 +9763,7 @@ parser_yylex(struct parser_params *p)
int token_seen = p->token_seen;
if (p->lex.strterm) {
- if (p->lex.strterm->flags & STRTERM_HEREDOC) {
+ if (strterm_is_heredoc((VALUE)p->lex.strterm)) {
token_flush(p);
return here_document(p, &p->lex.strterm->u.heredoc);
}
@@ -10121,7 +10107,7 @@ parser_yylex(struct parser_params *p)
if ((c != ':') ||
(c = peekc_n(p, 1)) == -1 ||
!(c == '\'' || c == '"' ||
- is_identchar((p->lex.pcur+1), p->lex.pend, p->enc))) {
+ is_identchar(p, (p->lex.pcur+1), p->lex.pend, p->enc))) {
rb_warning0("`&' interpreted as argument prefix");
}
c = tAMPER;
@@ -10696,7 +10682,7 @@ literal_concat0(struct parser_params *p, VALUE head, VALUE tail)
}
static VALUE
-string_literal_head(enum node_type htype, NODE *head)
+string_literal_head(struct parser_params *p, enum node_type htype, NODE *head)
{
if (htype != NODE_DSTR) return Qfalse;
if (head->nd_next) {
@@ -10735,7 +10721,7 @@ literal_concat(struct parser_params *p, NODE *head, NODE *tail, const YYLTYPE *l
}
switch (nd_type(tail)) {
case NODE_STR:
- if ((lit = string_literal_head(htype, head)) != Qfalse) {
+ if ((lit = string_literal_head(p, htype, head)) != Qfalse) {
htype = NODE_STR;
}
else {
@@ -10775,7 +10761,7 @@ literal_concat(struct parser_params *p, NODE *head, NODE *tail, const YYLTYPE *l
}
rb_discard_node(p, tail);
}
- else if ((lit = string_literal_head(htype, head)) != Qfalse) {
+ else if ((lit = string_literal_head(p, htype, head)) != Qfalse) {
if (!literal_concat0(p, lit, tail->nd_lit))
goto error;
tail->nd_lit = Qnil;
@@ -11235,11 +11221,11 @@ new_regexp(struct parser_params *p, VALUE re, VALUE opt, const YYLTYPE *loc)
{
VALUE src = 0, err;
int options = 0;
- if (ripper_is_node_yylval(re)) {
+ if (ripper_is_node_yylval(p, re)) {
src = RNODE(re)->nd_cval;
re = RNODE(re)->nd_rval;
}
- if (ripper_is_node_yylval(opt)) {
+ if (ripper_is_node_yylval(p, opt)) {
options = (int)RNODE(opt)->nd_tag;
opt = RNODE(opt)->nd_rval;
}
@@ -11267,7 +11253,7 @@ static const char rb_parser_lex_state_names[][8] = {
};
static VALUE
-append_lex_state_name(enum lex_state_e state, VALUE buf)
+append_lex_state_name(struct parser_params *p, enum lex_state_e state, VALUE buf)
{
int i, sep = 0;
unsigned int mask = 1;
@@ -11308,22 +11294,22 @@ rb_parser_trace_lex_state(struct parser_params *p, enum lex_state_e from,
{
VALUE mesg;
mesg = rb_str_new_cstr("lex_state: ");
- append_lex_state_name(from, mesg);
+ append_lex_state_name(p, from, mesg);
rb_str_cat_cstr(mesg, " -> ");
- append_lex_state_name(to, mesg);
+ append_lex_state_name(p, to, mesg);
rb_str_catf(mesg, " at line %d\n", line);
flush_debug_buffer(p, p->debug_output, mesg);
return to;
}
VALUE
-rb_parser_lex_state_name(enum lex_state_e state)
+rb_parser_lex_state_name(struct parser_params *p, enum lex_state_e state)
{
- return rb_fstring(append_lex_state_name(state, rb_str_new(0, 0)));
+ return rb_fstring(append_lex_state_name(p, state, rb_str_new(0, 0)));
}
static void
-append_bitstack_value(stack_type stack, VALUE mesg)
+append_bitstack_value(struct parser_params *p, stack_type stack, VALUE mesg)
{
if (stack == 0) {
rb_str_cat_cstr(mesg, "0");
@@ -11340,7 +11326,7 @@ rb_parser_show_bitstack(struct parser_params *p, stack_type stack,
const char *name, int line)
{
VALUE mesg = rb_sprintf("%s: ", name);
- append_bitstack_value(stack, mesg);
+ append_bitstack_value(p, stack, mesg);
rb_str_catf(mesg, " at line %d\n", line);
flush_debug_buffer(p, p->debug_output, mesg);
}
@@ -11358,13 +11344,13 @@ rb_parser_fatal(struct parser_params *p, const char *fmt, ...)
RB_GC_GUARD(mesg);
mesg = rb_str_new(0, 0);
- append_lex_state_name(p->lex.state, mesg);
+ append_lex_state_name(p, p->lex.state, mesg);
compile_error(p, "lex.state: %"PRIsVALUE, mesg);
rb_str_resize(mesg, 0);
- append_bitstack_value(p->cond_stack, mesg);
+ append_bitstack_value(p, p->cond_stack, mesg);
compile_error(p, "cond_stack: %"PRIsVALUE, mesg);
rb_str_resize(mesg, 0);
- append_bitstack_value(p->cmdarg_stack, mesg);
+ append_bitstack_value(p, p->cmdarg_stack, mesg);
compile_error(p, "cmdarg_stack: %"PRIsVALUE, mesg);
if (p->debug_output == rb_ractor_stdout())
p->debug_output = rb_ractor_stderr();
@@ -11527,7 +11513,7 @@ assignable(struct parser_params *p, VALUE lhs)
#endif
static int
-is_private_local_id(ID name)
+is_private_local_id(struct parser_params *p, ID name)
{
VALUE s;
if (name == idUScore) return 1;
@@ -11542,7 +11528,7 @@ shadowing_lvar_0(struct parser_params *p, ID name)
{
if (dyna_in_block(p)) {
if (dvar_curr(p, name)) {
- if (is_private_local_id(name)) return 1;
+ if (is_private_local_id(p, name)) return 1;
yyerror0("duplicated argument name");
}
else if (dvar_defined(p, name) || local_id(p, name)) {
@@ -11555,7 +11541,7 @@ shadowing_lvar_0(struct parser_params *p, ID name)
}
else {
if (local_id(p, name)) {
- if (is_private_local_id(name)) return 1;
+ if (is_private_local_id(p, name)) return 1;
yyerror0("duplicated argument name");
}
}
@@ -11768,8 +11754,6 @@ const_decl_path(struct parser_params *p, NODE **dest)
return n;
}
-extern VALUE rb_mRubyVMFrozenCore;
-
static NODE *
make_shareable_node(struct parser_params *p, NODE *value, bool copy, const YYLTYPE *loc)
{
@@ -11797,7 +11781,7 @@ ensure_shareable_node(struct parser_params *p, NODE **dest, NODE *value, const Y
static int is_static_content(NODE *node);
static VALUE
-shareable_literal_value(NODE *node)
+shareable_literal_value(struct parser_params *p, NODE *node)
{
if (!node) return Qnil;
enum node_type type = nd_type(node);
@@ -11870,7 +11854,7 @@ shareable_literal_constant(struct parser_params *p, enum shareability shareable,
}
}
if (RTEST(lit)) {
- VALUE e = shareable_literal_value(elt);
+ VALUE e = shareable_literal_value(p, elt);
if (!UNDEF_P(e)) {
rb_ary_push(lit, e);
}
@@ -11909,8 +11893,8 @@ shareable_literal_constant(struct parser_params *p, enum shareability shareable,
}
}
if (RTEST(lit)) {
- VALUE k = shareable_literal_value(key);
- VALUE v = shareable_literal_value(val);
+ 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);
}
@@ -12520,15 +12504,15 @@ negate_lit(struct parser_params *p, VALUE lit)
}
switch (BUILTIN_TYPE(lit)) {
case T_BIGNUM:
- BIGNUM_NEGATE(lit);
+ bignum_negate(lit);
lit = rb_big_norm(lit);
break;
case T_RATIONAL:
- RATIONAL_SET_NUM(lit, negate_lit(p, RRATIONAL(lit)->num));
+ rational_set_num(lit, negate_lit(p, rational_get_num(lit)));
break;
case T_COMPLEX:
- RCOMPLEX_SET_REAL(lit, negate_lit(p, RCOMPLEX(lit)->real));
- RCOMPLEX_SET_IMAG(lit, negate_lit(p, RCOMPLEX(lit)->imag));
+ rcomplex_set_real(lit, negate_lit(p, rcomplex_get_real(lit)));
+ rcomplex_set_imag(lit, negate_lit(p, rcomplex_get_imag(lit)));
break;
case T_FLOAT:
lit = DBL2NUM(-RFLOAT_VALUE(lit));
@@ -12827,40 +12811,14 @@ append_literal_keys(st_data_t k, st_data_t v, st_data_t h)
return ST_CONTINUE;
}
-static bool
-hash_literal_key_p(VALUE k)
-{
- switch (OBJ_BUILTIN_TYPE(k)) {
- case T_NODE:
- return false;
- default:
- return true;
- }
-}
-
-static int
-literal_cmp(VALUE val, VALUE lit)
-{
- if (val == lit) return 0;
- if (!hash_literal_key_p(val) || !hash_literal_key_p(lit)) return -1;
- return rb_iseq_cdhash_cmp(val, lit);
-}
-
-static st_index_t
-literal_hash(VALUE a)
-{
- if (!hash_literal_key_p(a)) return (st_index_t)a;
- return rb_iseq_cdhash_hash(a);
-}
-
-static const struct st_hash_type literal_type = {
- literal_cmp,
- literal_hash,
-};
-
static NODE *
remove_duplicate_keys(struct parser_params *p, NODE *hash)
{
+ struct st_hash_type literal_type = {
+ literal_cmp,
+ literal_hash,
+ };
+
st_table *literal_keys = st_init_table_with_size(&literal_type, hash->nd_alen / 2);
NODE *result = 0;
NODE *last_expr = 0;
@@ -12910,7 +12868,7 @@ new_hash(struct parser_params *p, NODE *hash, const YYLTYPE *loc)
static void
error_duplicate_pattern_variable(struct parser_params *p, ID id, const YYLTYPE *loc)
{
- if (is_private_local_id(id)) {
+ if (is_private_local_id(p, id)) {
return;
}
if (st_is_member(p->pvtbl, id)) {
@@ -13117,7 +13075,7 @@ warn_unused_var(struct parser_params *p, struct local_vars *local)
ID *u = local->used->tbl;
for (int i = 0; i < cnt; ++i) {
if (!v[i] || (u[i] & LVAR_USED)) continue;
- if (is_private_local_id(v[i])) continue;
+ if (is_private_local_id(p, v[i])) continue;
rb_warn1L((int)u[i], "assigned but unused variable - %"PRIsWARN, rb_id2str(v[i]));
}
#endif
@@ -13522,6 +13480,7 @@ reg_fragment_check(struct parser_params* p, VALUE str, int options)
return 1;
}
+#ifndef UNIVERSAL_PARSER
typedef struct {
struct parser_params* parser;
rb_encoding *enc;
@@ -13571,6 +13530,30 @@ reg_named_capture_assign(struct parser_params* p, VALUE regexp, const YYLTYPE *l
if (!arg.succ_block) return 0;
return arg.succ_block->nd_next;
}
+#endif
+
+int
+rb_reg_named_capture_assign_iter_impl(struct parser_params *p, const char *s, long len,
+ rb_encoding *enc, NODE **succ_block, const rb_code_location_t *loc)
+{
+ ID var;
+ NODE *node, *succ;
+
+ if (!len) return ST_CONTINUE;
+ if (rb_enc_symname_type(s, len, enc, (1U<<ID_LOCAL)) != ID_LOCAL)
+ return ST_CONTINUE;
+
+ var = intern_cstr(s, len, enc);
+ if (len < MAX_WORD_LENGTH && rb_reserved_word(s, (int)len)) {
+ if (!lvar_defined(p, var)) return ST_CONTINUE;
+ }
+ node = node_assign(p, assignable(p, var, 0, loc), NEW_LIT(ID2SYM(var), loc), NO_LEX_CTXT, loc);
+ succ = *succ_block;
+ if (!succ) succ = NEW_BEGIN(0, loc);
+ succ = block_append(p, succ, node);
+ *succ_block = succ;
+ return ST_CONTINUE;
+}
static VALUE
parser_reg_compile(struct parser_params* p, VALUE str, int options)
@@ -13607,7 +13590,7 @@ parser_reg_compile(struct parser_params* p, VALUE str, int options, VALUE *errms
{
VALUE err = rb_errinfo();
VALUE re;
- str = ripper_is_node_yylval(str) ? RNODE(str)->nd_cval : str;
+ str = ripper_is_node_yylval(p, str) ? RNODE(str)->nd_cval : str;
int c = rb_reg_fragment_setenc(p, str, options);
if (c) reg_fragment_enc_error(p, str, c);
re = rb_parser_reg_compile(p, str, options);
@@ -13621,10 +13604,8 @@ parser_reg_compile(struct parser_params* p, VALUE str, int options, VALUE *errms
#ifndef RIPPER
void
-rb_parser_set_options(VALUE vparser, int print, int loop, int chomp, int split)
+rb_ruby_parser_set_options(struct parser_params *p, int print, int loop, int chomp, int split)
{
- struct parser_params *p;
- TypedData_Get_Struct(vparser, struct parser_params, &parser_data_type, p);
p->do_print = print;
p->do_loop = loop;
p->do_chomp = chomp;
@@ -13708,12 +13689,13 @@ parser_initialize(struct parser_params *p)
}
#ifdef RIPPER
-#define parser_mark ripper_parser_mark
-#define parser_free ripper_parser_free
+#define rb_ruby_parser_mark ripper_parser_mark
+#define rb_ruby_parser_free ripper_parser_free
+#define rb_ruby_parser_memsize ripper_parser_memsize
#endif
-static void
-parser_mark(void *ptr)
+void
+rb_ruby_parser_mark(void *ptr)
{
struct parser_params *p = (struct parser_params*)ptr;
@@ -13743,11 +13725,14 @@ parser_mark(void *ptr)
#endif
}
-static void
-parser_free(void *ptr)
+void
+rb_ruby_parser_free(void *ptr)
{
struct parser_params *p = (struct parser_params*)ptr;
struct local_vars *local, *prev;
+#ifdef UNIVERSAL_PARSER
+ rb_parser_config_t *config = p->config;
+#endif
if (p->tokenbuf) {
ruby_sized_xfree(p->tokenbuf, p->toksiz);
@@ -13765,10 +13750,17 @@ parser_free(void *ptr)
}
}
xfree(ptr);
+
+#ifdef UNIVERSAL_PARSER
+ config->counter--;
+ if (config->counter <= 0) {
+ rb_ruby_parser_config_free(config);
+ }
+#endif
}
-static size_t
-parser_memsize(const void *ptr)
+size_t
+rb_ruby_parser_memsize(const void *ptr)
{
struct parser_params *p = (struct parser_params*)ptr;
struct local_vars *local;
@@ -13782,19 +13774,33 @@ parser_memsize(const void *ptr)
return size;
}
-static const rb_data_type_t parser_data_type = {
+#ifdef UNIVERSAL_PARSER
+rb_parser_config_t *
+rb_ruby_parser_config_new(void *(*malloc)(size_t size))
+{
+ return (rb_parser_config_t *)malloc(sizeof(rb_parser_config_t));
+}
+
+void
+rb_ruby_parser_config_free(rb_parser_config_t *config)
+{
+ config->free(config);
+}
+#endif
+
+#ifndef UNIVERSAL_PARSER
#ifndef RIPPER
+static const rb_data_type_t parser_data_type = {
"parser",
-#else
- "ripper",
-#endif
{
- parser_mark,
- parser_free,
- parser_memsize,
+ rb_ruby_parser_mark,
+ rb_ruby_parser_free,
+ rb_ruby_parser_memsize,
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY
};
+#endif
+#endif
#ifndef RIPPER
#undef rb_reserved_word
@@ -13805,181 +13811,362 @@ rb_reserved_word(const char *str, unsigned int len)
return reserved_word(str, len);
}
-VALUE
-rb_parser_new(void)
+#ifdef UNIVERSAL_PARSER
+rb_parser_t *
+rb_ruby_parser_allocate(rb_parser_config_t *config)
{
- struct parser_params *p;
- VALUE parser = TypedData_Make_Struct(0, struct parser_params,
- &parser_data_type, p);
- parser_initialize(p);
- return parser;
+ /* parser_initialize expects fields to be set to 0 */
+ rb_parser_t *p = (rb_parser_t *)config->calloc(1, sizeof(rb_parser_t));
+ p->config = config;
+ p->config->counter++;
+ return p;
}
-VALUE
-rb_parser_set_context(VALUE vparser, const struct rb_iseq_struct *base, int main)
+rb_parser_t *
+rb_ruby_parser_new(rb_parser_config_t *config)
{
- struct parser_params *p;
+ /* parser_initialize expects fields to be set to 0 */
+ rb_parser_t *p = rb_ruby_parser_allocate(config);
+ parser_initialize(p);
+ return p;
+}
+#endif
- TypedData_Get_Struct(vparser, struct parser_params, &parser_data_type, p);
+rb_parser_t *
+rb_ruby_parser_set_context(rb_parser_t *p, const struct rb_iseq_struct *base, int main)
+{
p->error_buffer = main ? Qfalse : Qnil;
p->parent_iseq = base;
- return vparser;
+ return p;
}
void
-rb_parser_keep_script_lines(VALUE vparser)
+rb_ruby_parser_keep_script_lines(rb_parser_t *p)
+{
+ p->keep_script_lines = 1;
+}
+
+void
+rb_ruby_parser_error_tolerant(rb_parser_t *p)
+{
+ p->error_tolerant = 1;
+ // TODO
+ p->end_expect_token_locations = rb_ary_new();
+}
+
+void
+rb_ruby_parser_keep_tokens(rb_parser_t *p)
+{
+ p->keep_tokens = 1;
+ // TODO
+ p->tokens = rb_ary_new();
+}
+
+#ifndef UNIVERSAL_PARSER
+rb_ast_t*
+rb_parser_compile_file_path(VALUE vparser, VALUE fname, VALUE file, int start)
{
struct parser_params *p;
TypedData_Get_Struct(vparser, struct parser_params, &parser_data_type, p);
- p->keep_script_lines = 1;
+ RB_GC_GUARD(vparser); /* prohibit tail call optimization */
+ return rb_ruby_parser_compile_file_path(p, fname, file, start);
}
-void
-rb_parser_error_tolerant(VALUE vparser)
+rb_ast_t*
+rb_parser_compile_generic(VALUE vparser, VALUE (*lex_gets)(VALUE, int), VALUE fname, VALUE input, int start)
{
struct parser_params *p;
TypedData_Get_Struct(vparser, struct parser_params, &parser_data_type, p);
- p->error_tolerant = 1;
- p->end_expect_token_locations = rb_ary_new();
+ RB_GC_GUARD(vparser); /* prohibit tail call optimization */
+ return rb_ruby_parser_compile_generic(p, lex_gets, fname, input, start);
}
-void
-rb_parser_keep_tokens(VALUE vparser)
+rb_ast_t*
+rb_parser_compile_string(VALUE vparser, const char *f, VALUE s, int line)
{
struct parser_params *p;
TypedData_Get_Struct(vparser, struct parser_params, &parser_data_type, p);
- p->keep_tokens = 1;
- p->tokens = rb_ary_new();
+ RB_GC_GUARD(vparser); /* prohibit tail call optimization */
+ return rb_ruby_parser_compile_string(p, f, s, line);
}
-#endif
+rb_ast_t*
+rb_parser_compile_string_path(VALUE vparser, VALUE f, VALUE s, int line)
+{
+ struct parser_params *p;
-#ifdef RIPPER
-#define rb_parser_end_seen_p ripper_parser_end_seen_p
-#define rb_parser_encoding ripper_parser_encoding
-#define rb_parser_get_yydebug ripper_parser_get_yydebug
-#define rb_parser_set_yydebug ripper_parser_set_yydebug
-#define rb_parser_get_debug_output ripper_parser_get_debug_output
-#define rb_parser_set_debug_output ripper_parser_set_debug_output
-static VALUE ripper_parser_end_seen_p(VALUE vparser);
-static VALUE ripper_parser_encoding(VALUE vparser);
-static VALUE ripper_parser_get_yydebug(VALUE self);
-static VALUE ripper_parser_set_yydebug(VALUE self, VALUE flag);
-static VALUE ripper_parser_get_debug_output(VALUE self);
-static VALUE ripper_parser_set_debug_output(VALUE self, VALUE output);
+ TypedData_Get_Struct(vparser, struct parser_params, &parser_data_type, p);
+ RB_GC_GUARD(vparser); /* prohibit tail call optimization */
+ return rb_ruby_parser_compile_string_path(p, f, s, line);
+}
-/*
- * call-seq:
- * ripper.error? -> Boolean
- *
- * Return true if parsed source has errors.
- */
-static VALUE
-ripper_error_p(VALUE vparser)
+VALUE
+rb_parser_encoding(VALUE vparser)
{
struct parser_params *p;
TypedData_Get_Struct(vparser, struct parser_params, &parser_data_type, p);
- return RBOOL(p->error_p);
+ return rb_ruby_parser_encoding(p);
}
-#endif
-/*
- * call-seq:
- * ripper.end_seen? -> Boolean
- *
- * Return true if parsed source ended by +\_\_END\_\_+.
- */
VALUE
rb_parser_end_seen_p(VALUE vparser)
{
struct parser_params *p;
TypedData_Get_Struct(vparser, struct parser_params, &parser_data_type, p);
- return RBOOL(p->ruby__end__seen);
+ return RBOOL(rb_ruby_parser_end_seen_p(p));
}
-/*
- * call-seq:
- * ripper.encoding -> encoding
- *
- * Return encoding of the source.
- */
-VALUE
-rb_parser_encoding(VALUE vparser)
+void
+rb_parser_error_tolerant(VALUE vparser)
{
struct parser_params *p;
TypedData_Get_Struct(vparser, struct parser_params, &parser_data_type, p);
- return rb_enc_from_encoding(p->enc);
+ rb_ruby_parser_error_tolerant(p);
+}
+
+void
+rb_parser_keep_script_lines(VALUE vparser)
+{
+ struct parser_params *p;
+
+ TypedData_Get_Struct(vparser, struct parser_params, &parser_data_type, p);
+ rb_ruby_parser_keep_script_lines(p);
+}
+
+void
+rb_parser_keep_tokens(VALUE vparser)
+{
+ struct parser_params *p;
+
+ TypedData_Get_Struct(vparser, struct parser_params, &parser_data_type, p);
+ rb_ruby_parser_keep_tokens(p);
}
-#ifdef RIPPER
-/*
- * call-seq:
- * ripper.yydebug -> true or false
- *
- * Get yydebug.
- */
VALUE
-rb_parser_get_yydebug(VALUE self)
+rb_parser_new(void)
{
struct parser_params *p;
+ VALUE parser = TypedData_Make_Struct(0, struct parser_params,
+ &parser_data_type, p);
+ parser_initialize(p);
+ return parser;
+}
- TypedData_Get_Struct(self, struct parser_params, &parser_data_type, p);
- return RBOOL(p->debug);
+VALUE
+rb_parser_set_context(VALUE vparser, const struct rb_iseq_struct *base, int main)
+{
+ struct parser_params *p;
+
+ TypedData_Get_Struct(vparser, struct parser_params, &parser_data_type, p);
+ rb_ruby_parser_set_context(p, base, main);
+ return vparser;
+}
+
+void
+rb_parser_set_options(VALUE vparser, int print, int loop, int chomp, int split)
+{
+ struct parser_params *p;
+
+ TypedData_Get_Struct(vparser, struct parser_params, &parser_data_type, p);
+ rb_ruby_parser_set_options(p, print, loop, chomp, split);
}
-#endif
-/*
- * call-seq:
- * ripper.yydebug = flag
- *
- * Set yydebug.
- */
VALUE
rb_parser_set_yydebug(VALUE self, VALUE flag)
{
struct parser_params *p;
TypedData_Get_Struct(self, struct parser_params, &parser_data_type, p);
- p->debug = RTEST(flag);
+ rb_ruby_parser_set_yydebug(p, RTEST(flag));
return flag;
}
-/*
- * call-seq:
- * ripper.debug_output -> obj
- *
- * Get debug output.
- */
+void
+rb_strterm_mark(VALUE obj)
+{
+ rb_strterm_t *strterm = (rb_strterm_t*)obj;
+ if (RBASIC(obj)->flags & STRTERM_HEREDOC) {
+ rb_strterm_heredoc_t *heredoc = &strterm->u.heredoc;
+ rb_gc_mark(heredoc->lastline);
+ }
+}
+#endif /* !UNIVERSAL_PARSER */
+#endif /* !RIPPER */
+
VALUE
-rb_parser_get_debug_output(VALUE self)
+rb_ruby_parser_encoding(rb_parser_t *p)
{
- struct parser_params *p;
+ return rb_enc_from_encoding(p->enc);
+}
- TypedData_Get_Struct(self, struct parser_params, &parser_data_type, p);
+int
+rb_ruby_parser_end_seen_p(rb_parser_t *p)
+{
+ return p->ruby__end__seen;
+}
+
+int
+rb_ruby_parser_set_yydebug(rb_parser_t *p, int flag)
+{
+ p->debug = flag;
+ return flag;
+}
+
+#ifdef RIPPER
+int
+rb_ruby_parser_get_yydebug(rb_parser_t *p)
+{
+ return p->debug;
+}
+
+void
+rb_ruby_parser_set_value(rb_parser_t *p, VALUE value)
+{
+ p->value = value;
+}
+
+int
+rb_ruby_parser_error_p(rb_parser_t *p)
+{
+ return p->error_p;
+}
+
+VALUE
+rb_ruby_parser_debug_output(rb_parser_t *p)
+{
return p->debug_output;
}
-/*
- * call-seq:
- * ripper.debug_output = obj
- *
- * Set debug output.
- */
+void
+rb_ruby_parser_set_debug_output(rb_parser_t *p, VALUE output)
+{
+ p->debug_output = output;
+}
+
VALUE
-rb_parser_set_debug_output(VALUE self, VALUE output)
+rb_ruby_parser_parsing_thread(rb_parser_t *p)
{
- struct parser_params *p;
+ return p->parsing_thread;
+}
- TypedData_Get_Struct(self, struct parser_params, &parser_data_type, p);
- return p->debug_output = output;
+void
+rb_ruby_parser_set_parsing_thread(rb_parser_t *p, VALUE parsing_thread)
+{
+ p->parsing_thread = parsing_thread;
+}
+
+void
+rb_ruby_parser_ripper_initialize(rb_parser_t *p, VALUE (*gets)(struct parser_params*,VALUE), VALUE input, VALUE sourcefile_string, const char *sourcefile, int sourceline)
+{
+ p->lex.gets = gets;
+ p->lex.input = input;
+ p->eofp = 0;
+ p->ruby_sourcefile_string = sourcefile_string;
+ p->ruby_sourcefile = sourcefile;
+ p->ruby_sourceline = sourceline;
+}
+
+VALUE
+rb_ruby_parser_result(rb_parser_t *p)
+{
+ return p->result;
+}
+
+rb_encoding *
+rb_ruby_parser_enc(rb_parser_t *p)
+{
+ return p->enc;
+}
+
+VALUE
+rb_ruby_parser_ruby_sourcefile_string(rb_parser_t *p)
+{
+ return p->ruby_sourcefile_string;
+}
+
+int
+rb_ruby_parser_ruby_sourceline(rb_parser_t *p)
+{
+ return p->ruby_sourceline;
+}
+
+int
+rb_ruby_parser_lex_state(rb_parser_t *p)
+{
+ return p->lex.state;
}
+void
+rb_ruby_ripper_parse0(rb_parser_t *p)
+{
+ parser_prepare(p);
+ p->ast = rb_ast_new();
+ ripper_yyparse((void*)p);
+ rb_ast_dispose(p->ast);
+ p->ast = 0;
+}
+
+int
+rb_ruby_ripper_dedent_string(rb_parser_t *p, VALUE string, int width)
+{
+ return dedent_string(p, string, width);
+}
+
+VALUE
+rb_ruby_ripper_lex_get_str(rb_parser_t *p, VALUE s)
+{
+ return lex_get_str(p, s);
+}
+
+int
+rb_ruby_ripper_initialized_p(rb_parser_t *p)
+{
+ return p->lex.input != 0;
+}
+
+void
+rb_ruby_ripper_parser_initialize(rb_parser_t *p)
+{
+ parser_initialize(p);
+}
+
+long
+rb_ruby_ripper_column(rb_parser_t *p)
+{
+ return p->lex.ptok - p->lex.pbeg;
+}
+
+long
+rb_ruby_ripper_token_len(rb_parser_t *p)
+{
+ return p->lex.pcur - p->lex.ptok;
+}
+
+VALUE
+rb_ruby_ripper_lex_lastline(rb_parser_t *p)
+{
+ return p->lex.lastline;
+}
+
+VALUE
+rb_ruby_ripper_lex_state_name(struct parser_params *p, int state)
+{
+ return rb_parser_lex_state_name(p, (enum lex_state_e)state);
+}
+
+struct parser_params*
+rb_ruby_ripper_parser_allocate(void)
+{
+ return (struct parser_params *)ruby_xcalloc(1, sizeof(struct parser_params));
+}
+#endif /* RIPPER */
+
#ifndef RIPPER
#ifdef YYMALLOC
#define HEAPCNT(n, size) ((n) * (size) / sizeof(YYSTYPE))
@@ -14262,377 +14449,21 @@ ripper_dispatch7(struct parser_params *p, ID mid, VALUE a, VALUE b, VALUE c, VAL
return rb_funcall(p->value, mid, 7, a, b, c, d, e, f, g);
}
-static ID
-ripper_get_id(VALUE v)
-{
- NODE *nd;
- if (!RB_TYPE_P(v, T_NODE)) return 0;
- nd = (NODE *)v;
- if (!nd_type_p(nd, NODE_RIPPER)) return 0;
- return nd->nd_vid;
-}
-
-static VALUE
-ripper_get_value(VALUE v)
-{
- NODE *nd;
- if (UNDEF_P(v)) return Qnil;
- if (!RB_TYPE_P(v, T_NODE)) return v;
- nd = (NODE *)v;
- if (!nd_type_p(nd, NODE_RIPPER)) return Qnil;
- return nd->nd_rval;
-}
-
-static void
+void
ripper_error(struct parser_params *p)
{
p->error_p = TRUE;
}
-static void
-ripper_compile_error(struct parser_params *p, const char *fmt, ...)
-{
- VALUE str;
- va_list args;
-
- va_start(args, fmt);
- str = rb_vsprintf(fmt, args);
- va_end(args);
- rb_funcall(p->value, rb_intern("compile_error"), 1, str);
- ripper_error(p);
-}
-
-static VALUE
-ripper_lex_get_generic(struct parser_params *p, VALUE src)
-{
- VALUE line = rb_funcallv_public(src, id_gets, 0, 0);
- if (!NIL_P(line) && !RB_TYPE_P(line, T_STRING)) {
- rb_raise(rb_eTypeError,
- "gets returned %"PRIsVALUE" (expected String or nil)",
- rb_obj_class(line));
- }
- return line;
-}
-
-static VALUE
-ripper_lex_io_get(struct parser_params *p, VALUE src)
-{
- return rb_io_gets(src);
-}
-
-static VALUE
-ripper_s_allocate(VALUE klass)
-{
- struct parser_params *p;
- VALUE self = TypedData_Make_Struct(klass, struct parser_params,
- &parser_data_type, p);
- p->value = self;
- return self;
-}
-
-#define ripper_initialized_p(r) ((r)->lex.input != 0)
-
-/*
- * call-seq:
- * Ripper.new(src, filename="(ripper)", lineno=1) -> ripper
- *
- * Create a new Ripper object.
- * _src_ must be a String, an IO, or an Object which has #gets method.
- *
- * This method does not starts parsing.
- * See also Ripper#parse and Ripper.parse.
- */
-static VALUE
-ripper_initialize(int argc, VALUE *argv, VALUE self)
-{
- struct parser_params *p;
- VALUE src, fname, lineno;
-
- TypedData_Get_Struct(self, struct parser_params, &parser_data_type, p);
- rb_scan_args(argc, argv, "12", &src, &fname, &lineno);
- if (RB_TYPE_P(src, T_FILE)) {
- p->lex.gets = ripper_lex_io_get;
- }
- else if (rb_respond_to(src, id_gets)) {
- p->lex.gets = ripper_lex_get_generic;
- }
- else {
- StringValue(src);
- p->lex.gets = lex_get_str;
- }
- p->lex.input = src;
- p->eofp = 0;
- if (NIL_P(fname)) {
- fname = STR_NEW2("(ripper)");
- OBJ_FREEZE(fname);
- }
- else {
- StringValueCStr(fname);
- fname = rb_str_new_frozen(fname);
- }
- parser_initialize(p);
-
- p->ruby_sourcefile_string = fname;
- p->ruby_sourcefile = RSTRING_PTR(fname);
- p->ruby_sourceline = NIL_P(lineno) ? 0 : NUM2INT(lineno) - 1;
-
- return Qnil;
-}
-
-static VALUE
-ripper_parse0(VALUE parser_v)
-{
- struct parser_params *p;
-
- TypedData_Get_Struct(parser_v, struct parser_params, &parser_data_type, p);
- parser_prepare(p);
- p->ast = rb_ast_new();
- ripper_yyparse((void*)p);
- rb_ast_dispose(p->ast);
- p->ast = 0;
- return p->result;
-}
-
-static VALUE
-ripper_ensure(VALUE parser_v)
-{
- struct parser_params *p;
-
- TypedData_Get_Struct(parser_v, struct parser_params, &parser_data_type, p);
- p->parsing_thread = Qnil;
- return Qnil;
-}
-
-/*
- * call-seq:
- * ripper.parse
- *
- * Start parsing and returns the value of the root action.
- */
-static VALUE
-ripper_parse(VALUE self)
-{
- struct parser_params *p;
-
- TypedData_Get_Struct(self, struct parser_params, &parser_data_type, p);
- if (!ripper_initialized_p(p)) {
- rb_raise(rb_eArgError, "method called for uninitialized object");
- }
- if (!NIL_P(p->parsing_thread)) {
- if (p->parsing_thread == rb_thread_current())
- rb_raise(rb_eArgError, "Ripper#parse is not reentrant");
- else
- rb_raise(rb_eArgError, "Ripper#parse is not multithread-safe");
- }
- p->parsing_thread = rb_thread_current();
- rb_ensure(ripper_parse0, self, ripper_ensure, self);
-
- return p->result;
-}
-
-/*
- * call-seq:
- * ripper.column -> Integer
- *
- * Return column number of current parsing line.
- * This number starts from 0.
- */
-static VALUE
-ripper_column(VALUE self)
-{
- struct parser_params *p;
- long col;
-
- TypedData_Get_Struct(self, struct parser_params, &parser_data_type, p);
- if (!ripper_initialized_p(p)) {
- rb_raise(rb_eArgError, "method called for uninitialized object");
- }
- if (NIL_P(p->parsing_thread)) return Qnil;
- col = p->lex.ptok - p->lex.pbeg;
- return LONG2NUM(col);
-}
-
-/*
- * call-seq:
- * ripper.filename -> String
- *
- * Return current parsing filename.
- */
-static VALUE
-ripper_filename(VALUE self)
-{
- struct parser_params *p;
-
- TypedData_Get_Struct(self, struct parser_params, &parser_data_type, p);
- if (!ripper_initialized_p(p)) {
- rb_raise(rb_eArgError, "method called for uninitialized object");
- }
- return p->ruby_sourcefile_string;
-}
-
-/*
- * call-seq:
- * ripper.lineno -> Integer
- *
- * Return line number of current parsing line.
- * This number starts from 1.
- */
-static VALUE
-ripper_lineno(VALUE self)
-{
- struct parser_params *p;
-
- TypedData_Get_Struct(self, struct parser_params, &parser_data_type, p);
- if (!ripper_initialized_p(p)) {
- rb_raise(rb_eArgError, "method called for uninitialized object");
- }
- if (NIL_P(p->parsing_thread)) return Qnil;
- return INT2NUM(p->ruby_sourceline);
-}
-
-/*
- * call-seq:
- * ripper.state -> Integer
- *
- * Return scanner state of current token.
- */
-static VALUE
-ripper_state(VALUE self)
-{
- struct parser_params *p;
-
- TypedData_Get_Struct(self, struct parser_params, &parser_data_type, p);
- if (!ripper_initialized_p(p)) {
- rb_raise(rb_eArgError, "method called for uninitialized object");
- }
- if (NIL_P(p->parsing_thread)) return Qnil;
- return INT2NUM(p->lex.state);
-}
-
-/*
- * call-seq:
- * ripper.token -> String
- *
- * Return the current token string.
- */
-static VALUE
-ripper_token(VALUE self)
-{
- struct parser_params *p;
- long pos, len;
-
- TypedData_Get_Struct(self, struct parser_params, &parser_data_type, p);
- if (!ripper_initialized_p(p)) {
- rb_raise(rb_eArgError, "method called for uninitialized object");
- }
- if (NIL_P(p->parsing_thread)) return Qnil;
- pos = p->lex.ptok - p->lex.pbeg;
- len = p->lex.pcur - p->lex.ptok;
- return rb_str_subseq(p->lex.lastline, pos, len);
-}
-
-#ifdef RIPPER_DEBUG
-/* :nodoc: */
-static VALUE
-ripper_assert_Qundef(VALUE self, VALUE obj, VALUE msg)
-{
- StringValue(msg);
- if (UNDEF_P(obj)) {
- rb_raise(rb_eArgError, "%"PRIsVALUE, msg);
- }
- return Qnil;
-}
-
-/* :nodoc: */
-static VALUE
-ripper_value(VALUE self, VALUE obj)
-{
- return ULONG2NUM(obj);
-}
-#endif
-
-/*
- * call-seq:
- * Ripper.lex_state_name(integer) -> string
- *
- * Returns a string representation of lex_state.
- */
-static VALUE
-ripper_lex_state_name(VALUE self, VALUE state)
-{
- return rb_parser_lex_state_name(NUM2INT(state));
-}
-
-void
-Init_ripper(void)
+VALUE
+ripper_value(struct parser_params *p)
{
- ripper_init_eventids1();
- ripper_init_eventids2();
- id_warn = rb_intern_const("warn");
- id_warning = rb_intern_const("warning");
- id_gets = rb_intern_const("gets");
- id_assoc = rb_intern_const("=>");
-
(void)yystpcpy; /* may not used in newer bison */
- InitVM(ripper);
+ return p->value;
}
-void
-InitVM_ripper(void)
-{
- VALUE Ripper;
-
- Ripper = rb_define_class("Ripper", rb_cObject);
- /* version of Ripper */
- rb_define_const(Ripper, "Version", rb_usascii_str_new2(RIPPER_VERSION));
- rb_define_alloc_func(Ripper, ripper_s_allocate);
- rb_define_method(Ripper, "initialize", ripper_initialize, -1);
- rb_define_method(Ripper, "parse", ripper_parse, 0);
- rb_define_method(Ripper, "column", ripper_column, 0);
- rb_define_method(Ripper, "filename", ripper_filename, 0);
- rb_define_method(Ripper, "lineno", ripper_lineno, 0);
- rb_define_method(Ripper, "state", ripper_state, 0);
- rb_define_method(Ripper, "token", ripper_token, 0);
- rb_define_method(Ripper, "end_seen?", rb_parser_end_seen_p, 0);
- rb_define_method(Ripper, "encoding", rb_parser_encoding, 0);
- rb_define_method(Ripper, "yydebug", rb_parser_get_yydebug, 0);
- rb_define_method(Ripper, "yydebug=", rb_parser_set_yydebug, 1);
- rb_define_method(Ripper, "debug_output", rb_parser_get_debug_output, 0);
- rb_define_method(Ripper, "debug_output=", rb_parser_set_debug_output, 1);
- rb_define_method(Ripper, "error?", ripper_error_p, 0);
-#ifdef RIPPER_DEBUG
- rb_define_method(Ripper, "assert_Qundef", ripper_assert_Qundef, 2);
- rb_define_method(Ripper, "rawVALUE", ripper_value, 1);
- rb_define_method(Ripper, "validate_object", ripper_validate_object, 1);
-#endif
-
- rb_define_singleton_method(Ripper, "dedent_string", parser_dedent_string, 2);
- rb_define_private_method(Ripper, "dedent_string", parser_dedent_string, 2);
-
- rb_define_singleton_method(Ripper, "lex_state_name", ripper_lex_state_name, 1);
-
-<% @exprs.each do |expr, desc| -%>
- /* <%=desc%> */
- rb_define_const(Ripper, "<%=expr%>", INT2NUM(<%=expr%>));
-<% end %>
- ripper_init_eventids1_table(Ripper);
- ripper_init_eventids2_table(Ripper);
-
-# if 0
- /* Hack to let RDoc document SCRIPT_LINES__ */
-
- /*
- * When a Hash is assigned to +SCRIPT_LINES__+ the contents of files loaded
- * after the assignment will be added as an Array of lines with the file
- * name as the key.
- */
- rb_define_global_const("SCRIPT_LINES__", Qnil);
-#endif
-
-}
#endif /* RIPPER */
-
/*
* Local variables:
* mode: c
diff --git a/parser_bits.h b/parser_bits.h
new file mode 100644
index 0000000000..ca7535280e
--- /dev/null
+++ b/parser_bits.h
@@ -0,0 +1,564 @@
+#ifndef INTERNAL_BITS2_H /*-*-C-*-vi:se ft=c:*/
+#define INTERNAL_BITS2_H
+/**
+ * @author Ruby developers <ruby-core@ruby-lang.org>
+ * @copyright This file is a part of the programming language Ruby.
+ * Permission is hereby granted, to either redistribute and/or
+ * modify this file, provided that the conditions mentioned in the
+ * file COPYING are met. Consult the file for details.
+ * @brief Internal header for bitwise integer algorithms.
+ * @see Henry S. Warren Jr., "Hacker's Delight" (2nd ed.), 2013.
+ * @see SEI CERT C Coding Standard INT32-C. "Ensure that operations on
+ * signed integers do not result in overflow"
+ * @see https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html
+ * @see https://clang.llvm.org/docs/LanguageExtensions.html#builtin-rotateleft
+ * @see https://clang.llvm.org/docs/LanguageExtensions.html#builtin-rotateright
+ * @see https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/byteswap-uint64-byteswap-ulong-byteswap-ushort
+ * @see https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/rotl-rotl64-rotr-rotr64
+ * @see https://docs.microsoft.com/en-us/cpp/intrinsics/bitscanforward-bitscanforward64
+ * @see https://docs.microsoft.com/en-us/cpp/intrinsics/bitscanreverse-bitscanreverse64
+ * @see https://docs.microsoft.com/en-us/cpp/intrinsics/lzcnt16-lzcnt-lzcnt64
+ * @see https://docs.microsoft.com/en-us/cpp/intrinsics/popcnt16-popcnt-popcnt64
+ * @see https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_lzcnt_u32
+ * @see https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_tzcnt_u32
+ * @see https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_rotl64
+ * @see https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_rotr64
+ * @see https://stackoverflow.com/a/776523
+ */
+#include "ruby/internal/config.h"
+#include <limits.h> /* for CHAR_BITS */
+#include <stdint.h> /* for uintptr_t */
+#include "internal/compilers.h" /* for MSC_VERSION_SINCE */
+
+#if MSC_VERSION_SINCE(1310)
+# include <stdlib.h> /* for _byteswap_uint64 */
+#endif
+
+#if defined(HAVE_X86INTRIN_H)
+# include <x86intrin.h> /* for _lzcnt_u64 */
+#elif MSC_VERSION_SINCE(1310)
+# include <intrin.h> /* for the following intrinsics */
+#endif
+
+#if defined(_MSC_VER) && defined(__AVX__)
+# pragma intrinsic(__popcnt)
+# pragma intrinsic(__popcnt64)
+#endif
+
+#if defined(_MSC_VER) && defined(__AVX2__)
+# pragma intrinsic(__lzcnt)
+# pragma intrinsic(__lzcnt64)
+#endif
+
+#if MSC_VERSION_SINCE(1310)
+# pragma intrinsic(_rotl)
+# pragma intrinsic(_rotr)
+# ifdef _WIN64
+# pragma intrinsic(_rotl64)
+# pragma intrinsic(_rotr64)
+# endif
+#endif
+
+#if MSC_VERSION_SINCE(1400)
+# pragma intrinsic(_BitScanForward)
+# pragma intrinsic(_BitScanReverse)
+# ifdef _WIN64
+# pragma intrinsic(_BitScanForward64)
+# pragma intrinsic(_BitScanReverse64)
+# endif
+#endif
+
+#include "parser_value.h" /* for VALUE */
+#include "internal/static_assert.h" /* for STATIC_ASSERT */
+
+/* The most significant bit of the lower part of half-long integer.
+ * If sizeof(long) == 4, this is 0x8000.
+ * If sizeof(long) == 8, this is 0x80000000.
+ */
+#define HALF_LONG_MSB ((SIGNED_VALUE)1<<((SIZEOF_LONG*CHAR_BIT-1)/2))
+
+#define SIGNED_INTEGER_TYPE_P(T) (0 > ((T)0)-1)
+
+#define SIGNED_INTEGER_MIN(T) \
+ ((sizeof(T) == sizeof(int8_t)) ? ((T)INT8_MIN) : \
+ ((sizeof(T) == sizeof(int16_t)) ? ((T)INT16_MIN) : \
+ ((sizeof(T) == sizeof(int32_t)) ? ((T)INT32_MIN) : \
+ ((sizeof(T) == sizeof(int64_t)) ? ((T)INT64_MIN) : \
+ 0))))
+
+#define SIGNED_INTEGER_MAX(T) ((T)(SIGNED_INTEGER_MIN(T) ^ ((T)~(T)0)))
+
+#define UNSIGNED_INTEGER_MAX(T) ((T)~(T)0)
+
+#if __has_builtin(__builtin_mul_overflow_p)
+# define MUL_OVERFLOW_P(a, b) \
+ __builtin_mul_overflow_p((a), (b), (__typeof__(a * b))0)
+#elif __has_builtin(__builtin_mul_overflow)
+# define MUL_OVERFLOW_P(a, b) \
+ __extension__ ({ __typeof__(a) c; __builtin_mul_overflow((a), (b), &c); })
+#endif
+
+#define MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, min, max) ( \
+ (a) == 0 ? 0 : \
+ (a) == -1 ? (b) < -(max) : \
+ (a) > 0 ? \
+ ((b) > 0 ? (max) / (a) < (b) : (min) / (a) > (b)) : \
+ ((b) > 0 ? (min) / (a) < (b) : (max) / (a) > (b)))
+
+#if __has_builtin(__builtin_mul_overflow_p)
+/* __builtin_mul_overflow_p can take bitfield */
+/* and GCC permits bitfields for integers other than int */
+# define MUL_OVERFLOW_FIXNUM_P(a, b) \
+ __extension__ ({ \
+ struct { long fixnum : sizeof(long) * CHAR_BIT - 1; } c = { 0 }; \
+ __builtin_mul_overflow_p((a), (b), c.fixnum); \
+ })
+#else
+# define MUL_OVERFLOW_FIXNUM_P(a, b) \
+ MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, FIXNUM_MIN, FIXNUM_MAX)
+#endif
+
+#ifdef MUL_OVERFLOW_P
+# define MUL_OVERFLOW_LONG_LONG_P(a, b) MUL_OVERFLOW_P(a, b)
+# define MUL_OVERFLOW_LONG_P(a, b) MUL_OVERFLOW_P(a, b)
+# define MUL_OVERFLOW_INT_P(a, b) MUL_OVERFLOW_P(a, b)
+#else
+# define MUL_OVERFLOW_LONG_LONG_P(a, b) MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, LLONG_MIN, LLONG_MAX)
+# define MUL_OVERFLOW_LONG_P(a, b) MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, LONG_MIN, LONG_MAX)
+# define MUL_OVERFLOW_INT_P(a, b) MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, INT_MIN, INT_MAX)
+#endif
+
+#ifdef HAVE_UINT128_T
+# define bit_length(x) \
+ (unsigned int) \
+ (sizeof(x) <= sizeof(int32_t) ? 32 - nlz_int32((uint32_t)(x)) : \
+ sizeof(x) <= sizeof(int64_t) ? 64 - nlz_int64((uint64_t)(x)) : \
+ 128 - nlz_int128((uint128_t)(x)))
+#else
+# define bit_length(x) \
+ (unsigned int) \
+ (sizeof(x) <= sizeof(int32_t) ? 32 - nlz_int32((uint32_t)(x)) : \
+ 64 - nlz_int64((uint64_t)(x)))
+#endif
+
+#ifndef swap16
+# define swap16 ruby_swap16
+#endif
+
+#ifndef swap32
+# define swap32 ruby_swap32
+#endif
+
+#ifndef swap64
+# define swap64 ruby_swap64
+#endif
+
+static inline uint16_t ruby_swap16(uint16_t);
+static inline uint32_t ruby_swap32(uint32_t);
+static inline uint64_t ruby_swap64(uint64_t);
+static inline unsigned nlz_int(unsigned x);
+static inline unsigned nlz_long(unsigned long x);
+static inline unsigned nlz_long_long(unsigned long long x);
+static inline unsigned nlz_intptr(uintptr_t x);
+static inline unsigned nlz_int32(uint32_t x);
+static inline unsigned nlz_int64(uint64_t x);
+#ifdef HAVE_UINT128_T
+static inline unsigned nlz_int128(uint128_t x);
+#endif
+static inline unsigned rb_popcount32(uint32_t x);
+static inline unsigned rb_popcount64(uint64_t x);
+static inline unsigned rb_popcount_intptr(uintptr_t x);
+static inline int ntz_int32(uint32_t x);
+static inline int ntz_int64(uint64_t x);
+static inline int ntz_intptr(uintptr_t x);
+static inline VALUE RUBY_BIT_ROTL(VALUE, int);
+static inline VALUE RUBY_BIT_ROTR(VALUE, int);
+
+static inline uint16_t
+ruby_swap16(uint16_t x)
+{
+#if __has_builtin(__builtin_bswap16)
+ return __builtin_bswap16(x);
+
+#elif MSC_VERSION_SINCE(1310)
+ return _byteswap_ushort(x);
+
+#else
+ return (x << 8) | (x >> 8);
+
+#endif
+}
+
+static inline uint32_t
+ruby_swap32(uint32_t x)
+{
+#if __has_builtin(__builtin_bswap32)
+ return __builtin_bswap32(x);
+
+#elif MSC_VERSION_SINCE(1310)
+ return _byteswap_ulong(x);
+
+#else
+ x = ((x & 0x0000FFFF) << 16) | ((x & 0xFFFF0000) >> 16);
+ x = ((x & 0x00FF00FF) << 8) | ((x & 0xFF00FF00) >> 8);
+ return x;
+
+#endif
+}
+
+static inline uint64_t
+ruby_swap64(uint64_t x)
+{
+#if __has_builtin(__builtin_bswap64)
+ return __builtin_bswap64(x);
+
+#elif MSC_VERSION_SINCE(1310)
+ return _byteswap_uint64(x);
+
+#else
+ x = ((x & 0x00000000FFFFFFFFULL) << 32) | ((x & 0xFFFFFFFF00000000ULL) >> 32);
+ x = ((x & 0x0000FFFF0000FFFFULL) << 16) | ((x & 0xFFFF0000FFFF0000ULL) >> 16);
+ x = ((x & 0x00FF00FF00FF00FFULL) << 8) | ((x & 0xFF00FF00FF00FF00ULL) >> 8);
+ return x;
+
+#endif
+}
+
+static inline unsigned int
+nlz_int32(uint32_t x)
+{
+#if defined(_MSC_VER) && defined(__AVX2__)
+ /* Note: It seems there is no such thing like __LZCNT__ predefined in MSVC.
+ * AMD CPUs have had this instruction for decades (since K10) but for
+ * Intel, Haswell is the oldest one. We need to use __AVX2__ for maximum
+ * safety. */
+ return (unsigned int)__lzcnt(x);
+
+#elif defined(__x86_64__) && defined(__LZCNT__)
+ return (unsigned int)_lzcnt_u32(x);
+
+#elif MSC_VERSION_SINCE(1400) /* &&! defined(__AVX2__) */
+ unsigned long r;
+ return _BitScanReverse(&r, x) ? (31 - (int)r) : 32;
+
+#elif __has_builtin(__builtin_clz)
+ STATIC_ASSERT(sizeof_int, sizeof(int) * CHAR_BIT == 32);
+ return x ? (unsigned int)__builtin_clz(x) : 32;
+
+#else
+ uint32_t y;
+ unsigned n = 32;
+ y = x >> 16; if (y) {n -= 16; x = y;}
+ y = x >> 8; if (y) {n -= 8; x = y;}
+ y = x >> 4; if (y) {n -= 4; x = y;}
+ y = x >> 2; if (y) {n -= 2; x = y;}
+ y = x >> 1; if (y) {return n - 2;}
+ return (unsigned int)(n - x);
+#endif
+}
+
+static inline unsigned int
+nlz_int64(uint64_t x)
+{
+#if defined(_MSC_VER) && defined(__AVX2__)
+ return (unsigned int)__lzcnt64(x);
+
+#elif defined(__x86_64__) && defined(__LZCNT__)
+ return (unsigned int)_lzcnt_u64(x);
+
+#elif defined(_WIN64) && MSC_VERSION_SINCE(1400) /* &&! defined(__AVX2__) */
+ unsigned long r;
+ return _BitScanReverse64(&r, x) ? (63u - (unsigned int)r) : 64;
+
+#elif __has_builtin(__builtin_clzl)
+ if (x == 0) {
+ return 64;
+ }
+ else if (sizeof(long) * CHAR_BIT == 64) {
+ return (unsigned int)__builtin_clzl((unsigned long)x);
+ }
+ else if (sizeof(long long) * CHAR_BIT == 64) {
+ return (unsigned int)__builtin_clzll((unsigned long long)x);
+ }
+ else {
+ /* :FIXME: Is there a way to make this branch a compile-time error? */
+ UNREACHABLE_RETURN(~0);
+ }
+
+#else
+ uint64_t y;
+ unsigned int n = 64;
+ y = x >> 32; if (y) {n -= 32; x = y;}
+ y = x >> 16; if (y) {n -= 16; x = y;}
+ y = x >> 8; if (y) {n -= 8; x = y;}
+ y = x >> 4; if (y) {n -= 4; x = y;}
+ y = x >> 2; if (y) {n -= 2; x = y;}
+ y = x >> 1; if (y) {return n - 2;}
+ return (unsigned int)(n - x);
+
+#endif
+}
+
+#ifdef HAVE_UINT128_T
+static inline unsigned int
+nlz_int128(uint128_t x)
+{
+ uint64_t y = (uint64_t)(x >> 64);
+
+ if (x == 0) {
+ return 128;
+ }
+ else if (y == 0) {
+ return (unsigned int)nlz_int64(x) + 64;
+ }
+ else {
+ return (unsigned int)nlz_int64(y);
+ }
+}
+#endif
+
+static inline unsigned int
+nlz_int(unsigned int x)
+{
+ if (sizeof(unsigned int) * CHAR_BIT == 32) {
+ return nlz_int32((uint32_t)x);
+ }
+ else if (sizeof(unsigned int) * CHAR_BIT == 64) {
+ return nlz_int64((uint64_t)x);
+ }
+ else {
+ UNREACHABLE_RETURN(~0);
+ }
+}
+
+static inline unsigned int
+nlz_long(unsigned long x)
+{
+ if (sizeof(unsigned long) * CHAR_BIT == 32) {
+ return nlz_int32((uint32_t)x);
+ }
+ else if (sizeof(unsigned long) * CHAR_BIT == 64) {
+ return nlz_int64((uint64_t)x);
+ }
+ else {
+ UNREACHABLE_RETURN(~0);
+ }
+}
+
+static inline unsigned int
+nlz_long_long(unsigned long long x)
+{
+ if (sizeof(unsigned long long) * CHAR_BIT == 64) {
+ return nlz_int64((uint64_t)x);
+ }
+#ifdef HAVE_UINT128_T
+ else if (sizeof(unsigned long long) * CHAR_BIT == 128) {
+ return nlz_int128((uint128_t)x);
+ }
+#endif
+ else {
+ UNREACHABLE_RETURN(~0);
+ }
+}
+
+static inline unsigned int
+nlz_intptr(uintptr_t x)
+{
+ if (sizeof(uintptr_t) == sizeof(unsigned int)) {
+ return nlz_int((unsigned int)x);
+ }
+ if (sizeof(uintptr_t) == sizeof(unsigned long)) {
+ return nlz_long((unsigned long)x);
+ }
+ if (sizeof(uintptr_t) == sizeof(unsigned long long)) {
+ return nlz_long_long((unsigned long long)x);
+ }
+ else {
+ UNREACHABLE_RETURN(~0);
+ }
+}
+
+static inline unsigned int
+rb_popcount32(uint32_t x)
+{
+#if defined(_MSC_VER) && defined(__AVX__)
+ /* Note: CPUs since Nehalem and Barcelona have had this instruction so SSE
+ * 4.2 should suffice, but it seems there is no such thing like __SSE_4_2__
+ * predefined macro in MSVC. They do have __AVX__ so use it instead. */
+ return (unsigned int)__popcnt(x);
+
+#elif __has_builtin(__builtin_popcount)
+ STATIC_ASSERT(sizeof_int, sizeof(int) * CHAR_BIT >= 32);
+ return (unsigned int)__builtin_popcount(x);
+
+#else
+ x = (x & 0x55555555) + (x >> 1 & 0x55555555);
+ x = (x & 0x33333333) + (x >> 2 & 0x33333333);
+ x = (x & 0x0f0f0f0f) + (x >> 4 & 0x0f0f0f0f);
+ x = (x & 0x001f001f) + (x >> 8 & 0x001f001f);
+ x = (x & 0x0000003f) + (x >>16 & 0x0000003f);
+ return (unsigned int)x;
+
+#endif
+}
+
+static inline unsigned int
+rb_popcount64(uint64_t x)
+{
+#if defined(_MSC_VER) && defined(__AVX__)
+ return (unsigned int)__popcnt64(x);
+
+#elif __has_builtin(__builtin_popcount)
+ if (sizeof(long) * CHAR_BIT == 64) {
+ return (unsigned int)__builtin_popcountl((unsigned long)x);
+ }
+ else if (sizeof(long long) * CHAR_BIT == 64) {
+ return (unsigned int)__builtin_popcountll((unsigned long long)x);
+ }
+ else {
+ /* :FIXME: Is there a way to make this branch a compile-time error? */
+ UNREACHABLE_RETURN(~0);
+ }
+
+#else
+ x = (x & 0x5555555555555555) + (x >> 1 & 0x5555555555555555);
+ x = (x & 0x3333333333333333) + (x >> 2 & 0x3333333333333333);
+ x = (x & 0x0707070707070707) + (x >> 4 & 0x0707070707070707);
+ x = (x & 0x001f001f001f001f) + (x >> 8 & 0x001f001f001f001f);
+ x = (x & 0x0000003f0000003f) + (x >>16 & 0x0000003f0000003f);
+ x = (x & 0x000000000000007f) + (x >>32 & 0x000000000000007f);
+ return (unsigned int)x;
+
+#endif
+}
+
+static inline unsigned int
+rb_popcount_intptr(uintptr_t x)
+{
+ if (sizeof(uintptr_t) * CHAR_BIT == 64) {
+ return rb_popcount64((uint64_t)x);
+ }
+ else if (sizeof(uintptr_t) * CHAR_BIT == 32) {
+ return rb_popcount32((uint32_t)x);
+ }
+ else {
+ UNREACHABLE_RETURN(~0);
+ }
+}
+
+static inline int
+ntz_int32(uint32_t x)
+{
+#if defined(__x86_64__) && defined(__BMI__)
+ return (unsigned)_tzcnt_u32(x);
+
+#elif MSC_VERSION_SINCE(1400)
+ /* :FIXME: Is there any way to issue TZCNT instead of BSF, apart from using
+ * assembly? Because issuing LZCNT seems possible (see nlz.h). */
+ unsigned long r;
+ return _BitScanForward(&r, x) ? (int)r : 32;
+
+#elif __has_builtin(__builtin_ctz)
+ STATIC_ASSERT(sizeof_int, sizeof(int) * CHAR_BIT == 32);
+ return x ? (unsigned)__builtin_ctz(x) : 32;
+
+#else
+ return rb_popcount32((~x) & (x-1));
+
+#endif
+}
+
+static inline int
+ntz_int64(uint64_t x)
+{
+#if defined(__x86_64__) && defined(__BMI__)
+ return (unsigned)_tzcnt_u64(x);
+
+#elif defined(_WIN64) && MSC_VERSION_SINCE(1400)
+ unsigned long r;
+ return _BitScanForward64(&r, x) ? (int)r : 64;
+
+#elif __has_builtin(__builtin_ctzl)
+ if (x == 0) {
+ return 64;
+ }
+ else if (sizeof(long) * CHAR_BIT == 64) {
+ return (unsigned)__builtin_ctzl((unsigned long)x);
+ }
+ else if (sizeof(long long) * CHAR_BIT == 64) {
+ return (unsigned)__builtin_ctzll((unsigned long long)x);
+ }
+ else {
+ /* :FIXME: Is there a way to make this branch a compile-time error? */
+ UNREACHABLE_RETURN(~0);
+ }
+
+#else
+ return rb_popcount64((~x) & (x-1));
+
+#endif
+}
+
+static inline int
+ntz_intptr(uintptr_t x)
+{
+ if (sizeof(uintptr_t) * CHAR_BIT == 64) {
+ return ntz_int64((uint64_t)x);
+ }
+ else if (sizeof(uintptr_t) * CHAR_BIT == 32) {
+ return ntz_int32((uint32_t)x);
+ }
+ else {
+ UNREACHABLE_RETURN(~0);
+ }
+}
+
+static inline VALUE
+RUBY_BIT_ROTL(VALUE v, int n)
+{
+#if __has_builtin(__builtin_rotateleft32) && (SIZEOF_VALUE * CHAR_BIT == 32)
+ return __builtin_rotateleft32(v, n);
+
+#elif __has_builtin(__builtin_rotateleft64) && (SIZEOF_VALUE * CHAR_BIT == 64)
+ return __builtin_rotateleft64(v, n);
+
+#elif MSC_VERSION_SINCE(1310) && (SIZEOF_VALUE * CHAR_BIT == 32)
+ return _rotl(v, n);
+
+#elif MSC_VERSION_SINCE(1310) && (SIZEOF_VALUE * CHAR_BIT == 64)
+ return _rotl64(v, n);
+
+#elif defined(_lrotl) && (SIZEOF_VALUE == SIZEOF_LONG)
+ return _lrotl(v, n);
+
+#else
+ const int m = (sizeof(VALUE) * CHAR_BIT) - 1;
+ return (v << (n & m)) | (v >> (-n & m));
+#endif
+}
+
+static inline VALUE
+RUBY_BIT_ROTR(VALUE v, int n)
+{
+#if __has_builtin(__builtin_rotateright32) && (SIZEOF_VALUE * CHAR_BIT == 32)
+ return __builtin_rotateright32(v, n);
+
+#elif __has_builtin(__builtin_rotateright64) && (SIZEOF_VALUE * CHAR_BIT == 64)
+ return __builtin_rotateright64(v, n);
+
+#elif MSC_VERSION_SINCE(1310) && (SIZEOF_VALUE * CHAR_BIT == 32)
+ return _rotr(v, n);
+
+#elif MSC_VERSION_SINCE(1310) && (SIZEOF_VALUE * CHAR_BIT == 64)
+ return _rotr64(v, n);
+
+#elif defined(_lrotr) && (SIZEOF_VALUE == SIZEOF_LONG)
+ return _lrotr(v, n);
+
+#else
+ const int m = (sizeof(VALUE) * CHAR_BIT) - 1;
+ return (v << (-n & m)) | (v >> (n & m));
+#endif
+}
+
+#endif /* INTERNAL_BITS2_H */
diff --git a/parser_node.h b/parser_node.h
new file mode 100644
index 0000000000..b776486fce
--- /dev/null
+++ b/parser_node.h
@@ -0,0 +1,133 @@
+#ifndef RUBY_PARSER_NODE_H
+#define RUBY_PARSER_NODE_H 1
+/*
+ * This is a header file used by only "parse.y"
+ */
+#include "rubyparser.h"
+#include "internal/compilers.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#if 0
+} /* satisfy cc-mode */
+#endif
+#endif
+
+static inline rb_code_location_t
+code_loc_gen(const rb_code_location_t *loc1, const rb_code_location_t *loc2)
+{
+ rb_code_location_t loc;
+ loc.beg_pos = loc1->beg_pos;
+ loc.end_pos = loc2->end_pos;
+ return loc;
+}
+
+#define RNODE(obj) ((struct RNode *)(obj))
+
+
+#define NEW_NODE(t,a0,a1,a2,loc) rb_node_newnode((t),(VALUE)(a0),(VALUE)(a1),(VALUE)(a2),loc)
+#define NEW_NODE_WITH_LOCALS(t,a1,a2,loc) node_newnode_with_locals(p, (t),(VALUE)(a1),(VALUE)(a2),loc)
+
+#define NEW_DEFN(i,a,d,loc) NEW_NODE(NODE_DEFN,0,i,NEW_SCOPE(a,d,loc),loc)
+#define NEW_DEFS(r,i,a,d,loc) NEW_NODE(NODE_DEFS,r,i,NEW_SCOPE(a,d,loc),loc)
+#define NEW_SCOPE(a,b,loc) NEW_NODE_WITH_LOCALS(NODE_SCOPE,b,a,loc)
+#define NEW_BLOCK(a,loc) NEW_NODE(NODE_BLOCK,a,0,0,loc)
+#define NEW_IF(c,t,e,loc) NEW_NODE(NODE_IF,c,t,e,loc)
+#define NEW_UNLESS(c,t,e,loc) NEW_NODE(NODE_UNLESS,c,t,e,loc)
+#define NEW_CASE(h,b,loc) NEW_NODE(NODE_CASE,h,b,0,loc)
+#define NEW_CASE2(b,loc) NEW_NODE(NODE_CASE2,0,b,0,loc)
+#define NEW_CASE3(h,b,loc) NEW_NODE(NODE_CASE3,h,b,0,loc)
+#define NEW_WHEN(c,t,e,loc) NEW_NODE(NODE_WHEN,c,t,e,loc)
+#define NEW_IN(c,t,e,loc) NEW_NODE(NODE_IN,c,t,e,loc)
+#define NEW_WHILE(c,b,n,loc) NEW_NODE(NODE_WHILE,c,b,n,loc)
+#define NEW_UNTIL(c,b,n,loc) NEW_NODE(NODE_UNTIL,c,b,n,loc)
+#define NEW_FOR(i,b,loc) NEW_NODE(NODE_FOR,0,b,i,loc)
+#define NEW_FOR_MASGN(v,loc) NEW_NODE(NODE_FOR_MASGN,v,0,0,loc)
+#define NEW_ITER(a,b,loc) NEW_NODE(NODE_ITER,0,NEW_SCOPE(a,b,loc),0,loc)
+#define NEW_LAMBDA(a,b,loc) NEW_NODE(NODE_LAMBDA,0,NEW_SCOPE(a,b,loc),0,loc)
+#define NEW_BREAK(s,loc) NEW_NODE(NODE_BREAK,s,0,0,loc)
+#define NEW_NEXT(s,loc) NEW_NODE(NODE_NEXT,s,0,0,loc)
+#define NEW_REDO(loc) NEW_NODE(NODE_REDO,0,0,0,loc)
+#define NEW_RETRY(loc) NEW_NODE(NODE_RETRY,0,0,0,loc)
+#define NEW_BEGIN(b,loc) NEW_NODE(NODE_BEGIN,0,b,0,loc)
+#define NEW_RESCUE(b,res,e,loc) NEW_NODE(NODE_RESCUE,b,res,e,loc)
+#define NEW_RESBODY(a,ex,n,loc) NEW_NODE(NODE_RESBODY,n,ex,a,loc)
+#define NEW_ENSURE(b,en,loc) NEW_NODE(NODE_ENSURE,b,0,en,loc)
+#define NEW_RETURN(s,loc) NEW_NODE(NODE_RETURN,s,0,0,loc)
+#define NEW_YIELD(a,loc) NEW_NODE(NODE_YIELD,a,0,0,loc)
+#define NEW_LIST(a,loc) NEW_NODE(NODE_LIST,a,1,0,loc)
+#define NEW_ZLIST(loc) NEW_NODE(NODE_ZLIST,0,0,0,loc)
+#define NEW_HASH(a,loc) NEW_NODE(NODE_HASH,a,0,0,loc)
+#define NEW_MASGN(l,r,loc) NEW_NODE(NODE_MASGN,l,0,r,loc)
+#define NEW_GASGN(v,val,loc) NEW_NODE(NODE_GASGN,v,val,v,loc)
+#define NEW_LASGN(v,val,loc) NEW_NODE(NODE_LASGN,v,val,0,loc)
+#define NEW_DASGN(v,val,loc) NEW_NODE(NODE_DASGN,v,val,0,loc)
+#define NEW_IASGN(v,val,loc) NEW_NODE(NODE_IASGN,v,val,0,loc)
+#define NEW_CDECL(v,val,path,loc) NEW_NODE(NODE_CDECL,v,val,path,loc)
+#define NEW_CVASGN(v,val,loc) NEW_NODE(NODE_CVASGN,v,val,0,loc)
+#define NEW_OP_ASGN1(p,id,a,loc) NEW_NODE(NODE_OP_ASGN1,p,id,a,loc)
+#define NEW_OP_ASGN2(r,t,i,o,val,loc) NEW_NODE(NODE_OP_ASGN2,r,val,NEW_OP_ASGN22(i,o,t,loc),loc)
+#define NEW_OP_ASGN22(i,o,t,loc) NEW_NODE(NODE_OP_ASGN2,i,o,t,loc)
+#define NEW_OP_ASGN_OR(i,val,loc) NEW_NODE(NODE_OP_ASGN_OR,i,val,0,loc)
+#define NEW_OP_ASGN_AND(i,val,loc) NEW_NODE(NODE_OP_ASGN_AND,i,val,0,loc)
+#define NEW_OP_CDECL(v,op,val,loc) NEW_NODE(NODE_OP_CDECL,v,val,op,loc)
+#define NEW_GVAR(v,loc) NEW_NODE(NODE_GVAR,v,0,v,loc)
+#define NEW_LVAR(v,loc) NEW_NODE(NODE_LVAR,v,0,0,loc)
+#define NEW_DVAR(v,loc) NEW_NODE(NODE_DVAR,v,0,0,loc)
+#define NEW_IVAR(v,loc) NEW_NODE(NODE_IVAR,v,0,0,loc)
+#define NEW_CONST(v,loc) NEW_NODE(NODE_CONST,v,0,0,loc)
+#define NEW_CVAR(v,loc) NEW_NODE(NODE_CVAR,v,0,0,loc)
+#define NEW_NTH_REF(n,loc) NEW_NODE(NODE_NTH_REF,0,n,0,loc)
+#define NEW_BACK_REF(n,loc) NEW_NODE(NODE_BACK_REF,0,n,0,loc)
+#define NEW_MATCH(c,loc) NEW_NODE(NODE_MATCH,c,0,0,loc)
+#define NEW_MATCH2(n1,n2,loc) NEW_NODE(NODE_MATCH2,n1,n2,0,loc)
+#define NEW_MATCH3(r,n2,loc) NEW_NODE(NODE_MATCH3,r,n2,0,loc)
+#define NEW_LIT(l,loc) NEW_NODE(NODE_LIT,l,0,0,loc)
+#define NEW_STR(s,loc) NEW_NODE(NODE_STR,s,0,0,loc)
+#define NEW_DSTR(s,loc) NEW_NODE(NODE_DSTR,s,1,0,loc)
+#define NEW_XSTR(s,loc) NEW_NODE(NODE_XSTR,s,0,0,loc)
+#define NEW_DXSTR(s,loc) NEW_NODE(NODE_DXSTR,s,0,0,loc)
+#define NEW_DSYM(s,loc) NEW_NODE(NODE_DSYM,s,0,0,loc)
+#define NEW_EVSTR(n,loc) NEW_NODE(NODE_EVSTR,0,(n),0,loc)
+#define NEW_CALL(r,m,a,loc) NEW_NODE(NODE_CALL,r,m,a,loc)
+#define NEW_OPCALL(r,m,a,loc) NEW_NODE(NODE_OPCALL,r,m,a,loc)
+#define NEW_FCALL(m,a,loc) NEW_NODE(NODE_FCALL,0,m,a,loc)
+#define NEW_VCALL(m,loc) NEW_NODE(NODE_VCALL,0,m,0,loc)
+#define NEW_SUPER(a,loc) NEW_NODE(NODE_SUPER,0,0,a,loc)
+#define NEW_ZSUPER(loc) NEW_NODE(NODE_ZSUPER,0,0,0,loc)
+#define NEW_ARGS_AUX(r,b,loc) NEW_NODE(NODE_ARGS_AUX,r,b,0,loc)
+#define NEW_OPT_ARG(i,v,loc) NEW_NODE(NODE_OPT_ARG,i,v,0,loc)
+#define NEW_KW_ARG(i,v,loc) NEW_NODE(NODE_KW_ARG,i,v,0,loc)
+#define NEW_POSTARG(i,v,loc) NEW_NODE(NODE_POSTARG,i,v,0,loc)
+#define NEW_ARGSCAT(a,b,loc) NEW_NODE(NODE_ARGSCAT,a,b,0,loc)
+#define NEW_ARGSPUSH(a,b,loc) NEW_NODE(NODE_ARGSPUSH,a,b,0,loc)
+#define NEW_SPLAT(a,loc) NEW_NODE(NODE_SPLAT,a,0,0,loc)
+#define NEW_BLOCK_PASS(b,loc) NEW_NODE(NODE_BLOCK_PASS,0,b,0,loc)
+#define NEW_ALIAS(n,o,loc) NEW_NODE(NODE_ALIAS,n,o,0,loc)
+#define NEW_VALIAS(n,o,loc) NEW_NODE(NODE_VALIAS,n,o,0,loc)
+#define NEW_UNDEF(i,loc) NEW_NODE(NODE_UNDEF,0,i,0,loc)
+#define NEW_CLASS(n,b,s,loc) NEW_NODE(NODE_CLASS,n,NEW_SCOPE(0,b,loc),(s),loc)
+#define NEW_SCLASS(r,b,loc) NEW_NODE(NODE_SCLASS,r,NEW_SCOPE(0,b,loc),0,loc)
+#define NEW_MODULE(n,b,loc) NEW_NODE(NODE_MODULE,n,NEW_SCOPE(0,b,loc),0,loc)
+#define NEW_COLON2(c,i,loc) NEW_NODE(NODE_COLON2,c,i,0,loc)
+#define NEW_COLON3(i,loc) NEW_NODE(NODE_COLON3,0,i,0,loc)
+#define NEW_DOT2(b,e,loc) NEW_NODE(NODE_DOT2,b,e,0,loc)
+#define NEW_DOT3(b,e,loc) NEW_NODE(NODE_DOT3,b,e,0,loc)
+#define NEW_SELF(loc) NEW_NODE(NODE_SELF,0,0,1,loc)
+#define NEW_NIL(loc) NEW_NODE(NODE_NIL,0,0,0,loc)
+#define NEW_TRUE(loc) NEW_NODE(NODE_TRUE,0,0,0,loc)
+#define NEW_FALSE(loc) NEW_NODE(NODE_FALSE,0,0,0,loc)
+#define NEW_ERRINFO(loc) NEW_NODE(NODE_ERRINFO,0,0,0,loc)
+#define NEW_DEFINED(e,loc) NEW_NODE(NODE_DEFINED,e,0,0,loc)
+#define NEW_POSTEXE(b,loc) NEW_NODE(NODE_POSTEXE,0,b,0,loc)
+#define NEW_ATTRASGN(r,m,a,loc) NEW_NODE(NODE_ATTRASGN,r,m,a,loc)
+#define NEW_ERROR(loc) NEW_NODE(NODE_ERROR,0,0,0,loc)
+
+#if defined(__cplusplus)
+#if 0
+{ /* satisfy cc-mode */
+#endif
+} /* extern "C" { */
+#endif
+
+#endif /* RUBY_PARSER_NODE_H */
diff --git a/parser_st.c b/parser_st.c
new file mode 100644
index 0000000000..74db6b9b13
--- /dev/null
+++ b/parser_st.c
@@ -0,0 +1,2118 @@
+/* This is a public domain general purpose hash table package
+ originally written by Peter Moore @ UCB.
+
+ The hash table data structures were redesigned and the package was
+ rewritten by Vladimir Makarov <vmakarov@redhat.com>. */
+
+/* The original package implemented classic bucket-based hash tables
+ with entries doubly linked for an access by their insertion order.
+ To decrease pointer chasing and as a consequence to improve a data
+ locality the current implementation is based on storing entries in
+ an array and using hash tables with open addressing. The current
+ entries are more compact in comparison with the original ones and
+ this also improves the data locality.
+
+ The hash table has two arrays called *bins* and *entries*.
+
+ bins:
+ -------
+ | | entries array:
+ |-------| --------------------------------
+ | index | | | entry: | | |
+ |-------| | | | | |
+ | ... | | ... | hash | ... | ... |
+ |-------| | | key | | |
+ | empty | | | record | | |
+ |-------| --------------------------------
+ | ... | ^ ^
+ |-------| |_ entries start |_ entries bound
+ |deleted|
+ -------
+
+ o The entry array contains table entries in the same order as they
+ were inserted.
+
+ When the first entry is deleted, a variable containing index of
+ the current first entry (*entries start*) is changed. In all
+ other cases of the deletion, we just mark the entry as deleted by
+ using a reserved hash value.
+
+ Such organization of the entry storage makes operations of the
+ table shift and the entries traversal very fast.
+
+ o The bins provide access to the entries by their keys. The
+ key hash is mapped to a bin containing *index* of the
+ corresponding entry in the entry array.
+
+ The bin array size is always power of two, it makes mapping very
+ fast by using the corresponding lower bits of the hash.
+ Generally it is not a good idea to ignore some part of the hash.
+ But alternative approach is worse. For example, we could use a
+ modulo operation for mapping and a prime number for the size of
+ the bin array. Unfortunately, the modulo operation for big
+ 64-bit numbers are extremely slow (it takes more than 100 cycles
+ on modern Intel CPUs).
+
+ Still other bits of the hash value are used when the mapping
+ results in a collision. In this case we use a secondary hash
+ value which is a result of a function of the collision bin
+ index and the original hash value. The function choice
+ guarantees that we can traverse all bins and finally find the
+ corresponding bin as after several iterations the function
+ becomes a full cycle linear congruential generator because it
+ satisfies requirements of the Hull-Dobell theorem.
+
+ When an entry is removed from the table besides marking the
+ hash in the corresponding entry described above, we also mark
+ the bin by a special value in order to find entries which had
+ a collision with the removed entries.
+
+ There are two reserved values for the bins. One denotes an
+ empty bin, another one denotes a bin for a deleted entry.
+
+ o The length of the bin array is at least two times more than the
+ entry array length. This keeps the table load factor healthy.
+ The trigger of rebuilding the table is always a case when we can
+ not insert an entry anymore at the entries bound. We could
+ change the entries bound too in case of deletion but than we need
+ a special code to count bins with corresponding deleted entries
+ and reset the bin values when there are too many bins
+ corresponding deleted entries
+
+ Table rebuilding is done by creation of a new entry array and
+ bins of an appropriate size. We also try to reuse the arrays
+ in some cases by compacting the array and removing deleted
+ entries.
+
+ o To save memory very small tables have no allocated arrays
+ bins. We use a linear search for an access by a key.
+
+ o To save more memory we use 8-, 16-, 32- and 64- bit indexes in
+ bins depending on the current hash table size.
+
+ o The implementation takes into account that the table can be
+ rebuilt during hashing or comparison functions. It can happen if
+ the functions are implemented in Ruby and a thread switch occurs
+ during their execution.
+
+ This implementation speeds up the Ruby hash table benchmarks in
+ average by more 40% on Intel Haswell CPU.
+
+*/
+
+#include "parser_st.h"
+#include "parser_bits.h"
+
+#ifndef TRUE
+# define TRUE 1
+#endif
+
+#ifndef FALSE
+# define FALSE 0
+#endif
+
+#define NOT_RUBY 1
+#undef RUBY
+
+#define MEMCPY(tab,p1,p2,type,n) (tab->functions->nonempty_memcpy((p1), (p2), sizeof(type), (n)))
+
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <string.h>
+#include <assert.h>
+
+#ifdef __GNUC__
+#define PREFETCH(addr, write_p) __builtin_prefetch(addr, write_p)
+#define EXPECT(expr, val) __builtin_expect(expr, val)
+#define ATTRIBUTE_UNUSED __attribute__((unused))
+#else
+#define PREFETCH(addr, write_p)
+#define EXPECT(expr, val) (expr)
+#define ATTRIBUTE_UNUSED
+#endif
+
+
+#define st_index_t parser_st_index_t
+#define st_hash_t parser_st_hash_t
+#define st_data_t parser_st_data_t
+#define st_hash_type parser_st_hash_type
+#define st_table parser_st_table
+#define st_table_entry parser_st_table_entry
+#define st_update_callback_func parser_st_update_callback_func
+#define st_foreach_check_callback_func parser_st_foreach_check_callback_func
+#define st_foreach_callback_func parser_st_foreach_callback_func
+#define st_retval parser_st_retval
+
+#define ST_CONTINUE ST2_CONTINUE
+#define ST_STOP ST2_STOP
+#define ST_DELETE ST2_DELETE
+#define ST_CHECK ST2_CHECK
+#define ST_REPLACE ST2_REPLACE
+
+#define st_numcmp rb_parser_st_numcmp
+#define st_numhash rb_parser_st_numhash
+#define st_free_table rb_parser_st_free_table
+#define rb_st_hash_start rb_parser_st_hash_start
+#define st_delete rb_parser_st_delete
+#define st_foreach rb_parser_st_foreach
+#define st_init_numtable rb_parser_st_init_numtable
+#define st_init_table_with_size rb_parser_st_init_table_with_size
+#define st_insert rb_parser_st_insert
+#define st_lookup rb_parser_st_lookup
+
+#define st_table_size rb_parser_st_table_size
+#define st_clear rb_parser_st_clear
+#define st_init_strtable rb_parser_st_init_strtable
+#define st_init_table rb_parser_st_init_table
+#define st_init_strcasetable rb_parser_st_init_strcasetable
+#define st_init_strtable_with_size rb_parser_st_init_strtable_with_size
+#define st_init_numtable_with_size rb_parser_st_init_numtable_with_size
+#define st_init_strcasetable_with_size rb_parser_st_init_strcasetable_with_size
+#define st_memsize rb_parser_st_memsize
+#define st_get_key rb_parser_st_get_key
+#define st_add_direct rb_parser_st_add_direct
+#define st_insert2 rb_parser_st_insert2
+#define st_copy rb_parser_st_copy
+#define st_delete_safe rb_parser_st_delete_safe
+#define st_shift rb_parser_st_shift
+#define st_cleanup_safe rb_parser_st_cleanup_safe
+#define st_update rb_parser_st_update
+#define st_foreach_with_replace rb_parser_st_foreach_with_replace
+#define st_foreach_check rb_parser_st_foreach_check
+#define st_keys rb_parser_st_keys
+#define st_keys_check rb_parser_st_keys_check
+#define st_values rb_parser_st_values
+#define st_values_check rb_parser_st_values_check
+#define st_hash rb_parser_st_hash
+#define st_hash_uint32 rb_parser_st_hash_uint32
+#define st_hash_uint rb_parser_st_hash_uint
+#define st_hash_end rb_parser_st_hash_end
+#define st_locale_insensitive_strcasecmp rb_parser_st_locale_insensitive_strcasecmp
+#define st_locale_insensitive_strncasecmp rb_parser_st_locale_insensitive_strncasecmp
+
+/* The type of hashes. */
+typedef st_index_t st_hash_t;
+
+struct st_table_entry {
+ st_hash_t hash;
+ st_data_t key;
+ st_data_t record;
+};
+
+#define type_numhash st_hashtype_num
+static const struct st_hash_type st_hashtype_num = {
+ st_numcmp,
+ st_numhash,
+};
+
+static int st_strcmp(st_data_t, st_data_t);
+static st_index_t strhash(st_data_t);
+static const struct st_hash_type type_strhash = {
+ st_strcmp,
+ strhash,
+};
+
+static int st_locale_insensitive_strcasecmp_i(st_data_t lhs, st_data_t rhs);
+static st_index_t strcasehash(st_data_t);
+static const struct st_hash_type type_strcasehash = {
+ st_locale_insensitive_strcasecmp_i,
+ strcasehash,
+};
+
+/* Value used to catch uninitialized entries/bins during debugging.
+ There is a possibility for a false alarm, but its probability is
+ extremely small. */
+#define ST_INIT_VAL 0xafafafafafafafaf
+#define ST_INIT_VAL_BYTE 0xafa
+
+#define EQUAL(tab,x,y) ((x) == (y) || (*(tab)->type->compare)((x),(y)) == 0)
+#define PTR_EQUAL(tab, ptr, hash_val, key_) \
+ ((ptr)->hash == (hash_val) && EQUAL((tab), (key_), (ptr)->key))
+
+/* As PTR_EQUAL only its result is returned in RES. REBUILT_P is set
+ up to TRUE if the table is rebuilt during the comparison. */
+#define DO_PTR_EQUAL_CHECK(tab, ptr, hash_val, key, res, rebuilt_p) \
+ do { \
+ unsigned int _old_rebuilds_num = (tab)->rebuilds_num; \
+ res = PTR_EQUAL(tab, ptr, hash_val, key); \
+ rebuilt_p = _old_rebuilds_num != (tab)->rebuilds_num; \
+ } while (FALSE)
+
+/* Features of a table. */
+struct st_features {
+ /* Power of 2 used for number of allocated entries. */
+ unsigned char entry_power;
+ /* Power of 2 used for number of allocated bins. Depending on the
+ table size, the number of bins is 2-4 times more than the
+ number of entries. */
+ unsigned char bin_power;
+ /* Enumeration of sizes of bins (8-bit, 16-bit etc). */
+ unsigned char size_ind;
+ /* Bins are packed in words of type st_index_t. The following is
+ a size of bins counted by words. */
+ st_index_t bins_words;
+};
+
+/* Features of all possible size tables. */
+#if SIZEOF_ST_INDEX_T == 8
+#define MAX_POWER2 62
+static const struct st_features features[] = {
+ {0, 1, 0, 0x0},
+ {1, 2, 0, 0x1},
+ {2, 3, 0, 0x1},
+ {3, 4, 0, 0x2},
+ {4, 5, 0, 0x4},
+ {5, 6, 0, 0x8},
+ {6, 7, 0, 0x10},
+ {7, 8, 0, 0x20},
+ {8, 9, 1, 0x80},
+ {9, 10, 1, 0x100},
+ {10, 11, 1, 0x200},
+ {11, 12, 1, 0x400},
+ {12, 13, 1, 0x800},
+ {13, 14, 1, 0x1000},
+ {14, 15, 1, 0x2000},
+ {15, 16, 1, 0x4000},
+ {16, 17, 2, 0x10000},
+ {17, 18, 2, 0x20000},
+ {18, 19, 2, 0x40000},
+ {19, 20, 2, 0x80000},
+ {20, 21, 2, 0x100000},
+ {21, 22, 2, 0x200000},
+ {22, 23, 2, 0x400000},
+ {23, 24, 2, 0x800000},
+ {24, 25, 2, 0x1000000},
+ {25, 26, 2, 0x2000000},
+ {26, 27, 2, 0x4000000},
+ {27, 28, 2, 0x8000000},
+ {28, 29, 2, 0x10000000},
+ {29, 30, 2, 0x20000000},
+ {30, 31, 2, 0x40000000},
+ {31, 32, 2, 0x80000000},
+ {32, 33, 3, 0x200000000},
+ {33, 34, 3, 0x400000000},
+ {34, 35, 3, 0x800000000},
+ {35, 36, 3, 0x1000000000},
+ {36, 37, 3, 0x2000000000},
+ {37, 38, 3, 0x4000000000},
+ {38, 39, 3, 0x8000000000},
+ {39, 40, 3, 0x10000000000},
+ {40, 41, 3, 0x20000000000},
+ {41, 42, 3, 0x40000000000},
+ {42, 43, 3, 0x80000000000},
+ {43, 44, 3, 0x100000000000},
+ {44, 45, 3, 0x200000000000},
+ {45, 46, 3, 0x400000000000},
+ {46, 47, 3, 0x800000000000},
+ {47, 48, 3, 0x1000000000000},
+ {48, 49, 3, 0x2000000000000},
+ {49, 50, 3, 0x4000000000000},
+ {50, 51, 3, 0x8000000000000},
+ {51, 52, 3, 0x10000000000000},
+ {52, 53, 3, 0x20000000000000},
+ {53, 54, 3, 0x40000000000000},
+ {54, 55, 3, 0x80000000000000},
+ {55, 56, 3, 0x100000000000000},
+ {56, 57, 3, 0x200000000000000},
+ {57, 58, 3, 0x400000000000000},
+ {58, 59, 3, 0x800000000000000},
+ {59, 60, 3, 0x1000000000000000},
+ {60, 61, 3, 0x2000000000000000},
+ {61, 62, 3, 0x4000000000000000},
+ {62, 63, 3, 0x8000000000000000},
+};
+
+#else
+#define MAX_POWER2 30
+
+static const struct st_features features[] = {
+ {0, 1, 0, 0x1},
+ {1, 2, 0, 0x1},
+ {2, 3, 0, 0x2},
+ {3, 4, 0, 0x4},
+ {4, 5, 0, 0x8},
+ {5, 6, 0, 0x10},
+ {6, 7, 0, 0x20},
+ {7, 8, 0, 0x40},
+ {8, 9, 1, 0x100},
+ {9, 10, 1, 0x200},
+ {10, 11, 1, 0x400},
+ {11, 12, 1, 0x800},
+ {12, 13, 1, 0x1000},
+ {13, 14, 1, 0x2000},
+ {14, 15, 1, 0x4000},
+ {15, 16, 1, 0x8000},
+ {16, 17, 2, 0x20000},
+ {17, 18, 2, 0x40000},
+ {18, 19, 2, 0x80000},
+ {19, 20, 2, 0x100000},
+ {20, 21, 2, 0x200000},
+ {21, 22, 2, 0x400000},
+ {22, 23, 2, 0x800000},
+ {23, 24, 2, 0x1000000},
+ {24, 25, 2, 0x2000000},
+ {25, 26, 2, 0x4000000},
+ {26, 27, 2, 0x8000000},
+ {27, 28, 2, 0x10000000},
+ {28, 29, 2, 0x20000000},
+ {29, 30, 2, 0x40000000},
+ {30, 31, 2, 0x80000000},
+};
+
+#endif
+
+/* The reserved hash value and its substitution. */
+#define RESERVED_HASH_VAL (~(st_hash_t) 0)
+#define RESERVED_HASH_SUBSTITUTION_VAL ((st_hash_t) 0)
+
+/* Return hash value of KEY for table TAB. */
+static inline st_hash_t
+do_hash(st_data_t key, st_table *tab)
+{
+ st_hash_t hash = (st_hash_t)(tab->type->hash)(key);
+
+ /* RESERVED_HASH_VAL is used for a deleted entry. Map it into
+ another value. Such mapping should be extremely rare. */
+ return hash == RESERVED_HASH_VAL ? RESERVED_HASH_SUBSTITUTION_VAL : hash;
+}
+
+/* Power of 2 defining the minimal number of allocated entries. */
+#define MINIMAL_POWER2 2
+
+#if MINIMAL_POWER2 < 2
+#error "MINIMAL_POWER2 should be >= 2"
+#endif
+
+/* If the power2 of the allocated `entries` is less than the following
+ value, don't allocate bins and use a linear search. */
+#define MAX_POWER2_FOR_TABLES_WITHOUT_BINS 4
+
+/* Return smallest n >= MINIMAL_POWER2 such 2^n > SIZE. */
+static int
+get_power2(st_index_t size)
+{
+ unsigned int n = ST_INDEX_BITS - nlz_intptr(size);
+ if (n <= MAX_POWER2)
+ return n < MINIMAL_POWER2 ? MINIMAL_POWER2 : n;
+#ifndef NOT_RUBY
+ /* Ran out of the table entries */
+ rb_raise(rb_eRuntimeError, "st_table too big");
+#endif
+ /* should raise exception */
+ return -1;
+}
+
+/* Return value of N-th bin in array BINS of table with bins size
+ index S. */
+static inline st_index_t
+get_bin(st_index_t *bins, int s, st_index_t n)
+{
+ return (s == 0 ? ((unsigned char *) bins)[n]
+ : s == 1 ? ((unsigned short *) bins)[n]
+ : s == 2 ? ((unsigned int *) bins)[n]
+ : ((st_index_t *) bins)[n]);
+}
+
+/* Set up N-th bin in array BINS of table with bins size index S to
+ value V. */
+static inline void
+set_bin(st_index_t *bins, int s, st_index_t n, st_index_t v)
+{
+ if (s == 0) ((unsigned char *) bins)[n] = (unsigned char) v;
+ else if (s == 1) ((unsigned short *) bins)[n] = (unsigned short) v;
+ else if (s == 2) ((unsigned int *) bins)[n] = (unsigned int) v;
+ else ((st_index_t *) bins)[n] = v;
+}
+
+/* These macros define reserved values for empty table bin and table
+ bin which contains a deleted entry. We will never use such values
+ for an entry index in bins. */
+#define EMPTY_BIN 0
+#define DELETED_BIN 1
+/* Base of a real entry index in the bins. */
+#define ENTRY_BASE 2
+
+/* Mark I-th bin of table TAB as empty, in other words not
+ corresponding to any entry. */
+#define MARK_BIN_EMPTY(tab, i) (set_bin((tab)->bins, get_size_ind(tab), i, EMPTY_BIN))
+
+/* Values used for not found entry and bin with given
+ characteristics. */
+#define UNDEFINED_ENTRY_IND (~(st_index_t) 0)
+#define UNDEFINED_BIN_IND (~(st_index_t) 0)
+
+/* Entry and bin values returned when we found a table rebuild during
+ the search. */
+#define REBUILT_TABLE_ENTRY_IND (~(st_index_t) 1)
+#define REBUILT_TABLE_BIN_IND (~(st_index_t) 1)
+
+/* Mark I-th bin of table TAB as corresponding to a deleted table
+ entry. Update number of entries in the table and number of bins
+ corresponding to deleted entries. */
+#define MARK_BIN_DELETED(tab, i) \
+ do { \
+ set_bin((tab)->bins, get_size_ind(tab), i, DELETED_BIN); \
+ } while (0)
+
+/* Macros to check that value B is used empty bins and bins
+ corresponding deleted entries. */
+#define EMPTY_BIN_P(b) ((b) == EMPTY_BIN)
+#define DELETED_BIN_P(b) ((b) == DELETED_BIN)
+#define EMPTY_OR_DELETED_BIN_P(b) ((b) <= DELETED_BIN)
+
+/* Macros to check empty bins and bins corresponding to deleted
+ entries. Bins are given by their index I in table TAB. */
+#define IND_EMPTY_BIN_P(tab, i) (EMPTY_BIN_P(get_bin((tab)->bins, get_size_ind(tab), i)))
+#define IND_DELETED_BIN_P(tab, i) (DELETED_BIN_P(get_bin((tab)->bins, get_size_ind(tab), i)))
+#define IND_EMPTY_OR_DELETED_BIN_P(tab, i) (EMPTY_OR_DELETED_BIN_P(get_bin((tab)->bins, get_size_ind(tab), i)))
+
+/* Macros for marking and checking deleted entries given by their
+ pointer E_PTR. */
+#define MARK_ENTRY_DELETED(e_ptr) ((e_ptr)->hash = RESERVED_HASH_VAL)
+#define DELETED_ENTRY_P(e_ptr) ((e_ptr)->hash == RESERVED_HASH_VAL)
+
+/* Return bin size index of table TAB. */
+static inline unsigned int
+get_size_ind(const st_table *tab)
+{
+ return tab->size_ind;
+}
+
+/* Return the number of allocated bins of table TAB. */
+static inline st_index_t
+get_bins_num(const st_table *tab)
+{
+ return ((st_index_t) 1)<<tab->bin_power;
+}
+
+/* Return mask for a bin index in table TAB. */
+static inline st_index_t
+bins_mask(const st_table *tab)
+{
+ return get_bins_num(tab) - 1;
+}
+
+/* Return the index of table TAB bin corresponding to
+ HASH_VALUE. */
+static inline st_index_t
+hash_bin(st_hash_t hash_value, st_table *tab)
+{
+ return hash_value & bins_mask(tab);
+}
+
+/* Return the number of allocated entries of table TAB. */
+static inline st_index_t
+get_allocated_entries(const st_table *tab)
+{
+ return ((st_index_t) 1)<<tab->entry_power;
+}
+
+/* Return size of the allocated bins of table TAB. */
+static inline st_index_t
+bins_size(const st_table *tab)
+{
+ return features[tab->entry_power].bins_words * sizeof (st_index_t);
+}
+
+/* Mark all bins of table TAB as empty. */
+static void
+initialize_bins(st_table *tab)
+{
+ memset(tab->bins, 0, bins_size(tab));
+}
+
+/* Make table TAB empty. */
+static void
+make_tab_empty(st_table *tab)
+{
+ tab->num_entries = 0;
+ tab->entries_start = tab->entries_bound = 0;
+ if (tab->bins != NULL)
+ initialize_bins(tab);
+}
+
+#ifdef HASH_LOG
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+static struct {
+ int all, total, num, str, strcase;
+} collision;
+
+/* Flag switching off output of package statistics at the end of
+ program. */
+static int init_st = 0;
+
+/* Output overall number of table searches and collisions into a
+ temporary file. */
+static void
+stat_col(void)
+{
+ char fname[10+sizeof(long)*3];
+ FILE *f;
+ if (!collision.total) return;
+ f = fopen((snprintf(fname, sizeof(fname), "/tmp/col%ld", (long)getpid()), fname), "w");
+ if (f == NULL)
+ return;
+ fprintf(f, "collision: %d / %d (%6.2f)\n", collision.all, collision.total,
+ ((double)collision.all / (collision.total)) * 100);
+ fprintf(f, "num: %d, str: %d, strcase: %d\n", collision.num, collision.str, collision.strcase);
+ fclose(f);
+}
+#endif
+
+/* Create and return table with TYPE which can hold at least SIZE
+ entries. The real number of entries which the table can hold is
+ the nearest power of two for SIZE. */
+st_table *
+st_init_table_with_size(const struct st_hash_type *type, st_functions_t *functions, st_index_t size)
+{
+ st_table *tab;
+ int n;
+
+#ifdef HASH_LOG
+#if HASH_LOG+0 < 0
+ {
+ const char *e = getenv("ST_HASH_LOG");
+ if (!e || !*e) init_st = 1;
+ }
+#endif
+ if (init_st == 0) {
+ init_st = 1;
+ atexit(stat_col);
+ }
+#endif
+
+ n = get_power2(size);
+#ifndef RUBY
+ if (n < 0)
+ return NULL;
+#endif
+ tab = (st_table *) malloc(sizeof (st_table));
+ tab->functions = functions;
+#ifndef RUBY
+ if (tab == NULL)
+ return NULL;
+#endif
+ tab->type = type;
+ tab->entry_power = n;
+ tab->bin_power = features[n].bin_power;
+ tab->size_ind = features[n].size_ind;
+ if (n <= MAX_POWER2_FOR_TABLES_WITHOUT_BINS)
+ tab->bins = NULL;
+ else {
+ tab->bins = (st_index_t *) malloc(bins_size(tab));
+#ifndef RUBY
+ if (tab->bins == NULL) {
+ free(tab);
+ return NULL;
+ }
+#endif
+ }
+ tab->entries = (st_table_entry *) malloc(get_allocated_entries(tab)
+ * sizeof(st_table_entry));
+#ifndef RUBY
+ if (tab->entries == NULL) {
+ st_free_table(tab);
+ return NULL;
+ }
+#endif
+ make_tab_empty(tab);
+ tab->rebuilds_num = 0;
+ return tab;
+}
+
+size_t
+st_table_size(const struct st_table *tbl)
+{
+ return tbl->num_entries;
+}
+
+/* Create and return table with TYPE which can hold a minimal number
+ of entries (see comments for get_power2). */
+st_table *
+st_init_table(const struct st_hash_type *type, st_functions_t *functions)
+{
+ return st_init_table_with_size(type, functions, 0);
+}
+
+/* Create and return table which can hold a minimal number of
+ numbers. */
+st_table *
+st_init_numtable(st_functions_t *functions)
+{
+ return st_init_table(&type_numhash, functions);
+}
+
+/* Create and return table which can hold SIZE numbers. */
+st_table *
+st_init_numtable_with_size(st_functions_t *functions, st_index_t size)
+{
+ return st_init_table_with_size(&type_numhash, functions, size);
+}
+
+/* Create and return table which can hold a minimal number of
+ strings. */
+st_table *
+st_init_strtable(st_functions_t *functions)
+{
+ return st_init_table(&type_strhash, functions);
+}
+
+/* Create and return table which can hold SIZE strings. */
+st_table *
+st_init_strtable_with_size(st_functions_t *functions, st_index_t size)
+{
+ return st_init_table_with_size(&type_strhash, functions, size);
+}
+
+/* Create and return table which can hold a minimal number of strings
+ whose character case is ignored. */
+st_table *
+st_init_strcasetable(st_functions_t *functions)
+{
+ return st_init_table(&type_strcasehash, functions);
+}
+
+/* Create and return table which can hold SIZE strings whose character
+ case is ignored. */
+st_table *
+st_init_strcasetable_with_size(st_functions_t *functions, st_index_t size)
+{
+ return st_init_table_with_size(&type_strcasehash, functions, size);
+}
+
+/* Make table TAB empty. */
+void
+st_clear(st_table *tab)
+{
+ make_tab_empty(tab);
+ tab->rebuilds_num++;
+}
+
+/* Free table TAB space. */
+void
+st_free_table(st_table *tab)
+{
+ if (tab->bins != NULL)
+ free(tab->bins);
+ free(tab->entries);
+ free(tab);
+}
+
+/* Return byte size of memory allocated for table TAB. */
+size_t
+st_memsize(const st_table *tab)
+{
+ return(sizeof(st_table)
+ + (tab->bins == NULL ? 0 : bins_size(tab))
+ + get_allocated_entries(tab) * sizeof(st_table_entry));
+}
+
+static st_index_t
+find_table_entry_ind(st_table *tab, st_hash_t hash_value, st_data_t key);
+
+static st_index_t
+find_table_bin_ind(st_table *tab, st_hash_t hash_value, st_data_t key);
+
+static st_index_t
+find_table_bin_ind_direct(st_table *table, st_hash_t hash_value, st_data_t key);
+
+static st_index_t
+find_table_bin_ptr_and_reserve(st_table *tab, st_hash_t *hash_value,
+ st_data_t key, st_index_t *bin_ind);
+
+#ifdef HASH_LOG
+static void
+count_collision(const struct st_hash_type *type)
+{
+ collision.all++;
+ if (type == &type_numhash) {
+ collision.num++;
+ }
+ else if (type == &type_strhash) {
+ collision.strcase++;
+ }
+ else if (type == &type_strcasehash) {
+ collision.str++;
+ }
+}
+
+#define COLLISION (collision_check ? count_collision(tab->type) : (void)0)
+#define FOUND_BIN (collision_check ? collision.total++ : (void)0)
+#define collision_check 0
+#else
+#define COLLISION
+#define FOUND_BIN
+#endif
+
+/* If the number of entries in the table is at least REBUILD_THRESHOLD
+ times less than the entry array length, decrease the table
+ size. */
+#define REBUILD_THRESHOLD 4
+
+#if REBUILD_THRESHOLD < 2
+#error "REBUILD_THRESHOLD should be >= 2"
+#endif
+
+/* Rebuild table TAB. Rebuilding removes all deleted bins and entries
+ and can change size of the table entries and bins arrays.
+ Rebuilding is implemented by creation of a new table or by
+ compaction of the existing one. */
+static void
+rebuild_table(st_table *tab)
+{
+ st_index_t i, ni;
+ unsigned int size_ind;
+ st_table *new_tab;
+ st_table_entry *new_entries;
+ st_table_entry *curr_entry_ptr;
+ st_index_t *bins;
+ st_index_t bin_ind;
+
+ if ((2 * tab->num_entries <= get_allocated_entries(tab)
+ && REBUILD_THRESHOLD * tab->num_entries > get_allocated_entries(tab))
+ || tab->num_entries < (1 << MINIMAL_POWER2)) {
+ /* Compaction: */
+ tab->num_entries = 0;
+ if (tab->bins != NULL)
+ initialize_bins(tab);
+ new_tab = tab;
+ new_entries = tab->entries;
+ }
+ else {
+ /* This allocation could trigger GC and compaction. If tab is the
+ * gen_iv_tbl, then tab could have changed in size due to objects being
+ * freed and/or moved. Do not store attributes of tab before this line. */
+ new_tab = st_init_table_with_size(tab->type, tab->functions,
+ 2 * tab->num_entries - 1);
+ new_entries = new_tab->entries;
+ }
+
+ ni = 0;
+ bins = new_tab->bins;
+ size_ind = get_size_ind(new_tab);
+ st_index_t bound = tab->entries_bound;
+ st_table_entry *entries = tab->entries;
+
+ for (i = tab->entries_start; i < bound; i++) {
+ curr_entry_ptr = &entries[i];
+ PREFETCH(entries + i + 1, 0);
+ if (EXPECT(DELETED_ENTRY_P(curr_entry_ptr), 0))
+ continue;
+ if (&new_entries[ni] != curr_entry_ptr)
+ new_entries[ni] = *curr_entry_ptr;
+ if (EXPECT(bins != NULL, 1)) {
+ bin_ind = find_table_bin_ind_direct(new_tab, curr_entry_ptr->hash,
+ curr_entry_ptr->key);
+ set_bin(bins, size_ind, bin_ind, ni + ENTRY_BASE);
+ }
+ new_tab->num_entries++;
+ ni++;
+ }
+ if (new_tab != tab) {
+ tab->entry_power = new_tab->entry_power;
+ tab->bin_power = new_tab->bin_power;
+ tab->size_ind = new_tab->size_ind;
+ if (tab->bins != NULL)
+ free(tab->bins);
+ tab->bins = new_tab->bins;
+ free(tab->entries);
+ tab->entries = new_tab->entries;
+ free(new_tab);
+ }
+ tab->entries_start = 0;
+ tab->entries_bound = tab->num_entries;
+ tab->rebuilds_num++;
+}
+
+/* Return the next secondary hash index for table TAB using previous
+ index IND and PERTURB. Finally modulo of the function becomes a
+ full *cycle linear congruential generator*, in other words it
+ guarantees traversing all table bins in extreme case.
+
+ According the Hull-Dobell theorem a generator
+ "Xnext = (a*Xprev + c) mod m" is a full cycle generator if and only if
+ o m and c are relatively prime
+ o a-1 is divisible by all prime factors of m
+ o a-1 is divisible by 4 if m is divisible by 4.
+
+ For our case a is 5, c is 1, and m is a power of two. */
+static inline st_index_t
+secondary_hash(st_index_t ind, st_table *tab, st_index_t *perturb)
+{
+ *perturb >>= 11;
+ ind = (ind << 2) + ind + *perturb + 1;
+ return hash_bin(ind, tab);
+}
+
+/* Find an entry with HASH_VALUE and KEY in TABLE using a linear
+ search. Return the index of the found entry in array `entries`.
+ If it is not found, return UNDEFINED_ENTRY_IND. If the table was
+ rebuilt during the search, return REBUILT_TABLE_ENTRY_IND. */
+static inline st_index_t
+find_entry(st_table *tab, st_hash_t hash_value, st_data_t key)
+{
+ int eq_p, rebuilt_p;
+ st_index_t i, bound;
+ st_table_entry *entries;
+
+ bound = tab->entries_bound;
+ entries = tab->entries;
+ for (i = tab->entries_start; i < bound; i++) {
+ DO_PTR_EQUAL_CHECK(tab, &entries[i], hash_value, key, eq_p, rebuilt_p);
+ if (EXPECT(rebuilt_p, 0))
+ return REBUILT_TABLE_ENTRY_IND;
+ if (eq_p)
+ return i;
+ }
+ return UNDEFINED_ENTRY_IND;
+}
+
+/* Use the quadratic probing. The method has a better data locality
+ but more collisions than the current approach. In average it
+ results in a bit slower search. */
+/*#define QUADRATIC_PROBE*/
+
+/* Return index of entry with HASH_VALUE and KEY in table TAB. If
+ there is no such entry, return UNDEFINED_ENTRY_IND. If the table
+ was rebuilt during the search, return REBUILT_TABLE_ENTRY_IND. */
+static st_index_t
+find_table_entry_ind(st_table *tab, st_hash_t hash_value, st_data_t key)
+{
+ int eq_p, rebuilt_p;
+ st_index_t ind;
+#ifdef QUADRATIC_PROBE
+ st_index_t d;
+#else
+ st_index_t perturb;
+#endif
+ st_index_t bin;
+ st_table_entry *entries = tab->entries;
+
+ ind = hash_bin(hash_value, tab);
+#ifdef QUADRATIC_PROBE
+ d = 1;
+#else
+ perturb = hash_value;
+#endif
+ FOUND_BIN;
+ for (;;) {
+ bin = get_bin(tab->bins, get_size_ind(tab), ind);
+ if (! EMPTY_OR_DELETED_BIN_P(bin)) {
+ DO_PTR_EQUAL_CHECK(tab, &entries[bin - ENTRY_BASE], hash_value, key, eq_p, rebuilt_p);
+ if (EXPECT(rebuilt_p, 0))
+ return REBUILT_TABLE_ENTRY_IND;
+ if (eq_p)
+ break;
+ }
+ else if (EMPTY_BIN_P(bin))
+ return UNDEFINED_ENTRY_IND;
+#ifdef QUADRATIC_PROBE
+ ind = hash_bin(ind + d, tab);
+ d++;
+#else
+ ind = secondary_hash(ind, tab, &perturb);
+#endif
+ COLLISION;
+ }
+ return bin;
+}
+
+/* Find and return index of table TAB bin corresponding to an entry
+ with HASH_VALUE and KEY. If there is no such bin, return
+ UNDEFINED_BIN_IND. If the table was rebuilt during the search,
+ return REBUILT_TABLE_BIN_IND. */
+static st_index_t
+find_table_bin_ind(st_table *tab, st_hash_t hash_value, st_data_t key)
+{
+ int eq_p, rebuilt_p;
+ st_index_t ind;
+#ifdef QUADRATIC_PROBE
+ st_index_t d;
+#else
+ st_index_t perturb;
+#endif
+ st_index_t bin;
+ st_table_entry *entries = tab->entries;
+
+ ind = hash_bin(hash_value, tab);
+#ifdef QUADRATIC_PROBE
+ d = 1;
+#else
+ perturb = hash_value;
+#endif
+ FOUND_BIN;
+ for (;;) {
+ bin = get_bin(tab->bins, get_size_ind(tab), ind);
+ if (! EMPTY_OR_DELETED_BIN_P(bin)) {
+ DO_PTR_EQUAL_CHECK(tab, &entries[bin - ENTRY_BASE], hash_value, key, eq_p, rebuilt_p);
+ if (EXPECT(rebuilt_p, 0))
+ return REBUILT_TABLE_BIN_IND;
+ if (eq_p)
+ break;
+ }
+ else if (EMPTY_BIN_P(bin))
+ return UNDEFINED_BIN_IND;
+#ifdef QUADRATIC_PROBE
+ ind = hash_bin(ind + d, tab);
+ d++;
+#else
+ ind = secondary_hash(ind, tab, &perturb);
+#endif
+ COLLISION;
+ }
+ return ind;
+}
+
+/* Find and return index of table TAB bin corresponding to an entry
+ with HASH_VALUE and KEY. The entry should be in the table
+ already. */
+static st_index_t
+find_table_bin_ind_direct(st_table *tab, st_hash_t hash_value, st_data_t key)
+{
+ st_index_t ind;
+#ifdef QUADRATIC_PROBE
+ st_index_t d;
+#else
+ st_index_t perturb;
+#endif
+ st_index_t bin;
+
+ ind = hash_bin(hash_value, tab);
+#ifdef QUADRATIC_PROBE
+ d = 1;
+#else
+ perturb = hash_value;
+#endif
+ FOUND_BIN;
+ for (;;) {
+ bin = get_bin(tab->bins, get_size_ind(tab), ind);
+ if (EMPTY_OR_DELETED_BIN_P(bin))
+ return ind;
+#ifdef QUADRATIC_PROBE
+ ind = hash_bin(ind + d, tab);
+ d++;
+#else
+ ind = secondary_hash(ind, tab, &perturb);
+#endif
+ COLLISION;
+ }
+}
+
+/* Return index of table TAB bin for HASH_VALUE and KEY through
+ BIN_IND and the pointed value as the function result. Reserve the
+ bin for inclusion of the corresponding entry into the table if it
+ is not there yet. We always find such bin as bins array length is
+ bigger entries array. Although we can reuse a deleted bin, the
+ result bin value is always empty if the table has no entry with
+ KEY. Return the entries array index of the found entry or
+ UNDEFINED_ENTRY_IND if it is not found. If the table was rebuilt
+ during the search, return REBUILT_TABLE_ENTRY_IND. */
+static st_index_t
+find_table_bin_ptr_and_reserve(st_table *tab, st_hash_t *hash_value,
+ st_data_t key, st_index_t *bin_ind)
+{
+ int eq_p, rebuilt_p;
+ st_index_t ind;
+ st_hash_t curr_hash_value = *hash_value;
+#ifdef QUADRATIC_PROBE
+ st_index_t d;
+#else
+ st_index_t perturb;
+#endif
+ st_index_t entry_index;
+ st_index_t first_deleted_bin_ind;
+ st_table_entry *entries;
+
+ ind = hash_bin(curr_hash_value, tab);
+#ifdef QUADRATIC_PROBE
+ d = 1;
+#else
+ perturb = curr_hash_value;
+#endif
+ FOUND_BIN;
+ first_deleted_bin_ind = UNDEFINED_BIN_IND;
+ entries = tab->entries;
+ for (;;) {
+ entry_index = get_bin(tab->bins, get_size_ind(tab), ind);
+ if (EMPTY_BIN_P(entry_index)) {
+ tab->num_entries++;
+ entry_index = UNDEFINED_ENTRY_IND;
+ if (first_deleted_bin_ind != UNDEFINED_BIN_IND) {
+ /* We can reuse bin of a deleted entry. */
+ ind = first_deleted_bin_ind;
+ MARK_BIN_EMPTY(tab, ind);
+ }
+ break;
+ }
+ else if (! DELETED_BIN_P(entry_index)) {
+ DO_PTR_EQUAL_CHECK(tab, &entries[entry_index - ENTRY_BASE], curr_hash_value, key, eq_p, rebuilt_p);
+ if (EXPECT(rebuilt_p, 0))
+ return REBUILT_TABLE_ENTRY_IND;
+ if (eq_p)
+ break;
+ }
+ else if (first_deleted_bin_ind == UNDEFINED_BIN_IND)
+ first_deleted_bin_ind = ind;
+#ifdef QUADRATIC_PROBE
+ ind = hash_bin(ind + d, tab);
+ d++;
+#else
+ ind = secondary_hash(ind, tab, &perturb);
+#endif
+ COLLISION;
+ }
+ *bin_ind = ind;
+ return entry_index;
+}
+
+/* Find an entry with KEY in table TAB. Return non-zero if we found
+ it. Set up *RECORD to the found entry record. */
+int
+st_lookup(st_table *tab, st_data_t key, st_data_t *value)
+{
+ st_index_t bin;
+ st_hash_t hash = do_hash(key, tab);
+
+ retry:
+ if (tab->bins == NULL) {
+ bin = find_entry(tab, hash, key);
+ if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
+ goto retry;
+ if (bin == UNDEFINED_ENTRY_IND)
+ return 0;
+ }
+ else {
+ bin = find_table_entry_ind(tab, hash, key);
+ if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
+ goto retry;
+ if (bin == UNDEFINED_ENTRY_IND)
+ return 0;
+ bin -= ENTRY_BASE;
+ }
+ if (value != 0)
+ *value = tab->entries[bin].record;
+ return 1;
+}
+
+/* Find an entry with KEY in table TAB. Return non-zero if we found
+ it. Set up *RESULT to the found table entry key. */
+int
+st_get_key(st_table *tab, st_data_t key, st_data_t *result)
+{
+ st_index_t bin;
+ st_hash_t hash = do_hash(key, tab);
+
+ retry:
+ if (tab->bins == NULL) {
+ bin = find_entry(tab, hash, key);
+ if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
+ goto retry;
+ if (bin == UNDEFINED_ENTRY_IND)
+ return 0;
+ }
+ else {
+ bin = find_table_entry_ind(tab, hash, key);
+ if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
+ goto retry;
+ if (bin == UNDEFINED_ENTRY_IND)
+ return 0;
+ bin -= ENTRY_BASE;
+ }
+ if (result != 0)
+ *result = tab->entries[bin].key;
+ return 1;
+}
+
+/* Check the table and rebuild it if it is necessary. */
+static inline void
+rebuild_table_if_necessary (st_table *tab)
+{
+ st_index_t bound = tab->entries_bound;
+
+ if (bound == get_allocated_entries(tab))
+ rebuild_table(tab);
+}
+
+/* Insert (KEY, VALUE) into table TAB and return zero. If there is
+ already entry with KEY in the table, return nonzero and update
+ the value of the found entry. */
+int
+st_insert(st_table *tab, st_data_t key, st_data_t value)
+{
+ st_table_entry *entry;
+ st_index_t bin;
+ st_index_t ind;
+ st_hash_t hash_value;
+ st_index_t bin_ind;
+ int new_p;
+
+ hash_value = do_hash(key, tab);
+ retry:
+ rebuild_table_if_necessary(tab);
+ if (tab->bins == NULL) {
+ bin = find_entry(tab, hash_value, key);
+ if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
+ goto retry;
+ new_p = bin == UNDEFINED_ENTRY_IND;
+ if (new_p)
+ tab->num_entries++;
+ bin_ind = UNDEFINED_BIN_IND;
+ }
+ else {
+ bin = find_table_bin_ptr_and_reserve(tab, &hash_value,
+ key, &bin_ind);
+ if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
+ goto retry;
+ new_p = bin == UNDEFINED_ENTRY_IND;
+ bin -= ENTRY_BASE;
+ }
+ if (new_p) {
+ ind = tab->entries_bound++;
+ entry = &tab->entries[ind];
+ entry->hash = hash_value;
+ entry->key = key;
+ entry->record = value;
+ if (bin_ind != UNDEFINED_BIN_IND)
+ set_bin(tab->bins, get_size_ind(tab), bin_ind, ind + ENTRY_BASE);
+ return 0;
+ }
+ tab->entries[bin].record = value;
+ return 1;
+}
+
+/* Insert (KEY, VALUE, HASH) into table TAB. The table should not have
+ entry with KEY before the insertion. */
+static inline void
+st_add_direct_with_hash(st_table *tab,
+ st_data_t key, st_data_t value, st_hash_t hash)
+{
+ st_table_entry *entry;
+ st_index_t ind;
+ st_index_t bin_ind;
+
+ rebuild_table_if_necessary(tab);
+ ind = tab->entries_bound++;
+ entry = &tab->entries[ind];
+ entry->hash = hash;
+ entry->key = key;
+ entry->record = value;
+ tab->num_entries++;
+ if (tab->bins != NULL) {
+ bin_ind = find_table_bin_ind_direct(tab, hash, key);
+ set_bin(tab->bins, get_size_ind(tab), bin_ind, ind + ENTRY_BASE);
+ }
+}
+
+/* Insert (KEY, VALUE) into table TAB. The table should not have
+ entry with KEY before the insertion. */
+void
+st_add_direct(st_table *tab, st_data_t key, st_data_t value)
+{
+ st_hash_t hash_value;
+
+ hash_value = do_hash(key, tab);
+ st_add_direct_with_hash(tab, key, value, hash_value);
+}
+
+/* Insert (FUNC(KEY), VALUE) into table TAB and return zero. If
+ there is already entry with KEY in the table, return nonzero and
+ update the value of the found entry. */
+int
+st_insert2(st_table *tab, st_data_t key, st_data_t value,
+ st_data_t (*func)(st_data_t))
+{
+ st_table_entry *entry;
+ st_index_t bin;
+ st_index_t ind;
+ st_hash_t hash_value;
+ st_index_t bin_ind;
+ int new_p;
+
+ hash_value = do_hash(key, tab);
+ retry:
+ rebuild_table_if_necessary (tab);
+ if (tab->bins == NULL) {
+ bin = find_entry(tab, hash_value, key);
+ if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
+ goto retry;
+ new_p = bin == UNDEFINED_ENTRY_IND;
+ if (new_p)
+ tab->num_entries++;
+ bin_ind = UNDEFINED_BIN_IND;
+ }
+ else {
+ bin = find_table_bin_ptr_and_reserve(tab, &hash_value,
+ key, &bin_ind);
+ if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
+ goto retry;
+ new_p = bin == UNDEFINED_ENTRY_IND;
+ bin -= ENTRY_BASE;
+ }
+ if (new_p) {
+ key = (*func)(key);
+ ind = tab->entries_bound++;
+ entry = &tab->entries[ind];
+ entry->hash = hash_value;
+ entry->key = key;
+ entry->record = value;
+ if (bin_ind != UNDEFINED_BIN_IND)
+ set_bin(tab->bins, get_size_ind(tab), bin_ind, ind + ENTRY_BASE);
+ return 0;
+ }
+ tab->entries[bin].record = value;
+ return 1;
+}
+
+/* Create and return a copy of table OLD_TAB. */
+st_table *
+st_copy(st_table *old_tab)
+{
+ st_table *new_tab;
+
+ new_tab = (st_table *) malloc(sizeof(st_table));
+ new_tab->functions = old_tab->functions;
+#ifndef RUBY
+ if (new_tab == NULL)
+ return NULL;
+#endif
+ *new_tab = *old_tab;
+ if (old_tab->bins == NULL)
+ new_tab->bins = NULL;
+ else {
+ new_tab->bins = (st_index_t *) malloc(bins_size(old_tab));
+#ifndef RUBY
+ if (new_tab->bins == NULL) {
+ free(new_tab);
+ return NULL;
+ }
+#endif
+ }
+ new_tab->entries = (st_table_entry *) malloc(get_allocated_entries(old_tab)
+ * sizeof(st_table_entry));
+#ifndef RUBY
+ if (new_tab->entries == NULL) {
+ st_free_table(new_tab);
+ return NULL;
+ }
+#endif
+ MEMCPY(new_tab, new_tab->entries, old_tab->entries, st_table_entry,
+ get_allocated_entries(old_tab));
+ if (old_tab->bins != NULL)
+ MEMCPY(new_tab, new_tab->bins, old_tab->bins, char, bins_size(old_tab));
+ return new_tab;
+}
+
+/* Update the entries start of table TAB after removing an entry
+ with index N in the array entries. */
+static inline void
+update_range_for_deleted(st_table *tab, st_index_t n)
+{
+ /* Do not update entries_bound here. Otherwise, we can fill all
+ bins by deleted entry value before rebuilding the table. */
+ if (tab->entries_start == n) {
+ st_index_t start = n + 1;
+ st_index_t bound = tab->entries_bound;
+ st_table_entry *entries = tab->entries;
+ while (start < bound && DELETED_ENTRY_P(&entries[start])) start++;
+ tab->entries_start = start;
+ }
+}
+
+/* Delete entry with KEY from table TAB, set up *VALUE (unless
+ VALUE is zero) from deleted table entry, and return non-zero. If
+ there is no entry with KEY in the table, clear *VALUE (unless VALUE
+ is zero), and return zero. */
+static int
+st_general_delete(st_table *tab, st_data_t *key, st_data_t *value)
+{
+ st_table_entry *entry;
+ st_index_t bin;
+ st_index_t bin_ind;
+ st_hash_t hash;
+
+ hash = do_hash(*key, tab);
+ retry:
+ if (tab->bins == NULL) {
+ bin = find_entry(tab, hash, *key);
+ if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
+ goto retry;
+ if (bin == UNDEFINED_ENTRY_IND) {
+ if (value != 0) *value = 0;
+ return 0;
+ }
+ }
+ else {
+ bin_ind = find_table_bin_ind(tab, hash, *key);
+ if (EXPECT(bin_ind == REBUILT_TABLE_BIN_IND, 0))
+ goto retry;
+ if (bin_ind == UNDEFINED_BIN_IND) {
+ if (value != 0) *value = 0;
+ return 0;
+ }
+ bin = get_bin(tab->bins, get_size_ind(tab), bin_ind) - ENTRY_BASE;
+ MARK_BIN_DELETED(tab, bin_ind);
+ }
+ entry = &tab->entries[bin];
+ *key = entry->key;
+ if (value != 0) *value = entry->record;
+ MARK_ENTRY_DELETED(entry);
+ tab->num_entries--;
+ update_range_for_deleted(tab, bin);
+ return 1;
+}
+
+int
+st_delete(st_table *tab, st_data_t *key, st_data_t *value)
+{
+ return st_general_delete(tab, key, value);
+}
+
+/* The function and other functions with suffix '_safe' or '_check'
+ are originated from the previous implementation of the hash tables.
+ It was necessary for correct deleting entries during traversing
+ tables. The current implementation permits deletion during
+ traversing without a specific way to do this. */
+int
+st_delete_safe(st_table *tab, st_data_t *key, st_data_t *value,
+ st_data_t never ATTRIBUTE_UNUSED)
+{
+ return st_general_delete(tab, key, value);
+}
+
+/* If table TAB is empty, clear *VALUE (unless VALUE is zero), and
+ return zero. Otherwise, remove the first entry in the table.
+ Return its key through KEY and its record through VALUE (unless
+ VALUE is zero). */
+int
+st_shift(st_table *tab, st_data_t *key, st_data_t *value)
+{
+ st_index_t i, bound;
+ st_index_t bin;
+ st_table_entry *entries, *curr_entry_ptr;
+ st_index_t bin_ind;
+
+ entries = tab->entries;
+ bound = tab->entries_bound;
+ for (i = tab->entries_start; i < bound; i++) {
+ curr_entry_ptr = &entries[i];
+ if (! DELETED_ENTRY_P(curr_entry_ptr)) {
+ st_hash_t entry_hash = curr_entry_ptr->hash;
+ st_data_t entry_key = curr_entry_ptr->key;
+
+ if (value != 0) *value = curr_entry_ptr->record;
+ *key = entry_key;
+ retry:
+ if (tab->bins == NULL) {
+ bin = find_entry(tab, entry_hash, entry_key);
+ if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0)) {
+ entries = tab->entries;
+ goto retry;
+ }
+ curr_entry_ptr = &entries[bin];
+ }
+ else {
+ bin_ind = find_table_bin_ind(tab, entry_hash, entry_key);
+ if (EXPECT(bin_ind == REBUILT_TABLE_BIN_IND, 0)) {
+ entries = tab->entries;
+ goto retry;
+ }
+ curr_entry_ptr = &entries[get_bin(tab->bins, get_size_ind(tab), bin_ind)
+ - ENTRY_BASE];
+ MARK_BIN_DELETED(tab, bin_ind);
+ }
+ MARK_ENTRY_DELETED(curr_entry_ptr);
+ tab->num_entries--;
+ update_range_for_deleted(tab, i);
+ return 1;
+ }
+ }
+ if (value != 0) *value = 0;
+ return 0;
+}
+
+/* See comments for function st_delete_safe. */
+void
+st_cleanup_safe(st_table *tab ATTRIBUTE_UNUSED,
+ st_data_t never ATTRIBUTE_UNUSED)
+{
+}
+
+/* Find entry with KEY in table TAB, call FUNC with pointers to copies
+ of the key and the value of the found entry, and non-zero as the
+ 3rd argument. If the entry is not found, call FUNC with a pointer
+ to KEY, a pointer to zero, and a zero argument. If the call
+ returns ST_CONTINUE, the table will have an entry with key and
+ value returned by FUNC through the 1st and 2nd parameters. If the
+ call of FUNC returns ST_DELETE, the table will not have entry with
+ KEY. The function returns flag of that the entry with KEY was in
+ the table before the call. */
+int
+st_update(st_table *tab, st_data_t key,
+ st_update_callback_func *func, st_data_t arg)
+{
+ st_table_entry *entry = NULL; /* to avoid uninitialized value warning */
+ st_index_t bin = 0; /* Ditto */
+ st_table_entry *entries;
+ st_index_t bin_ind;
+ st_data_t value = 0, old_key;
+ int retval, existing;
+ st_hash_t hash = do_hash(key, tab);
+
+ retry:
+ entries = tab->entries;
+ if (tab->bins == NULL) {
+ bin = find_entry(tab, hash, key);
+ if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
+ goto retry;
+ existing = bin != UNDEFINED_ENTRY_IND;
+ entry = &entries[bin];
+ bin_ind = UNDEFINED_BIN_IND;
+ }
+ else {
+ bin_ind = find_table_bin_ind(tab, hash, key);
+ if (EXPECT(bin_ind == REBUILT_TABLE_BIN_IND, 0))
+ goto retry;
+ existing = bin_ind != UNDEFINED_BIN_IND;
+ if (existing) {
+ bin = get_bin(tab->bins, get_size_ind(tab), bin_ind) - ENTRY_BASE;
+ entry = &entries[bin];
+ }
+ }
+ if (existing) {
+ key = entry->key;
+ value = entry->record;
+ }
+ old_key = key;
+ retval = (*func)(&key, &value, arg, existing);
+ switch (retval) {
+ case ST_CONTINUE:
+ if (! existing) {
+ st_add_direct_with_hash(tab, key, value, hash);
+ break;
+ }
+ if (old_key != key) {
+ entry->key = key;
+ }
+ entry->record = value;
+ break;
+ case ST_DELETE:
+ if (existing) {
+ if (bin_ind != UNDEFINED_BIN_IND)
+ MARK_BIN_DELETED(tab, bin_ind);
+ MARK_ENTRY_DELETED(entry);
+ tab->num_entries--;
+ update_range_for_deleted(tab, bin);
+ }
+ break;
+ }
+ return existing;
+}
+
+/* Traverse all entries in table TAB calling FUNC with current entry
+ key and value and zero. If the call returns ST_STOP, stop
+ traversing. If the call returns ST_DELETE, delete the current
+ entry from the table. In case of ST_CHECK or ST_CONTINUE, continue
+ traversing. The function returns zero unless an error is found.
+ CHECK_P is flag of st_foreach_check call. The behavior is a bit
+ different for ST_CHECK and when the current element is removed
+ during traversing. */
+static inline int
+st_general_foreach(st_table *tab, st_foreach_check_callback_func *func, st_update_callback_func *replace, st_data_t arg,
+ int check_p)
+{
+ st_index_t bin;
+ st_index_t bin_ind;
+ st_table_entry *entries, *curr_entry_ptr;
+ enum st_retval retval;
+ st_index_t i, rebuilds_num;
+ st_hash_t hash;
+ st_data_t key;
+ int error_p, packed_p = tab->bins == NULL;
+
+ entries = tab->entries;
+ /* The bound can change inside the loop even without rebuilding
+ the table, e.g. by an entry insertion. */
+ for (i = tab->entries_start; i < tab->entries_bound; i++) {
+ curr_entry_ptr = &entries[i];
+ if (EXPECT(DELETED_ENTRY_P(curr_entry_ptr), 0))
+ continue;
+ key = curr_entry_ptr->key;
+ rebuilds_num = tab->rebuilds_num;
+ hash = curr_entry_ptr->hash;
+ retval = (*func)(key, curr_entry_ptr->record, arg, 0);
+
+ if (retval == ST_REPLACE && replace) {
+ st_data_t value;
+ value = curr_entry_ptr->record;
+ retval = (*replace)(&key, &value, arg, TRUE);
+ curr_entry_ptr->key = key;
+ curr_entry_ptr->record = value;
+ }
+
+ if (rebuilds_num != tab->rebuilds_num) {
+ retry:
+ entries = tab->entries;
+ packed_p = tab->bins == NULL;
+ if (packed_p) {
+ i = find_entry(tab, hash, key);
+ if (EXPECT(i == REBUILT_TABLE_ENTRY_IND, 0))
+ goto retry;
+ error_p = i == UNDEFINED_ENTRY_IND;
+ }
+ else {
+ i = find_table_entry_ind(tab, hash, key);
+ if (EXPECT(i == REBUILT_TABLE_ENTRY_IND, 0))
+ goto retry;
+ error_p = i == UNDEFINED_ENTRY_IND;
+ i -= ENTRY_BASE;
+ }
+ if (error_p && check_p) {
+ /* call func with error notice */
+ retval = (*func)(0, 0, arg, 1);
+ return 1;
+ }
+ curr_entry_ptr = &entries[i];
+ }
+ switch (retval) {
+ case ST_REPLACE:
+ break;
+ case ST_CONTINUE:
+ break;
+ case ST_CHECK:
+ if (check_p)
+ break;
+ case ST_STOP:
+ return 0;
+ case ST_DELETE: {
+ st_data_t key = curr_entry_ptr->key;
+
+ again:
+ if (packed_p) {
+ bin = find_entry(tab, hash, key);
+ if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
+ goto again;
+ if (bin == UNDEFINED_ENTRY_IND)
+ break;
+ }
+ else {
+ bin_ind = find_table_bin_ind(tab, hash, key);
+ if (EXPECT(bin_ind == REBUILT_TABLE_BIN_IND, 0))
+ goto again;
+ if (bin_ind == UNDEFINED_BIN_IND)
+ break;
+ bin = get_bin(tab->bins, get_size_ind(tab), bin_ind) - ENTRY_BASE;
+ MARK_BIN_DELETED(tab, bin_ind);
+ }
+ curr_entry_ptr = &entries[bin];
+ MARK_ENTRY_DELETED(curr_entry_ptr);
+ tab->num_entries--;
+ update_range_for_deleted(tab, bin);
+ break;
+ }
+ }
+ }
+ return 0;
+}
+
+int
+st_foreach_with_replace(st_table *tab, st_foreach_check_callback_func *func, st_update_callback_func *replace, st_data_t arg)
+{
+ return st_general_foreach(tab, func, replace, arg, TRUE);
+}
+
+struct functor {
+ st_foreach_callback_func *func;
+ st_data_t arg;
+};
+
+static int
+apply_functor(st_data_t k, st_data_t v, st_data_t d, int _)
+{
+ const struct functor *f = (void *)d;
+ return f->func(k, v, f->arg);
+}
+
+int
+st_foreach(st_table *tab, st_foreach_callback_func *func, st_data_t arg)
+{
+ const struct functor f = { func, arg };
+ return st_general_foreach(tab, apply_functor, 0, (st_data_t)&f, FALSE);
+}
+
+/* See comments for function st_delete_safe. */
+int
+st_foreach_check(st_table *tab, st_foreach_check_callback_func *func, st_data_t arg,
+ st_data_t never ATTRIBUTE_UNUSED)
+{
+ return st_general_foreach(tab, func, 0, arg, TRUE);
+}
+
+/* Set up array KEYS by at most SIZE keys of head table TAB entries.
+ Return the number of keys set up in array KEYS. */
+static inline st_index_t
+st_general_keys(st_table *tab, st_data_t *keys, st_index_t size)
+{
+ st_index_t i, bound;
+ st_data_t key, *keys_start, *keys_end;
+ st_table_entry *curr_entry_ptr, *entries = tab->entries;
+
+ bound = tab->entries_bound;
+ keys_start = keys;
+ keys_end = keys + size;
+ for (i = tab->entries_start; i < bound; i++) {
+ if (keys == keys_end)
+ break;
+ curr_entry_ptr = &entries[i];
+ key = curr_entry_ptr->key;
+ if (! DELETED_ENTRY_P(curr_entry_ptr))
+ *keys++ = key;
+ }
+
+ return keys - keys_start;
+}
+
+st_index_t
+st_keys(st_table *tab, st_data_t *keys, st_index_t size)
+{
+ return st_general_keys(tab, keys, size);
+}
+
+/* See comments for function st_delete_safe. */
+st_index_t
+st_keys_check(st_table *tab, st_data_t *keys, st_index_t size,
+ st_data_t never ATTRIBUTE_UNUSED)
+{
+ return st_general_keys(tab, keys, size);
+}
+
+/* Set up array VALUES by at most SIZE values of head table TAB
+ entries. Return the number of values set up in array VALUES. */
+static inline st_index_t
+st_general_values(st_table *tab, st_data_t *values, st_index_t size)
+{
+ st_index_t i, bound;
+ st_data_t *values_start, *values_end;
+ st_table_entry *curr_entry_ptr, *entries = tab->entries;
+
+ values_start = values;
+ values_end = values + size;
+ bound = tab->entries_bound;
+ for (i = tab->entries_start; i < bound; i++) {
+ if (values == values_end)
+ break;
+ curr_entry_ptr = &entries[i];
+ if (! DELETED_ENTRY_P(curr_entry_ptr))
+ *values++ = curr_entry_ptr->record;
+ }
+
+ return values - values_start;
+}
+
+st_index_t
+st_values(st_table *tab, st_data_t *values, st_index_t size)
+{
+ return st_general_values(tab, values, size);
+}
+
+/* See comments for function st_delete_safe. */
+st_index_t
+st_values_check(st_table *tab, st_data_t *values, st_index_t size,
+ st_data_t never ATTRIBUTE_UNUSED)
+{
+ return st_general_values(tab, values, size);
+}
+
+#define FNV1_32A_INIT 0x811c9dc5
+
+/*
+ * 32 bit magic FNV-1a prime
+ */
+#define FNV_32_PRIME 0x01000193
+
+/* __POWERPC__ added to accommodate Darwin case. */
+#ifndef UNALIGNED_WORD_ACCESS
+# if defined(__i386) || defined(__i386__) || defined(_M_IX86) || \
+ defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || \
+ defined(__powerpc64__) || defined(__POWERPC__) || defined(__aarch64__) || \
+ defined(__mc68020__)
+# define UNALIGNED_WORD_ACCESS 1
+# endif
+#endif
+#ifndef UNALIGNED_WORD_ACCESS
+# define UNALIGNED_WORD_ACCESS 0
+#endif
+
+/* This hash function is quite simplified MurmurHash3
+ * Simplification is legal, cause most of magic still happens in finalizator.
+ * And finalizator is almost the same as in MurmurHash3 */
+#define BIG_CONSTANT(x,y) ((st_index_t)(x)<<32|(st_index_t)(y))
+#define ROTL(x,n) ((x)<<(n)|(x)>>(SIZEOF_ST_INDEX_T*CHAR_BIT-(n)))
+
+#if ST_INDEX_BITS <= 32
+#define C1 (st_index_t)0xcc9e2d51
+#define C2 (st_index_t)0x1b873593
+#else
+#define C1 BIG_CONSTANT(0x87c37b91,0x114253d5);
+#define C2 BIG_CONSTANT(0x4cf5ad43,0x2745937f);
+#endif
+
+#if defined(NO_SANITIZE) && RBIMPL_COMPILER_IS(GCC)
+/* GCC warns about unknown sanitizer, which is annoying. */
+# include "internal/warnings.h"
+# undef NO_SANITIZE
+# define NO_SANITIZE(x, y) \
+ COMPILER_WARNING_PUSH; \
+ COMPILER_WARNING_IGNORED(-Wattributes); \
+ __attribute__((__no_sanitize__(x))) y; \
+ COMPILER_WARNING_POP
+#endif
+
+#ifndef NO_SANITIZE
+# define NO_SANITIZE(x, y) y
+#endif
+
+NO_SANITIZE("unsigned-integer-overflow", static inline st_index_t murmur_step(st_index_t h, st_index_t k));
+NO_SANITIZE("unsigned-integer-overflow", static inline st_index_t murmur_finish(st_index_t h));
+NO_SANITIZE("unsigned-integer-overflow", extern st_index_t st_hash(const void *ptr, size_t len, st_index_t h));
+
+static inline st_index_t
+murmur_step(st_index_t h, st_index_t k)
+{
+#if ST_INDEX_BITS <= 32
+#define r1 (17)
+#define r2 (11)
+#else
+#define r1 (33)
+#define r2 (24)
+#endif
+ k *= C1;
+ h ^= ROTL(k, r1);
+ h *= C2;
+ h = ROTL(h, r2);
+ return h;
+}
+#undef r1
+#undef r2
+
+static inline st_index_t
+murmur_finish(st_index_t h)
+{
+#if ST_INDEX_BITS <= 32
+#define r1 (16)
+#define r2 (13)
+#define r3 (16)
+ const st_index_t c1 = 0x85ebca6b;
+ const st_index_t c2 = 0xc2b2ae35;
+#else
+/* values are taken from Mix13 on http://zimbry.blogspot.ru/2011/09/better-bit-mixing-improving-on.html */
+#define r1 (30)
+#define r2 (27)
+#define r3 (31)
+ const st_index_t c1 = BIG_CONSTANT(0xbf58476d,0x1ce4e5b9);
+ const st_index_t c2 = BIG_CONSTANT(0x94d049bb,0x133111eb);
+#endif
+#if ST_INDEX_BITS > 64
+ h ^= h >> 64;
+ h *= c2;
+ h ^= h >> 65;
+#endif
+ h ^= h >> r1;
+ h *= c1;
+ h ^= h >> r2;
+ h *= c2;
+ h ^= h >> r3;
+ return h;
+}
+#undef r1
+#undef r2
+#undef r3
+
+st_index_t
+st_hash(const void *ptr, size_t len, st_index_t h)
+{
+ const char *data = ptr;
+ st_index_t t = 0;
+ size_t l = len;
+
+#define data_at(n) (st_index_t)((unsigned char)data[(n)])
+#define UNALIGNED_ADD_4 UNALIGNED_ADD(2); UNALIGNED_ADD(1); UNALIGNED_ADD(0)
+#if SIZEOF_ST_INDEX_T > 4
+#define UNALIGNED_ADD_8 UNALIGNED_ADD(6); UNALIGNED_ADD(5); UNALIGNED_ADD(4); UNALIGNED_ADD(3); UNALIGNED_ADD_4
+#if SIZEOF_ST_INDEX_T > 8
+#define UNALIGNED_ADD_16 UNALIGNED_ADD(14); UNALIGNED_ADD(13); UNALIGNED_ADD(12); UNALIGNED_ADD(11); \
+ UNALIGNED_ADD(10); UNALIGNED_ADD(9); UNALIGNED_ADD(8); UNALIGNED_ADD(7); UNALIGNED_ADD_8
+#define UNALIGNED_ADD_ALL UNALIGNED_ADD_16
+#endif
+#define UNALIGNED_ADD_ALL UNALIGNED_ADD_8
+#else
+#define UNALIGNED_ADD_ALL UNALIGNED_ADD_4
+#endif
+#undef SKIP_TAIL
+ if (len >= sizeof(st_index_t)) {
+#if !UNALIGNED_WORD_ACCESS
+ int align = (int)((st_data_t)data % sizeof(st_index_t));
+ if (align) {
+ st_index_t d = 0;
+ int sl, sr, pack;
+
+ switch (align) {
+#ifdef WORDS_BIGENDIAN
+# define UNALIGNED_ADD(n) case SIZEOF_ST_INDEX_T - (n) - 1: \
+ t |= data_at(n) << CHAR_BIT*(SIZEOF_ST_INDEX_T - (n) - 2)
+#else
+# define UNALIGNED_ADD(n) case SIZEOF_ST_INDEX_T - (n) - 1: \
+ t |= data_at(n) << CHAR_BIT*(n)
+#endif
+ UNALIGNED_ADD_ALL;
+#undef UNALIGNED_ADD
+ }
+
+#ifdef WORDS_BIGENDIAN
+ t >>= (CHAR_BIT * align) - CHAR_BIT;
+#else
+ t <<= (CHAR_BIT * align);
+#endif
+
+ data += sizeof(st_index_t)-align;
+ len -= sizeof(st_index_t)-align;
+
+ sl = CHAR_BIT * (SIZEOF_ST_INDEX_T-align);
+ sr = CHAR_BIT * align;
+
+ while (len >= sizeof(st_index_t)) {
+ d = *(st_index_t *)data;
+#ifdef WORDS_BIGENDIAN
+ t = (t << sr) | (d >> sl);
+#else
+ t = (t >> sr) | (d << sl);
+#endif
+ h = murmur_step(h, t);
+ t = d;
+ data += sizeof(st_index_t);
+ len -= sizeof(st_index_t);
+ }
+
+ pack = len < (size_t)align ? (int)len : align;
+ d = 0;
+ switch (pack) {
+#ifdef WORDS_BIGENDIAN
+# define UNALIGNED_ADD(n) case (n) + 1: \
+ d |= data_at(n) << CHAR_BIT*(SIZEOF_ST_INDEX_T - (n) - 1)
+#else
+# define UNALIGNED_ADD(n) case (n) + 1: \
+ d |= data_at(n) << CHAR_BIT*(n)
+#endif
+ UNALIGNED_ADD_ALL;
+#undef UNALIGNED_ADD
+ }
+#ifdef WORDS_BIGENDIAN
+ t = (t << sr) | (d >> sl);
+#else
+ t = (t >> sr) | (d << sl);
+#endif
+
+ if (len < (size_t)align) goto skip_tail;
+# define SKIP_TAIL 1
+ h = murmur_step(h, t);
+ data += pack;
+ len -= pack;
+ }
+ else
+#endif
+#ifdef HAVE_BUILTIN___BUILTIN_ASSUME_ALIGNED
+#define aligned_data __builtin_assume_aligned(data, sizeof(st_index_t))
+#else
+#define aligned_data data
+#endif
+ {
+ do {
+ h = murmur_step(h, *(st_index_t *)aligned_data);
+ data += sizeof(st_index_t);
+ len -= sizeof(st_index_t);
+ } while (len >= sizeof(st_index_t));
+ }
+ }
+
+ t = 0;
+ switch (len) {
+#if UNALIGNED_WORD_ACCESS && SIZEOF_ST_INDEX_T <= 8 && CHAR_BIT == 8
+ /* in this case byteorder doesn't really matter */
+#if SIZEOF_ST_INDEX_T > 4
+ case 7: t |= data_at(6) << 48;
+ case 6: t |= data_at(5) << 40;
+ case 5: t |= data_at(4) << 32;
+ case 4:
+ t |= (st_index_t)*(uint32_t*)aligned_data;
+ goto skip_tail;
+# define SKIP_TAIL 1
+#endif
+ case 3: t |= data_at(2) << 16;
+ case 2: t |= data_at(1) << 8;
+ case 1: t |= data_at(0);
+#else
+#ifdef WORDS_BIGENDIAN
+# define UNALIGNED_ADD(n) case (n) + 1: \
+ t |= data_at(n) << CHAR_BIT*(SIZEOF_ST_INDEX_T - (n) - 1)
+#else
+# define UNALIGNED_ADD(n) case (n) + 1: \
+ t |= data_at(n) << CHAR_BIT*(n)
+#endif
+ UNALIGNED_ADD_ALL;
+#undef UNALIGNED_ADD
+#endif
+#ifdef SKIP_TAIL
+ skip_tail:
+#endif
+ h ^= t; h -= ROTL(t, 7);
+ h *= C2;
+ }
+ h ^= l;
+#undef aligned_data
+
+ return murmur_finish(h);
+}
+
+st_index_t
+st_hash_uint32(st_index_t h, uint32_t i)
+{
+ return murmur_step(h, i);
+}
+
+NO_SANITIZE("unsigned-integer-overflow", extern st_index_t st_hash_uint(st_index_t h, st_index_t i));
+st_index_t
+st_hash_uint(st_index_t h, st_index_t i)
+{
+ i += h;
+/* no matter if it is BigEndian or LittleEndian,
+ * we hash just integers */
+#if SIZEOF_ST_INDEX_T*CHAR_BIT > 8*8
+ h = murmur_step(h, i >> 8*8);
+#endif
+ h = murmur_step(h, i);
+ return h;
+}
+
+st_index_t
+st_hash_end(st_index_t h)
+{
+ h = murmur_finish(h);
+ return h;
+}
+
+#undef st_hash_start
+st_index_t
+rb_st_hash_start(st_index_t h)
+{
+ return h;
+}
+
+static st_index_t
+strhash(st_data_t arg)
+{
+ register const char *string = (const char *)arg;
+ return st_hash(string, strlen(string), FNV1_32A_INIT);
+}
+
+int
+st_locale_insensitive_strcasecmp(const char *s1, const char *s2)
+{
+ char c1, c2;
+
+ while (1) {
+ c1 = *s1++;
+ c2 = *s2++;
+ if (c1 == '\0' || c2 == '\0') {
+ if (c1 != '\0') return 1;
+ if (c2 != '\0') return -1;
+ return 0;
+ }
+ if (('A' <= c1) && (c1 <= 'Z')) c1 += 'a' - 'A';
+ if (('A' <= c2) && (c2 <= 'Z')) c2 += 'a' - 'A';
+ if (c1 != c2) {
+ if (c1 > c2)
+ return 1;
+ else
+ return -1;
+ }
+ }
+}
+
+int
+st_locale_insensitive_strncasecmp(const char *s1, const char *s2, size_t n)
+{
+ char c1, c2;
+ size_t i;
+
+ for (i = 0; i < n; i++) {
+ c1 = *s1++;
+ c2 = *s2++;
+ if (c1 == '\0' || c2 == '\0') {
+ if (c1 != '\0') return 1;
+ if (c2 != '\0') return -1;
+ return 0;
+ }
+ if (('A' <= c1) && (c1 <= 'Z')) c1 += 'a' - 'A';
+ if (('A' <= c2) && (c2 <= 'Z')) c2 += 'a' - 'A';
+ if (c1 != c2) {
+ if (c1 > c2)
+ return 1;
+ else
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int
+st_strcmp(st_data_t lhs, st_data_t rhs)
+{
+ const char *s1 = (char *)lhs;
+ const char *s2 = (char *)rhs;
+ return strcmp(s1, s2);
+}
+
+static int
+st_locale_insensitive_strcasecmp_i(st_data_t lhs, st_data_t rhs)
+{
+ const char *s1 = (char *)lhs;
+ const char *s2 = (char *)rhs;
+ return st_locale_insensitive_strcasecmp(s1, s2);
+}
+
+NO_SANITIZE("unsigned-integer-overflow", PUREFUNC(static st_index_t strcasehash(st_data_t)));
+static st_index_t
+strcasehash(st_data_t arg)
+{
+ register const char *string = (const char *)arg;
+ register st_index_t hval = FNV1_32A_INIT;
+
+ /*
+ * FNV-1a hash each octet in the buffer
+ */
+ while (*string) {
+ unsigned int c = (unsigned char)*string++;
+ if ((unsigned int)(c - 'A') <= ('Z' - 'A')) c += 'a' - 'A';
+ hval ^= c;
+
+ /* multiply by the 32 bit FNV magic prime mod 2^32 */
+ hval *= FNV_32_PRIME;
+ }
+ return hval;
+}
+
+int
+st_numcmp(st_data_t x, st_data_t y)
+{
+ return x != y;
+}
+
+st_index_t
+st_numhash(st_data_t n)
+{
+ enum {s1 = 11, s2 = 3};
+ return (st_index_t)((n>>s1|(n<<s2)) ^ (n>>s2));
+}
diff --git a/parser_st.h b/parser_st.h
new file mode 100644
index 0000000000..f22b5def4f
--- /dev/null
+++ b/parser_st.h
@@ -0,0 +1,165 @@
+/* This is a public domain general purpose hash table package
+ originally written by Peter Moore @ UCB.
+
+ The hash table data structures were redesigned and the package was
+ rewritten by Vladimir Makarov <vmakarov@redhat.com>. */
+
+#ifndef RUBY_ST2_H
+#define RUBY_ST2_H 1
+
+#if defined(__cplusplus)
+extern "C" {
+#if 0
+} /* satisfy cc-mode */
+#endif
+#endif
+
+#include <stddef.h>
+#include <stdint.h>
+#include "ruby/config.h"
+#include "ruby/backward/2/long_long.h"
+#include "ruby/defines.h"
+
+RUBY_SYMBOL_EXPORT_BEGIN
+
+#if SIZEOF_LONG == SIZEOF_VOIDP
+typedef unsigned long parser_st_data_t;
+#elif SIZEOF_LONG_LONG == SIZEOF_VOIDP
+typedef unsigned LONG_LONG parser_st_data_t;
+#else
+# error ---->> parser_st.c requires sizeof(void*) == sizeof(long) or sizeof(LONG_LONG) to be compiled. <<----
+#endif
+#define ST2_DATA_T_DEFINED
+
+#ifndef CHAR_BIT
+# ifdef HAVE_LIMITS_H
+# include <limits.h>
+# else
+# define CHAR_BIT 8
+# endif
+#endif
+#ifndef _
+# define _(args) args
+#endif
+#ifndef ANYARGS
+# ifdef __cplusplus
+# define ANYARGS ...
+# else
+# define ANYARGS
+# endif
+#endif
+
+typedef struct parser_st_table parser_st_table;
+
+typedef parser_st_data_t parser_st_index_t;
+
+/* Maximal value of unsigned integer type parser_st_index_t. */
+#define MAX_ST2_INDEX_VAL (~(parser_st_index_t) 0)
+
+typedef int parser_st_compare_func(parser_st_data_t, parser_st_data_t);
+typedef parser_st_index_t parser_st_hash_func(parser_st_data_t);
+
+typedef char st_check_for_sizeof_parser_st_index_t[SIZEOF_VOIDP == (int)sizeof(parser_st_index_t) ? 1 : -1];
+#define SIZEOF_ST_INDEX_T SIZEOF_VOIDP
+
+struct parser_st_hash_type {
+ int (*compare)(parser_st_data_t, parser_st_data_t); /* parser_st_compare_func* */
+ parser_st_index_t (*hash)(parser_st_data_t); /* parser_st_hash_func* */
+};
+
+typedef struct st_functions {
+ void *(*nonempty_memcpy)(void *dest, const void *src, size_t t, size_t n);
+} st_functions_t;
+
+#define ST_INDEX_BITS (SIZEOF_ST_INDEX_T * CHAR_BIT)
+
+#if defined(HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR) && defined(HAVE_BUILTIN___BUILTIN_TYPES_COMPATIBLE_P)
+# define ST2_DATA_COMPATIBLE_P(type) \
+ __builtin_choose_expr(__builtin_types_compatible_p(type, parser_st_data_t), 1, 0)
+#else
+# define ST2_DATA_COMPATIBLE_P(type) 0
+#endif
+
+typedef struct parser_st_table_entry parser_st_table_entry;
+
+struct parser_st_table_entry; /* defined in parser_st.c */
+
+struct parser_st_table {
+ /* Cached features of the table -- see st.c for more details. */
+ unsigned char entry_power, bin_power, size_ind;
+ /* How many times the table was rebuilt. */
+ unsigned int rebuilds_num;
+ const struct parser_st_hash_type *type;
+ /* Number of entries currently in the table. */
+ parser_st_index_t num_entries;
+ /* Array of bins used for access by keys. */
+ parser_st_index_t *bins;
+ /* Start and bound index of entries in array entries.
+ entries_starts and entries_bound are in interval
+ [0,allocated_entries]. */
+ parser_st_index_t entries_start, entries_bound;
+ /* Array of size 2^entry_power. */
+ parser_st_table_entry *entries;
+ st_functions_t *functions;
+};
+
+#define parser_st_is_member(table,key) rb_parser_st_lookup((table),(key),(parser_st_data_t *)0)
+
+enum parser_st_retval {ST2_CONTINUE, ST2_STOP, ST2_DELETE, ST2_CHECK, ST2_REPLACE};
+
+size_t rb_parser_st_table_size(const struct parser_st_table *tbl);
+parser_st_table *rb_parser_st_init_table(const struct parser_st_hash_type *, st_functions_t *);
+parser_st_table *rb_parser_st_init_table_with_size(const struct parser_st_hash_type *, st_functions_t *, parser_st_index_t);
+parser_st_table *rb_parser_st_init_numtable(st_functions_t *);
+parser_st_table *rb_parser_st_init_numtable_with_size(st_functions_t *, parser_st_index_t);
+parser_st_table *rb_parser_st_init_strtable(st_functions_t *);
+parser_st_table *rb_parser_st_init_strtable_with_size(st_functions_t *, parser_st_index_t);
+parser_st_table *rb_parser_st_init_strcasetable(st_functions_t *);
+parser_st_table *rb_parser_st_init_strcasetable_with_size(st_functions_t *, parser_st_index_t);
+int rb_parser_st_delete(parser_st_table *, parser_st_data_t *, parser_st_data_t *); /* returns 0:notfound 1:deleted */
+int rb_parser_st_delete_safe(parser_st_table *, parser_st_data_t *, parser_st_data_t *, parser_st_data_t);
+int rb_parser_st_shift(parser_st_table *, parser_st_data_t *, parser_st_data_t *); /* returns 0:notfound 1:deleted */
+int rb_parser_st_insert(parser_st_table *, parser_st_data_t, parser_st_data_t);
+int rb_parser_st_insert2(parser_st_table *, parser_st_data_t, parser_st_data_t, parser_st_data_t (*)(parser_st_data_t));
+int rb_parser_st_lookup(parser_st_table *, parser_st_data_t, parser_st_data_t *);
+int rb_parser_st_get_key(parser_st_table *, parser_st_data_t, parser_st_data_t *);
+typedef int parser_st_update_callback_func(parser_st_data_t *key, parser_st_data_t *value, parser_st_data_t arg, int existing);
+/* *key may be altered, but must equal to the old key, i.e., the
+ * results of hash() are same and compare() returns 0, otherwise the
+ * behavior is undefined */
+int rb_parser_st_update(parser_st_table *table, parser_st_data_t key, parser_st_update_callback_func *func, parser_st_data_t arg);
+typedef int parser_st_foreach_callback_func(parser_st_data_t, parser_st_data_t, parser_st_data_t);
+typedef int parser_st_foreach_check_callback_func(parser_st_data_t, parser_st_data_t, parser_st_data_t, int);
+int rb_parser_st_foreach_with_replace(parser_st_table *tab, parser_st_foreach_check_callback_func *func, parser_st_update_callback_func *replace, parser_st_data_t arg);
+int rb_parser_st_foreach(parser_st_table *, parser_st_foreach_callback_func *, parser_st_data_t);
+int rb_parser_st_foreach_check(parser_st_table *, parser_st_foreach_check_callback_func *, parser_st_data_t, parser_st_data_t);
+parser_st_index_t rb_parser_st_keys(parser_st_table *table, parser_st_data_t *keys, parser_st_index_t size);
+parser_st_index_t rb_parser_st_keys_check(parser_st_table *table, parser_st_data_t *keys, parser_st_index_t size, parser_st_data_t never);
+parser_st_index_t rb_parser_st_values(parser_st_table *table, parser_st_data_t *values, parser_st_index_t size);
+parser_st_index_t rb_parser_st_values_check(parser_st_table *table, parser_st_data_t *values, parser_st_index_t size, parser_st_data_t never);
+void rb_parser_st_add_direct(parser_st_table *, parser_st_data_t, parser_st_data_t);
+void rb_parser_st_free_table(parser_st_table *);
+void rb_parser_st_cleanup_safe(parser_st_table *, parser_st_data_t);
+void rb_parser_st_clear(parser_st_table *);
+parser_st_table *rb_parser_st_copy(parser_st_table *);
+CONSTFUNC(int rb_parser_st_numcmp(parser_st_data_t, parser_st_data_t));
+CONSTFUNC(parser_st_index_t rb_parser_st_numhash(parser_st_data_t));
+PUREFUNC(int rb_parser_st_locale_insensitive_strcasecmp(const char *s1, const char *s2));
+PUREFUNC(int rb_parser_st_locale_insensitive_strncasecmp(const char *s1, const char *s2, size_t n));
+PUREFUNC(size_t rb_parser_st_memsize(const parser_st_table *));
+PUREFUNC(parser_st_index_t rb_parser_st_hash(const void *ptr, size_t len, parser_st_index_t h));
+CONSTFUNC(parser_st_index_t rb_parser_st_hash_uint32(parser_st_index_t h, uint32_t i));
+CONSTFUNC(parser_st_index_t rb_parser_st_hash_uint(parser_st_index_t h, parser_st_index_t i));
+CONSTFUNC(parser_st_index_t rb_parser_st_hash_end(parser_st_index_t h));
+CONSTFUNC(parser_st_index_t rb_parser_st_hash_start(parser_st_index_t h));
+
+RUBY_SYMBOL_EXPORT_END
+
+#if defined(__cplusplus)
+#if 0
+{ /* satisfy cc-mode */
+#endif
+} /* extern "C" { */
+#endif
+
+#endif /* RUBY_ST2_H */
diff --git a/parser_value.h b/parser_value.h
new file mode 100644
index 0000000000..4fe444e82f
--- /dev/null
+++ b/parser_value.h
@@ -0,0 +1,106 @@
+#ifndef EXTERNAL_VALUE_H
+#define EXTERNAL_VALUE_H
+
+#include "ruby/config.h"
+
+#if defined(__DOXYGEN__)
+
+/**
+ * Type that represents a Ruby object. It is an unsigned integer of some kind,
+ * depending on platforms.
+ *
+ * ```CXX
+ * VALUE value = rb_eval_string("ARGF.readlines.map.with_index");
+ * ```
+ *
+ * @warning ::VALUE is not a pointer.
+ * @warning ::VALUE can be wider than `long`.
+ */
+typedef uintptr_t VALUE;
+
+/**
+ * Type that represents a Ruby identifier such as a variable name.
+ *
+ * ```CXX
+ * ID method = rb_intern("method");
+ * VALUE result = rb_funcall(obj, method, 0);
+ * ```
+ *
+ * @note ::rb_cSymbol is a Ruby-level data type for the same thing.
+ */
+typedef uintptr_t ID;
+
+/**
+ * A signed integer type that has the same width with ::VALUE.
+ *
+ * @internal
+ *
+ * @shyouhei wonders: is it guaranteed that `uintptr_t` and `intptr_t` are the
+ * same width? As far as I read ISO/IEC 9899:2018 section 7.20.1.4 paragraph 1
+ * no such description is given... or defined elsewhere?
+ */
+typedef intptr_t SIGNED_VALUE;
+
+/**
+ * Identical to `sizeof(VALUE)`, except it is a macro that can also be used
+ * inside of preprocessor directives such as `#if`. Handy on occasions.
+ */
+#define SIZEOF_VALUE SIZEOF_UINTPTR_T
+
+/**
+ * @private
+ *
+ * A compile-time constant of type ::VALUE whose value is 0.
+ */
+#define RBIMPL_VALUE_NULL UINTPTR_C(0)
+
+/**
+ * @private
+ *
+ * A compile-time constant of type ::VALUE whose value is 1.
+ */
+#define RBIMPL_VALUE_ONE UINTPTR_C(1)
+
+/**
+ * @private
+ *
+ * Maximum possible value that a ::VALUE can take.
+ */
+#define RBIMPL_VALUE_FULL UINTPTR_MAX
+
+#elif defined HAVE_UINTPTR_T && 0
+typedef uintptr_t VALUE;
+typedef uintptr_t ID;
+# define SIGNED_VALUE intptr_t
+# define SIZEOF_VALUE SIZEOF_UINTPTR_T
+# undef PRI_VALUE_PREFIX
+# define RBIMPL_VALUE_NULL UINTPTR_C(0)
+# define RBIMPL_VALUE_ONE UINTPTR_C(1)
+# define RBIMPL_VALUE_FULL UINTPTR_MAX
+
+#elif SIZEOF_LONG == SIZEOF_VOIDP
+typedef unsigned long VALUE;
+typedef unsigned long ID;
+# define SIGNED_VALUE long
+# define SIZEOF_VALUE SIZEOF_LONG
+# define PRI_VALUE_PREFIX "l"
+# define RBIMPL_VALUE_NULL 0UL
+# define RBIMPL_VALUE_ONE 1UL
+# define RBIMPL_VALUE_FULL ULONG_MAX
+
+#elif SIZEOF_LONG_LONG == SIZEOF_VOIDP
+typedef unsigned LONG_LONG VALUE;
+typedef unsigned LONG_LONG ID;
+# define SIGNED_VALUE LONG_LONG
+# define LONG_LONG_VALUE 1
+# define SIZEOF_VALUE SIZEOF_LONG_LONG
+# define PRI_VALUE_PREFIX PRI_LL_PREFIX
+# define RBIMPL_VALUE_NULL 0ULL
+# define RBIMPL_VALUE_ONE 1ULL
+# define RBIMPL_VALUE_FULL ULLONG_MAX
+
+#else
+# error ---->> ruby requires sizeof(void*) == sizeof(long) or sizeof(LONG_LONG) to be compiled. <<----
+#endif
+
+#endif /* EXTERNAL_VALUE_H */
diff --git a/ruby.c b/ruby.c
index 8716de88ab..f95d193f78 100644
--- a/ruby.c
+++ b/ruby.c
@@ -53,7 +53,7 @@
#include "internal/loadpath.h"
#include "internal/missing.h"
#include "internal/object.h"
-#include "internal/parse.h"
+#include "internal/ruby_parser.h"
#include "internal/variable.h"
#include "ruby/encoding.h"
#include "ruby/thread.h"
diff --git a/ruby_parser.c b/ruby_parser.c
new file mode 100644
index 0000000000..42c267fbdf
--- /dev/null
+++ b/ruby_parser.c
@@ -0,0 +1,983 @@
+/* This is a wrapper for parse.y */
+#ifdef UNIVERSAL_PARSER
+
+#include "internal.h"
+#include "internal/array.h"
+#include "internal/bignum.h"
+#include "internal/compile.h"
+#include "internal/complex.h"
+#include "internal/encoding.h"
+#include "internal/error.h"
+#include "internal/gc.h"
+#include "internal/hash.h"
+#include "internal/io.h"
+#include "internal/parse.h"
+#include "internal/rational.h"
+#include "internal/re.h"
+#include "internal/ruby_parser.h"
+#include "internal/string.h"
+#include "internal/symbol.h"
+#include "internal/thread.h"
+
+#include "ruby/ractor.h"
+#include "ruby/ruby.h"
+#include "ruby/util.h"
+#include "node.h"
+#include "internal.h"
+#include "vm_core.h"
+#include "symbol.h"
+
+struct ruby_parser {
+ rb_parser_t *parser_params;
+};
+
+static void
+parser_mark(void *ptr)
+{
+ struct ruby_parser *parser = (struct ruby_parser*)ptr;
+ rb_ruby_parser_mark(parser->parser_params);
+}
+
+static void
+parser_free(void *ptr)
+{
+ struct ruby_parser *parser = (struct ruby_parser*)ptr;
+ rb_ruby_parser_free(parser->parser_params);
+}
+
+static size_t
+parser_memsize(const void *ptr)
+{
+ struct ruby_parser *parser = (struct ruby_parser*)ptr;
+ return rb_ruby_parser_memsize(parser->parser_params);
+}
+
+static const rb_data_type_t ruby_parser_data_type = {
+ "parser",
+ {
+ parser_mark,
+ parser_free,
+ parser_memsize,
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
+};
+
+static void
+bignum_negate(VALUE b)
+{
+ BIGNUM_NEGATE(b);
+}
+
+static int
+is_ascii_string2(VALUE str)
+{
+ return is_ascii_string(str);
+}
+
+static void
+rational_set_num(VALUE r, VALUE n)
+{
+ RATIONAL_SET_NUM(r, n);
+}
+
+static VALUE
+rational_get_num(VALUE obj)
+{
+ return RRATIONAL(obj)->num;
+}
+
+static void
+rcomplex_set_real(VALUE cmp, VALUE r)
+{
+ RCOMPLEX_SET_REAL(cmp, r);
+}
+
+static void
+rcomplex_set_imag(VALUE cmp, VALUE i)
+{
+ RCOMPLEX_SET_IMAG(cmp, i);
+}
+
+static VALUE
+rcomplex_get_real(VALUE obj)
+{
+ return RCOMPLEX(obj)->real;
+}
+
+static VALUE
+rcomplex_get_imag(VALUE obj)
+{
+ return RCOMPLEX(obj)->imag;
+}
+
+static VALUE
+syntax_error_append(VALUE exc, VALUE file, int line, int column,
+ void *enc, const char *fmt, va_list args)
+{
+ return rb_syntax_error_append(exc, file, line, column, (rb_encoding *)enc, fmt, args);
+}
+
+static int
+vm_keep_script_lines(void)
+{
+ return ruby_vm_keep_script_lines;
+}
+
+static int
+local_defined(ID id, const void *p)
+{
+ return rb_local_defined(id, (const rb_iseq_t *)p);
+}
+
+static int
+dvar_defined(ID id, const void *p)
+{
+ return rb_dvar_defined(id, (const rb_iseq_t *)p);
+}
+
+static bool
+hash_literal_key_p(VALUE k)
+{
+ switch (OBJ_BUILTIN_TYPE(k)) {
+ case T_NODE:
+ return false;
+ default:
+ return true;
+ }
+}
+
+static int
+literal_cmp(VALUE val, VALUE lit)
+{
+ if (val == lit) return 0;
+ if (!hash_literal_key_p(val) || !hash_literal_key_p(lit)) return -1;
+ return rb_iseq_cdhash_cmp(val, lit);
+}
+
+static st_index_t
+literal_hash(VALUE a)
+{
+ if (!hash_literal_key_p(a)) return (st_index_t)a;
+ return rb_iseq_cdhash_hash(a);
+}
+
+static int
+is_usascii_enc(void *enc)
+{
+ return rb_is_usascii_enc((rb_encoding *)enc);
+}
+
+static int
+is_local_id2(ID id)
+{
+ return is_local_id(id);
+}
+
+static int
+is_attrset_id2(ID id)
+{
+ return is_attrset_id(id);
+}
+
+static int
+is_notop_id2(ID id)
+{
+ return is_notop_id(id);
+}
+
+static VALUE
+enc_str_new(const char *ptr, long len, void *enc)
+{
+ return rb_enc_str_new(ptr, len, (rb_encoding *)enc);
+}
+
+static int
+enc_isalnum(OnigCodePoint c, void *enc)
+{
+ return rb_enc_isalnum(c, (rb_encoding *)enc);
+}
+
+static int
+enc_precise_mbclen(const char *p, const char *e, void *enc)
+{
+ return rb_enc_precise_mbclen(p, e, (rb_encoding *)enc);
+}
+
+static int
+mbclen_charfound_p(int len)
+{
+ return MBCLEN_CHARFOUND_P(len);
+}
+
+static const char *
+enc_name(void *enc)
+{
+ return rb_enc_name((rb_encoding *)enc);
+}
+
+static char *
+enc_prev_char(const char *s, const char *p, const char *e, void *enc)
+{
+ return rb_enc_prev_char(s, p, e, (rb_encoding *)enc);
+}
+
+static void *
+enc_get(VALUE obj)
+{
+ return (void *)rb_enc_get(obj);
+}
+
+static int
+enc_asciicompat(void *enc)
+{
+ return rb_enc_asciicompat((rb_encoding *)enc);
+}
+
+static void *
+utf8_encoding(void)
+{
+ return (void *)rb_utf8_encoding();
+}
+
+static VALUE
+enc_associate(VALUE obj, void *enc)
+{
+ return rb_enc_associate(obj, (rb_encoding *)enc);
+}
+
+static void *
+ascii8bit_encoding(void)
+{
+ return (void *)rb_ascii8bit_encoding();
+}
+
+static int
+enc_codelen(int c, void *enc)
+{
+ return rb_enc_codelen(c, (rb_encoding *)enc);
+}
+
+static VALUE
+enc_str_buf_cat(VALUE str, const char *ptr, long len, void *enc)
+{
+ return rb_enc_str_buf_cat(str, ptr, len, (rb_encoding *)enc);
+}
+
+static int
+enc_mbcput(unsigned int c, void *buf, void *enc)
+{
+ return rb_enc_mbcput(c, buf, (rb_encoding *)enc);
+}
+
+static void *
+enc_from_index(int idx)
+{
+ return (void *)rb_enc_from_index(idx);
+}
+
+static int
+enc_isspace(OnigCodePoint c, void *enc)
+{
+ return rb_enc_isspace(c, (rb_encoding *)enc);
+}
+
+static ID
+intern3(const char *name, long len, void *enc)
+{
+ return rb_intern3(name, len, (rb_encoding *)enc);
+}
+
+static void *
+enc_compatible(VALUE str1, VALUE str2)
+{
+ return (void *)rb_enc_compatible(str1, str2);
+}
+
+static VALUE
+enc_from_encoding(void *enc)
+{
+ return rb_enc_from_encoding((rb_encoding *)enc);
+}
+
+static int
+encoding_get(VALUE obj)
+{
+ return ENCODING_GET(obj);
+}
+
+static void
+encoding_set(VALUE obj, int encindex)
+{
+ ENCODING_SET(obj, encindex);
+}
+
+static int
+encoding_is_ascii8bit(VALUE obj)
+{
+ return ENCODING_IS_ASCII8BIT(obj);
+}
+
+static void *
+usascii_encoding(void)
+{
+ return (void *)rb_usascii_encoding();
+}
+
+static int
+enc_symname_type(const char *name, long len, void *enc, unsigned int allowed_attrset)
+{
+ return rb_enc_symname_type(name, len, (rb_encoding *)enc, allowed_attrset);
+}
+
+typedef struct {
+ struct parser_params *parser;
+ rb_encoding *enc;
+ NODE *succ_block;
+ const rb_code_location_t *loc;
+} reg_named_capture_assign_t;
+
+static int
+reg_named_capture_assign_iter(const OnigUChar *name, const OnigUChar *name_end,
+ int back_num, int *back_refs, OnigRegex regex, void *arg0)
+{
+ reg_named_capture_assign_t *arg = (reg_named_capture_assign_t*)arg0;
+ struct parser_params* p = arg->parser;
+ rb_encoding *enc = arg->enc;
+ const rb_code_location_t *loc = arg->loc;
+ long len = name_end - name;
+ const char *s = (const char *)name;
+
+ return rb_reg_named_capture_assign_iter_impl(p, s, len, (void *)enc, &arg->succ_block, loc);
+}
+
+static NODE *
+reg_named_capture_assign(struct parser_params* p, VALUE regexp, const rb_code_location_t *loc)
+{
+ reg_named_capture_assign_t arg;
+
+ arg.parser = p;
+ arg.enc = rb_enc_get(regexp);
+ arg.succ_block = 0;
+ arg.loc = loc;
+ onig_foreach_name(RREGEXP_PTR(regexp), reg_named_capture_assign_iter, &arg);
+
+ if (!arg.succ_block) return 0;
+ return arg.succ_block->nd_next;
+}
+
+static VALUE
+rbool(VALUE v)
+{
+ return RBOOL(v);
+}
+
+static int
+undef_p(VALUE v)
+{
+ return RB_UNDEF_P(v);
+}
+
+static int
+rtest(VALUE obj)
+{
+ return (int)RB_TEST(obj);
+}
+
+static int
+nil_p(VALUE obj)
+{
+ return (int)NIL_P(obj);
+}
+
+static int
+flonum_p(VALUE obj)
+{
+ return (int)RB_FLONUM_P(obj);
+}
+
+static VALUE
+int2fix(long i)
+{
+ return INT2FIX(i);
+}
+
+static int
+script_lines_defined(void)
+{
+ ID script_lines;
+ CONST_ID(script_lines, "SCRIPT_LINES__");
+
+ return rb_const_defined_at(rb_cObject, script_lines);
+}
+
+static VALUE
+script_lines_get(void)
+{
+ ID script_lines;
+ CONST_ID(script_lines, "SCRIPT_LINES__");
+
+ return rb_const_get_at(rb_cObject, script_lines);
+}
+
+static VALUE
+syntax_error_new(void)
+{
+ return rb_class_new_instance(0, 0, rb_eSyntaxError);
+}
+
+static int
+obj_frozen(VALUE obj)
+{
+ return (int)RB_OBJ_FROZEN(obj);
+}
+
+static VALUE
+obj_write(VALUE old, VALUE *slot, VALUE young)
+{
+ return RB_OBJ_WRITE(old, slot, young);
+}
+
+static VALUE
+obj_written(VALUE old, VALUE slot, VALUE young)
+{
+ return RB_OBJ_WRITTEN(old, slot, young);
+}
+
+static VALUE
+default_rs(void)
+{
+ return rb_default_rs;
+}
+
+static VALUE
+rational_raw1(VALUE x)
+{
+ return rb_rational_raw1(x);
+}
+
+static void *
+memmove2(void *dest, const void *src, size_t t, size_t n)
+{
+ return memmove(dest, src, rbimpl_size_mul_or_raise(t, n));
+}
+
+static void *
+nonempty_memcpy(void *dest, const void *src, size_t t, size_t n)
+{
+ return ruby_nonempty_memcpy(dest, src, rbimpl_size_mul_or_raise(t, n));
+}
+
+static VALUE
+ruby_verbose2(void)
+{
+ return ruby_verbose;
+}
+
+static int
+type_p(VALUE obj, int t)
+{
+ return (int)RB_TYPE_P(obj, t);
+}
+
+static int
+fixnum_p(VALUE obj)
+{
+ return (int)RB_FIXNUM_P(obj);
+}
+
+static int
+symbol_p(VALUE obj)
+{
+ return (int)RB_SYMBOL_P(obj);
+}
+
+static void *
+zalloc(size_t elemsiz)
+{
+ return ruby_xcalloc(1, elemsiz);
+}
+
+static VALUE
+new_strterm(VALUE v1, VALUE v2, VALUE v3, VALUE v0, int heredoc)
+{
+ rb_strterm_t *imemo = (rb_strterm_t *)rb_imemo_new(imemo_parser_strterm, v1, v2, v3, v0);
+ if (heredoc) {
+ imemo->flags |= STRTERM_HEREDOC;
+ }
+
+ return (VALUE)imemo;
+}
+
+static int
+strterm_is_heredoc(VALUE strterm)
+{
+ return ((rb_strterm_t *)strterm)->flags & STRTERM_HEREDOC;
+}
+
+static void
+gc_guard(VALUE obj)
+{
+ RB_GC_GUARD(obj);
+}
+
+void
+rb_strterm_mark(VALUE obj)
+{
+ rb_strterm_t *strterm = (rb_strterm_t*)obj;
+ if (RBASIC(obj)->flags & STRTERM_HEREDOC) {
+ rb_strterm_heredoc_t *heredoc = &strterm->u.heredoc;
+ rb_gc_mark(heredoc->lastline);
+ }
+}
+
+static rb_imemo_tmpbuf_t *
+tmpbuf_parser_heap(void *buf, rb_imemo_tmpbuf_t *old_heap, size_t cnt)
+{
+ return rb_imemo_tmpbuf_parser_heap(buf, old_heap, cnt);
+}
+
+static int
+special_const_p(VALUE obj)
+{
+ return (int)RB_SPECIAL_CONST_P(obj);
+}
+
+static int
+builtin_type(VALUE obj)
+{
+ return (int)RB_BUILTIN_TYPE(obj);
+}
+
+static rb_ast_t *
+ast_new(VALUE nb)
+{
+ rb_ast_t *ast = (rb_ast_t *)rb_imemo_new(imemo_ast, 0, 0, 0, nb);
+ return ast;
+}
+
+static VALUE
+static_id2sym(ID id)
+{
+ return (((VALUE)(id)<<RUBY_SPECIAL_SHIFT)|SYMBOL_FLAG);
+}
+
+static long
+str_coderange_scan_restartable(const char *s, const char *e, void *enc, int *cr)
+{
+ return rb_str_coderange_scan_restartable(s, e, (rb_encoding *)enc, cr);
+}
+
+VALUE rb_io_gets_internal(VALUE io);
+extern VALUE rb_mRubyVMFrozenCore;
+VALUE rb_node_case_when_optimizable_literal(const NODE *const node);
+
+void
+rb_parser_config_initialize(rb_parser_config_t *config)
+{
+ config->counter = 0;
+
+ config->st_functions.nonempty_memcpy = nonempty_memcpy;
+
+ config->malloc = ruby_xmalloc;
+ config->calloc = ruby_xcalloc;
+ config->realloc = ruby_xrealloc;
+ config->free = ruby_xfree;
+ config->alloc_n = ruby_xmalloc2;
+ config->alloc = ruby_xmalloc;
+ config->realloc_n = ruby_xrealloc2;
+ config->zalloc = zalloc;
+ config->rb_memmove = memmove2;
+ config->nonempty_memcpy = nonempty_memcpy;
+ config->xmalloc_mul_add = rb_xmalloc_mul_add;
+
+ config->new_strterm = new_strterm;
+ config->strterm_is_heredoc = strterm_is_heredoc;
+ config->tmpbuf_auto_free_pointer = rb_imemo_tmpbuf_auto_free_pointer;
+ config->tmpbuf_set_ptr = rb_imemo_tmpbuf_set_ptr;
+ config->tmpbuf_parser_heap = tmpbuf_parser_heap;
+ config->ast_new = ast_new;
+
+ config->compile_callback = rb_suppress_tracing;
+ config->reg_named_capture_assign = reg_named_capture_assign;
+ config->script_lines_defined = script_lines_defined;
+ config->script_lines_get = script_lines_get;
+
+ config->obj_freeze = rb_obj_freeze;
+ config->obj_hide = rb_obj_hide;
+ config->obj_frozen = obj_frozen;
+ config->type_p = type_p;
+ config->obj_freeze_raw = OBJ_FREEZE_RAW;
+
+ config->fixnum_p = fixnum_p;
+ config->symbol_p = symbol_p;
+
+ config->attr_get = rb_attr_get;
+
+ config->ary_new = rb_ary_new;
+ config->ary_push = rb_ary_push;
+ config->ary_new_from_args = rb_ary_new_from_args;
+ config->ary_pop = rb_ary_pop;
+ config->ary_last = rb_ary_last;
+ config->ary_unshift = rb_ary_unshift;
+ config->ary_new2 = rb_ary_new2;
+ config->ary_entry = rb_ary_entry;
+ config->ary_join = rb_ary_join;
+ config->ary_reverse = rb_ary_reverse;
+ config->ary_clear = rb_ary_clear;
+ config->array_len = rb_array_len;
+ config->array_aref = RARRAY_AREF;
+
+ config->sym_intern_ascii_cstr = rb_sym_intern_ascii_cstr;
+ config->make_temporary_id = rb_make_temporary_id;
+ config->is_local_id = is_local_id2;
+ config->is_attrset_id = is_attrset_id2;
+ config->is_global_name_punct = is_global_name_punct;
+ config->id_type = id_type;
+ config->id_attrset = rb_id_attrset;
+ config->intern = rb_intern;
+ config->intern2 = rb_intern2;
+ config->intern3 = intern3;
+ config->intern_str = rb_intern_str;
+ config->is_notop_id = is_notop_id2;
+ config->enc_symname_type = enc_symname_type;
+ config->str_intern = rb_str_intern;
+ config->id2name = rb_id2name;
+ config->id2str = rb_id2str;
+ config->id2sym = rb_id2sym;
+ config->sym2id = rb_sym2id;
+
+ config->str_catf = rb_str_catf;
+ config->str_cat_cstr = rb_str_cat_cstr;
+ config->str_subseq = rb_str_subseq;
+ config->str_dup = rb_str_dup;
+ config->str_new_frozen = rb_str_new_frozen;
+ config->str_buf_new = rb_str_buf_new;
+ config->str_buf_cat = rb_str_buf_cat;
+ config->str_modify = rb_str_modify;
+ config->str_set_len = rb_str_set_len;
+ config->str_cat = rb_str_cat;
+ config->str_resize = rb_str_resize;
+ config->str_new = rb_str_new;
+ config->str_new_cstr = rb_str_new_cstr;
+ config->fstring = rb_fstring;
+ config->is_ascii_string = is_ascii_string2;
+ config->enc_str_new = enc_str_new;
+ config->enc_str_buf_cat = enc_str_buf_cat;
+ config->str_buf_append = rb_str_buf_append;
+ config->str_vcatf = rb_str_vcatf;
+ config->string_value_cstr = rb_string_value_cstr;
+ config->rb_sprintf = rb_sprintf;
+ config->rstring_ptr = RSTRING_PTR;
+ config->rstring_end = RSTRING_END;
+ config->rstring_len = RSTRING_LEN;
+ config->filesystem_str_new_cstr = rb_filesystem_str_new_cstr;
+ config->obj_as_string = rb_obj_as_string;
+
+ config->hash_clear = rb_hash_clear;
+ config->hash_new = rb_hash_new;
+ config->hash_aset = rb_hash_aset;
+ config->hash_lookup = rb_hash_lookup;
+ config->ident_hash_new = rb_ident_hash_new;
+
+ config->int2fix = int2fix;
+
+ config->bignum_negate = bignum_negate;
+ config->big_norm = rb_big_norm;
+ config->int2big = rb_int2big;
+ config->cstr_to_inum = rb_cstr_to_inum;
+
+ config->float_new = rb_float_new;
+ config->float_value = rb_float_value;
+
+ config->fix2int = rb_fix2int;
+ config->num2int = rb_num2int_inline;
+ config->int_positive_pow = rb_int_positive_pow;
+ config->int2num = rb_int2num_inline;
+ config->fix2long = rb_fix2long;
+
+ config->rational_new = rb_rational_new;
+ config->rational_raw = rb_rational_raw;
+ config->rational_raw1 = rational_raw1;
+ config->rational_set_num = rational_set_num;
+ config->rational_get_num = rational_get_num;
+
+ config->complex_raw = rb_complex_raw;
+ config->rcomplex_set_real = rcomplex_set_real;
+ config->rcomplex_set_imag = rcomplex_set_imag;
+ config->rcomplex_get_real = rcomplex_get_real;
+ config->rcomplex_get_imag = rcomplex_get_imag;
+
+ config->stderr_tty_p = rb_stderr_tty_p;
+ config->write_error_str = rb_write_error_str;
+ config->default_rs = default_rs;
+ config->io_write = rb_io_write;
+ config->io_flush = rb_io_flush;
+ config->io_puts = rb_io_puts;
+ config->io_gets_internal= rb_io_gets_internal;
+
+ config->debug_output_stdout = rb_ractor_stdout;
+ config->debug_output_stderr = rb_ractor_stderr;
+
+ config->is_usascii_enc = is_usascii_enc;
+ config->enc_isalnum = enc_isalnum;
+ config->enc_precise_mbclen = enc_precise_mbclen;
+ config->mbclen_charfound_p = mbclen_charfound_p;
+ config->enc_name = enc_name;
+ config->enc_prev_char = enc_prev_char;
+ config->enc_get = enc_get;
+ config->enc_asciicompat = enc_asciicompat;
+ config->utf8_encoding = utf8_encoding;
+ config->enc_associate = enc_associate;
+ config->ascii8bit_encoding = ascii8bit_encoding;
+ config->enc_codelen = enc_codelen;
+ config->enc_mbcput = enc_mbcput;
+ config->char_to_option_kcode = rb_char_to_option_kcode;
+ config->ascii8bit_encindex = rb_ascii8bit_encindex;
+ config->enc_find_index = rb_enc_find_index;
+ config->enc_from_index = enc_from_index;
+ config->enc_associate_index = rb_enc_associate_index;
+ config->enc_isspace = enc_isspace;
+ config->enc_coderange_7bit = ENC_CODERANGE_7BIT;
+ config->enc_coderange_unknown = ENC_CODERANGE_UNKNOWN;
+ config->enc_compatible = enc_compatible;
+ config->enc_from_encoding = enc_from_encoding;
+ config->encoding_get = encoding_get;
+ config->encoding_set = encoding_set;
+ config->encoding_is_ascii8bit = encoding_is_ascii8bit;
+ config->usascii_encoding = usascii_encoding;
+
+ config->ractor_make_shareable = rb_ractor_make_shareable;
+
+ config->vm_keep_script_lines = vm_keep_script_lines;
+ config->local_defined = local_defined;
+ config->dvar_defined = dvar_defined;
+
+ config->literal_cmp = literal_cmp;
+ config->literal_hash = literal_hash;
+
+ config->builtin_class_name = rb_builtin_class_name;
+ config->syntax_error_append = syntax_error_append;
+ config->raise = rb_raise;
+ config->syntax_error_new = syntax_error_new;
+
+ config->errinfo = rb_errinfo;
+ config->set_errinfo = rb_set_errinfo;
+ config->exc_raise = rb_exc_raise;
+ config->make_exception = rb_make_exception;
+
+ config->sized_xfree = ruby_sized_xfree;
+ config->sized_realloc_n = ruby_sized_realloc_n;
+ config->obj_write = obj_write;
+ config->obj_written = obj_written;
+ config->gc_register_mark_object = rb_gc_register_mark_object;
+ config->gc_guard = gc_guard;
+ config->gc_mark = rb_gc_mark;
+ config->gc_mark_movable = rb_gc_mark_movable;
+ config->gc_location = rb_gc_location;
+
+ config->reg_compile = rb_reg_compile;
+ config->reg_check_preprocess = rb_reg_check_preprocess;
+ config->memcicmp = rb_memcicmp;
+
+ config->compile_warn = rb_compile_warn;
+ config->compile_warning = rb_compile_warning;
+ config->bug = rb_bug;
+ config->fatal = rb_fatal;
+ config->verbose = ruby_verbose2;
+
+ config->make_backtrace = rb_make_backtrace;
+
+ config->scan_hex = ruby_scan_hex;
+ config->scan_oct = ruby_scan_oct;
+ config->scan_digits = ruby_scan_digits;
+ config->strtod = ruby_strtod;
+
+ config->isspace = rb_isspace;
+ config->isascii = rb_isascii;
+ config->iscntrl = rb_iscntrl;
+ config->isalpha = rb_isalpha;
+ config->isdigit = rb_isdigit;
+ config->isalnum = rb_isalnum;
+ config->isxdigit = rb_isxdigit;
+ config->strcasecmp = st_locale_insensitive_strcasecmp;
+ config->strncasecmp = st_locale_insensitive_strncasecmp;
+
+ config->rbool = rbool;
+ config->undef_p = undef_p;
+ config->rtest = rtest;
+ config->nil_p = nil_p;
+ config->flonum_p = flonum_p;
+ config->qnil = Qnil;
+ config->qtrue = Qtrue;
+ config->qfalse = Qfalse;
+ config->qundef = Qundef;
+ config->eArgError = rb_eArgError;
+ config->mRubyVMFrozenCore = rb_mRubyVMFrozenCore;
+ config->long2int = rb_long2int;
+ config->special_const_p = special_const_p;
+ config->builtin_type = builtin_type;
+ config->snprintf = snprintf;
+
+ config->node_case_when_optimizable_literal = rb_node_case_when_optimizable_literal;
+
+ /* For Ripper */
+ config->static_id2sym = static_id2sym;
+ config->str_coderange_scan_restartable = str_coderange_scan_restartable;
+}
+
+VALUE
+rb_parser_new(void)
+{
+ struct ruby_parser *parser;
+ rb_parser_config_t *config;
+ rb_parser_t *parser_params;
+
+ config = rb_ruby_parser_config_new(ruby_xmalloc);
+ rb_parser_config_initialize(config);
+
+ /*
+ * Create parser_params ahead of vparser because
+ * rb_ruby_parser_new can run GC so if create vparser
+ * first, parser_mark tries to mark not initialized parser_params.
+ */
+ parser_params = rb_ruby_parser_new(config);
+ VALUE vparser = TypedData_Make_Struct(0, struct ruby_parser,
+ &ruby_parser_data_type, parser);
+ parser->parser_params = parser_params;
+
+ return vparser;
+}
+
+void
+rb_parser_set_options(VALUE vparser, int print, int loop, int chomp, int split)
+{
+ struct ruby_parser *parser;
+
+ TypedData_Get_Struct(vparser, struct ruby_parser, &ruby_parser_data_type, parser);
+ rb_ruby_parser_set_options(parser->parser_params, print, loop, chomp, split);
+}
+
+VALUE
+rb_parser_set_context(VALUE vparser, const struct rb_iseq_struct *base, int main)
+{
+ struct ruby_parser *parser;
+
+ TypedData_Get_Struct(vparser, struct ruby_parser, &ruby_parser_data_type, parser);
+ rb_ruby_parser_set_context(parser->parser_params, base, main);
+ return vparser;
+}
+
+void
+rb_parser_keep_script_lines(VALUE vparser)
+{
+ struct ruby_parser *parser;
+
+ TypedData_Get_Struct(vparser, struct ruby_parser, &ruby_parser_data_type, parser);
+ rb_ruby_parser_keep_script_lines(parser->parser_params);
+}
+
+void
+rb_parser_error_tolerant(VALUE vparser)
+{
+ struct ruby_parser *parser;
+
+ TypedData_Get_Struct(vparser, struct ruby_parser, &ruby_parser_data_type, parser);
+ rb_ruby_parser_error_tolerant(parser->parser_params);
+}
+
+rb_ast_t*
+rb_parser_compile_file_path(VALUE vparser, VALUE fname, VALUE file, int start)
+{
+ struct ruby_parser *parser;
+ rb_ast_t *ast;
+
+ TypedData_Get_Struct(vparser, struct ruby_parser, &ruby_parser_data_type, parser);
+ ast = rb_ruby_parser_compile_file_path(parser->parser_params, fname, file, start);
+ RB_GC_GUARD(vparser);
+
+ return ast;
+}
+
+void
+rb_parser_keep_tokens(VALUE vparser)
+{
+ struct ruby_parser *parser;
+
+ TypedData_Get_Struct(vparser, struct ruby_parser, &ruby_parser_data_type, parser);
+ rb_ruby_parser_keep_tokens(parser->parser_params);
+}
+
+rb_ast_t*
+rb_parser_compile_generic(VALUE vparser, VALUE (*lex_gets)(VALUE, int), VALUE fname, VALUE input, int start)
+{
+ struct ruby_parser *parser;
+ rb_ast_t *ast;
+
+ TypedData_Get_Struct(vparser, struct ruby_parser, &ruby_parser_data_type, parser);
+ ast = rb_ruby_parser_compile_generic(parser->parser_params, lex_gets, fname, input, start);
+ RB_GC_GUARD(vparser);
+
+ return ast;
+}
+
+rb_ast_t*
+rb_parser_compile_string(VALUE vparser, const char *f, VALUE s, int line)
+{
+ struct ruby_parser *parser;
+ rb_ast_t *ast;
+
+ TypedData_Get_Struct(vparser, struct ruby_parser, &ruby_parser_data_type, parser);
+ ast = rb_ruby_parser_compile_string(parser->parser_params, f, s, line);
+ RB_GC_GUARD(vparser);
+
+ return ast;
+}
+
+rb_ast_t*
+rb_parser_compile_string_path(VALUE vparser, VALUE f, VALUE s, int line)
+{
+ struct ruby_parser *parser;
+ rb_ast_t *ast;
+
+ TypedData_Get_Struct(vparser, struct ruby_parser, &ruby_parser_data_type, parser);
+ ast = rb_ruby_parser_compile_string_path(parser->parser_params, f, s, line);
+ RB_GC_GUARD(vparser);
+
+ return ast;
+}
+
+VALUE
+rb_parser_encoding(VALUE vparser)
+{
+ struct ruby_parser *parser;
+
+ TypedData_Get_Struct(vparser, struct ruby_parser, &ruby_parser_data_type, parser);
+ return rb_ruby_parser_encoding(parser->parser_params);
+}
+
+VALUE
+rb_parser_end_seen_p(VALUE vparser)
+{
+ struct ruby_parser *parser;
+
+ TypedData_Get_Struct(vparser, struct ruby_parser, &ruby_parser_data_type, parser);
+ return RBOOL(rb_ruby_parser_end_seen_p(parser->parser_params));
+}
+
+VALUE
+rb_parser_set_yydebug(VALUE vparser, VALUE flag)
+{
+ struct ruby_parser *parser;
+
+ TypedData_Get_Struct(vparser, struct ruby_parser, &ruby_parser_data_type, parser);
+ rb_ruby_parser_set_yydebug(parser->parser_params, RTEST(flag));
+ return flag;
+}
+
+#else
+
+/* For "ISO C requires a translation unit to contain at least one declaration" */
+void
+rb_parser_dummy(void)
+{}
+#endif
diff --git a/rubyparser.h b/rubyparser.h
new file mode 100644
index 0000000000..c3e3d870e2
--- /dev/null
+++ b/rubyparser.h
@@ -0,0 +1,642 @@
+#ifndef RUBY_RUBYPARSER_H
+#define RUBY_RUBYPARSER_H 1
+/*
+ * This is a header file for librubyparser interface
+ */
+
+#ifdef UNIVERSAL_PARSER
+
+#define rb_encoding void
+#define OnigCodePoint unsigned int
+#include "parser_st.h"
+#include "parser_value.h"
+
+#else
+
+#include "ruby/encoding.h"
+
+#endif
+
+/*
+ * AST Node
+ */
+enum node_type {
+ NODE_SCOPE,
+ NODE_BLOCK,
+ NODE_IF,
+ NODE_UNLESS,
+ NODE_CASE,
+ NODE_CASE2,
+ NODE_CASE3,
+ NODE_WHEN,
+ NODE_IN,
+ NODE_WHILE,
+ NODE_UNTIL,
+ NODE_ITER,
+ NODE_FOR,
+ NODE_FOR_MASGN,
+ NODE_BREAK,
+ NODE_NEXT,
+ NODE_REDO,
+ NODE_RETRY,
+ NODE_BEGIN,
+ NODE_RESCUE,
+ NODE_RESBODY,
+ NODE_ENSURE,
+ NODE_AND,
+ NODE_OR,
+ NODE_MASGN,
+ NODE_LASGN,
+ NODE_DASGN,
+ NODE_GASGN,
+ NODE_IASGN,
+ NODE_CDECL,
+ NODE_CVASGN,
+ NODE_OP_ASGN1,
+ NODE_OP_ASGN2,
+ NODE_OP_ASGN_AND,
+ NODE_OP_ASGN_OR,
+ NODE_OP_CDECL,
+ NODE_CALL,
+ NODE_OPCALL,
+ NODE_FCALL,
+ NODE_VCALL,
+ NODE_QCALL,
+ NODE_SUPER,
+ NODE_ZSUPER,
+ NODE_LIST,
+ NODE_ZLIST,
+ NODE_VALUES,
+ NODE_HASH,
+ NODE_RETURN,
+ NODE_YIELD,
+ NODE_LVAR,
+ NODE_DVAR,
+ NODE_GVAR,
+ NODE_IVAR,
+ NODE_CONST,
+ NODE_CVAR,
+ NODE_NTH_REF,
+ NODE_BACK_REF,
+ NODE_MATCH,
+ NODE_MATCH2,
+ NODE_MATCH3,
+ NODE_LIT,
+ NODE_STR,
+ NODE_DSTR,
+ NODE_XSTR,
+ NODE_DXSTR,
+ NODE_EVSTR,
+ NODE_DREGX,
+ NODE_ONCE,
+ NODE_ARGS,
+ NODE_ARGS_AUX,
+ NODE_OPT_ARG,
+ NODE_KW_ARG,
+ NODE_POSTARG,
+ NODE_ARGSCAT,
+ NODE_ARGSPUSH,
+ NODE_SPLAT,
+ NODE_BLOCK_PASS,
+ NODE_DEFN,
+ NODE_DEFS,
+ NODE_ALIAS,
+ NODE_VALIAS,
+ NODE_UNDEF,
+ NODE_CLASS,
+ NODE_MODULE,
+ NODE_SCLASS,
+ NODE_COLON2,
+ NODE_COLON3,
+ NODE_DOT2,
+ NODE_DOT3,
+ NODE_FLIP2,
+ NODE_FLIP3,
+ NODE_SELF,
+ NODE_NIL,
+ NODE_TRUE,
+ NODE_FALSE,
+ NODE_ERRINFO,
+ NODE_DEFINED,
+ NODE_POSTEXE,
+ NODE_DSYM,
+ NODE_ATTRASGN,
+ NODE_LAMBDA,
+ NODE_ARYPTN,
+ NODE_HSHPTN,
+ NODE_FNDPTN,
+ NODE_ERROR,
+ NODE_LAST
+};
+
+
+#define nd_head u1.node
+#define nd_alen u2.argc
+#define nd_next u3.node
+
+#define nd_cond u1.node
+#define nd_body u2.node
+#define nd_else u3.node
+
+#define nd_resq u2.node
+#define nd_ensr u3.node
+
+#define nd_1st u1.node
+#define nd_2nd u2.node
+
+#define nd_stts u1.node
+
+#define nd_entry u3.id
+#define nd_vid u1.id
+
+#define nd_var u1.node
+#define nd_iter u3.node
+
+#define nd_value u2.node
+#define nd_aid u3.id
+
+#define nd_lit u1.value
+
+#define nd_recv u1.node
+#define nd_mid u2.id
+#define nd_args u3.node
+#define nd_ainfo u3.args
+
+#define nd_defn u3.node
+
+#define nd_cpath u1.node
+#define nd_super u3.node
+
+#define nd_beg u1.node
+#define nd_end u2.node
+#define nd_state u3.state
+
+#define nd_nth u2.argc
+
+#define nd_alias u1.id
+#define nd_orig u2.id
+#define nd_undef u2.node
+
+#define nd_brace u2.argc
+
+#define nd_pconst u1.node
+#define nd_pkwargs u2.node
+#define nd_pkwrestarg u3.node
+
+#define nd_apinfo u3.apinfo
+
+#define nd_fpinfo u3.fpinfo
+
+// for NODE_SCOPE
+#define nd_tbl u1.tbl
+
+// for NODE_ARGS_AUX
+#define nd_pid u1.id
+#define nd_plen u2.argc
+#define nd_cflag u2.id
+
+// for ripper
+#define nd_cval u3.value
+#define nd_rval u2.value
+#define nd_tag u1.id
+
+#ifndef FLEX_ARY_LEN
+/* From internal/compilers.h */
+/* A macro for defining a flexible array, like: VALUE ary[FLEX_ARY_LEN]; */
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+# define FLEX_ARY_LEN /* VALUE ary[]; */
+#elif defined(__GNUC__) && !defined(__STRICT_ANSI__)
+# define FLEX_ARY_LEN 0 /* VALUE ary[0]; */
+#else
+# define FLEX_ARY_LEN 1 /* VALUE ary[1]; */
+#endif
+#endif
+
+typedef struct rb_ast_id_table {
+ int size;
+ ID ids[FLEX_ARY_LEN];
+} rb_ast_id_table_t;
+
+typedef struct rb_code_position_struct {
+ int lineno;
+ int column;
+} rb_code_position_t;
+
+typedef struct rb_code_location_struct {
+ rb_code_position_t beg_pos;
+ rb_code_position_t end_pos;
+} rb_code_location_t;
+
+typedef struct RNode {
+ VALUE flags;
+ union {
+ struct RNode *node;
+ ID id;
+ VALUE value;
+ rb_ast_id_table_t *tbl;
+ } u1;
+ union {
+ struct RNode *node;
+ ID id;
+ long argc;
+ VALUE value;
+ } u2;
+ union {
+ struct RNode *node;
+ ID id;
+ long state;
+ struct rb_args_info *args;
+ struct rb_ary_pattern_info *apinfo;
+ struct rb_fnd_pattern_info *fpinfo;
+ VALUE value;
+ } u3;
+ rb_code_location_t nd_loc;
+ int node_id;
+} NODE;
+
+/* FL : 0..4: T_TYPES, 5: KEEP_WB, 6: PROMOTED, 7: FINALIZE, 8: UNUSED, 9: UNUSED, 10: EXIVAR, 11: FREEZE */
+/* NODE_FL: 0..4: T_TYPES, 5: KEEP_WB, 6: PROMOTED, 7: NODE_FL_NEWLINE,
+ * 8..14: nd_type,
+ * 15..: nd_line
+ */
+#define NODE_FL_NEWLINE (((VALUE)1)<<7)
+
+#define NODE_TYPESHIFT 8
+#define NODE_TYPEMASK (((VALUE)0x7f)<<NODE_TYPESHIFT)
+
+#define nd_type(n) ((int) (((n)->flags & NODE_TYPEMASK)>>NODE_TYPESHIFT))
+#define nd_set_type(n,t) \
+ rb_node_set_type(n, t)
+#define nd_init_type(n,t) \
+ (n)->flags=(((n)->flags&~NODE_TYPEMASK)|((((unsigned long)(t))<<NODE_TYPESHIFT)&NODE_TYPEMASK))
+
+struct rb_args_info {
+ NODE *pre_init;
+ NODE *post_init;
+
+ int pre_args_num; /* count of mandatory pre-arguments */
+ int post_args_num; /* count of mandatory post-arguments */
+
+ ID first_post_arg;
+
+ ID rest_arg;
+ ID block_arg;
+
+ NODE *kw_args;
+ NODE *kw_rest_arg;
+
+ NODE *opt_args;
+ unsigned int no_kwarg: 1;
+ unsigned int ruby2_keywords: 1;
+ unsigned int forwarding: 1;
+
+ VALUE imemo;
+};
+
+struct rb_ary_pattern_info {
+ NODE *pre_args;
+ NODE *rest_arg;
+ NODE *post_args;
+};
+
+struct rb_fnd_pattern_info {
+ NODE *pre_rest_arg;
+ NODE *args;
+ NODE *post_rest_arg;
+};
+
+typedef struct node_buffer_struct node_buffer_t;
+/* T_IMEMO/ast */
+typedef struct rb_ast_body_struct {
+ const NODE *root;
+ VALUE compile_option;
+ VALUE script_lines;
+ // script_lines is either:
+ // - a Fixnum that represents the line count of the original source, or
+ // - an Array that contains the lines of the original source
+} rb_ast_body_t;
+typedef struct rb_ast_struct {
+ VALUE flags;
+ node_buffer_t *node_buffer;
+ rb_ast_body_t body;
+} rb_ast_t;
+
+
+
+/*
+ * Parser Interface
+ */
+
+typedef struct parser_params rb_parser_t;
+typedef struct rb_imemo_tmpbuf_struct rb_imemo_tmpbuf_t;
+
+#ifdef UNIVERSAL_PARSER
+typedef struct rb_parser_config_struct {
+ /*
+ * Reference counter.
+ * This is needed because both parser and ast refer
+ * same config pointer.
+ * We can remove this, once decuple parser and ast from Ruby GC.
+ */
+ int counter;
+
+ /* For parser_st */
+ st_functions_t st_functions;
+
+ /* Memory */
+ void *(*malloc)(size_t size);
+ void *(*calloc)(size_t number, size_t size);
+ void *(*realloc)(void *ptr, size_t newsiz);
+ void (*free)(void *ptr);
+ void *(*alloc_n)(size_t nelems, size_t elemsiz);
+ void *(*alloc)(size_t elemsiz);
+ void *(*realloc_n)(void *ptr, size_t newelems, size_t newsiz);
+ void *(*zalloc)(size_t elemsiz);
+ void *(*rb_memmove)(void *dest, const void *src, size_t t, size_t n);
+ void *(*nonempty_memcpy)(void *dest, const void *src, size_t t, size_t n);
+ void *(*xmalloc_mul_add)(size_t x, size_t y, size_t z);
+
+ /* imemo */
+ // TODO: Should it return `rb_strterm_t *'?
+ VALUE (*new_strterm)(VALUE v1, VALUE v2, VALUE v3, VALUE v0, int heredoc);
+ int (*strterm_is_heredoc)(VALUE strterm);
+ VALUE (*tmpbuf_auto_free_pointer)(void);
+ void *(*tmpbuf_set_ptr)(VALUE v, void *ptr);
+ rb_imemo_tmpbuf_t *(*tmpbuf_parser_heap)(void *buf, rb_imemo_tmpbuf_t *old_heap, size_t cnt);
+ rb_ast_t *(*ast_new)(VALUE nb);
+
+ // VALUE rb_suppress_tracing(VALUE (*func)(VALUE), VALUE arg);
+ VALUE (*compile_callback)(VALUE (*func)(VALUE), VALUE arg);
+ NODE *(*reg_named_capture_assign)(struct parser_params* p, VALUE regexp, const rb_code_location_t *loc);
+ int (*script_lines_defined)(void);
+ VALUE (*script_lines_get)(void);
+
+ /* Object */
+ VALUE (*obj_freeze)(VALUE obj);
+ VALUE (*obj_hide)(VALUE obj);
+ int (*obj_frozen)(VALUE obj);
+ int (*type_p)(VALUE, int);
+ void (*obj_freeze_raw)(VALUE obj);
+
+ int (*fixnum_p)(VALUE);
+ int (*symbol_p)(VALUE);
+
+ /* Variable */
+ VALUE (*attr_get)(VALUE obj, ID id);
+
+ /* Array */
+ VALUE (*ary_new)(void);
+ VALUE (*ary_push)(VALUE ary, VALUE elem);
+ VALUE (*ary_new_from_args)(long n, ...);
+ VALUE (*ary_pop)(VALUE ary);
+ VALUE (*ary_last)(int argc, const VALUE *argv, VALUE ary);
+ VALUE (*ary_unshift)(VALUE ary, VALUE item);
+ VALUE (*ary_new2)(long capa); // ary_new_capa
+ VALUE (*ary_entry)(VALUE ary, long offset);
+ VALUE (*ary_join)(VALUE ary, VALUE sep);
+ VALUE (*ary_reverse)(VALUE ary);
+ VALUE (*ary_clear)(VALUE ary);
+ long (*array_len)(VALUE a);
+ VALUE (*array_aref)(VALUE, long);
+
+ /* Symbol */
+ VALUE (*sym_intern_ascii_cstr)(const char *ptr);
+ ID (*make_temporary_id)(size_t n);
+ int (*is_local_id)(ID);
+ int (*is_attrset_id)(ID);
+ int (*is_global_name_punct)(const int c);
+ int (*id_type)(ID id);
+ ID (*id_attrset)(ID);
+ ID (*intern)(const char *name);
+ ID (*intern2)(const char *name, long len);
+ ID (*intern3)(const char *name, long len, rb_encoding *enc);
+ ID (*intern_str)(VALUE str);
+ int (*is_notop_id)(ID);
+ int (*enc_symname_type)(const char *name, long len, rb_encoding *enc, unsigned int allowed_attrset);
+ VALUE (*str_intern)(VALUE str);
+ const char *(*id2name)(ID id);
+ VALUE (*id2str)(ID id);
+ VALUE (*id2sym)(ID x);
+ ID (*sym2id)(VALUE sym);
+
+ /* String */
+ VALUE (*str_catf)(VALUE str, const char *format, ...);
+ VALUE (*str_cat_cstr)(VALUE str, const char *ptr);
+ VALUE (*str_subseq)(VALUE str, long beg, long len);
+ VALUE (*str_dup)(VALUE str);
+ VALUE (*str_new_frozen)(VALUE orig);
+ VALUE (*str_buf_new)(long capa);
+ VALUE (*str_buf_cat)(VALUE, const char*, long);
+ void (*str_modify)(VALUE str);
+ void (*str_set_len)(VALUE str, long len);
+ VALUE (*str_cat)(VALUE str, const char *ptr, long len);
+ VALUE (*str_resize)(VALUE str, long len);
+ VALUE (*str_new)(const char *ptr, long len);
+ VALUE (*str_new_cstr)(const char *ptr);
+ VALUE (*fstring)(VALUE);
+ int (*is_ascii_string)(VALUE str);
+ VALUE (*enc_str_new)(const char *ptr, long len, rb_encoding *enc);
+ VALUE (*enc_str_buf_cat)(VALUE str, const char *ptr, long len, rb_encoding *enc);
+ VALUE (*str_buf_append)(VALUE str, VALUE str2);
+ VALUE (*str_vcatf)(VALUE str, const char *fmt, va_list ap);
+ char *(*string_value_cstr)(volatile VALUE *ptr);
+ VALUE (*rb_sprintf)(const char *format, ...);
+ char *(*rstring_ptr)(VALUE str);
+ char *(*rstring_end)(VALUE str);
+ long (*rstring_len)(VALUE str);
+ VALUE (*filesystem_str_new_cstr)(const char *ptr);
+ VALUE (*obj_as_string)(VALUE);
+
+ /* Hash */
+ VALUE (*hash_clear)(VALUE hash);
+ VALUE (*hash_new)(void);
+ VALUE (*hash_aset)(VALUE hash, VALUE key, VALUE val);
+ VALUE (*hash_lookup)(VALUE hash, VALUE key);
+ VALUE (*ident_hash_new)(void);
+
+ /* Fixnum */
+ VALUE (*int2fix)(long i);
+
+ /* Bignum */
+ void (*bignum_negate)(VALUE b);
+ VALUE (*big_norm)(VALUE x);
+ VALUE (*int2big)(intptr_t n);
+ VALUE (*cstr_to_inum)(const char *str, int base, int badcheck);
+
+ /* Float */
+ VALUE (*float_new)(double d);
+ double (*float_value)(VALUE v);
+
+ /* Numeric */
+ long (*fix2int)(VALUE val);
+ int (*num2int)(VALUE val);
+ VALUE (*int_positive_pow)(long x, unsigned long y);
+ VALUE (*int2num)(int v);
+ long (*fix2long)(VALUE val);
+
+ /* Rational */
+ VALUE (*rational_new)(VALUE x, VALUE y);
+ VALUE (*rational_raw)(VALUE x, VALUE y);
+ VALUE (*rational_raw1)(VALUE x);
+ void (*rational_set_num)(VALUE r, VALUE n);
+ VALUE (*rational_get_num)(VALUE obj);
+
+ /* Complex */
+ VALUE (*complex_raw)(VALUE x, VALUE y);
+ void (*rcomplex_set_real)(VALUE cmp, VALUE r);
+ void (*rcomplex_set_imag)(VALUE cmp, VALUE i);
+ VALUE (*rcomplex_get_real)(VALUE obj);
+ VALUE (*rcomplex_get_imag)(VALUE obj);
+
+ /* IO */
+ int (*stderr_tty_p)(void);
+ void (*write_error_str)(VALUE mesg);
+ VALUE (*default_rs)(void);
+ VALUE (*io_write)(VALUE io, VALUE str);
+ VALUE (*io_flush)(VALUE io);
+ VALUE (*io_puts)(int argc, const VALUE *argv, VALUE out);
+ VALUE (*io_gets_internal)(VALUE io);
+
+ /* IO (Ractor) */
+ VALUE (*debug_output_stdout)(void);
+ VALUE (*debug_output_stderr)(void);
+
+ /* Encoding */
+ int (*is_usascii_enc)(rb_encoding *enc);
+ int (*enc_isalnum)(OnigCodePoint c, rb_encoding *enc);
+ int (*enc_precise_mbclen)(const char *p, const char *e, rb_encoding *enc);
+ int (*mbclen_charfound_p)(int len);
+ const char *(*enc_name)(rb_encoding *enc);
+ char *(*enc_prev_char)(const char *s, const char *p, const char *e, rb_encoding *enc);
+ rb_encoding* (*enc_get)(VALUE obj);
+ int (*enc_asciicompat)(rb_encoding *enc);
+ rb_encoding *(*utf8_encoding)(void);
+ VALUE (*enc_associate)(VALUE obj, rb_encoding *enc);
+ rb_encoding *(*ascii8bit_encoding)(void);
+ int (*enc_codelen)(int c, rb_encoding *enc);
+ int (*enc_mbcput)(unsigned int c, void *buf, rb_encoding *enc);
+ int (*char_to_option_kcode)(int c, int *option, int *kcode);
+ int (*ascii8bit_encindex)(void);
+ int (*enc_find_index)(const char *name);
+ rb_encoding *(*enc_from_index)(int idx);
+ VALUE (*enc_associate_index)(VALUE obj, int encindex);
+ int (*enc_isspace)(OnigCodePoint c, rb_encoding *enc);
+ int enc_coderange_7bit;
+ int enc_coderange_unknown;
+ rb_encoding *(*enc_compatible)(VALUE str1, VALUE str2);
+ VALUE (*enc_from_encoding)(rb_encoding *enc);
+ int (*encoding_get)(VALUE obj);
+ void (*encoding_set)(VALUE obj, int encindex);
+ int (*encoding_is_ascii8bit)(VALUE obj);
+ rb_encoding *(*usascii_encoding)(void);
+
+ /* Ractor */
+ VALUE (*ractor_make_shareable)(VALUE obj);
+
+ /* Compile */
+ int (*vm_keep_script_lines)(void);
+ // int rb_local_defined(ID id, const rb_iseq_t *iseq);
+ int (*local_defined)(ID, const void*);
+ // int rb_dvar_defined(ID id, const rb_iseq_t *iseq);
+ int (*dvar_defined)(ID, const void*);
+
+ /* Compile (parse.y) */
+ int (*literal_cmp)(VALUE val, VALUE lit);
+ parser_st_index_t (*literal_hash)(VALUE a);
+
+ /* Error (Exception) */
+ const char *(*builtin_class_name)(VALUE x);
+ VALUE (*syntax_error_append)(VALUE, VALUE, int, int, rb_encoding*, const char*, va_list);
+ void (*raise)(VALUE exc, const char *fmt, ...);
+ VALUE (*syntax_error_new)(void);
+
+ /* Eval */
+ VALUE (*errinfo)(void);
+ void (*set_errinfo)(VALUE err);
+ void (*exc_raise)(VALUE mesg);
+ VALUE (*make_exception)(int argc, const VALUE *argv);
+
+ /* GC */
+ void (*sized_xfree)(void *x, size_t size);
+ void *(*sized_realloc_n)(void *ptr, size_t new_count, size_t element_size, size_t old_count);
+ VALUE (*obj_write)(VALUE, VALUE *, VALUE);
+ VALUE (*obj_written)(VALUE, VALUE, VALUE);
+ void (*gc_register_mark_object)(VALUE object);
+ void (*gc_guard)(VALUE);
+ void (*gc_mark)(VALUE);
+ void (*gc_mark_movable)(VALUE ptr);
+ VALUE (*gc_location)(VALUE value);
+
+ /* Re */
+ VALUE (*reg_compile)(VALUE str, int options, const char *sourcefile, int sourceline);
+ VALUE (*reg_check_preprocess)(VALUE str);
+ int (*memcicmp)(const void *x, const void *y, long len);
+
+ /* Error */
+ void (*compile_warn)(const char *file, int line, const char *fmt, ...);
+ void (*compile_warning)(const char *file, int line, const char *fmt, ...);
+ void (*bug)(const char *fmt, ...);
+ void (*fatal)(const char *fmt, ...);
+ VALUE (*verbose)(void);
+
+ /* VM */
+ VALUE (*make_backtrace)(void);
+
+ /* Util */
+ unsigned long (*scan_hex)(const char *start, size_t len, size_t *retlen);
+ unsigned long (*scan_oct)(const char *start, size_t len, size_t *retlen);
+ unsigned long (*scan_digits)(const char *str, ssize_t len, int base, size_t *retlen, int *overflow);
+ double (*strtod)(const char *s00, char **se);
+
+ /* ctype */
+ int (*isspace)(int c);
+ int (*isascii)(int c);
+ int (*iscntrl)(int c);
+ int (*isalpha)(int c);
+ int (*isdigit)(int c);
+ int (*isalnum)(int c);
+ int (*isxdigit)(int c);
+ int (*strcasecmp)(const char *s1, const char *s2);
+ int (*strncasecmp)(const char *s1, const char *s2, size_t n);
+
+ /* Misc */
+ VALUE (*rbool)(VALUE);
+ int (*undef_p)(VALUE);
+ int (*rtest)(VALUE obj);
+ int (*nil_p)(VALUE obj);
+ int (*flonum_p)(VALUE obj);
+ VALUE qnil;
+ VALUE qtrue;
+ VALUE qfalse;
+ VALUE qundef;
+ VALUE eArgError;
+ VALUE mRubyVMFrozenCore;
+ int (*long2int)(long);
+ int (*special_const_p)(VALUE);
+ int (*builtin_type)(VALUE);
+ int (*snprintf)(char *str, size_t n, char const *fmt, ...);
+
+ VALUE (*node_case_when_optimizable_literal)(const NODE *const node);
+
+ /* For Ripper */
+ VALUE (*static_id2sym)(ID id);
+ long (*str_coderange_scan_restartable)(const char *s, const char *e, rb_encoding *enc, int *cr);
+} rb_parser_config_t;
+
+#undef rb_encoding
+#undef OnigCodePoint
+#endif /* UNIVERSAL_PARSER */
+
+RUBY_SYMBOL_EXPORT_BEGIN
+void rb_ruby_parser_free(void *ptr);
+rb_ast_t* rb_ruby_parser_compile_string(rb_parser_t *p, const char *f, VALUE s, int line);
+
+#ifdef UNIVERSAL_PARSER
+rb_parser_config_t *rb_ruby_parser_config_new(void *(*malloc)(size_t size));
+void rb_ruby_parser_config_free(rb_parser_config_t *config);
+rb_parser_t *rb_ruby_parser_allocate(rb_parser_config_t *config);
+rb_parser_t *rb_ruby_parser_new(rb_parser_config_t *config);
+#endif
+RUBY_SYMBOL_EXPORT_END
+
+#endif /* RUBY_RUBYPARSER_H */
diff --git a/template/prelude.c.tmpl b/template/prelude.c.tmpl
index ebf9bc0693..6e00a9a0fc 100644
--- a/template/prelude.c.tmpl
+++ b/template/prelude.c.tmpl
@@ -86,6 +86,7 @@ Prelude.new(output, ARGV, vpath).instance_eval do
*/
%unless @preludes.empty?
#include "internal.h"
+#include "internal/ruby_parser.h"
#include "internal/warnings.h"
#include "iseq.h"
#include "ruby/ruby.h"
diff --git a/tool/update-deps b/tool/update-deps
index 6b8bb67236..5e241aa819 100755
--- a/tool/update-deps
+++ b/tool/update-deps
@@ -111,6 +111,7 @@ FILES_NEED_VPATH = %w[
ext/ripper/eventids1.c
ext/ripper/eventids2table.c
ext/ripper/ripper.c
+ ext/ripper/ripper_init.c
golf_prelude.c
id.c
id.h
diff --git a/universal_parser.c b/universal_parser.c
new file mode 100644
index 0000000000..9e4260f05d
--- /dev/null
+++ b/universal_parser.c
@@ -0,0 +1,400 @@
+#include <alloca.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stddef.h>
+
+/* Dependency */
+#include "internal/parse.h"
+#include "node.h"
+#include "id.h"
+
+#include "internal/compilers.h"
+#include "ruby/backward/2/inttypes.h"
+#include "probes.h"
+
+#define LIKELY(x) RB_LIKELY(x)
+#define UNLIKELY(x) RB_UNLIKELY(x)
+#ifndef TRUE
+# define TRUE 1
+#endif
+
+#ifndef FALSE
+# define FALSE 0
+#endif
+#define numberof(array) ((int)(sizeof(array) / sizeof((array)[0])))
+#define rb_strlen_lit(str) (sizeof(str "") - 1)
+#undef FIXNUM_MAX
+#define FIXNUM_MAX (LONG_MAX / 2)
+#undef RSTRING_GETMEM
+#define RSTRING_GETMEM(str, ptrvar, lenvar) \
+ ((ptrvar) = RSTRING_PTR(str), \
+ (lenvar) = RSTRING_LEN(str))
+#if defined(USE_FLONUM)
+# /* Take that. */
+#elif SIZEOF_VALUE >= SIZEOF_DOUBLE
+# define USE_FLONUM 1
+#else
+# define USE_FLONUM 0
+#endif
+
+/* parser_st */
+#define st_table parser_st_table
+#define st_data_t parser_st_data_t
+#define st_hash_type parser_st_hash_type
+#define ST_CONTINUE ST2_CONTINUE
+#define ST_STOP ST2_STOP
+#define ST_DELETE ST2_DELETE
+#define ST_CHECK ST2_CHECK
+#define ST_REPLACE ST2_REPLACE
+#undef st_init_numtable
+#define st_init_numtable() rb_parser_st_init_numtable((&p->config->st_functions))
+#undef st_free_table
+#define st_free_table rb_parser_st_free_table
+#undef st_init_table_with_size
+#define st_init_table_with_size rb_parser_st_init_table_with_size
+#undef st_insert
+#define st_insert rb_parser_st_insert
+#undef st_foreach
+#define st_foreach rb_parser_st_foreach
+#undef st_delete
+#define st_delete rb_parser_st_delete
+#undef st_is_member
+#define st_is_member parser_st_is_member
+
+#define rb_encoding void
+
+#undef T_FLOAT
+#define T_FLOAT 0x04
+#undef T_REGEXP
+#define T_REGEXP 0x06
+#undef T_HASH
+#define T_HASH 0x08
+#undef T_BIGNUM
+#define T_BIGNUM 0x0a
+#undef T_COMPLEX
+#define T_COMPLEX 0x0e
+#undef T_RATIONAL
+#define T_RATIONAL 0x0f
+
+struct rb_imemo_tmpbuf_struct {
+ VALUE flags;
+ VALUE reserved;
+ VALUE *ptr; /* malloc'ed buffer */
+ struct rb_imemo_tmpbuf_struct *next; /* next imemo */
+ size_t cnt; /* buffer size in VALUE */
+};
+
+#undef xmalloc
+#define xmalloc p->config->malloc
+#undef xcalloc
+#define xcalloc p->config->calloc
+#undef xrealloc
+#define xrealloc p->config->realloc
+#undef ALLOC_N
+#define ALLOC_N(type,n) ((type *)p->config->alloc_n((n), sizeof(type)))
+#undef ALLOC
+#define ALLOC(type) ((type *)p->config->alloc(sizeof(type)))
+#undef xfree
+#define xfree p->config->free
+#undef ALLOCA_N
+// alloca(rbimpl_size_mul_or_raise(x, y));
+#define ALLOCA_N(type,n) ((type *)alloca(sizeof(type) * (n)))
+#undef REALLOC_N
+#define REALLOC_N(var,type,n) ((var) = (type *)p->config->realloc_n((void *)var, n, sizeof(type)))
+#undef ZALLOC
+#define ZALLOC(type) ((type *)p->config->zalloc(sizeof(type)))
+#undef MEMMOVE
+#define MEMMOVE(p1,p2,type,n) (p->config->rb_memmove((p1), (p2), sizeof(type), (n)))
+#undef MEMCPY
+#define MEMCPY(p1,p2,type,n) (p->config->nonempty_memcpy((p1), (p2), sizeof(type), (n)))
+
+#define new_strterm p->config->new_strterm
+#define strterm_is_heredoc p->config->strterm_is_heredoc
+#define rb_imemo_tmpbuf_auto_free_pointer p->config->tmpbuf_auto_free_pointer
+#define rb_imemo_tmpbuf_set_ptr p->config->tmpbuf_set_ptr
+#define rb_imemo_tmpbuf_parser_heap p->config->tmpbuf_parser_heap
+
+#define compile_callback p->config->compile_callback
+#define reg_named_capture_assign p->config->reg_named_capture_assign
+#define script_lines_defined p->config->script_lines_defined
+#define script_lines_get p->config->script_lines_get
+
+#define rb_obj_freeze p->config->obj_freeze
+#define rb_obj_hide p->config->obj_hide
+#undef RB_OBJ_FROZEN
+#define RB_OBJ_FROZEN p->config->obj_frozen
+#undef RB_TYPE_P
+#define RB_TYPE_P p->config->type_p
+#undef OBJ_FREEZE_RAW
+#define OBJ_FREEZE_RAW p->config->obj_freeze_raw
+
+#undef FIXNUM_P
+#define FIXNUM_P p->config->fixnum_p
+#undef SYMBOL_P
+#define SYMBOL_P p->config->symbol_p
+
+#define rb_attr_get p->config->attr_get
+
+#define rb_ary_new p->config->ary_new
+#define rb_ary_push p->config->ary_push
+#undef rb_ary_new_from_args
+#define rb_ary_new_from_args p->config->ary_new_from_args
+#define rb_ary_pop p->config->ary_pop
+#define rb_ary_last p->config->ary_last
+#define rb_ary_unshift p->config->ary_unshift
+#undef rb_ary_new2
+#define rb_ary_new2 p->config->ary_new2
+#define rb_ary_entry p->config->ary_entry
+#define rb_ary_join p->config->ary_join
+#define rb_ary_reverse p->config->ary_reverse
+#define rb_ary_clear p->config->ary_clear
+#undef RARRAY_LEN
+#define RARRAY_LEN p->config->array_len
+#define RARRAY_AREF p->config->array_aref
+
+#undef rb_sym_intern_ascii_cstr
+#define rb_sym_intern_ascii_cstr p->config->sym_intern_ascii_cstr
+#define rb_make_temporary_id p->config->make_temporary_id
+#define is_local_id p->config->is_local_id
+#define is_attrset_id p->config->is_attrset_id
+#define is_global_name_punct p->config->is_global_name_punct
+#define id_type p->config->id_type
+#define rb_id_attrset p->config->id_attrset
+#undef rb_intern
+#define rb_intern p->config->intern
+#define rb_intern2 p->config->intern2
+#define rb_intern3 p->config->intern3
+#define rb_intern_str p->config->intern_str
+#define is_notop_id p->config->is_notop_id
+#define rb_enc_symname_type p->config->enc_symname_type
+#define rb_str_intern p->config->str_intern
+#define rb_id2name p->config->id2name
+#define rb_id2str p->config->id2str
+#define rb_id2sym p->config->id2sym
+#undef ID2SYM
+#define ID2SYM p->config->id2sym
+#undef SYM2ID
+#define SYM2ID p->config->sym2id
+
+#define rb_str_catf p->config->str_catf
+#undef rb_str_cat_cstr
+#define rb_str_cat_cstr p->config->str_cat_cstr
+#define rb_str_subseq p->config->str_subseq
+#define rb_str_dup p->config->str_dup
+#define rb_str_new_frozen p->config->str_new_frozen
+#define rb_str_buf_new p->config->str_buf_new
+#undef rb_str_buf_cat
+#define rb_str_buf_cat p->config->str_buf_cat
+#define rb_str_modify p->config->str_modify
+#define rb_str_set_len p->config->str_set_len
+#define rb_str_cat p->config->str_cat
+#define rb_str_resize p->config->str_resize
+#undef rb_str_new
+#define rb_str_new p->config->str_new
+#undef rb_str_new_cstr
+#define rb_str_new_cstr p->config->str_new_cstr
+#define rb_fstring p->config->fstring
+#define is_ascii_string p->config->is_ascii_string
+#define rb_enc_str_new p->config->enc_str_new
+#define rb_enc_str_buf_cat p->config->enc_str_buf_cat
+#define rb_str_buf_append p->config->str_buf_append
+#define rb_str_vcatf p->config->str_vcatf
+#undef StringValueCStr
+#define StringValueCStr(v) p->config->string_value_cstr(&(v))
+#define rb_sprintf p->config->rb_sprintf
+#undef RSTRING_PTR
+#define RSTRING_PTR p->config->rstring_ptr
+#undef RSTRING_END
+#define RSTRING_END p->config->rstring_end
+#undef RSTRING_LEN
+#define RSTRING_LEN p->config->rstring_len
+#define rb_filesystem_str_new_cstr p->config->filesystem_str_new_cstr
+#define rb_obj_as_string p->config->obj_as_string
+
+#define rb_hash_clear p->config->hash_clear
+#define rb_hash_new p->config->hash_new
+#define rb_hash_aset p->config->hash_aset
+#define rb_hash_lookup p->config->hash_lookup
+#define rb_ident_hash_new p->config->ident_hash_new
+
+#undef INT2FIX
+#define INT2FIX p->config->int2fix
+#undef LONG2FIX
+#define LONG2FIX p->config->int2fix
+
+#define bignum_negate p->config->bignum_negate
+#define rb_big_norm p->config->big_norm
+#define rb_int2big p->config->int2big
+#define rb_cstr_to_inum p->config->cstr_to_inum
+
+#define rb_float_new p->config->float_new
+#undef RFLOAT_VALUE
+#define RFLOAT_VALUE p->config->float_value
+#undef DBL2NUM
+#define DBL2NUM p->config->float_new
+
+#define rb_fix2int p->config->fix2int
+#undef NUM2INT
+#define NUM2INT p->config->num2int
+#define rb_int_positive_pow p->config->int_positive_pow
+#undef INT2NUM
+#define INT2NUM p->config->int2num
+#undef FIX2LONG
+#define FIX2LONG p->config->fix2long
+
+#define rb_rational_new p->config->rational_new
+#define rb_rational_raw p->config->rational_raw
+#undef rb_rational_raw1
+#define rb_rational_raw1 p->config->rational_raw1
+#define rational_set_num p->config->rational_set_num
+#define rational_get_num p->config->rational_get_num
+
+#define rb_complex_raw p->config->complex_raw
+#define rcomplex_set_real p->config->rcomplex_set_real
+#define rcomplex_set_imag p->config->rcomplex_set_imag
+#define rcomplex_get_real p->config->rcomplex_get_real
+#define rcomplex_get_imag p->config->rcomplex_get_imag
+
+#define rb_stderr_tty_p p->config->stderr_tty_p
+#define rb_write_error_str p->config->write_error_str
+#define rb_default_rs p->config->default_rs()
+#define rb_io_write p->config->io_write
+#define rb_io_flush p->config->io_flush
+#define rb_io_puts p->config->io_puts
+#define rb_io_gets_internal p->config->io_gets_internal
+
+#define rb_ractor_stdout p->config->debug_output_stdout
+#define rb_ractor_stderr p->config->debug_output_stderr
+
+#define rb_is_usascii_enc p->config->is_usascii_enc
+#define rb_enc_isalnum p->config->enc_isalnum
+#define rb_enc_precise_mbclen p->config->enc_precise_mbclen
+#define MBCLEN_CHARFOUND_P p->config->mbclen_charfound_p
+#define rb_enc_name p->config->enc_name
+#define rb_enc_prev_char p->config->enc_prev_char
+#define rb_enc_get p->config->enc_get
+#define rb_enc_asciicompat p->config->enc_asciicompat
+#define rb_utf8_encoding p->config->utf8_encoding
+#define rb_enc_associate p->config->enc_associate
+#define rb_ascii8bit_encoding p->config->ascii8bit_encoding
+#define rb_enc_codelen p->config->enc_codelen
+#define rb_enc_mbcput p->config->enc_mbcput
+#define rb_char_to_option_kcode p->config->char_to_option_kcode
+#define rb_ascii8bit_encindex p->config->ascii8bit_encindex
+#define rb_enc_find_index p->config->enc_find_index
+#define rb_enc_from_index p->config->enc_from_index
+#define rb_enc_associate_index p->config->enc_associate_index
+#define rb_enc_isspace p->config->enc_isspace
+#define ENC_CODERANGE_7BIT p->config->enc_coderange_7bit
+#define ENC_CODERANGE_UNKNOWN p->config->enc_coderange_unknown
+#define rb_enc_compatible p->config->enc_compatible
+#define rb_enc_from_encoding p->config->enc_from_encoding
+#define ENCODING_GET p->config->encoding_get
+#define ENCODING_SET p->config->encoding_set
+#define ENCODING_IS_ASCII8BIT p->config->encoding_is_ascii8bit
+#define rb_usascii_encoding p->config->usascii_encoding
+
+#define rb_ractor_make_shareable p->config->ractor_make_shareable
+
+#define ruby_vm_keep_script_lines p->config->vm_keep_script_lines()
+#define rb_local_defined p->config->local_defined
+#define rb_dvar_defined p->config->dvar_defined
+
+#define literal_cmp p->config->literal_cmp
+#define literal_hash p->config->literal_hash
+
+#define rb_builtin_class_name p->config->builtin_class_name
+#define rb_syntax_error_append p->config->syntax_error_append
+#define rb_raise p->config->raise
+#define syntax_error_new p->config->syntax_error_new
+
+#define rb_errinfo p->config->errinfo
+#define rb_set_errinfo p->config->set_errinfo
+#define rb_exc_raise p->config->exc_raise
+#define rb_make_exception p->config->make_exception
+
+#define ruby_sized_xfree p->config->sized_xfree
+#define SIZED_REALLOC_N(v, T, m, n) ((v) = (T *)p->config->sized_realloc_n((void *)(v), (m), sizeof(T), (n)))
+#undef RB_OBJ_WRITE
+#define RB_OBJ_WRITE(old, slot, young) p->config->obj_write((VALUE)(old), (VALUE *)(slot), (VALUE)(young))
+#undef RB_OBJ_WRITTEN
+#define RB_OBJ_WRITTEN(old, oldv, young) p->config->obj_written((VALUE)(old), (VALUE)(oldv), (VALUE)(young))
+#define rb_gc_register_mark_object p->config->gc_register_mark_object
+#undef RB_GC_GUARD
+#define RB_GC_GUARD p->config->gc_guard
+#define rb_gc_mark p->config->gc_mark
+
+#define rb_reg_compile p->config->reg_compile
+#define rb_reg_check_preprocess p->config->reg_check_preprocess
+#define rb_memcicmp p->config->memcicmp
+
+#define rb_compile_warn p->config->compile_warn
+#define rb_compile_warning p->config->compile_warning
+#define rb_bug p->config->bug
+#define rb_fatal p->config->fatal
+#undef ruby_verbose
+#define ruby_verbose p->config->verbose()
+
+#define rb_make_backtrace p->config->make_backtrace
+
+#define ruby_scan_hex p->config->scan_hex
+#define ruby_scan_oct p->config->scan_oct
+#define ruby_scan_digits p->config->scan_digits
+#define strtod p->config->strtod
+
+#undef ISSPACE
+#define ISSPACE(c) ((p->config->isspace)(c))
+#undef ISASCII
+#define ISASCII(c) ((p->config->isascii)(c))
+#undef ISCNTRL
+#define ISCNTRL(c) ((p->config->iscntrl)(c))
+#undef ISALPHA
+#define ISALPHA(c) ((p->config->isalpha)(c))
+#undef ISDIGIT
+#define ISDIGIT(c) ((p->config->isdigit)(c))
+#undef ISALNUM
+#define ISALNUM(c) ((p->config->isalnum)(c))
+#undef ISXDIGIT
+#define ISXDIGIT(c) ((p->config->isxdigit)(c))
+#undef STRCASECMP
+#define STRCASECMP p->config->strcasecmp
+#undef STRNCASECMP
+#define STRNCASECMP p->config->strncasecmp
+
+#undef RBOOL
+#define RBOOL p->config->rbool
+#undef UNDEF_P
+#define UNDEF_P p->config->undef_p
+#undef RTEST
+#define RTEST p->config->rtest
+#undef NIL_P
+#define NIL_P p->config->nil_p
+#undef FLONUM_P
+#define FLONUM_P p->config->flonum_p
+#undef Qnil
+#define Qnil p->config->qnil
+#undef Qtrue
+#define Qtrue p->config->qtrue
+#undef Qfalse
+#define Qfalse p->config->qfalse
+#undef Qundef
+#define Qundef p->config->qundef
+#define rb_eArgError p->config->eArgError
+#define rb_mRubyVMFrozenCore p->config->mRubyVMFrozenCore
+#undef rb_long2int
+#define rb_long2int p->config->long2int
+#undef SPECIAL_CONST_P
+#define SPECIAL_CONST_P p->config->special_const_p
+#undef BUILTIN_TYPE
+#define BUILTIN_TYPE p->config->builtin_type
+#define ruby_snprintf p->config->snprintf
+
+#define rb_node_case_when_optimizable_literal p->config->node_case_when_optimizable_literal
+
+#undef st_init_table_with_size
+#define st_init_table_with_size(type, size) \
+ rb_parser_st_init_table_with_size(type, &p->config->st_functions, size)
+
+#define rb_ast_new() \
+ rb_ast_new(p->config)
diff --git a/vm.c b/vm.c
index b6b8ca80f5..93e51dd847 100644
--- a/vm.c
+++ b/vm.c
@@ -20,9 +20,9 @@
#include "internal/gc.h"
#include "internal/inits.h"
#include "internal/object.h"
-#include "internal/parse.h"
#include "internal/proc.h"
#include "internal/re.h"
+#include "internal/ruby_parser.h"
#include "internal/symbol.h"
#include "internal/thread.h"
#include "internal/vm.h"