prism 1.2.0 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -137,14 +137,15 @@
137
137
  #endif
138
138
 
139
139
  /**
140
- * isinf on Windows is defined as accepting a float, but on POSIX systems it
141
- * accepts a float, a double, or a long double. We want to mirror this behavior
142
- * on windows.
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 _WIN32
145
- # include <float.h>
146
- # undef isinf
147
- # define isinf(x) (sizeof(x) == sizeof(float) ? !_finitef(x) : !_finite(x))
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
@@ -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 2
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.2.0"
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
  *
@@ -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
- ffi_lib File.expand_path("../../build/libprism.#{RbConfig::CONFIG["SOEXT"]}", __dir__)
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(File.expand_path("../../include/#{header}", __dir__)) do |line|
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}│ "]