prism 0.18.0 → 0.19.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|