prism 1.1.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 +39 -1
- data/Makefile +1 -1
- data/config.yml +422 -3
- data/docs/build_system.md +8 -11
- data/docs/relocation.md +34 -0
- data/ext/prism/api_node.c +18 -10
- data/ext/prism/extconf.rb +13 -36
- data/ext/prism/extension.c +68 -0
- data/ext/prism/extension.h +1 -1
- data/include/prism/ast.h +427 -3
- data/include/prism/defines.h +22 -7
- data/include/prism/diagnostic.h +1 -0
- data/include/prism/parser.h +25 -12
- data/include/prism/version.h +2 -2
- data/include/prism.h +47 -0
- data/lib/prism/dot_visitor.rb +10 -0
- data/lib/prism/dsl.rb +4 -4
- data/lib/prism/ffi.rb +49 -2
- data/lib/prism/inspect_visitor.rb +2 -0
- data/lib/prism/node.rb +1839 -96
- data/lib/prism/parse_result/errors.rb +1 -1
- data/lib/prism/parse_result.rb +140 -3
- data/lib/prism/reflection.rb +2 -2
- data/lib/prism/relocation.rb +504 -0
- data/lib/prism/serialize.rb +17 -5
- data/lib/prism/string_query.rb +30 -0
- data/lib/prism/translation/parser/compiler.rb +36 -26
- data/lib/prism/translation/parser.rb +3 -3
- data/lib/prism/translation/ripper.rb +1 -5
- data/lib/prism/translation/ruby_parser.rb +14 -5
- data/lib/prism.rb +6 -4
- data/prism.gemspec +7 -1
- data/rbi/prism/dsl.rbi +4 -4
- data/rbi/prism/node.rbi +5118 -1030
- data/rbi/prism/parse_result.rbi +29 -0
- data/rbi/prism/string_query.rbi +12 -0
- data/rbi/prism.rbi +34 -34
- data/sig/prism/dsl.rbs +2 -2
- data/sig/prism/node.rbs +13 -98
- data/sig/prism/parse_result.rbs +20 -0
- data/sig/prism/relocation.rbs +185 -0
- data/sig/prism/string_query.rbs +11 -0
- data/src/diagnostic.c +3 -1
- data/src/node.c +18 -0
- data/src/prettyprint.c +32 -0
- data/src/prism.c +586 -195
- data/src/regexp.c +7 -3
- data/src/serialize.c +12 -0
- data/src/static_literals.c +1 -1
- data/src/util/pm_char.c +1 -1
- data/src/util/pm_string.c +1 -0
- metadata +9 -3
data/include/prism/defines.h
CHANGED
@@ -137,14 +137,15 @@
|
|
137
137
|
#endif
|
138
138
|
|
139
139
|
/**
|
140
|
-
* isinf on
|
141
|
-
*
|
142
|
-
*
|
140
|
+
* isinf on POSIX systems it accepts a float, a double, or a long double.
|
141
|
+
* But mingw didn't provide an isinf macro, only an isinf function that only
|
142
|
+
* accepts floats, so we need to use _finite instead.
|
143
143
|
*/
|
144
|
-
#ifdef
|
145
|
-
#
|
146
|
-
#
|
147
|
-
#
|
144
|
+
#ifdef __MINGW64__
|
145
|
+
#include <float.h>
|
146
|
+
#define PRISM_ISINF(x) (!_finite(x))
|
147
|
+
#else
|
148
|
+
#define PRISM_ISINF(x) isinf(x)
|
148
149
|
#endif
|
149
150
|
|
150
151
|
/**
|
@@ -239,4 +240,18 @@
|
|
239
240
|
#define PRISM_UNLIKELY(x) (x)
|
240
241
|
#endif
|
241
242
|
|
243
|
+
/**
|
244
|
+
* We use -Wimplicit-fallthrough to guard potentially unintended fall-through between cases of a switch.
|
245
|
+
* Use PRISM_FALLTHROUGH to explicitly annotate cases where the fallthrough is intentional.
|
246
|
+
*/
|
247
|
+
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L // C23 or later
|
248
|
+
#define PRISM_FALLTHROUGH [[fallthrough]];
|
249
|
+
#elif defined(__GNUC__) || defined(__clang__)
|
250
|
+
#define PRISM_FALLTHROUGH __attribute__((fallthrough));
|
251
|
+
#elif defined(_MSC_VER)
|
252
|
+
#define PRISM_FALLTHROUGH __fallthrough;
|
253
|
+
#else
|
254
|
+
#define PRISM_FALLTHROUGH
|
255
|
+
#endif
|
256
|
+
|
242
257
|
#endif
|
data/include/prism/diagnostic.h
CHANGED
data/include/prism/parser.h
CHANGED
@@ -82,6 +82,23 @@ typedef enum {
|
|
82
82
|
PM_HEREDOC_INDENT_TILDE,
|
83
83
|
} pm_heredoc_indent_t;
|
84
84
|
|
85
|
+
/**
|
86
|
+
* All of the information necessary to store to lexing a heredoc.
|
87
|
+
*/
|
88
|
+
typedef struct {
|
89
|
+
/** A pointer to the start of the heredoc identifier. */
|
90
|
+
const uint8_t *ident_start;
|
91
|
+
|
92
|
+
/** The length of the heredoc identifier. */
|
93
|
+
size_t ident_length;
|
94
|
+
|
95
|
+
/** The type of quote that the heredoc uses. */
|
96
|
+
pm_heredoc_quote_t quote;
|
97
|
+
|
98
|
+
/** The type of indentation that the heredoc uses. */
|
99
|
+
pm_heredoc_indent_t indent;
|
100
|
+
} pm_heredoc_lex_mode_t;
|
101
|
+
|
85
102
|
/**
|
86
103
|
* When lexing Ruby source, the lexer has a small amount of state to tell which
|
87
104
|
* kind of token it is currently lexing. For example, when we find the start of
|
@@ -210,17 +227,10 @@ typedef struct pm_lex_mode {
|
|
210
227
|
} string;
|
211
228
|
|
212
229
|
struct {
|
213
|
-
/**
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
size_t ident_length;
|
218
|
-
|
219
|
-
/** The type of quote that the heredoc uses. */
|
220
|
-
pm_heredoc_quote_t quote;
|
221
|
-
|
222
|
-
/** The type of indentation that the heredoc uses. */
|
223
|
-
pm_heredoc_indent_t indent;
|
230
|
+
/**
|
231
|
+
* All of the data necessary to lex a heredoc.
|
232
|
+
*/
|
233
|
+
pm_heredoc_lex_mode_t base;
|
224
234
|
|
225
235
|
/**
|
226
236
|
* This is the pointer to the character where lexing should resume
|
@@ -233,7 +243,7 @@ typedef struct pm_lex_mode {
|
|
233
243
|
* line so that we know how much to dedent each line in the case of
|
234
244
|
* a tilde heredoc.
|
235
245
|
*/
|
236
|
-
size_t common_whitespace;
|
246
|
+
size_t *common_whitespace;
|
237
247
|
|
238
248
|
/** True if the previous token ended with a line continuation. */
|
239
249
|
bool line_continuation;
|
@@ -382,6 +392,9 @@ typedef enum {
|
|
382
392
|
/** a rescue statement within a module statement */
|
383
393
|
PM_CONTEXT_MODULE_RESCUE,
|
384
394
|
|
395
|
+
/** a multiple target expression */
|
396
|
+
PM_CONTEXT_MULTI_TARGET,
|
397
|
+
|
385
398
|
/** a parenthesized expression */
|
386
399
|
PM_CONTEXT_PARENS,
|
387
400
|
|
data/include/prism/version.h
CHANGED
@@ -14,7 +14,7 @@
|
|
14
14
|
/**
|
15
15
|
* The minor version of the Prism library as an int.
|
16
16
|
*/
|
17
|
-
#define PRISM_VERSION_MINOR
|
17
|
+
#define PRISM_VERSION_MINOR 3
|
18
18
|
|
19
19
|
/**
|
20
20
|
* The patch version of the Prism library as an int.
|
@@ -24,6 +24,6 @@
|
|
24
24
|
/**
|
25
25
|
* The version of the Prism library as a constant string.
|
26
26
|
*/
|
27
|
-
#define PRISM_VERSION "1.
|
27
|
+
#define PRISM_VERSION "1.3.0"
|
28
28
|
|
29
29
|
#endif
|
data/include/prism.h
CHANGED
@@ -234,6 +234,53 @@ PRISM_EXPORTED_FUNCTION void pm_dump_json(pm_buffer_t *buffer, const pm_parser_t
|
|
234
234
|
|
235
235
|
#endif
|
236
236
|
|
237
|
+
/**
|
238
|
+
* Represents the results of a slice query.
|
239
|
+
*/
|
240
|
+
typedef enum {
|
241
|
+
/** Returned if the encoding given to a slice query was invalid. */
|
242
|
+
PM_STRING_QUERY_ERROR = -1,
|
243
|
+
|
244
|
+
/** Returned if the result of the slice query is false. */
|
245
|
+
PM_STRING_QUERY_FALSE,
|
246
|
+
|
247
|
+
/** Returned if the result of the slice query is true. */
|
248
|
+
PM_STRING_QUERY_TRUE
|
249
|
+
} pm_string_query_t;
|
250
|
+
|
251
|
+
/**
|
252
|
+
* Check that the slice is a valid local variable name.
|
253
|
+
*
|
254
|
+
* @param source The source to check.
|
255
|
+
* @param length The length of the source.
|
256
|
+
* @param encoding_name The name of the encoding of the source.
|
257
|
+
* @return PM_STRING_QUERY_TRUE if the query is true, PM_STRING_QUERY_FALSE if
|
258
|
+
* the query is false, and PM_STRING_QUERY_ERROR if the encoding was invalid.
|
259
|
+
*/
|
260
|
+
PRISM_EXPORTED_FUNCTION pm_string_query_t pm_string_query_local(const uint8_t *source, size_t length, const char *encoding_name);
|
261
|
+
|
262
|
+
/**
|
263
|
+
* Check that the slice is a valid constant name.
|
264
|
+
*
|
265
|
+
* @param source The source to check.
|
266
|
+
* @param length The length of the source.
|
267
|
+
* @param encoding_name The name of the encoding of the source.
|
268
|
+
* @return PM_STRING_QUERY_TRUE if the query is true, PM_STRING_QUERY_FALSE if
|
269
|
+
* the query is false, and PM_STRING_QUERY_ERROR if the encoding was invalid.
|
270
|
+
*/
|
271
|
+
PRISM_EXPORTED_FUNCTION pm_string_query_t pm_string_query_constant(const uint8_t *source, size_t length, const char *encoding_name);
|
272
|
+
|
273
|
+
/**
|
274
|
+
* Check that the slice is a valid method name.
|
275
|
+
*
|
276
|
+
* @param source The source to check.
|
277
|
+
* @param length The length of the source.
|
278
|
+
* @param encoding_name The name of the encoding of the source.
|
279
|
+
* @return PM_STRING_QUERY_TRUE if the query is true, PM_STRING_QUERY_FALSE if
|
280
|
+
* the query is false, and PM_STRING_QUERY_ERROR if the encoding was invalid.
|
281
|
+
*/
|
282
|
+
PRISM_EXPORTED_FUNCTION pm_string_query_t pm_string_query_method_name(const uint8_t *source, size_t length, const char *encoding_name);
|
283
|
+
|
237
284
|
/**
|
238
285
|
* @mainpage
|
239
286
|
*
|
data/lib/prism/dot_visitor.rb
CHANGED
@@ -4414,6 +4414,11 @@ module Prism
|
|
4414
4414
|
# keyword_loc
|
4415
4415
|
table.field("keyword_loc", location_inspect(node.keyword_loc))
|
4416
4416
|
|
4417
|
+
# do_keyword_loc
|
4418
|
+
unless (do_keyword_loc = node.do_keyword_loc).nil?
|
4419
|
+
table.field("do_keyword_loc", location_inspect(do_keyword_loc))
|
4420
|
+
end
|
4421
|
+
|
4417
4422
|
# closing_loc
|
4418
4423
|
unless (closing_loc = node.closing_loc).nil?
|
4419
4424
|
table.field("closing_loc", location_inspect(closing_loc))
|
@@ -4490,6 +4495,11 @@ module Prism
|
|
4490
4495
|
# keyword_loc
|
4491
4496
|
table.field("keyword_loc", location_inspect(node.keyword_loc))
|
4492
4497
|
|
4498
|
+
# do_keyword_loc
|
4499
|
+
unless (do_keyword_loc = node.do_keyword_loc).nil?
|
4500
|
+
table.field("do_keyword_loc", location_inspect(do_keyword_loc))
|
4501
|
+
end
|
4502
|
+
|
4493
4503
|
# closing_loc
|
4494
4504
|
unless (closing_loc = node.closing_loc).nil?
|
4495
4505
|
table.field("closing_loc", location_inspect(closing_loc))
|
data/lib/prism/dsl.rb
CHANGED
@@ -804,8 +804,8 @@ module Prism
|
|
804
804
|
end
|
805
805
|
|
806
806
|
# Create a new UntilNode node.
|
807
|
-
def until_node(source: default_source, node_id: 0, location: default_location, flags: 0, keyword_loc: location, closing_loc: nil, predicate: default_node(source, location), statements: nil)
|
808
|
-
UntilNode.new(source, node_id, location, flags, keyword_loc, closing_loc, predicate, statements)
|
807
|
+
def until_node(source: default_source, node_id: 0, location: default_location, flags: 0, keyword_loc: location, do_keyword_loc: nil, closing_loc: nil, predicate: default_node(source, location), statements: nil)
|
808
|
+
UntilNode.new(source, node_id, location, flags, keyword_loc, do_keyword_loc, closing_loc, predicate, statements)
|
809
809
|
end
|
810
810
|
|
811
811
|
# Create a new WhenNode node.
|
@@ -814,8 +814,8 @@ module Prism
|
|
814
814
|
end
|
815
815
|
|
816
816
|
# Create a new WhileNode node.
|
817
|
-
def while_node(source: default_source, node_id: 0, location: default_location, flags: 0, keyword_loc: location, closing_loc: nil, predicate: default_node(source, location), statements: nil)
|
818
|
-
WhileNode.new(source, node_id, location, flags, keyword_loc, closing_loc, predicate, statements)
|
817
|
+
def while_node(source: default_source, node_id: 0, location: default_location, flags: 0, keyword_loc: location, do_keyword_loc: nil, closing_loc: nil, predicate: default_node(source, location), statements: nil)
|
818
|
+
WhileNode.new(source, node_id, location, flags, keyword_loc, do_keyword_loc, closing_loc, predicate, statements)
|
819
819
|
end
|
820
820
|
|
821
821
|
# Create a new XStringNode node.
|
data/lib/prism/ffi.rb
CHANGED
@@ -13,7 +13,15 @@ module Prism
|
|
13
13
|
|
14
14
|
# Define the library that we will be pulling functions from. Note that this
|
15
15
|
# must align with the build shared library from make/rake.
|
16
|
-
|
16
|
+
libprism_in_build = File.expand_path("../../build/libprism.#{RbConfig::CONFIG["SOEXT"]}", __dir__)
|
17
|
+
libprism_in_libdir = "#{RbConfig::CONFIG["libdir"]}/prism/libprism.#{RbConfig::CONFIG["SOEXT"]}"
|
18
|
+
if File.exist? libprism_in_build
|
19
|
+
INCLUDE_DIR = File.expand_path("../../include", __dir__)
|
20
|
+
ffi_lib libprism_in_build
|
21
|
+
else
|
22
|
+
INCLUDE_DIR = "#{RbConfig::CONFIG["libdir"]}/prism/include"
|
23
|
+
ffi_lib libprism_in_libdir
|
24
|
+
end
|
17
25
|
|
18
26
|
# Convert a native C type declaration into a symbol that FFI understands.
|
19
27
|
# For example:
|
@@ -38,7 +46,7 @@ module Prism
|
|
38
46
|
# given functions. For each one, define a function with the same name and
|
39
47
|
# signature as the C function.
|
40
48
|
def self.load_exported_functions_from(header, *functions, callbacks)
|
41
|
-
File.foreach(
|
49
|
+
File.foreach("#{INCLUDE_DIR}/#{header}") do |line|
|
42
50
|
# We only want to attempt to load exported functions.
|
43
51
|
next unless line.start_with?("PRISM_EXPORTED_FUNCTION ")
|
44
52
|
|
@@ -73,6 +81,7 @@ module Prism
|
|
73
81
|
|
74
82
|
callback :pm_parse_stream_fgets_t, [:pointer, :int, :pointer], :pointer
|
75
83
|
enum :pm_string_init_result_t, %i[PM_STRING_INIT_SUCCESS PM_STRING_INIT_ERROR_GENERIC PM_STRING_INIT_ERROR_DIRECTORY]
|
84
|
+
enum :pm_string_query_t, [:PM_STRING_QUERY_ERROR, -1, :PM_STRING_QUERY_FALSE, :PM_STRING_QUERY_TRUE]
|
76
85
|
|
77
86
|
load_exported_functions_from(
|
78
87
|
"prism.h",
|
@@ -83,6 +92,9 @@ module Prism
|
|
83
92
|
"pm_serialize_lex",
|
84
93
|
"pm_serialize_parse_lex",
|
85
94
|
"pm_parse_success_p",
|
95
|
+
"pm_string_query_local",
|
96
|
+
"pm_string_query_constant",
|
97
|
+
"pm_string_query_method_name",
|
86
98
|
[:pm_parse_stream_fgets_t]
|
87
99
|
)
|
88
100
|
|
@@ -492,4 +504,39 @@ module Prism
|
|
492
504
|
values.pack(template)
|
493
505
|
end
|
494
506
|
end
|
507
|
+
|
508
|
+
# Here we are going to patch StringQuery to put in the class-level methods so
|
509
|
+
# that it can maintain a consistent interface
|
510
|
+
class StringQuery
|
511
|
+
class << self
|
512
|
+
# Mirrors the C extension's StringQuery::local? method.
|
513
|
+
def local?(string)
|
514
|
+
query(LibRubyParser.pm_string_query_local(string, string.bytesize, string.encoding.name))
|
515
|
+
end
|
516
|
+
|
517
|
+
# Mirrors the C extension's StringQuery::constant? method.
|
518
|
+
def constant?(string)
|
519
|
+
query(LibRubyParser.pm_string_query_constant(string, string.bytesize, string.encoding.name))
|
520
|
+
end
|
521
|
+
|
522
|
+
# Mirrors the C extension's StringQuery::method_name? method.
|
523
|
+
def method_name?(string)
|
524
|
+
query(LibRubyParser.pm_string_query_method_name(string, string.bytesize, string.encoding.name))
|
525
|
+
end
|
526
|
+
|
527
|
+
private
|
528
|
+
|
529
|
+
# Parse the enum result and return an appropriate boolean.
|
530
|
+
def query(result)
|
531
|
+
case result
|
532
|
+
when :PM_STRING_QUERY_ERROR
|
533
|
+
raise ArgumentError, "Invalid or non ascii-compatible encoding"
|
534
|
+
when :PM_STRING_QUERY_FALSE
|
535
|
+
false
|
536
|
+
when :PM_STRING_QUERY_TRUE
|
537
|
+
true
|
538
|
+
end
|
539
|
+
end
|
540
|
+
end
|
541
|
+
end
|
495
542
|
end
|
@@ -2287,6 +2287,7 @@ module Prism
|
|
2287
2287
|
flags = [("newline" if node.newline?), ("static_literal" if node.static_literal?), ("begin_modifier" if node.begin_modifier?)].compact
|
2288
2288
|
commands << ["├── flags: #{flags.empty? ? "∅" : flags.join(", ")}\n", indent]
|
2289
2289
|
commands << ["├── keyword_loc: #{inspect_location(node.keyword_loc)}\n", indent]
|
2290
|
+
commands << ["├── do_keyword_loc: #{inspect_location(node.do_keyword_loc)}\n", indent]
|
2290
2291
|
commands << ["├── closing_loc: #{inspect_location(node.closing_loc)}\n", indent]
|
2291
2292
|
commands << ["├── predicate:\n", indent]
|
2292
2293
|
commands << [node.predicate, "#{indent}│ "]
|
@@ -2328,6 +2329,7 @@ module Prism
|
|
2328
2329
|
flags = [("newline" if node.newline?), ("static_literal" if node.static_literal?), ("begin_modifier" if node.begin_modifier?)].compact
|
2329
2330
|
commands << ["├── flags: #{flags.empty? ? "∅" : flags.join(", ")}\n", indent]
|
2330
2331
|
commands << ["├── keyword_loc: #{inspect_location(node.keyword_loc)}\n", indent]
|
2332
|
+
commands << ["├── do_keyword_loc: #{inspect_location(node.do_keyword_loc)}\n", indent]
|
2331
2333
|
commands << ["├── closing_loc: #{inspect_location(node.closing_loc)}\n", indent]
|
2332
2334
|
commands << ["├── predicate:\n", indent]
|
2333
2335
|
commands << [node.predicate, "#{indent}│ "]
|