prism 0.18.0 → 0.19.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 +31 -1
- data/README.md +2 -1
- data/config.yml +188 -55
- data/docs/building.md +9 -2
- data/docs/configuration.md +10 -9
- data/docs/encoding.md +24 -56
- data/docs/local_variable_depth.md +229 -0
- data/docs/ruby_api.md +2 -0
- data/docs/serialization.md +18 -13
- data/ext/prism/api_node.c +337 -195
- data/ext/prism/extconf.rb +13 -7
- data/ext/prism/extension.c +96 -32
- data/ext/prism/extension.h +1 -1
- data/include/prism/ast.h +340 -137
- data/include/prism/defines.h +17 -0
- data/include/prism/diagnostic.h +11 -5
- data/include/prism/encoding.h +248 -0
- data/include/prism/options.h +2 -2
- data/include/prism/parser.h +62 -42
- data/include/prism/regexp.h +2 -2
- data/include/prism/util/pm_buffer.h +9 -1
- data/include/prism/util/pm_memchr.h +2 -2
- data/include/prism/util/pm_strpbrk.h +3 -3
- data/include/prism/version.h +2 -2
- data/include/prism.h +13 -15
- data/lib/prism/compiler.rb +12 -0
- data/lib/prism/debug.rb +9 -4
- data/lib/prism/desugar_compiler.rb +3 -3
- data/lib/prism/dispatcher.rb +56 -0
- data/lib/prism/dot_visitor.rb +476 -198
- data/lib/prism/dsl.rb +66 -46
- data/lib/prism/ffi.rb +16 -3
- data/lib/prism/lex_compat.rb +19 -9
- data/lib/prism/mutation_compiler.rb +20 -0
- data/lib/prism/node.rb +1173 -450
- data/lib/prism/node_ext.rb +41 -16
- data/lib/prism/parse_result.rb +12 -15
- data/lib/prism/ripper_compat.rb +49 -34
- data/lib/prism/serialize.rb +242 -212
- data/lib/prism/visitor.rb +12 -0
- data/lib/prism.rb +20 -4
- data/prism.gemspec +4 -10
- data/rbi/prism.rbi +605 -230
- data/rbi/prism_static.rbi +3 -0
- data/sig/prism.rbs +379 -124
- data/sig/prism_static.rbs +1 -0
- data/src/diagnostic.c +228 -222
- data/src/encoding.c +5137 -0
- data/src/node.c +66 -0
- data/src/options.c +21 -2
- data/src/prettyprint.c +806 -406
- data/src/prism.c +1092 -700
- data/src/regexp.c +3 -3
- data/src/serialize.c +227 -157
- data/src/util/pm_buffer.c +10 -1
- data/src/util/pm_memchr.c +1 -1
- data/src/util/pm_strpbrk.c +4 -4
- metadata +5 -11
- data/include/prism/enc/pm_encoding.h +0 -227
- data/src/enc/pm_big5.c +0 -116
- data/src/enc/pm_cp51932.c +0 -57
- data/src/enc/pm_euc_jp.c +0 -69
- data/src/enc/pm_gbk.c +0 -65
- data/src/enc/pm_shift_jis.c +0 -57
- data/src/enc/pm_tables.c +0 -2073
- data/src/enc/pm_unicode.c +0 -2369
- data/src/enc/pm_windows_31j.c +0 -57
data/lib/prism/node_ext.rb
CHANGED
@@ -14,8 +14,49 @@ module Prism
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
+
class InterpolatedMatchLastLineNode < Node
|
18
|
+
include RegularExpressionOptions
|
19
|
+
end
|
20
|
+
|
21
|
+
class InterpolatedRegularExpressionNode < Node
|
22
|
+
include RegularExpressionOptions
|
23
|
+
end
|
24
|
+
|
25
|
+
class MatchLastLineNode < Node
|
26
|
+
include RegularExpressionOptions
|
27
|
+
end
|
28
|
+
|
29
|
+
class RegularExpressionNode < Node
|
30
|
+
include RegularExpressionOptions
|
31
|
+
end
|
32
|
+
|
17
33
|
private_constant :RegularExpressionOptions
|
18
34
|
|
35
|
+
module HeredocQuery # :nodoc:
|
36
|
+
# Returns true if this node was represented as a heredoc in the source code.
|
37
|
+
def heredoc?
|
38
|
+
opening&.start_with?("<<")
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
class InterpolatedStringNode < Node
|
43
|
+
include HeredocQuery
|
44
|
+
end
|
45
|
+
|
46
|
+
class InterpolatedXStringNode < Node
|
47
|
+
include HeredocQuery
|
48
|
+
end
|
49
|
+
|
50
|
+
class StringNode < Node
|
51
|
+
include HeredocQuery
|
52
|
+
end
|
53
|
+
|
54
|
+
class XStringNode < Node
|
55
|
+
include HeredocQuery
|
56
|
+
end
|
57
|
+
|
58
|
+
private_constant :HeredocQuery
|
59
|
+
|
19
60
|
class FloatNode < Node
|
20
61
|
# Returns the value of the node as a Ruby Float.
|
21
62
|
def value
|
@@ -37,18 +78,6 @@ module Prism
|
|
37
78
|
end
|
38
79
|
end
|
39
80
|
|
40
|
-
class InterpolatedMatchLastLineNode < Node
|
41
|
-
include RegularExpressionOptions
|
42
|
-
end
|
43
|
-
|
44
|
-
class InterpolatedRegularExpressionNode < Node
|
45
|
-
include RegularExpressionOptions
|
46
|
-
end
|
47
|
-
|
48
|
-
class MatchLastLineNode < Node
|
49
|
-
include RegularExpressionOptions
|
50
|
-
end
|
51
|
-
|
52
81
|
class RationalNode < Node
|
53
82
|
# Returns the value of the node as a Ruby Rational.
|
54
83
|
def value
|
@@ -56,10 +85,6 @@ module Prism
|
|
56
85
|
end
|
57
86
|
end
|
58
87
|
|
59
|
-
class RegularExpressionNode < Node
|
60
|
-
include RegularExpressionOptions
|
61
|
-
end
|
62
|
-
|
63
88
|
class ConstantReadNode < Node
|
64
89
|
# Returns the list of parts for the full name of this constant.
|
65
90
|
# For example: [:Foo]
|
data/lib/prism/parse_result.rb
CHANGED
@@ -238,11 +238,6 @@ module Prism
|
|
238
238
|
def deconstruct_keys(keys)
|
239
239
|
{ location: location }
|
240
240
|
end
|
241
|
-
|
242
|
-
# This can only be true for inline comments.
|
243
|
-
def trailing?
|
244
|
-
false
|
245
|
-
end
|
246
241
|
end
|
247
242
|
|
248
243
|
# InlineComment objects are the most common. They correspond to comments in
|
@@ -263,18 +258,14 @@ module Prism
|
|
263
258
|
# EmbDocComment objects correspond to comments that are surrounded by =begin
|
264
259
|
# and =end.
|
265
260
|
class EmbDocComment < Comment
|
266
|
-
#
|
267
|
-
def
|
268
|
-
|
261
|
+
# This can only be true for inline comments.
|
262
|
+
def trailing?
|
263
|
+
false
|
269
264
|
end
|
270
|
-
end
|
271
265
|
|
272
|
-
# DATAComment objects correspond to comments that are after the __END__
|
273
|
-
# keyword in a source file.
|
274
|
-
class DATAComment < Comment
|
275
266
|
# Returns a string representation of this comment.
|
276
267
|
def inspect
|
277
|
-
"#<Prism::
|
268
|
+
"#<Prism::EmbDocComment @location=#{location.inspect}>"
|
278
269
|
end
|
279
270
|
end
|
280
271
|
|
@@ -378,6 +369,11 @@ module Prism
|
|
378
369
|
# The list of magic comments that were encountered during parsing.
|
379
370
|
attr_reader :magic_comments
|
380
371
|
|
372
|
+
# An optional location that represents the location of the content after the
|
373
|
+
# __END__ marker. This content is loaded into the DATA constant when the
|
374
|
+
# file being parsed is the main file being executed.
|
375
|
+
attr_reader :data_loc
|
376
|
+
|
381
377
|
# The list of errors that were generated during parsing.
|
382
378
|
attr_reader :errors
|
383
379
|
|
@@ -388,10 +384,11 @@ module Prism
|
|
388
384
|
attr_reader :source
|
389
385
|
|
390
386
|
# Create a new parse result object with the given values.
|
391
|
-
def initialize(value, comments, magic_comments, errors, warnings, source)
|
387
|
+
def initialize(value, comments, magic_comments, data_loc, errors, warnings, source)
|
392
388
|
@value = value
|
393
389
|
@comments = comments
|
394
390
|
@magic_comments = magic_comments
|
391
|
+
@data_loc = data_loc
|
395
392
|
@errors = errors
|
396
393
|
@warnings = warnings
|
397
394
|
@source = source
|
@@ -399,7 +396,7 @@ module Prism
|
|
399
396
|
|
400
397
|
# Implement the hash pattern matching interface for ParseResult.
|
401
398
|
def deconstruct_keys(keys)
|
402
|
-
{ value: value, comments: comments, magic_comments: magic_comments, errors: errors, warnings: warnings }
|
399
|
+
{ value: value, comments: comments, magic_comments: magic_comments, data_loc: data_loc, errors: errors, warnings: warnings }
|
403
400
|
end
|
404
401
|
|
405
402
|
# Returns true if there were no errors during parsing and false if there
|
data/lib/prism/ripper_compat.rb
CHANGED
@@ -3,6 +3,10 @@
|
|
3
3
|
require "ripper"
|
4
4
|
|
5
5
|
module Prism
|
6
|
+
# Note: This integration is not finished, and therefore still has many
|
7
|
+
# inconsistencies with Ripper. If you'd like to help out, pull requests would
|
8
|
+
# be greatly appreciated!
|
9
|
+
#
|
6
10
|
# This class is meant to provide a compatibility layer between prism and
|
7
11
|
# Ripper. It functions by parsing the entire tree first and then walking it
|
8
12
|
# and executing each of the Ripper callbacks as it goes.
|
@@ -10,7 +14,10 @@ module Prism
|
|
10
14
|
# This class is going to necessarily be slower than the native Ripper API. It
|
11
15
|
# is meant as a stopgap until developers migrate to using prism. It is also
|
12
16
|
# meant as a test harness for the prism parser.
|
13
|
-
|
17
|
+
#
|
18
|
+
# To use this class, you treat `Prism::RipperCompat` effectively as you would
|
19
|
+
# treat the `Ripper` class.
|
20
|
+
class RipperCompat < Visitor
|
14
21
|
# This class mirrors the ::Ripper::SexpBuilder subclass of ::Ripper that
|
15
22
|
# returns the arrays of [type, *children].
|
16
23
|
class SexpBuilder < RipperCompat
|
@@ -77,43 +84,63 @@ module Prism
|
|
77
84
|
|
78
85
|
# True if the parser encountered an error during parsing.
|
79
86
|
def error?
|
80
|
-
result.
|
87
|
+
result.failure?
|
81
88
|
end
|
82
89
|
|
83
90
|
# Parse the source and return the result.
|
84
91
|
def parse
|
85
|
-
result.
|
92
|
+
result.magic_comments.each do |magic_comment|
|
93
|
+
on_magic_comment(magic_comment.key, magic_comment.value)
|
94
|
+
end
|
95
|
+
|
96
|
+
if error?
|
97
|
+
result.errors.each do |error|
|
98
|
+
on_parse_error(error.message)
|
99
|
+
end
|
100
|
+
else
|
101
|
+
result.value.accept(self)
|
102
|
+
end
|
86
103
|
end
|
87
104
|
|
88
105
|
############################################################################
|
89
106
|
# Visitor methods
|
90
107
|
############################################################################
|
91
108
|
|
92
|
-
# This method is responsible for dispatching to the correct visitor method
|
93
|
-
# based on the type of the node.
|
94
|
-
def visit(node)
|
95
|
-
node&.accept(self)
|
96
|
-
end
|
97
|
-
|
98
109
|
# Visit a CallNode node.
|
99
110
|
def visit_call_node(node)
|
100
|
-
if !node.opening_loc && node.arguments
|
101
|
-
bounds(node.receiver.location)
|
111
|
+
if !node.message.match?(/^[[:alpha:]_]/) && node.opening_loc.nil? && node.arguments&.arguments&.length == 1
|
102
112
|
left = visit(node.receiver)
|
103
|
-
|
104
|
-
bounds(node.arguments.arguments.first.location)
|
105
113
|
right = visit(node.arguments.arguments.first)
|
106
114
|
|
107
|
-
|
115
|
+
bounds(node.location)
|
116
|
+
on_binary(left, node.name, right)
|
108
117
|
else
|
109
118
|
raise NotImplementedError
|
110
119
|
end
|
111
120
|
end
|
112
121
|
|
122
|
+
# Visit a FloatNode node.
|
123
|
+
def visit_float_node(node)
|
124
|
+
bounds(node.location)
|
125
|
+
on_float(node.slice)
|
126
|
+
end
|
127
|
+
|
128
|
+
# Visit a ImaginaryNode node.
|
129
|
+
def visit_imaginary_node(node)
|
130
|
+
bounds(node.location)
|
131
|
+
on_imaginary(node.slice)
|
132
|
+
end
|
133
|
+
|
113
134
|
# Visit an IntegerNode node.
|
114
135
|
def visit_integer_node(node)
|
115
136
|
bounds(node.location)
|
116
|
-
on_int(
|
137
|
+
on_int(node.slice)
|
138
|
+
end
|
139
|
+
|
140
|
+
# Visit a RationalNode node.
|
141
|
+
def visit_rational_node(node)
|
142
|
+
bounds(node.location)
|
143
|
+
on_rational(node.slice)
|
117
144
|
end
|
118
145
|
|
119
146
|
# Visit a StatementsNode node.
|
@@ -124,24 +151,11 @@ module Prism
|
|
124
151
|
end
|
125
152
|
end
|
126
153
|
|
127
|
-
# Visit a token found during parsing.
|
128
|
-
def visit_token(node)
|
129
|
-
bounds(node.location)
|
130
|
-
|
131
|
-
case node.type
|
132
|
-
when :MINUS
|
133
|
-
on_op(node.value)
|
134
|
-
when :PLUS
|
135
|
-
on_op(node.value)
|
136
|
-
else
|
137
|
-
raise NotImplementedError, "Unknown token: #{node.type}"
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
154
|
# Visit a ProgramNode node.
|
142
155
|
def visit_program_node(node)
|
156
|
+
statements = visit(node.statements)
|
143
157
|
bounds(node.location)
|
144
|
-
on_program(
|
158
|
+
on_program(statements)
|
145
159
|
end
|
146
160
|
|
147
161
|
############################################################################
|
@@ -166,10 +180,8 @@ module Prism
|
|
166
180
|
# This method could be drastically improved with some caching on the start
|
167
181
|
# of every line, but for now it's good enough.
|
168
182
|
def bounds(location)
|
169
|
-
|
170
|
-
|
171
|
-
@lineno = source[0..start_offset].count("\n") + 1
|
172
|
-
@column = start_offset - (source.rindex("\n", start_offset) || 0)
|
183
|
+
@lineno = location.start_line
|
184
|
+
@column = location.start_column
|
173
185
|
end
|
174
186
|
|
175
187
|
# Lazily initialize the parse result.
|
@@ -185,6 +197,9 @@ module Prism
|
|
185
197
|
def _dispatch5(_, _, _, _, _); end # :nodoc:
|
186
198
|
def _dispatch7(_, _, _, _, _, _, _); end # :nodoc:
|
187
199
|
|
200
|
+
alias_method :on_parse_error, :_dispatch1
|
201
|
+
alias_method :on_magic_comment, :_dispatch2
|
202
|
+
|
188
203
|
(Ripper::SCANNER_EVENT_TABLE.merge(Ripper::PARSER_EVENT_TABLE)).each do |event, arity|
|
189
204
|
alias_method :"on_#{event}", :"_dispatch#{arity}"
|
190
205
|
end
|