prism 0.15.0 → 0.16.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +27 -1
  3. data/Makefile +6 -0
  4. data/README.md +2 -0
  5. data/config.yml +21 -20
  6. data/docs/configuration.md +2 -0
  7. data/docs/javascript.md +90 -0
  8. data/docs/releasing.md +27 -0
  9. data/docs/ruby_api.md +2 -0
  10. data/ext/prism/api_node.c +66 -68
  11. data/ext/prism/extension.c +73 -0
  12. data/ext/prism/extension.h +1 -1
  13. data/include/prism/ast.h +40 -40
  14. data/include/prism/defines.h +9 -0
  15. data/include/prism/enc/pm_encoding.h +1 -0
  16. data/include/prism/node.h +0 -17
  17. data/include/prism/parser.h +1 -0
  18. data/include/prism/prettyprint.h +15 -0
  19. data/include/prism/util/pm_buffer.h +10 -4
  20. data/include/prism/util/pm_constant_pool.h +1 -1
  21. data/include/prism/util/pm_newline_list.h +1 -1
  22. data/include/prism/version.h +2 -2
  23. data/include/prism.h +11 -11
  24. data/lib/prism/compiler.rb +0 -3
  25. data/lib/prism/debug.rb +20 -6
  26. data/lib/prism/desugar_compiler.rb +1 -1
  27. data/lib/prism/dispatcher.rb +0 -14
  28. data/lib/prism/dsl.rb +8 -13
  29. data/lib/prism/ffi.rb +25 -0
  30. data/lib/prism/lex_compat.rb +1 -1
  31. data/lib/prism/mutation_compiler.rb +3 -8
  32. data/lib/prism/node.rb +123 -159
  33. data/lib/prism/node_ext.rb +23 -16
  34. data/lib/prism/parse_result.rb +21 -5
  35. data/lib/prism/pattern.rb +3 -3
  36. data/lib/prism/serialize.rb +900 -304
  37. data/lib/prism/visitor.rb +0 -3
  38. data/prism.gemspec +8 -1
  39. data/rbi/prism.rbi +7261 -0
  40. data/rbi/prism_static.rbi +182 -0
  41. data/sig/prism.rbs +4439 -0
  42. data/sig/prism_static.rbs +110 -0
  43. data/src/enc/pm_unicode.c +1 -1
  44. data/src/node.c +28 -29
  45. data/src/prettyprint.c +7674 -1647
  46. data/src/prism.c +353 -300
  47. data/src/regexp.c +2 -0
  48. data/src/serialize.c +392 -381
  49. data/src/util/pm_buffer.c +47 -12
  50. data/src/util/pm_constant_pool.c +2 -2
  51. data/src/util/pm_newline_list.c +8 -54
  52. metadata +9 -2
@@ -396,6 +396,24 @@ parse_input(pm_string_t *input, const char *filepath) {
396
396
  return result;
397
397
  }
398
398
 
399
+ // Parse the given input and return an array of Comment objects.
400
+ static VALUE
401
+ parse_input_comments(pm_string_t *input, const char *filepath) {
402
+ pm_parser_t parser;
403
+ pm_parser_init(&parser, pm_string_source(input), pm_string_length(input), filepath);
404
+
405
+ pm_node_t *node = pm_parse(&parser);
406
+ rb_encoding *encoding = rb_enc_find(parser.encoding.name);
407
+
408
+ VALUE source = pm_source_new(&parser, encoding);
409
+ VALUE comments = parser_comments(&parser, source);
410
+
411
+ pm_node_destroy(&parser, node);
412
+ pm_parser_free(&parser);
413
+
414
+ return comments;
415
+ }
416
+
399
417
  // Parse the given string and return a ParseResult instance.
400
418
  static VALUE
401
419
  parse(int argc, VALUE *argv, VALUE self) {
@@ -436,6 +454,33 @@ parse_file(VALUE self, VALUE filepath) {
436
454
  return value;
437
455
  }
438
456
 
457
+ // Parse the given string and return an array of Comment objects.
458
+ static VALUE
459
+ parse_comments(int argc, VALUE *argv, VALUE self) {
460
+ VALUE string;
461
+ VALUE filepath;
462
+ rb_scan_args(argc, argv, "11", &string, &filepath);
463
+
464
+ pm_string_t input;
465
+ input_load_string(&input, string);
466
+
467
+ return parse_input_comments(&input, check_string(filepath));
468
+ }
469
+
470
+ // Parse the given file and return an array of Comment objects.
471
+ static VALUE
472
+ parse_file_comments(VALUE self, VALUE filepath) {
473
+ pm_string_t input;
474
+
475
+ const char *checked = check_string(filepath);
476
+ if (!pm_string_mapped_init(&input, checked)) return Qnil;
477
+
478
+ VALUE value = parse_input_comments(&input, checked);
479
+ pm_string_free(&input);
480
+
481
+ return value;
482
+ }
483
+
439
484
  // Parse the given string and return a ParseResult instance.
440
485
  static VALUE
441
486
  parse_lex(int argc, VALUE *argv, VALUE self) {
@@ -554,6 +599,31 @@ parse_serialize_file_metadata(VALUE self, VALUE filepath, VALUE metadata) {
554
599
  return result;
555
600
  }
556
601
 
602
+ // Inspect the AST that represents the given source using the prism pretty print
603
+ // as opposed to the Ruby implementation.
604
+ static VALUE
605
+ inspect_node(VALUE self, VALUE source) {
606
+ pm_string_t input;
607
+ input_load_string(&input, source);
608
+
609
+ pm_parser_t parser;
610
+ pm_parser_init(&parser, pm_string_source(&input), pm_string_length(&input), NULL);
611
+
612
+ pm_node_t *node = pm_parse(&parser);
613
+ pm_buffer_t buffer = { 0 };
614
+
615
+ pm_prettyprint(&buffer, &parser, node);
616
+
617
+ rb_encoding *encoding = rb_enc_find(parser.encoding.name);
618
+ VALUE string = rb_enc_str_new(pm_buffer_value(&buffer), pm_buffer_length(&buffer), encoding);
619
+
620
+ pm_buffer_free(&buffer);
621
+ pm_node_destroy(&parser, node);
622
+ pm_parser_free(&parser);
623
+
624
+ return string;
625
+ }
626
+
557
627
  /******************************************************************************/
558
628
  /* Initialization of the extension */
559
629
  /******************************************************************************/
@@ -596,6 +666,8 @@ Init_prism(void) {
596
666
  rb_define_singleton_method(rb_cPrism, "lex_file", lex_file, 1);
597
667
  rb_define_singleton_method(rb_cPrism, "parse", parse, -1);
598
668
  rb_define_singleton_method(rb_cPrism, "parse_file", parse_file, 1);
669
+ rb_define_singleton_method(rb_cPrism, "parse_comments", parse_comments, -1);
670
+ rb_define_singleton_method(rb_cPrism, "parse_file_comments", parse_file_comments, 1);
599
671
  rb_define_singleton_method(rb_cPrism, "parse_lex", parse_lex, -1);
600
672
  rb_define_singleton_method(rb_cPrism, "parse_lex_file", parse_lex_file, 1);
601
673
 
@@ -606,6 +678,7 @@ Init_prism(void) {
606
678
  rb_define_singleton_method(rb_cPrismDebug, "memsize", memsize, 1);
607
679
  rb_define_singleton_method(rb_cPrismDebug, "profile_file", profile_file, 1);
608
680
  rb_define_singleton_method(rb_cPrismDebug, "parse_serialize_file_metadata", parse_serialize_file_metadata, 2);
681
+ rb_define_singleton_method(rb_cPrismDebug, "inspect_node", inspect_node, 1);
609
682
 
610
683
  // Next, initialize the other APIs.
611
684
  Init_prism_api_node();
@@ -1,7 +1,7 @@
1
1
  #ifndef PRISM_EXT_NODE_H
2
2
  #define PRISM_EXT_NODE_H
3
3
 
4
- #define EXPECTED_PRISM_VERSION "0.15.0"
4
+ #define EXPECTED_PRISM_VERSION "0.16.0"
5
5
 
6
6
  #include <ruby.h>
7
7
  #include <ruby/encoding.h>
data/include/prism/ast.h CHANGED
@@ -327,32 +327,31 @@ enum pm_node_type {
327
327
  PM_RATIONAL_NODE = 116,
328
328
  PM_REDO_NODE = 117,
329
329
  PM_REGULAR_EXPRESSION_NODE = 118,
330
- PM_REQUIRED_DESTRUCTURED_PARAMETER_NODE = 119,
331
- PM_REQUIRED_PARAMETER_NODE = 120,
332
- PM_RESCUE_MODIFIER_NODE = 121,
333
- PM_RESCUE_NODE = 122,
334
- PM_REST_PARAMETER_NODE = 123,
335
- PM_RETRY_NODE = 124,
336
- PM_RETURN_NODE = 125,
337
- PM_SELF_NODE = 126,
338
- PM_SINGLETON_CLASS_NODE = 127,
339
- PM_SOURCE_ENCODING_NODE = 128,
340
- PM_SOURCE_FILE_NODE = 129,
341
- PM_SOURCE_LINE_NODE = 130,
342
- PM_SPLAT_NODE = 131,
343
- PM_STATEMENTS_NODE = 132,
344
- PM_STRING_CONCAT_NODE = 133,
345
- PM_STRING_NODE = 134,
346
- PM_SUPER_NODE = 135,
347
- PM_SYMBOL_NODE = 136,
348
- PM_TRUE_NODE = 137,
349
- PM_UNDEF_NODE = 138,
350
- PM_UNLESS_NODE = 139,
351
- PM_UNTIL_NODE = 140,
352
- PM_WHEN_NODE = 141,
353
- PM_WHILE_NODE = 142,
354
- PM_X_STRING_NODE = 143,
355
- PM_YIELD_NODE = 144,
330
+ PM_REQUIRED_PARAMETER_NODE = 119,
331
+ PM_RESCUE_MODIFIER_NODE = 120,
332
+ PM_RESCUE_NODE = 121,
333
+ PM_REST_PARAMETER_NODE = 122,
334
+ PM_RETRY_NODE = 123,
335
+ PM_RETURN_NODE = 124,
336
+ PM_SELF_NODE = 125,
337
+ PM_SINGLETON_CLASS_NODE = 126,
338
+ PM_SOURCE_ENCODING_NODE = 127,
339
+ PM_SOURCE_FILE_NODE = 128,
340
+ PM_SOURCE_LINE_NODE = 129,
341
+ PM_SPLAT_NODE = 130,
342
+ PM_STATEMENTS_NODE = 131,
343
+ PM_STRING_CONCAT_NODE = 132,
344
+ PM_STRING_NODE = 133,
345
+ PM_SUPER_NODE = 134,
346
+ PM_SYMBOL_NODE = 135,
347
+ PM_TRUE_NODE = 136,
348
+ PM_UNDEF_NODE = 137,
349
+ PM_UNLESS_NODE = 138,
350
+ PM_UNTIL_NODE = 139,
351
+ PM_WHEN_NODE = 140,
352
+ PM_WHILE_NODE = 141,
353
+ PM_X_STRING_NODE = 142,
354
+ PM_YIELD_NODE = 143,
356
355
  PM_SCOPE_NODE
357
356
  };
358
357
 
@@ -427,6 +426,8 @@ typedef struct pm_and_node {
427
426
  // ArgumentsNode
428
427
  //
429
428
  // Type: PM_ARGUMENTS_NODE
429
+ // Flags:
430
+ // PM_ARGUMENTS_NODE_FLAGS_KEYWORD_SPLAT
430
431
  typedef struct pm_arguments_node {
431
432
  pm_node_t base;
432
433
  struct pm_node_list arguments;
@@ -1065,8 +1066,8 @@ typedef struct pm_hash_node {
1065
1066
  typedef struct pm_hash_pattern_node {
1066
1067
  pm_node_t base;
1067
1068
  struct pm_node *constant;
1068
- struct pm_node_list assocs;
1069
- struct pm_node *kwrest;
1069
+ struct pm_node_list elements;
1070
+ struct pm_node *rest;
1070
1071
  pm_location_t opening_loc;
1071
1072
  pm_location_t closing_loc;
1072
1073
  } pm_hash_pattern_node_t;
@@ -1488,7 +1489,9 @@ typedef struct pm_module_node {
1488
1489
  // Type: PM_MULTI_TARGET_NODE
1489
1490
  typedef struct pm_multi_target_node {
1490
1491
  pm_node_t base;
1491
- struct pm_node_list targets;
1492
+ struct pm_node_list lefts;
1493
+ struct pm_node *rest;
1494
+ struct pm_node_list rights;
1492
1495
  pm_location_t lparen_loc;
1493
1496
  pm_location_t rparen_loc;
1494
1497
  } pm_multi_target_node_t;
@@ -1498,7 +1501,9 @@ typedef struct pm_multi_target_node {
1498
1501
  // Type: PM_MULTI_WRITE_NODE
1499
1502
  typedef struct pm_multi_write_node {
1500
1503
  pm_node_t base;
1501
- struct pm_node_list targets;
1504
+ struct pm_node_list lefts;
1505
+ struct pm_node *rest;
1506
+ struct pm_node_list rights;
1502
1507
  pm_location_t lparen_loc;
1503
1508
  pm_location_t rparen_loc;
1504
1509
  pm_location_t operator_loc;
@@ -1681,16 +1686,6 @@ typedef struct pm_regular_expression_node {
1681
1686
  pm_string_t unescaped;
1682
1687
  } pm_regular_expression_node_t;
1683
1688
 
1684
- // RequiredDestructuredParameterNode
1685
- //
1686
- // Type: PM_REQUIRED_DESTRUCTURED_PARAMETER_NODE
1687
- typedef struct pm_required_destructured_parameter_node {
1688
- pm_node_t base;
1689
- struct pm_node_list parameters;
1690
- pm_location_t opening_loc;
1691
- pm_location_t closing_loc;
1692
- } pm_required_destructured_parameter_node_t;
1693
-
1694
1689
  // RequiredParameterNode
1695
1690
  //
1696
1691
  // Type: PM_REQUIRED_PARAMETER_NODE
@@ -1938,6 +1933,11 @@ typedef struct pm_yield_node {
1938
1933
  pm_location_t rparen_loc;
1939
1934
  } pm_yield_node_t;
1940
1935
 
1936
+ // ArgumentsNodeFlags
1937
+ typedef enum pm_arguments_node_flags {
1938
+ PM_ARGUMENTS_NODE_FLAGS_KEYWORD_SPLAT = 1 << 0,
1939
+ } pm_arguments_node_flags_t;
1940
+
1941
1941
  // CallNodeFlags
1942
1942
  typedef enum pm_call_node_flags {
1943
1943
  PM_CALL_NODE_FLAGS_SAFE_NAVIGATION = 1 << 0,
@@ -23,6 +23,15 @@
23
23
  # endif
24
24
  #endif
25
25
 
26
+ // PRISM_ATTRIBUTE_FORMAT
27
+ #if defined(__GNUC__)
28
+ # define PRISM_ATTRIBUTE_FORMAT(string_index, argument_index) __attribute__((format(printf, string_index, argument_index)))
29
+ #elif defined(__clang__)
30
+ # define PRISM_ATTRIBUTE_FORMAT(string_index, argument_index) __attribute__((__format__(__printf__, string_index, argument_index)))
31
+ #else
32
+ # define PRISM_ATTRIBUTE_FORMAT(string_index, argument_index)
33
+ #endif
34
+
26
35
  // PRISM_ATTRIBUTE_UNUSED
27
36
  #if defined(__GNUC__)
28
37
  # define PRISM_ATTRIBUTE_UNUSED __attribute__((unused))
@@ -57,6 +57,7 @@ bool pm_encoding_ascii_isupper_char(const uint8_t *b, PRISM_ATTRIBUTE_UNUSED ptr
57
57
  // the parser so they need to be internally visible.
58
58
  size_t pm_encoding_utf_8_alpha_char(const uint8_t *b, ptrdiff_t n);
59
59
  size_t pm_encoding_utf_8_alnum_char(const uint8_t *b, ptrdiff_t n);
60
+ bool pm_encoding_utf_8_isupper_char(const uint8_t *b, ptrdiff_t n);
60
61
 
61
62
  // This lookup table is referenced in both the UTF-8 encoding file and the
62
63
  // parser directly in order to speed up the default encoding processing.
data/include/prism/node.h CHANGED
@@ -29,21 +29,4 @@ PRISM_EXPORTED_FUNCTION const char * pm_node_type_to_str(pm_node_type_t node_typ
29
29
 
30
30
  #define PM_EMPTY_NODE_LIST ((pm_node_list_t) { .nodes = NULL, .size = 0, .capacity = 0 })
31
31
 
32
- // ScopeNodes are helper nodes, and will never be part of the AST. We manually
33
- // declare them here to avoid generating them.
34
- typedef struct pm_scope_node {
35
- pm_node_t base;
36
- struct pm_scope_node *previous;
37
- pm_node_t *ast_node;
38
- struct pm_parameters_node *parameters;
39
- pm_node_t *body;
40
- pm_constant_id_list_t locals;
41
- pm_parser_t *parser;
42
-
43
- // We don't have the CRuby types ID and st_table within Prism
44
- // so we use void *
45
- void *constants; // ID *constants
46
- void *index_lookup_table; // st_table *index_lookup_table
47
- } pm_scope_node_t;
48
-
49
32
  #endif // PRISM_NODE_H
@@ -212,6 +212,7 @@ typedef enum {
212
212
  PM_CONTEXT_EMBEXPR, // an interpolated expression
213
213
  PM_CONTEXT_ENSURE, // an ensure statement
214
214
  PM_CONTEXT_FOR, // a for loop
215
+ PM_CONTEXT_FOR_INDEX, // a for loop's index
215
216
  PM_CONTEXT_IF, // an if statement
216
217
  PM_CONTEXT_LAMBDA_BRACES, // a lambda expression with braces
217
218
  PM_CONTEXT_LAMBDA_DO_END, // a lambda expression with do..end
@@ -0,0 +1,15 @@
1
+ #ifndef PRISM_PRETTYPRINT_H
2
+ #define PRISM_PRETTYPRINT_H
3
+
4
+ #include "prism/defines.h"
5
+
6
+ #include <stdio.h>
7
+
8
+ #include "prism/ast.h"
9
+ #include "prism/parser.h"
10
+ #include "prism/util/pm_buffer.h"
11
+
12
+ // Pretty-prints the AST represented by the given node to the given buffer.
13
+ PRISM_EXPORTED_FUNCTION void pm_prettyprint(pm_buffer_t *output_buffer, const pm_parser_t *parser, const pm_node_t *node);
14
+
15
+ #endif
@@ -13,9 +13,9 @@
13
13
  // block of memory. It is used to store the serialized representation of a
14
14
  // prism tree.
15
15
  typedef struct {
16
- char *value;
17
16
  size_t length;
18
17
  size_t capacity;
18
+ char *value;
19
19
  } pm_buffer_t;
20
20
 
21
21
  // Return the size of the pm_buffer_t struct.
@@ -36,17 +36,23 @@ PRISM_EXPORTED_FUNCTION size_t pm_buffer_length(pm_buffer_t *buffer);
36
36
  // Append the given amount of space as zeroes to the buffer.
37
37
  void pm_buffer_append_zeroes(pm_buffer_t *buffer, size_t length);
38
38
 
39
+ // Append a formatted string to the buffer.
40
+ void pm_buffer_append_format(pm_buffer_t *buffer, const char *format, ...) PRISM_ATTRIBUTE_FORMAT(2, 3);
41
+
39
42
  // Append a string to the buffer.
40
- void pm_buffer_append_str(pm_buffer_t *buffer, const char *value, size_t length);
43
+ void pm_buffer_append_string(pm_buffer_t *buffer, const char *value, size_t length);
41
44
 
42
45
  // Append a list of bytes to the buffer.
43
46
  void pm_buffer_append_bytes(pm_buffer_t *buffer, const uint8_t *value, size_t length);
44
47
 
45
48
  // Append a single byte to the buffer.
46
- void pm_buffer_append_u8(pm_buffer_t *buffer, uint8_t value);
49
+ void pm_buffer_append_byte(pm_buffer_t *buffer, uint8_t value);
47
50
 
48
51
  // Append a 32-bit unsigned integer to the buffer.
49
- void pm_buffer_append_u32(pm_buffer_t *buffer, uint32_t value);
52
+ void pm_buffer_append_varint(pm_buffer_t *buffer, uint32_t value);
53
+
54
+ // Append one buffer onto another.
55
+ void pm_buffer_concat(pm_buffer_t *destination, const pm_buffer_t *source);
50
56
 
51
57
  // Free the memory associated with the buffer.
52
58
  PRISM_EXPORTED_FUNCTION void pm_buffer_free(pm_buffer_t *buffer);
@@ -76,7 +76,7 @@ typedef struct {
76
76
  bool pm_constant_pool_init(pm_constant_pool_t *pool, uint32_t capacity);
77
77
 
78
78
  // Return a pointer to the constant indicated by the given constant id.
79
- pm_constant_t * pm_constant_pool_id_to_constant(pm_constant_pool_t *pool, pm_constant_id_t constant_id);
79
+ pm_constant_t * pm_constant_pool_id_to_constant(const pm_constant_pool_t *pool, pm_constant_id_t constant_id);
80
80
 
81
81
  // Insert a constant into a constant pool that is a slice of a source string.
82
82
  // Returns the id of the constant, or 0 if any potential calls to resize fail.
@@ -53,7 +53,7 @@ bool pm_newline_list_check_append(pm_newline_list_t *list, const uint8_t *cursor
53
53
  // Returns the line and column of the given offset. If the offset is not in the
54
54
  // list, the line and column of the closest offset less than the given offset
55
55
  // are returned.
56
- pm_line_column_t pm_newline_list_line_column(pm_newline_list_t *list, const uint8_t *cursor);
56
+ pm_line_column_t pm_newline_list_line_column(const pm_newline_list_t *list, const uint8_t *cursor);
57
57
 
58
58
  // Free the internal memory allocated for the newline list.
59
59
  void pm_newline_list_free(pm_newline_list_t *list);
@@ -1,4 +1,4 @@
1
1
  #define PRISM_VERSION_MAJOR 0
2
- #define PRISM_VERSION_MINOR 15
2
+ #define PRISM_VERSION_MINOR 16
3
3
  #define PRISM_VERSION_PATCH 0
4
- #define PRISM_VERSION "0.15.0"
4
+ #define PRISM_VERSION "0.16.0"
data/include/prism.h CHANGED
@@ -2,16 +2,17 @@
2
2
  #define PRISM_H
3
3
 
4
4
  #include "prism/defines.h"
5
+ #include "prism/util/pm_buffer.h"
6
+ #include "prism/util/pm_char.h"
7
+ #include "prism/util/pm_memchr.h"
8
+ #include "prism/util/pm_strpbrk.h"
5
9
  #include "prism/ast.h"
6
10
  #include "prism/diagnostic.h"
7
11
  #include "prism/node.h"
8
12
  #include "prism/pack.h"
9
13
  #include "prism/parser.h"
14
+ #include "prism/prettyprint.h"
10
15
  #include "prism/regexp.h"
11
- #include "prism/util/pm_buffer.h"
12
- #include "prism/util/pm_char.h"
13
- #include "prism/util/pm_memchr.h"
14
- #include "prism/util/pm_strpbrk.h"
15
16
  #include "prism/version.h"
16
17
 
17
18
  #include <assert.h>
@@ -29,12 +30,11 @@
29
30
 
30
31
  void pm_serialize_content(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer);
31
32
 
32
- void pm_print_node(pm_parser_t *parser, pm_node_t *node);
33
+ void pm_serialize_encoding(pm_encoding_t *encoding, pm_buffer_t *buffer);
33
34
 
34
- void pm_parser_metadata(pm_parser_t *parser, const char *metadata);
35
+ void pm_serialize_comment_list(pm_parser_t *parser, pm_list_t *list, pm_buffer_t *buffer);
35
36
 
36
- // Generate a scope node from the given node.
37
- void pm_scope_node_init(const pm_node_t *node, pm_scope_node_t *scope, pm_scope_node_t *previous, pm_parser_t *parser);
37
+ void pm_parser_metadata(pm_parser_t *parser, const char *metadata);
38
38
 
39
39
  // The prism version and the serialization format.
40
40
  PRISM_EXPORTED_FUNCTION const char * pm_version(void);
@@ -59,15 +59,15 @@ PRISM_EXPORTED_FUNCTION void pm_parser_free(pm_parser_t *parser);
59
59
  // Parse the Ruby source associated with the given parser and return the tree.
60
60
  PRISM_EXPORTED_FUNCTION pm_node_t * pm_parse(pm_parser_t *parser);
61
61
 
62
- // Pretty-prints the AST represented by the given node to the given buffer.
63
- PRISM_EXPORTED_FUNCTION void pm_prettyprint(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer);
64
-
65
62
  // Serialize the AST represented by the given node to the given buffer.
66
63
  PRISM_EXPORTED_FUNCTION void pm_serialize(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer);
67
64
 
68
65
  // Parse the given source to the AST and serialize the AST to the given buffer.
69
66
  PRISM_EXPORTED_FUNCTION void pm_parse_serialize(const uint8_t *source, size_t size, pm_buffer_t *buffer, const char *metadata);
70
67
 
68
+ // Parse and serialize the comments in the given source to the given buffer.
69
+ PRISM_EXPORTED_FUNCTION void pm_parse_serialize_comments(const uint8_t *source, size_t size, pm_buffer_t *buffer, const char *metadata);
70
+
71
71
  // Lex the given source and serialize to the given buffer.
72
72
  PRISM_EXPORTED_FUNCTION void pm_lex_serialize(const uint8_t *source, size_t size, const char *filepath, pm_buffer_t *buffer);
73
73
 
@@ -393,9 +393,6 @@ module Prism
393
393
  # Compile a RegularExpressionNode node
394
394
  alias visit_regular_expression_node visit_child_nodes
395
395
 
396
- # Compile a RequiredDestructuredParameterNode node
397
- alias visit_required_destructured_parameter_node visit_child_nodes
398
-
399
396
  # Compile a RequiredParameterNode node
400
397
  alias visit_required_parameter_node visit_child_nodes
401
398
 
data/lib/prism/debug.rb CHANGED
@@ -52,9 +52,21 @@ module Prism
52
52
  stack = [ISeq.new(RubyVM::InstructionSequence.compile(source).to_a)]
53
53
 
54
54
  while (iseq = stack.pop)
55
- # For some reason, CRuby occasionally pushes this special local
56
- # variable when there are splat arguments. We get rid of that here.
57
- locals << (iseq.local_table - [:"#arg_rest"])
55
+ names = [*iseq.local_table]
56
+ names.map!.with_index do |name, index|
57
+ # When an anonymous local variable is present in the iseq's local
58
+ # table, it is represented as the stack offset from the top.
59
+ # However, when these are dumped to binary and read back in, they
60
+ # are replaced with the symbol :#arg_rest. To consistently handle
61
+ # this, we replace them here with their index.
62
+ if name == :"#arg_rest"
63
+ names.length - index + 1
64
+ else
65
+ name
66
+ end
67
+ end
68
+
69
+ locals << names
58
70
  iseq.each_child { |child| stack << child }
59
71
  end
60
72
 
@@ -110,11 +122,13 @@ module Prism
110
122
 
111
123
  # Recurse down the parameter tree to find any destructured
112
124
  # parameters and add them after the other parameters.
113
- param_stack = params.requireds.concat(params.posts).grep(RequiredDestructuredParameterNode).reverse
125
+ param_stack = params.requireds.concat(params.posts).grep(MultiTargetNode).reverse
114
126
  while (param = param_stack.pop)
115
127
  case param
116
- when RequiredDestructuredParameterNode
117
- param_stack.concat(param.parameters.reverse)
128
+ when MultiTargetNode
129
+ param_stack.concat(param.rights.reverse)
130
+ param_stack << param.rest
131
+ param_stack.concat(param.lefts.reverse)
118
132
  when RequiredParameterNode
119
133
  sorted << param.name
120
134
  when SplatNode
@@ -161,7 +161,7 @@ module Prism
161
161
  nil,
162
162
  node.operator_loc.copy(length: node.operator_loc.length - 1),
163
163
  nil,
164
- ArgumentsNode.new([node.value], node.value.location),
164
+ ArgumentsNode.new([node.value], 0, node.value.location),
165
165
  nil,
166
166
  nil,
167
167
  0,
@@ -1008,14 +1008,6 @@ module Prism
1008
1008
  listeners[:on_regular_expression_node_leave]&.each { |listener| listener.on_regular_expression_node_leave(node) }
1009
1009
  end
1010
1010
 
1011
- # Dispatch enter and leave events for RequiredDestructuredParameterNode nodes and continue
1012
- # walking the tree.
1013
- def visit_required_destructured_parameter_node(node)
1014
- listeners[:on_required_destructured_parameter_node_enter]&.each { |listener| listener.on_required_destructured_parameter_node_enter(node) }
1015
- super
1016
- listeners[:on_required_destructured_parameter_node_leave]&.each { |listener| listener.on_required_destructured_parameter_node_leave(node) }
1017
- end
1018
-
1019
1011
  # Dispatch enter and leave events for RequiredParameterNode nodes and continue
1020
1012
  # walking the tree.
1021
1013
  def visit_required_parameter_node(node)
@@ -1931,12 +1923,6 @@ module Prism
1931
1923
  listeners[:on_regular_expression_node_leave]&.each { |listener| listener.on_regular_expression_node_leave(node) }
1932
1924
  end
1933
1925
 
1934
- # Dispatch enter and leave events for RequiredDestructuredParameterNode nodes.
1935
- def visit_required_destructured_parameter_node(node)
1936
- listeners[:on_required_destructured_parameter_node_enter]&.each { |listener| listener.on_required_destructured_parameter_node_enter(node) }
1937
- listeners[:on_required_destructured_parameter_node_leave]&.each { |listener| listener.on_required_destructured_parameter_node_leave(node) }
1938
- end
1939
-
1940
1926
  # Dispatch enter and leave events for RequiredParameterNode nodes.
1941
1927
  def visit_required_parameter_node(node)
1942
1928
  listeners[:on_required_parameter_node_enter]&.each { |listener| listener.on_required_parameter_node_enter(node) }
data/lib/prism/dsl.rb CHANGED
@@ -63,8 +63,8 @@ module Prism
63
63
  end
64
64
 
65
65
  # Create a new ArgumentsNode node
66
- def ArgumentsNode(arguments, location = Location())
67
- ArgumentsNode.new(arguments, location)
66
+ def ArgumentsNode(arguments, flags, location = Location())
67
+ ArgumentsNode.new(arguments, flags, location)
68
68
  end
69
69
 
70
70
  # Create a new ArrayNode node
@@ -358,8 +358,8 @@ module Prism
358
358
  end
359
359
 
360
360
  # Create a new HashPatternNode node
361
- def HashPatternNode(constant, assocs, kwrest, opening_loc, closing_loc, location = Location())
362
- HashPatternNode.new(constant, assocs, kwrest, opening_loc, closing_loc, location)
361
+ def HashPatternNode(constant, elements, rest, opening_loc, closing_loc, location = Location())
362
+ HashPatternNode.new(constant, elements, rest, opening_loc, closing_loc, location)
363
363
  end
364
364
 
365
365
  # Create a new IfNode node
@@ -538,13 +538,13 @@ module Prism
538
538
  end
539
539
 
540
540
  # Create a new MultiTargetNode node
541
- def MultiTargetNode(targets, lparen_loc, rparen_loc, location = Location())
542
- MultiTargetNode.new(targets, lparen_loc, rparen_loc, location)
541
+ def MultiTargetNode(lefts, rest, rights, lparen_loc, rparen_loc, location = Location())
542
+ MultiTargetNode.new(lefts, rest, rights, lparen_loc, rparen_loc, location)
543
543
  end
544
544
 
545
545
  # Create a new MultiWriteNode node
546
- def MultiWriteNode(targets, lparen_loc, rparen_loc, operator_loc, value, location = Location())
547
- MultiWriteNode.new(targets, lparen_loc, rparen_loc, operator_loc, value, location)
546
+ def MultiWriteNode(lefts, rest, rights, lparen_loc, rparen_loc, operator_loc, value, location = Location())
547
+ MultiWriteNode.new(lefts, rest, rights, lparen_loc, rparen_loc, operator_loc, value, location)
548
548
  end
549
549
 
550
550
  # Create a new NextNode node
@@ -632,11 +632,6 @@ module Prism
632
632
  RegularExpressionNode.new(opening_loc, content_loc, closing_loc, unescaped, flags, location)
633
633
  end
634
634
 
635
- # Create a new RequiredDestructuredParameterNode node
636
- def RequiredDestructuredParameterNode(parameters, opening_loc, closing_loc, location = Location())
637
- RequiredDestructuredParameterNode.new(parameters, opening_loc, closing_loc, location)
638
- end
639
-
640
635
  # Create a new RequiredParameterNode node
641
636
  def RequiredParameterNode(name, location = Location())
642
637
  RequiredParameterNode.new(name, location)
data/lib/prism/ffi.rb CHANGED
@@ -70,6 +70,7 @@ module Prism
70
70
  "prism.h",
71
71
  "pm_version",
72
72
  "pm_parse_serialize",
73
+ "pm_parse_serialize_comments",
73
74
  "pm_lex_serialize",
74
75
  "pm_parse_lex_serialize"
75
76
  )
@@ -224,6 +225,30 @@ module Prism
224
225
  end
225
226
  end
226
227
 
228
+ # Mirror the Prism.parse_comments API by using the serialization API.
229
+ def self.parse_comments(code, filepath = nil)
230
+ LibRubyParser::PrismBuffer.with do |buffer|
231
+ metadata = [filepath.bytesize, filepath.b, 0].pack("LA*L") if filepath
232
+ LibRubyParser.pm_parse_serialize_comments(code, code.bytesize, buffer.pointer, metadata)
233
+
234
+ source = Source.new(code)
235
+ loader = Serialize::Loader.new(source, buffer.read)
236
+
237
+ loader.load_header
238
+ loader.load_force_encoding
239
+ loader.load_comments
240
+ end
241
+ end
242
+
243
+ # Mirror the Prism.parse_file_comments API by using the serialization
244
+ # API. This uses native strings instead of Ruby strings because it allows us
245
+ # to use mmap when it is available.
246
+ def self.parse_file_comments(filepath)
247
+ LibRubyParser::PrismString.with(filepath) do |string|
248
+ parse_comments(string.read, filepath)
249
+ end
250
+ end
251
+
227
252
  # Mirror the Prism.parse_lex API by using the serialization API.
228
253
  def self.parse_lex(code, filepath = nil)
229
254
  LibRubyParser::PrismBuffer.with do |buffer|
@@ -529,7 +529,7 @@ module Prism
529
529
  line.each_char.with_index do |char, i|
530
530
  case char
531
531
  when "\r"
532
- if line.chars[i + 1] == "\n"
532
+ if line[i + 1] == "\n"
533
533
  break
534
534
  end
535
535
  when "\n"