prism 1.2.0 → 1.3.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 +23 -1
- data/Makefile +1 -1
- data/config.yml +420 -2
- 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 +426 -2
- data/include/prism/defines.h +22 -7
- 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 +1838 -95
- data/lib/prism/parse_result/errors.rb +1 -1
- data/lib/prism/parse_result.rb +2 -2
- data/lib/prism/reflection.rb +2 -2
- data/lib/prism/relocation.rb +504 -0
- data/lib/prism/serialize.rb +5 -5
- data/lib/prism/string_query.rb +30 -0
- data/lib/prism/translation/parser/compiler.rb +36 -26
- data/lib/prism/translation/ruby_parser.rb +12 -3
- data/lib/prism.rb +6 -4
- data/prism.gemspec +7 -1
- data/rbi/prism/dsl.rbi +4 -4
- data/rbi/prism/node.rbi +22 -10
- data/rbi/prism/string_query.rbi +12 -0
- data/sig/prism/dsl.rbs +2 -2
- data/sig/prism/node.rbs +12 -8
- data/sig/prism/relocation.rbs +185 -0
- data/sig/prism/string_query.rbs +11 -0
- data/src/node.c +18 -0
- data/src/prettyprint.c +32 -0
- data/src/prism.c +364 -81
- 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/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}│ "]
|