prism 0.29.0 → 1.3.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 +115 -1
- data/CONTRIBUTING.md +0 -4
- data/Makefile +1 -1
- data/README.md +4 -0
- data/config.yml +920 -148
- data/docs/build_system.md +8 -11
- data/docs/fuzzing.md +1 -1
- data/docs/parsing_rules.md +4 -1
- data/docs/relocation.md +34 -0
- data/docs/ripper_translation.md +22 -0
- data/docs/serialization.md +3 -0
- data/ext/prism/api_node.c +2863 -2079
- data/ext/prism/extconf.rb +14 -37
- data/ext/prism/extension.c +241 -391
- data/ext/prism/extension.h +2 -2
- data/include/prism/ast.h +2156 -453
- data/include/prism/defines.h +58 -7
- data/include/prism/diagnostic.h +24 -6
- data/include/prism/node.h +0 -21
- data/include/prism/options.h +94 -3
- data/include/prism/parser.h +82 -40
- 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 +47 -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 +55 -34
- data/lib/prism/dsl.rb +660 -468
- data/lib/prism/ffi.rb +113 -8
- data/lib/prism/inspect_visitor.rb +296 -64
- data/lib/prism/lex_compat.rb +1 -1
- data/lib/prism/mutation_compiler.rb +11 -6
- data/lib/prism/node.rb +4262 -5023
- 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 +183 -6
- data/lib/prism/reflection.rb +12 -10
- data/lib/prism/relocation.rb +504 -0
- data/lib/prism/serialize.rb +496 -609
- data/lib/prism/string_query.rb +30 -0
- data/lib/prism/translation/parser/compiler.rb +185 -155
- data/lib/prism/translation/parser/lexer.rb +26 -4
- data/lib/prism/translation/parser.rb +9 -4
- data/lib/prism/translation/ripper.rb +23 -25
- data/lib/prism/translation/ruby_parser.rb +86 -17
- data/lib/prism/visitor.rb +3 -0
- data/lib/prism.rb +6 -8
- data/prism.gemspec +9 -5
- data/rbi/prism/dsl.rbi +521 -0
- data/rbi/prism/node.rbi +1115 -1120
- data/rbi/prism/parse_result.rbi +29 -0
- data/rbi/prism/string_query.rbi +12 -0
- 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 +678 -632
- data/sig/prism/parse_result.rbs +22 -0
- data/sig/prism/relocation.rbs +185 -0
- data/sig/prism/string_query.rbs +11 -0
- data/sig/prism/visitor.rbs +1 -0
- data/sig/prism.rbs +103 -64
- data/src/diagnostic.c +64 -28
- data/src/node.c +502 -1739
- data/src/options.c +76 -27
- data/src/prettyprint.c +188 -112
- data/src/prism.c +3376 -2293
- data/src/regexp.c +208 -71
- data/src/serialize.c +182 -50
- data/src/static_literals.c +64 -85
- data/src/token_type.c +4 -4
- data/src/util/pm_char.c +1 -1
- 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 +131 -80
- data/src/util/pm_strpbrk.c +32 -6
- metadata +11 -7
- 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
@@ -134,7 +134,7 @@ module Prism
|
|
134
134
|
MINUS_GREATER: :tLAMBDA,
|
135
135
|
NEWLINE: :tNL,
|
136
136
|
NUMBERED_REFERENCE: :tNTH_REF,
|
137
|
-
PARENTHESIS_LEFT: :
|
137
|
+
PARENTHESIS_LEFT: :tLPAREN2,
|
138
138
|
PARENTHESIS_LEFT_PARENTHESES: :tLPAREN_ARG,
|
139
139
|
PARENTHESIS_RIGHT: :tRPAREN,
|
140
140
|
PERCENT: :tPERCENT,
|
@@ -173,7 +173,7 @@ module Prism
|
|
173
173
|
UMINUS_NUM: :tUNARY_NUM,
|
174
174
|
UPLUS: :tUPLUS,
|
175
175
|
USTAR: :tSTAR,
|
176
|
-
USTAR_STAR: :
|
176
|
+
USTAR_STAR: :tDSTAR,
|
177
177
|
WORDS_SEP: :tSPACE
|
178
178
|
}
|
179
179
|
|
@@ -187,7 +187,20 @@ module Prism
|
|
187
187
|
EXPR_BEG = 0x1 # :nodoc:
|
188
188
|
EXPR_LABEL = 0x400 # :nodoc:
|
189
189
|
|
190
|
-
|
190
|
+
# It is used to determine whether `do` is of the token type `kDO` or `kDO_LAMBDA`.
|
191
|
+
#
|
192
|
+
# NOTE: In edge cases like `-> (foo = -> (bar) {}) do end`, please note that `kDO` is still returned
|
193
|
+
# instead of `kDO_LAMBDA`, which is expected: https://github.com/ruby/prism/pull/3046
|
194
|
+
LAMBDA_TOKEN_TYPES = [:kDO_LAMBDA, :tLAMBDA, :tLAMBEG]
|
195
|
+
|
196
|
+
# The `PARENTHESIS_LEFT` token in Prism is classified as either `tLPAREN` or `tLPAREN2` in the Parser gem.
|
197
|
+
# The following token types are listed as those classified as `tLPAREN`.
|
198
|
+
LPAREN_CONVERSION_TOKEN_TYPES = [
|
199
|
+
:kBREAK, :kCASE, :tDIVIDE, :kFOR, :kIF, :kNEXT, :kRETURN, :kUNTIL, :kWHILE, :tAMPER, :tANDOP, :tBANG, :tCOMMA, :tDOT2, :tDOT3,
|
200
|
+
:tEQL, :tLPAREN, :tLPAREN2, :tLSHFT, :tNL, :tOP_ASGN, :tOROP, :tPIPE, :tSEMI, :tSTRING_DBEG, :tUMINUS, :tUPLUS
|
201
|
+
]
|
202
|
+
|
203
|
+
private_constant :TYPES, :EXPR_BEG, :EXPR_LABEL, :LAMBDA_TOKEN_TYPES, :LPAREN_CONVERSION_TOKEN_TYPES
|
191
204
|
|
192
205
|
# The Parser::Source::Buffer that the tokens were lexed from.
|
193
206
|
attr_reader :source_buffer
|
@@ -229,6 +242,13 @@ module Prism
|
|
229
242
|
location = Range.new(source_buffer, offset_cache[token.location.start_offset], offset_cache[token.location.end_offset])
|
230
243
|
|
231
244
|
case type
|
245
|
+
when :kDO
|
246
|
+
types = tokens.map(&:first)
|
247
|
+
nearest_lambda_token_type = types.reverse.find { |type| LAMBDA_TOKEN_TYPES.include?(type) }
|
248
|
+
|
249
|
+
if nearest_lambda_token_type == :tLAMBDA
|
250
|
+
type = :kDO_LAMBDA
|
251
|
+
end
|
232
252
|
when :tCHARACTER
|
233
253
|
value.delete_prefix!("?")
|
234
254
|
when :tCOMMENT
|
@@ -268,6 +288,8 @@ module Prism
|
|
268
288
|
value.chomp!(":")
|
269
289
|
when :tLCURLY
|
270
290
|
type = :tLBRACE if state == EXPR_BEG | EXPR_LABEL
|
291
|
+
when :tLPAREN2
|
292
|
+
type = :tLPAREN if tokens.empty? || LPAREN_CONVERSION_TOKEN_TYPES.include?(tokens.dig(-1, 0))
|
271
293
|
when :tNTH_REF
|
272
294
|
value = parse_integer(value.delete_prefix("$"))
|
273
295
|
when :tOP_ASGN
|
@@ -339,7 +361,7 @@ module Prism
|
|
339
361
|
location = Range.new(source_buffer, offset_cache[token.location.start_offset], offset_cache[token.location.start_offset + 1])
|
340
362
|
end
|
341
363
|
when :tSYMBEG
|
342
|
-
if (next_token = lexed[index][0]) && next_token.type != :STRING_CONTENT && next_token.type != :EMBEXPR_BEGIN && next_token.type != :EMBVAR
|
364
|
+
if (next_token = lexed[index][0]) && next_token.type != :STRING_CONTENT && next_token.type != :EMBEXPR_BEGIN && next_token.type != :EMBVAR && next_token.type != :STRING_END
|
343
365
|
next_location = token.location.join(next_token.location)
|
344
366
|
type = :tSYMBOL
|
345
367
|
value = next_token.value
|
@@ -1,6 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
begin
|
4
|
+
require "parser"
|
5
|
+
rescue LoadError
|
6
|
+
warn(%q{Error: Unable to load parser. Add `gem "parser"` to your Gemfile.})
|
7
|
+
exit(1)
|
8
|
+
end
|
4
9
|
|
5
10
|
module Prism
|
6
11
|
module Translation
|
@@ -46,7 +51,7 @@ module Prism
|
|
46
51
|
source = source_buffer.source
|
47
52
|
|
48
53
|
offset_cache = build_offset_cache(source)
|
49
|
-
result = unwrap(Prism.parse(source, filepath: source_buffer.name, version: convert_for_prism(version),
|
54
|
+
result = unwrap(Prism.parse(source, filepath: source_buffer.name, version: convert_for_prism(version), partial_script: true, encoding: false), offset_cache)
|
50
55
|
|
51
56
|
build_ast(result.value, offset_cache)
|
52
57
|
ensure
|
@@ -59,7 +64,7 @@ module Prism
|
|
59
64
|
source = source_buffer.source
|
60
65
|
|
61
66
|
offset_cache = build_offset_cache(source)
|
62
|
-
result = unwrap(Prism.parse(source, filepath: source_buffer.name, version: convert_for_prism(version),
|
67
|
+
result = unwrap(Prism.parse(source, filepath: source_buffer.name, version: convert_for_prism(version), partial_script: true, encoding: false), offset_cache)
|
63
68
|
|
64
69
|
[
|
65
70
|
build_ast(result.value, offset_cache),
|
@@ -78,7 +83,7 @@ module Prism
|
|
78
83
|
offset_cache = build_offset_cache(source)
|
79
84
|
result =
|
80
85
|
begin
|
81
|
-
unwrap(Prism.parse_lex(source, filepath: source_buffer.name, version: convert_for_prism(version),
|
86
|
+
unwrap(Prism.parse_lex(source, filepath: source_buffer.name, version: convert_for_prism(version), partial_script: true, encoding: false), offset_cache)
|
82
87
|
rescue ::Parser::SyntaxError
|
83
88
|
raise if !recover
|
84
89
|
end
|
@@ -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 =
|
@@ -3267,11 +3269,7 @@ module Prism
|
|
3267
3269
|
|
3268
3270
|
# Lazily initialize the parse result.
|
3269
3271
|
def result
|
3270
|
-
@result ||=
|
3271
|
-
begin
|
3272
|
-
scopes = RUBY_VERSION >= "3.3.0" ? [] : [[]]
|
3273
|
-
Prism.parse(source, scopes: scopes)
|
3274
|
-
end
|
3272
|
+
@result ||= Prism.parse(source, partial_script: true)
|
3275
3273
|
end
|
3276
3274
|
|
3277
3275
|
##########################################################################
|
@@ -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
|
@@ -859,6 +881,7 @@ module Prism
|
|
859
881
|
# Visit the interpolated content of the string-like node.
|
860
882
|
private def visit_interpolated_parts(parts)
|
861
883
|
visited = []
|
884
|
+
|
862
885
|
parts.each do |part|
|
863
886
|
result = visit(part)
|
864
887
|
|
@@ -870,14 +893,25 @@ module Prism
|
|
870
893
|
else
|
871
894
|
visited << result
|
872
895
|
end
|
896
|
+
visited << :space
|
897
|
+
elsif result[0] == :dstr
|
898
|
+
if !visited.empty? && part.parts[0].is_a?(StringNode)
|
899
|
+
# If we are in the middle of an implicitly concatenated string,
|
900
|
+
# we should not have a bare string as the first part. In this
|
901
|
+
# case we need to visit just that first part and then we can
|
902
|
+
# push the rest of the parts onto the visited array.
|
903
|
+
result[1] = visit(part.parts[0])
|
904
|
+
end
|
905
|
+
visited.concat(result[1..-1])
|
873
906
|
else
|
874
907
|
visited << result
|
875
908
|
end
|
876
909
|
end
|
877
910
|
|
878
911
|
state = :beginning #: :beginning | :string_content | :interpolated_content
|
912
|
+
results = []
|
879
913
|
|
880
|
-
visited.
|
914
|
+
visited.each_with_index do |result, index|
|
881
915
|
case state
|
882
916
|
when :beginning
|
883
917
|
if result.is_a?(String)
|
@@ -892,7 +926,9 @@ module Prism
|
|
892
926
|
state = :interpolated_content
|
893
927
|
end
|
894
928
|
when :string_content
|
895
|
-
if result
|
929
|
+
if result == :space
|
930
|
+
# continue
|
931
|
+
elsif result.is_a?(String)
|
896
932
|
results[0] << result
|
897
933
|
elsif result.is_a?(Array) && result[0] == :str
|
898
934
|
results[0] << result[1]
|
@@ -900,10 +936,25 @@ module Prism
|
|
900
936
|
results << result
|
901
937
|
state = :interpolated_content
|
902
938
|
end
|
903
|
-
|
904
|
-
|
939
|
+
when :interpolated_content
|
940
|
+
if result == :space
|
941
|
+
# continue
|
942
|
+
elsif visited[index - 1] != :space && result.is_a?(Array) && result[0] == :str && results[-1][0] == :str && (results[-1].line_max == result.line)
|
943
|
+
results[-1][1] << result[1]
|
944
|
+
results[-1].line_max = result.line_max
|
945
|
+
else
|
946
|
+
results << result
|
947
|
+
end
|
905
948
|
end
|
906
949
|
end
|
950
|
+
|
951
|
+
results
|
952
|
+
end
|
953
|
+
|
954
|
+
# -> { it }
|
955
|
+
# ^^
|
956
|
+
def visit_it_local_variable_read_node(node)
|
957
|
+
s(node, :call, nil, :it)
|
907
958
|
end
|
908
959
|
|
909
960
|
# foo(bar: baz)
|
@@ -1118,7 +1169,19 @@ module Prism
|
|
1118
1169
|
# a or b
|
1119
1170
|
# ^^^^^^
|
1120
1171
|
def visit_or_node(node)
|
1121
|
-
|
1172
|
+
left = visit(node.left)
|
1173
|
+
|
1174
|
+
if left[0] == :or
|
1175
|
+
# ruby_parser has the or keyword as right-associative as opposed to
|
1176
|
+
# prism which has it as left-associative. We reverse that
|
1177
|
+
# associativity here.
|
1178
|
+
nest = left
|
1179
|
+
nest = nest[2] while nest[2][0] == :or
|
1180
|
+
nest[2] = s(node, :or, nest[2], visit(node.right))
|
1181
|
+
left
|
1182
|
+
else
|
1183
|
+
s(node, :or, left, visit(node.right))
|
1184
|
+
end
|
1122
1185
|
end
|
1123
1186
|
|
1124
1187
|
# def foo(bar, *baz); end
|
@@ -1374,7 +1437,13 @@ module Prism
|
|
1374
1437
|
# "foo"
|
1375
1438
|
# ^^^^^
|
1376
1439
|
def visit_string_node(node)
|
1377
|
-
|
1440
|
+
unescaped = node.unescaped
|
1441
|
+
|
1442
|
+
if node.forced_binary_encoding?
|
1443
|
+
unescaped.force_encoding(Encoding::BINARY)
|
1444
|
+
end
|
1445
|
+
|
1446
|
+
s(node, :str, unescaped)
|
1378
1447
|
end
|
1379
1448
|
|
1380
1449
|
# super(foo)
|
@@ -1416,7 +1485,7 @@ module Prism
|
|
1416
1485
|
# bar unless foo
|
1417
1486
|
# ^^^^^^^^^^^^^^
|
1418
1487
|
def visit_unless_node(node)
|
1419
|
-
s(node, :if, visit(node.predicate), visit(node.
|
1488
|
+
s(node, :if, visit(node.predicate), visit(node.else_clause), visit(node.statements))
|
1420
1489
|
end
|
1421
1490
|
|
1422
1491
|
# until foo; bar end
|
@@ -1536,13 +1605,13 @@ module Prism
|
|
1536
1605
|
# Parse the given source and translate it into the seattlerb/ruby_parser
|
1537
1606
|
# gem's Sexp format.
|
1538
1607
|
def parse(source, filepath = "(string)")
|
1539
|
-
translate(Prism.parse(source, filepath: filepath,
|
1608
|
+
translate(Prism.parse(source, filepath: filepath, partial_script: true), filepath)
|
1540
1609
|
end
|
1541
1610
|
|
1542
1611
|
# Parse the given file and translate it into the seattlerb/ruby_parser
|
1543
1612
|
# gem's Sexp format.
|
1544
1613
|
def parse_file(filepath)
|
1545
|
-
translate(Prism.parse_file(filepath,
|
1614
|
+
translate(Prism.parse_file(filepath, partial_script: true), filepath)
|
1546
1615
|
end
|
1547
1616
|
|
1548
1617
|
class << self
|
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"
|
@@ -25,14 +24,15 @@ module Prism
|
|
25
24
|
autoload :Pack, "prism/pack"
|
26
25
|
autoload :Pattern, "prism/pattern"
|
27
26
|
autoload :Reflection, "prism/reflection"
|
27
|
+
autoload :Relocation, "prism/relocation"
|
28
28
|
autoload :Serialize, "prism/serialize"
|
29
|
+
autoload :StringQuery, "prism/string_query"
|
29
30
|
autoload :Translation, "prism/translation"
|
30
31
|
autoload :Visitor, "prism/visitor"
|
31
32
|
|
32
33
|
# Some of these constants are not meant to be exposed, so marking them as
|
33
34
|
# private here.
|
34
35
|
|
35
|
-
private_constant :Debug
|
36
36
|
private_constant :LexCompat
|
37
37
|
private_constant :LexRipper
|
38
38
|
|
@@ -71,21 +71,19 @@ require_relative "prism/polyfill/byteindex"
|
|
71
71
|
require_relative "prism/node"
|
72
72
|
require_relative "prism/node_ext"
|
73
73
|
require_relative "prism/parse_result"
|
74
|
-
require_relative "prism/parse_result/comments"
|
75
|
-
require_relative "prism/parse_result/newlines"
|
76
74
|
|
77
75
|
# This is a Ruby implementation of the prism parser. If we're running on CRuby
|
78
76
|
# and we haven't explicitly set the PRISM_FFI_BACKEND environment variable, then
|
79
77
|
# it's going to require the built library. Otherwise, it's going to require a
|
80
78
|
# module that uses FFI to call into the library.
|
81
79
|
if RUBY_ENGINE == "ruby" and !ENV["PRISM_FFI_BACKEND"]
|
82
|
-
require "prism/prism"
|
83
|
-
|
84
80
|
# The C extension is the default backend on CRuby.
|
85
81
|
Prism::BACKEND = :CEXT
|
86
|
-
else
|
87
|
-
require_relative "prism/ffi"
|
88
82
|
|
83
|
+
require "prism/prism"
|
84
|
+
else
|
89
85
|
# The FFI backend is used on other Ruby implementations.
|
90
86
|
Prism::BACKEND = :FFI
|
87
|
+
|
88
|
+
require_relative "prism/ffi"
|
91
89
|
end
|
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.3.0"
|
6
6
|
spec.authors = ["Shopify"]
|
7
7
|
spec.email = ["ruby@shopify.com"]
|
8
8
|
|
@@ -35,6 +35,7 @@ Gem::Specification.new do |spec|
|
|
35
35
|
"docs/parser_translation.md",
|
36
36
|
"docs/parsing_rules.md",
|
37
37
|
"docs/releasing.md",
|
38
|
+
"docs/relocation.md",
|
38
39
|
"docs/ripper_translation.md",
|
39
40
|
"docs/ruby_api.md",
|
40
41
|
"docs/ruby_parser_translation.md",
|
@@ -65,12 +66,10 @@ Gem::Specification.new do |spec|
|
|
65
66
|
"include/prism/util/pm_newline_list.h",
|
66
67
|
"include/prism/util/pm_strncasecmp.h",
|
67
68
|
"include/prism/util/pm_string.h",
|
68
|
-
"include/prism/util/pm_string_list.h",
|
69
69
|
"include/prism/util/pm_strpbrk.h",
|
70
70
|
"include/prism/version.h",
|
71
71
|
"lib/prism.rb",
|
72
72
|
"lib/prism/compiler.rb",
|
73
|
-
"lib/prism/debug.rb",
|
74
73
|
"lib/prism/desugar_compiler.rb",
|
75
74
|
"lib/prism/dispatcher.rb",
|
76
75
|
"lib/prism/dot_visitor.rb",
|
@@ -84,19 +83,21 @@ Gem::Specification.new do |spec|
|
|
84
83
|
"lib/prism/pack.rb",
|
85
84
|
"lib/prism/parse_result.rb",
|
86
85
|
"lib/prism/parse_result/comments.rb",
|
86
|
+
"lib/prism/parse_result/errors.rb",
|
87
87
|
"lib/prism/parse_result/newlines.rb",
|
88
88
|
"lib/prism/pattern.rb",
|
89
89
|
"lib/prism/polyfill/byteindex.rb",
|
90
90
|
"lib/prism/polyfill/unpack1.rb",
|
91
91
|
"lib/prism/reflection.rb",
|
92
|
+
"lib/prism/relocation.rb",
|
92
93
|
"lib/prism/serialize.rb",
|
94
|
+
"lib/prism/string_query.rb",
|
93
95
|
"lib/prism/translation.rb",
|
94
96
|
"lib/prism/translation/parser.rb",
|
95
97
|
"lib/prism/translation/parser33.rb",
|
96
98
|
"lib/prism/translation/parser34.rb",
|
97
99
|
"lib/prism/translation/parser/compiler.rb",
|
98
100
|
"lib/prism/translation/parser/lexer.rb",
|
99
|
-
"lib/prism/translation/parser/rubocop.rb",
|
100
101
|
"lib/prism/translation/ripper.rb",
|
101
102
|
"lib/prism/translation/ripper/sexp.rb",
|
102
103
|
"lib/prism/translation/ripper/shim.rb",
|
@@ -105,11 +106,13 @@ Gem::Specification.new do |spec|
|
|
105
106
|
"prism.gemspec",
|
106
107
|
"rbi/prism.rbi",
|
107
108
|
"rbi/prism/compiler.rbi",
|
109
|
+
"rbi/prism/dsl.rbi",
|
108
110
|
"rbi/prism/inspect_visitor.rbi",
|
109
111
|
"rbi/prism/node_ext.rbi",
|
110
112
|
"rbi/prism/node.rbi",
|
111
113
|
"rbi/prism/parse_result.rbi",
|
112
114
|
"rbi/prism/reflection.rbi",
|
115
|
+
"rbi/prism/string_query.rbi",
|
113
116
|
"rbi/prism/translation/parser.rbi",
|
114
117
|
"rbi/prism/translation/parser33.rbi",
|
115
118
|
"rbi/prism/translation/parser34.rbi",
|
@@ -129,7 +132,9 @@ Gem::Specification.new do |spec|
|
|
129
132
|
"sig/prism/parse_result.rbs",
|
130
133
|
"sig/prism/pattern.rbs",
|
131
134
|
"sig/prism/reflection.rbs",
|
135
|
+
"sig/prism/relocation.rbs",
|
132
136
|
"sig/prism/serialize.rbs",
|
137
|
+
"sig/prism/string_query.rbs",
|
133
138
|
"sig/prism/visitor.rbs",
|
134
139
|
"src/diagnostic.c",
|
135
140
|
"src/encoding.c",
|
@@ -149,7 +154,6 @@ Gem::Specification.new do |spec|
|
|
149
154
|
"src/util/pm_list.c",
|
150
155
|
"src/util/pm_memchr.c",
|
151
156
|
"src/util/pm_newline_list.c",
|
152
|
-
"src/util/pm_string_list.c",
|
153
157
|
"src/util/pm_string.c",
|
154
158
|
"src/util/pm_strncasecmp.c",
|
155
159
|
"src/util/pm_strpbrk.c"
|