prism 0.29.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +77 -1
- data/CONTRIBUTING.md +0 -4
- data/README.md +4 -0
- data/config.yml +498 -145
- data/docs/fuzzing.md +1 -1
- data/docs/parsing_rules.md +4 -1
- data/docs/ripper_translation.md +22 -0
- data/docs/serialization.md +3 -0
- data/ext/prism/api_node.c +2858 -2082
- data/ext/prism/extconf.rb +1 -1
- data/ext/prism/extension.c +203 -421
- data/ext/prism/extension.h +2 -2
- data/include/prism/ast.h +1732 -453
- data/include/prism/defines.h +36 -0
- data/include/prism/diagnostic.h +23 -6
- data/include/prism/node.h +0 -21
- data/include/prism/options.h +94 -3
- data/include/prism/parser.h +57 -28
- data/include/prism/regexp.h +18 -8
- data/include/prism/static_literals.h +3 -2
- data/include/prism/util/pm_char.h +1 -2
- data/include/prism/util/pm_constant_pool.h +0 -8
- data/include/prism/util/pm_integer.h +22 -15
- data/include/prism/util/pm_newline_list.h +11 -0
- data/include/prism/util/pm_string.h +28 -12
- data/include/prism/version.h +3 -3
- data/include/prism.h +0 -11
- data/lib/prism/compiler.rb +3 -0
- data/lib/prism/desugar_compiler.rb +111 -74
- data/lib/prism/dispatcher.rb +16 -1
- data/lib/prism/dot_visitor.rb +45 -34
- data/lib/prism/dsl.rb +660 -468
- data/lib/prism/ffi.rb +64 -6
- data/lib/prism/inspect_visitor.rb +294 -64
- data/lib/prism/lex_compat.rb +1 -1
- data/lib/prism/mutation_compiler.rb +11 -6
- data/lib/prism/node.rb +2469 -4973
- data/lib/prism/node_ext.rb +91 -14
- data/lib/prism/parse_result/comments.rb +0 -7
- data/lib/prism/parse_result/errors.rb +65 -0
- data/lib/prism/parse_result/newlines.rb +101 -11
- data/lib/prism/parse_result.rb +43 -3
- data/lib/prism/reflection.rb +10 -8
- data/lib/prism/serialize.rb +484 -609
- data/lib/prism/translation/parser/compiler.rb +152 -132
- data/lib/prism/translation/parser/lexer.rb +26 -4
- data/lib/prism/translation/parser.rb +9 -4
- data/lib/prism/translation/ripper.rb +22 -20
- data/lib/prism/translation/ruby_parser.rb +73 -13
- data/lib/prism/visitor.rb +3 -0
- data/lib/prism.rb +0 -4
- data/prism.gemspec +3 -5
- data/rbi/prism/dsl.rbi +521 -0
- data/rbi/prism/node.rbi +744 -4837
- data/rbi/prism/visitor.rbi +3 -0
- data/rbi/prism.rbi +36 -30
- data/sig/prism/dsl.rbs +190 -303
- data/sig/prism/mutation_compiler.rbs +1 -0
- data/sig/prism/node.rbs +759 -628
- data/sig/prism/parse_result.rbs +2 -0
- data/sig/prism/visitor.rbs +1 -0
- data/sig/prism.rbs +103 -64
- data/src/diagnostic.c +62 -28
- data/src/node.c +499 -1754
- data/src/options.c +76 -27
- data/src/prettyprint.c +156 -112
- data/src/prism.c +2773 -2081
- data/src/regexp.c +202 -69
- data/src/serialize.c +170 -50
- data/src/static_literals.c +63 -84
- data/src/token_type.c +4 -4
- data/src/util/pm_constant_pool.c +0 -8
- data/src/util/pm_integer.c +53 -25
- data/src/util/pm_newline_list.c +29 -0
- data/src/util/pm_string.c +130 -80
- data/src/util/pm_strpbrk.c +32 -6
- metadata +4 -6
- data/include/prism/util/pm_string_list.h +0 -44
- data/lib/prism/debug.rb +0 -249
- data/lib/prism/translation/parser/rubocop.rb +0 -73
- data/src/util/pm_string_list.c +0 -28
@@ -1273,8 +1273,8 @@ module Prism
|
|
1273
1273
|
def visit_case_node(node)
|
1274
1274
|
predicate = visit(node.predicate)
|
1275
1275
|
clauses =
|
1276
|
-
node.conditions.reverse_each.inject(visit(node.
|
1277
|
-
on_when(*visit(condition),
|
1276
|
+
node.conditions.reverse_each.inject(visit(node.else_clause)) do |current, condition|
|
1277
|
+
on_when(*visit(condition), current)
|
1278
1278
|
end
|
1279
1279
|
|
1280
1280
|
bounds(node.location)
|
@@ -1286,8 +1286,8 @@ module Prism
|
|
1286
1286
|
def visit_case_match_node(node)
|
1287
1287
|
predicate = visit(node.predicate)
|
1288
1288
|
clauses =
|
1289
|
-
node.conditions.reverse_each.inject(visit(node.
|
1290
|
-
on_in(*visit(condition),
|
1289
|
+
node.conditions.reverse_each.inject(visit(node.else_clause)) do |current, condition|
|
1290
|
+
on_in(*visit(condition), current)
|
1291
1291
|
end
|
1292
1292
|
|
1293
1293
|
bounds(node.location)
|
@@ -1908,7 +1908,7 @@ module Prism
|
|
1908
1908
|
if node.then_keyword == "?"
|
1909
1909
|
predicate = visit(node.predicate)
|
1910
1910
|
truthy = visit(node.statements.body.first)
|
1911
|
-
falsy = visit(node.
|
1911
|
+
falsy = visit(node.subsequent.statements.body.first)
|
1912
1912
|
|
1913
1913
|
bounds(node.location)
|
1914
1914
|
on_ifop(predicate, truthy, falsy)
|
@@ -1921,13 +1921,13 @@ module Prism
|
|
1921
1921
|
else
|
1922
1922
|
visit(node.statements)
|
1923
1923
|
end
|
1924
|
-
|
1924
|
+
subsequent = visit(node.subsequent)
|
1925
1925
|
|
1926
1926
|
bounds(node.location)
|
1927
1927
|
if node.if_keyword == "if"
|
1928
|
-
on_if(predicate, statements,
|
1928
|
+
on_if(predicate, statements, subsequent)
|
1929
1929
|
else
|
1930
|
-
on_elsif(predicate, statements,
|
1930
|
+
on_elsif(predicate, statements, subsequent)
|
1931
1931
|
end
|
1932
1932
|
else
|
1933
1933
|
statements = visit(node.statements.body.first)
|
@@ -1960,7 +1960,7 @@ module Prism
|
|
1960
1960
|
# ^^^^^^^^^^^^^^^^^^^^^
|
1961
1961
|
def visit_in_node(node)
|
1962
1962
|
# This is a special case where we're not going to call on_in directly
|
1963
|
-
# because we don't have access to the
|
1963
|
+
# because we don't have access to the subsequent. Instead, we'll return
|
1964
1964
|
# the component parts and let the parent node handle it.
|
1965
1965
|
pattern = visit_pattern_node(node.pattern)
|
1966
1966
|
statements =
|
@@ -2217,6 +2217,13 @@ module Prism
|
|
2217
2217
|
end
|
2218
2218
|
end
|
2219
2219
|
|
2220
|
+
# -> { it }
|
2221
|
+
# ^^
|
2222
|
+
def visit_it_local_variable_read_node(node)
|
2223
|
+
bounds(node.location)
|
2224
|
+
on_vcall(on_ident(node.slice))
|
2225
|
+
end
|
2226
|
+
|
2220
2227
|
# -> { it }
|
2221
2228
|
# ^^^^^^^^^
|
2222
2229
|
def visit_it_parameters_node(node)
|
@@ -2312,12 +2319,7 @@ module Prism
|
|
2312
2319
|
# ^^^
|
2313
2320
|
def visit_local_variable_read_node(node)
|
2314
2321
|
bounds(node.location)
|
2315
|
-
|
2316
|
-
if node.name == :"0it"
|
2317
|
-
on_vcall(on_ident(node.slice))
|
2318
|
-
else
|
2319
|
-
on_var_ref(on_ident(node.slice))
|
2320
|
-
end
|
2322
|
+
on_var_ref(on_ident(node.slice))
|
2321
2323
|
end
|
2322
2324
|
|
2323
2325
|
# foo = 1
|
@@ -2806,10 +2808,10 @@ module Prism
|
|
2806
2808
|
visit(node.statements)
|
2807
2809
|
end
|
2808
2810
|
|
2809
|
-
|
2811
|
+
subsequent = visit(node.subsequent)
|
2810
2812
|
|
2811
2813
|
bounds(node.location)
|
2812
|
-
on_rescue(exceptions, reference, statements,
|
2814
|
+
on_rescue(exceptions, reference, statements, subsequent)
|
2813
2815
|
end
|
2814
2816
|
|
2815
2817
|
# def foo(*bar); end
|
@@ -3130,10 +3132,10 @@ module Prism
|
|
3130
3132
|
else
|
3131
3133
|
visit(node.statements)
|
3132
3134
|
end
|
3133
|
-
|
3135
|
+
else_clause = visit(node.else_clause)
|
3134
3136
|
|
3135
3137
|
bounds(node.location)
|
3136
|
-
on_unless(predicate, statements,
|
3138
|
+
on_unless(predicate, statements, else_clause)
|
3137
3139
|
else
|
3138
3140
|
statements = visit(node.statements.body.first)
|
3139
3141
|
predicate = visit(node.predicate)
|
@@ -3174,7 +3176,7 @@ module Prism
|
|
3174
3176
|
# ^^^^^^^^^^^^^
|
3175
3177
|
def visit_when_node(node)
|
3176
3178
|
# This is a special case where we're not going to call on_when directly
|
3177
|
-
# because we don't have access to the
|
3179
|
+
# because we don't have access to the subsequent. Instead, we'll return
|
3178
3180
|
# the component parts and let the parent node handle it.
|
3179
3181
|
conditions = visit_arguments(node.conditions)
|
3180
3182
|
statements =
|
@@ -1,6 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
begin
|
4
|
+
require "ruby_parser"
|
5
|
+
rescue LoadError
|
6
|
+
warn(%q{Error: Unable to load ruby_parser. Add `gem "ruby_parser"` to your Gemfile.})
|
7
|
+
exit(1)
|
8
|
+
end
|
4
9
|
|
5
10
|
module Prism
|
6
11
|
module Translation
|
@@ -50,7 +55,19 @@ module Prism
|
|
50
55
|
# a and b
|
51
56
|
# ^^^^^^^
|
52
57
|
def visit_and_node(node)
|
53
|
-
|
58
|
+
left = visit(node.left)
|
59
|
+
|
60
|
+
if left[0] == :and
|
61
|
+
# ruby_parser has the and keyword as right-associative as opposed to
|
62
|
+
# prism which has it as left-associative. We reverse that
|
63
|
+
# associativity here.
|
64
|
+
nest = left
|
65
|
+
nest = nest[2] while nest[2][0] == :and
|
66
|
+
nest[2] = s(node, :and, nest[2], visit(node.right))
|
67
|
+
left
|
68
|
+
else
|
69
|
+
s(node, :and, left, visit(node.right))
|
70
|
+
end
|
54
71
|
end
|
55
72
|
|
56
73
|
# []
|
@@ -130,7 +147,7 @@ module Prism
|
|
130
147
|
end
|
131
148
|
|
132
149
|
current = node.rescue_clause
|
133
|
-
until (current = current.
|
150
|
+
until (current = current.subsequent).nil?
|
134
151
|
result << visit(current)
|
135
152
|
end
|
136
153
|
end
|
@@ -246,6 +263,11 @@ module Prism
|
|
246
263
|
when RegularExpressionNode, InterpolatedRegularExpressionNode
|
247
264
|
return s(node, :match2, visit(node.receiver), visit(node.arguments.arguments.first))
|
248
265
|
end
|
266
|
+
|
267
|
+
case node.arguments.arguments.first
|
268
|
+
when RegularExpressionNode, InterpolatedRegularExpressionNode
|
269
|
+
return s(node, :match3, visit(node.arguments.arguments.first), visit(node.receiver))
|
270
|
+
end
|
249
271
|
end
|
250
272
|
end
|
251
273
|
|
@@ -325,13 +347,13 @@ module Prism
|
|
325
347
|
# case foo; when bar; end
|
326
348
|
# ^^^^^^^^^^^^^^^^^^^^^^^
|
327
349
|
def visit_case_node(node)
|
328
|
-
s(node, :case, visit(node.predicate)).concat(visit_all(node.conditions)) << visit(node.
|
350
|
+
s(node, :case, visit(node.predicate)).concat(visit_all(node.conditions)) << visit(node.else_clause)
|
329
351
|
end
|
330
352
|
|
331
353
|
# case foo; in bar; end
|
332
354
|
# ^^^^^^^^^^^^^^^^^^^^^
|
333
355
|
def visit_case_match_node(node)
|
334
|
-
s(node, :case, visit(node.predicate)).concat(visit_all(node.conditions)) << visit(node.
|
356
|
+
s(node, :case, visit(node.predicate)).concat(visit_all(node.conditions)) << visit(node.else_clause)
|
335
357
|
end
|
336
358
|
|
337
359
|
# class Foo; end
|
@@ -480,9 +502,9 @@ module Prism
|
|
480
502
|
def visit_constant_path_target_node(node)
|
481
503
|
inner =
|
482
504
|
if node.parent.nil?
|
483
|
-
s(node, :colon3, node.
|
505
|
+
s(node, :colon3, node.name)
|
484
506
|
else
|
485
|
-
s(node, :colon2, visit(node.parent), node.
|
507
|
+
s(node, :colon2, visit(node.parent), node.name)
|
486
508
|
end
|
487
509
|
|
488
510
|
s(node, :const, inner)
|
@@ -678,7 +700,7 @@ module Prism
|
|
678
700
|
# foo ? bar : baz
|
679
701
|
# ^^^^^^^^^^^^^^^
|
680
702
|
def visit_if_node(node)
|
681
|
-
s(node, :if, visit(node.predicate), visit(node.statements), visit(node.
|
703
|
+
s(node, :if, visit(node.predicate), visit(node.statements), visit(node.subsequent))
|
682
704
|
end
|
683
705
|
|
684
706
|
# 1i
|
@@ -870,6 +892,15 @@ module Prism
|
|
870
892
|
else
|
871
893
|
visited << result
|
872
894
|
end
|
895
|
+
elsif result[0] == :dstr
|
896
|
+
if !visited.empty? && part.parts[0].is_a?(StringNode)
|
897
|
+
# If we are in the middle of an implicitly concatenated string,
|
898
|
+
# we should not have a bare string as the first part. In this
|
899
|
+
# case we need to visit just that first part and then we can
|
900
|
+
# push the rest of the parts onto the visited array.
|
901
|
+
result[1] = visit(part.parts[0])
|
902
|
+
end
|
903
|
+
visited.concat(result[1..-1])
|
873
904
|
else
|
874
905
|
visited << result
|
875
906
|
end
|
@@ -900,12 +931,23 @@ module Prism
|
|
900
931
|
results << result
|
901
932
|
state = :interpolated_content
|
902
933
|
end
|
903
|
-
|
904
|
-
results
|
934
|
+
when :interpolated_content
|
935
|
+
if result.is_a?(Array) && result[0] == :str && results[-1][0] == :str && (results[-1].line_max == result.line)
|
936
|
+
results[-1][1] << result[1]
|
937
|
+
results[-1].line_max = result.line_max
|
938
|
+
else
|
939
|
+
results << result
|
940
|
+
end
|
905
941
|
end
|
906
942
|
end
|
907
943
|
end
|
908
944
|
|
945
|
+
# -> { it }
|
946
|
+
# ^^
|
947
|
+
def visit_it_local_variable_read_node(node)
|
948
|
+
s(node, :call, nil, :it)
|
949
|
+
end
|
950
|
+
|
909
951
|
# foo(bar: baz)
|
910
952
|
# ^^^^^^^^
|
911
953
|
def visit_keyword_hash_node(node)
|
@@ -1118,7 +1160,19 @@ module Prism
|
|
1118
1160
|
# a or b
|
1119
1161
|
# ^^^^^^
|
1120
1162
|
def visit_or_node(node)
|
1121
|
-
|
1163
|
+
left = visit(node.left)
|
1164
|
+
|
1165
|
+
if left[0] == :or
|
1166
|
+
# ruby_parser has the or keyword as right-associative as opposed to
|
1167
|
+
# prism which has it as left-associative. We reverse that
|
1168
|
+
# associativity here.
|
1169
|
+
nest = left
|
1170
|
+
nest = nest[2] while nest[2][0] == :or
|
1171
|
+
nest[2] = s(node, :or, nest[2], visit(node.right))
|
1172
|
+
left
|
1173
|
+
else
|
1174
|
+
s(node, :or, left, visit(node.right))
|
1175
|
+
end
|
1122
1176
|
end
|
1123
1177
|
|
1124
1178
|
# def foo(bar, *baz); end
|
@@ -1374,7 +1428,13 @@ module Prism
|
|
1374
1428
|
# "foo"
|
1375
1429
|
# ^^^^^
|
1376
1430
|
def visit_string_node(node)
|
1377
|
-
|
1431
|
+
unescaped = node.unescaped
|
1432
|
+
|
1433
|
+
if node.forced_binary_encoding?
|
1434
|
+
unescaped.force_encoding(Encoding::BINARY)
|
1435
|
+
end
|
1436
|
+
|
1437
|
+
s(node, :str, unescaped)
|
1378
1438
|
end
|
1379
1439
|
|
1380
1440
|
# super(foo)
|
@@ -1416,7 +1476,7 @@ module Prism
|
|
1416
1476
|
# bar unless foo
|
1417
1477
|
# ^^^^^^^^^^^^^^
|
1418
1478
|
def visit_unless_node(node)
|
1419
|
-
s(node, :if, visit(node.predicate), visit(node.
|
1479
|
+
s(node, :if, visit(node.predicate), visit(node.else_clause), visit(node.statements))
|
1420
1480
|
end
|
1421
1481
|
|
1422
1482
|
# until foo; bar end
|
data/lib/prism/visitor.rb
CHANGED
@@ -313,6 +313,9 @@ module Prism
|
|
313
313
|
# Visit a InterpolatedXStringNode node
|
314
314
|
alias visit_interpolated_x_string_node visit_child_nodes
|
315
315
|
|
316
|
+
# Visit a ItLocalVariableReadNode node
|
317
|
+
alias visit_it_local_variable_read_node visit_child_nodes
|
318
|
+
|
316
319
|
# Visit a ItParametersNode node
|
317
320
|
alias visit_it_parameters_node visit_child_nodes
|
318
321
|
|
data/lib/prism.rb
CHANGED
@@ -13,7 +13,6 @@ module Prism
|
|
13
13
|
|
14
14
|
autoload :BasicVisitor, "prism/visitor"
|
15
15
|
autoload :Compiler, "prism/compiler"
|
16
|
-
autoload :Debug, "prism/debug"
|
17
16
|
autoload :DesugarCompiler, "prism/desugar_compiler"
|
18
17
|
autoload :Dispatcher, "prism/dispatcher"
|
19
18
|
autoload :DotVisitor, "prism/dot_visitor"
|
@@ -32,7 +31,6 @@ module Prism
|
|
32
31
|
# Some of these constants are not meant to be exposed, so marking them as
|
33
32
|
# private here.
|
34
33
|
|
35
|
-
private_constant :Debug
|
36
34
|
private_constant :LexCompat
|
37
35
|
private_constant :LexRipper
|
38
36
|
|
@@ -71,8 +69,6 @@ require_relative "prism/polyfill/byteindex"
|
|
71
69
|
require_relative "prism/node"
|
72
70
|
require_relative "prism/node_ext"
|
73
71
|
require_relative "prism/parse_result"
|
74
|
-
require_relative "prism/parse_result/comments"
|
75
|
-
require_relative "prism/parse_result/newlines"
|
76
72
|
|
77
73
|
# This is a Ruby implementation of the prism parser. If we're running on CRuby
|
78
74
|
# and we haven't explicitly set the PRISM_FFI_BACKEND environment variable, then
|
data/prism.gemspec
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |spec|
|
4
4
|
spec.name = "prism"
|
5
|
-
spec.version = "
|
5
|
+
spec.version = "1.1.0"
|
6
6
|
spec.authors = ["Shopify"]
|
7
7
|
spec.email = ["ruby@shopify.com"]
|
8
8
|
|
@@ -65,12 +65,10 @@ Gem::Specification.new do |spec|
|
|
65
65
|
"include/prism/util/pm_newline_list.h",
|
66
66
|
"include/prism/util/pm_strncasecmp.h",
|
67
67
|
"include/prism/util/pm_string.h",
|
68
|
-
"include/prism/util/pm_string_list.h",
|
69
68
|
"include/prism/util/pm_strpbrk.h",
|
70
69
|
"include/prism/version.h",
|
71
70
|
"lib/prism.rb",
|
72
71
|
"lib/prism/compiler.rb",
|
73
|
-
"lib/prism/debug.rb",
|
74
72
|
"lib/prism/desugar_compiler.rb",
|
75
73
|
"lib/prism/dispatcher.rb",
|
76
74
|
"lib/prism/dot_visitor.rb",
|
@@ -84,6 +82,7 @@ Gem::Specification.new do |spec|
|
|
84
82
|
"lib/prism/pack.rb",
|
85
83
|
"lib/prism/parse_result.rb",
|
86
84
|
"lib/prism/parse_result/comments.rb",
|
85
|
+
"lib/prism/parse_result/errors.rb",
|
87
86
|
"lib/prism/parse_result/newlines.rb",
|
88
87
|
"lib/prism/pattern.rb",
|
89
88
|
"lib/prism/polyfill/byteindex.rb",
|
@@ -96,7 +95,6 @@ Gem::Specification.new do |spec|
|
|
96
95
|
"lib/prism/translation/parser34.rb",
|
97
96
|
"lib/prism/translation/parser/compiler.rb",
|
98
97
|
"lib/prism/translation/parser/lexer.rb",
|
99
|
-
"lib/prism/translation/parser/rubocop.rb",
|
100
98
|
"lib/prism/translation/ripper.rb",
|
101
99
|
"lib/prism/translation/ripper/sexp.rb",
|
102
100
|
"lib/prism/translation/ripper/shim.rb",
|
@@ -105,6 +103,7 @@ Gem::Specification.new do |spec|
|
|
105
103
|
"prism.gemspec",
|
106
104
|
"rbi/prism.rbi",
|
107
105
|
"rbi/prism/compiler.rbi",
|
106
|
+
"rbi/prism/dsl.rbi",
|
108
107
|
"rbi/prism/inspect_visitor.rbi",
|
109
108
|
"rbi/prism/node_ext.rbi",
|
110
109
|
"rbi/prism/node.rbi",
|
@@ -149,7 +148,6 @@ Gem::Specification.new do |spec|
|
|
149
148
|
"src/util/pm_list.c",
|
150
149
|
"src/util/pm_memchr.c",
|
151
150
|
"src/util/pm_newline_list.c",
|
152
|
-
"src/util/pm_string_list.c",
|
153
151
|
"src/util/pm_string.c",
|
154
152
|
"src/util/pm_strncasecmp.c",
|
155
153
|
"src/util/pm_strpbrk.c"
|