prism 2.0.0.rc2 → 2.0.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.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +9 -2
  3. data/docs/serialization.md +19 -6
  4. data/ext/prism/api_node.c +80 -80
  5. data/ext/prism/extension.c +34 -67
  6. data/ext/prism/extension.h +1 -1
  7. data/include/prism/arena.h +8 -0
  8. data/include/prism/arena.hpp +42 -0
  9. data/include/prism/ast.h +11 -1
  10. data/include/prism/ast.hpp +641 -0
  11. data/include/prism/buffer.h +8 -0
  12. data/include/prism/buffer.hpp +55 -0
  13. data/include/prism/comments.h +17 -0
  14. data/include/prism/compiler/branch.h +26 -0
  15. data/include/prism/compiler/cplusplus.hpp +16 -0
  16. data/include/prism/compiler/exceptions.hpp +17 -0
  17. data/include/prism/compiler/format.h +2 -0
  18. data/include/prism/compiler/lifetimebound.hpp +25 -0
  19. data/include/prism/constant_pool.h +25 -0
  20. data/include/prism/diagnostic.h +18 -0
  21. data/include/prism/errors_format.h +8 -0
  22. data/include/prism/internal/node.h +8 -4
  23. data/include/prism/internal/stringy.h +1 -6
  24. data/include/prism/json.h +8 -0
  25. data/include/prism/line_offset_list.h +8 -0
  26. data/include/prism/magic_comments.h +18 -0
  27. data/include/prism/node.h +55 -10
  28. data/include/prism/node.hpp +272 -0
  29. data/include/prism/node_type.hpp +38 -0
  30. data/include/prism/options.h +10 -1
  31. data/include/prism/options.hpp +43 -0
  32. data/include/prism/parser.h +72 -64
  33. data/include/prism/parser.hpp +274 -0
  34. data/include/prism/prettyprint.h +8 -0
  35. data/include/prism/serialize.h +8 -0
  36. data/include/prism/source.h +8 -0
  37. data/include/prism/stream.h +8 -0
  38. data/include/prism/string_query.h +8 -0
  39. data/include/prism/stringy.h +16 -27
  40. data/include/prism/stringy.hpp +31 -0
  41. data/include/prism/version.h +9 -1
  42. data/include/prism.h +0 -8
  43. data/include/prism.hpp +24 -0
  44. data/lib/prism/serialize.rb +2549 -3281
  45. data/prism.gemspec +14 -1
  46. data/rbi/generated/prism/node.rbi +736 -0
  47. data/rbi/generated/prism/serialize.rbi +6 -5
  48. data/sig/generated/prism/node.rbs +736 -0
  49. data/sig/generated/prism/serialize.rbs +7 -5
  50. data/src/comments.c +2 -2
  51. data/src/diagnostic.c +8 -0
  52. data/src/node.c +216 -368
  53. data/src/options.c +7 -13
  54. data/src/parser.c +52 -48
  55. data/src/prism.c +175 -194
  56. data/src/regexp.c +0 -1
  57. data/src/serialize.c +2300 -1950
  58. data/src/source.c +8 -2
  59. data/src/stringy.c +3 -33
  60. metadata +14 -1
@@ -0,0 +1,274 @@
1
+ /**
2
+ * @file parser.hpp
3
+ *
4
+ * Ownership of parsers from C++, and lookups through a parser into the source,
5
+ * the constant pool, comments, and diagnostics.
6
+ */
7
+ #ifndef PRISM_PARSER_HPP
8
+ #define PRISM_PARSER_HPP
9
+
10
+ #include "prism/compiler/cplusplus.hpp"
11
+ #include "prism/compiler/lifetimebound.hpp"
12
+
13
+ #include "prism/arena.h"
14
+ #include "prism/constant_pool.h"
15
+ #include "prism/line_offset_list.h"
16
+ #include "prism/parser.h"
17
+
18
+ #include <cassert>
19
+ #include <cstddef>
20
+ #include <cstdint>
21
+ #include <iterator>
22
+ #include <memory>
23
+ #include <string_view>
24
+
25
+ namespace prism {
26
+
27
+ /** Frees a parser with pm_parser_free. */
28
+ struct parser_deleter {
29
+ /**
30
+ * Free the given parser.
31
+ *
32
+ * @param parser The parser to free.
33
+ */
34
+ void operator()(pm_parser_t *parser) const noexcept { pm_parser_free(parser); }
35
+ };
36
+
37
+ /** An owned parser. */
38
+ using unique_parser = std::unique_ptr<pm_parser_t, parser_deleter>;
39
+
40
+ /**
41
+ * Allocate a new parser over the given source. The source, the arena, and the
42
+ * options (which may be null) are not copied, so all three must outlive the
43
+ * parser. Allocation failure aborts, so this never throws.
44
+ *
45
+ * @param arena The arena to use for allocations.
46
+ * @param source The source code to parse.
47
+ * @param options The parse options, or null for defaults.
48
+ * @return A unique_parser owning the newly allocated parser.
49
+ */
50
+ [[nodiscard]] inline unique_parser
51
+ make_parser(pm_arena_t *arena PRISM_LIFETIMEBOUND, std::string_view source PRISM_LIFETIMEBOUND, const pm_options_t *options PRISM_LIFETIMEBOUND = nullptr) noexcept {
52
+ return unique_parser(pm_parser_new(arena, reinterpret_cast<const std::uint8_t *>(source.data()), source.size(), options));
53
+ }
54
+
55
+ /**
56
+ * The name of the constant with the given id, which must not be zero. Fields
57
+ * holding an optional constant use zero for none, so check those first.
58
+ *
59
+ * @param parser The parser containing the constant.
60
+ * @param constant_id The id of the constant.
61
+ * @return The value of the constant.
62
+ */
63
+ [[nodiscard]] inline std::string_view
64
+ constant(const pm_parser_t *parser PRISM_LIFETIMEBOUND, pm_constant_id_t constant_id) noexcept {
65
+ assert(constant_id != 0);
66
+ const pm_constant_t *entry = pm_parser_constant(parser, constant_id);
67
+ return std::string_view(reinterpret_cast<const char *>(pm_constant_start(entry)), pm_constant_length(entry));
68
+ }
69
+
70
+ /**
71
+ * The bytes of source that the given location covers.
72
+ *
73
+ * @param parser The parser containing the source.
74
+ * @param location The location in the source.
75
+ * @return The bytes of source covered by the location.
76
+ */
77
+ [[nodiscard]] inline std::string_view
78
+ slice(const pm_parser_t *parser PRISM_LIFETIMEBOUND, pm_location_t location) noexcept {
79
+ return std::string_view(reinterpret_cast<const char *>(pm_parser_start(parser) + location.start), location.length);
80
+ }
81
+
82
+ /**
83
+ * The line and column of the given byte offset into the source. Lines start at
84
+ * the parser's start line, and columns are byte offsets from the line start.
85
+ *
86
+ * @param parser The parser containing the source.
87
+ * @param offset The byte offset into the source.
88
+ * @return The line and column of the byte offset.
89
+ */
90
+ [[nodiscard]] inline pm_line_column_t
91
+ line_column(const pm_parser_t *parser, std::uint32_t offset) noexcept {
92
+ return pm_line_offset_list_line_column(pm_parser_line_offsets(parser), offset, pm_parser_start_line(parser));
93
+ }
94
+
95
+ namespace detail {
96
+
97
+ /**
98
+ * The diagnostics, comments, or magic comments found while parsing, usable in a
99
+ * range-based for loop and with the standard algorithms. Each element is a
100
+ * pointer to the C struct, which the C accessors read, and Next is the C
101
+ * function that returns the item after a given one. It refers to the parser
102
+ * rather than copying from it, so the parser must outlive it. It is used
103
+ * through diagnostic_range, comment_range, and magic_comment_range.
104
+ */
105
+ template <typename T, const T *(*Next)(const T *)> class next_range {
106
+ public:
107
+ /** Steps through the items one after another. */
108
+ class iterator {
109
+ public:
110
+ /** The iterator category, for the standard algorithms. */
111
+ using iterator_category = std::forward_iterator_tag;
112
+
113
+ /** The type of each element. */
114
+ using value_type = const T *;
115
+
116
+ /** The type of the distance between two iterators. */
117
+ using difference_type = std::ptrdiff_t;
118
+
119
+ /** The type of a pointer to an element. */
120
+ using pointer = const value_type *;
121
+
122
+ /** The type of a reference to an element. */
123
+ using reference = const value_type &;
124
+
125
+ /** Create the iterator that marks the end of the items. */
126
+ iterator() noexcept = default;
127
+
128
+ /**
129
+ * Create an iterator at the given item.
130
+ *
131
+ * @param current The current item.
132
+ */
133
+ explicit iterator(const T *current) noexcept : current_(current) {}
134
+
135
+ /**
136
+ * The item at this position, which must not be the end.
137
+ *
138
+ * @return The current item.
139
+ */
140
+ reference operator*() const noexcept { return current_; }
141
+
142
+ /**
143
+ * Advance to the next item.
144
+ *
145
+ * @return The iterator after advancing.
146
+ */
147
+ iterator &
148
+ operator++() noexcept {
149
+ assert(current_ != nullptr);
150
+ current_ = Next(current_);
151
+ return *this;
152
+ }
153
+
154
+ /**
155
+ * Advance to the next item, returning the iterator from before.
156
+ *
157
+ * @return The iterator from before advancing.
158
+ */
159
+ iterator
160
+ operator++(int) noexcept {
161
+ iterator previous = *this;
162
+ ++*this;
163
+ return previous;
164
+ }
165
+
166
+ /** Whether the two iterators are at the same item. */
167
+ friend bool operator==(iterator left, iterator right) noexcept { return left.current_ == right.current_; }
168
+
169
+ /** Whether the two iterators are at different items. */
170
+ friend bool operator!=(iterator left, iterator right) noexcept { return left.current_ != right.current_; }
171
+
172
+ private:
173
+ const T *current_ = nullptr;
174
+ };
175
+
176
+ /**
177
+ * Create a range of the given number of items starting at first.
178
+ *
179
+ * @param first The first item.
180
+ * @param size The number of items.
181
+ */
182
+ next_range(const T *first, std::size_t size) noexcept : first_(first), size_(size) {}
183
+
184
+ /**
185
+ * An iterator at the first item.
186
+ *
187
+ * @return An iterator at the first item.
188
+ */
189
+ iterator begin() const noexcept { return iterator(first_); }
190
+
191
+ /**
192
+ * An iterator past the last item.
193
+ *
194
+ * @return An iterator past the last item.
195
+ */
196
+ iterator end() const noexcept { return iterator(); }
197
+
198
+ /**
199
+ * The number of items.
200
+ *
201
+ * @return The number of items.
202
+ */
203
+ std::size_t size() const noexcept { return size_; }
204
+
205
+ /**
206
+ * Whether there are no items.
207
+ *
208
+ * @return Whether there are no items.
209
+ */
210
+ [[nodiscard]] bool empty() const noexcept { return size_ == 0; }
211
+
212
+ private:
213
+ const T *first_;
214
+ std::size_t size_;
215
+ };
216
+
217
+ }
218
+
219
+ /** The errors or warnings found while parsing. */
220
+ using diagnostic_range = detail::next_range<pm_diagnostic_t, pm_diagnostic_next>;
221
+
222
+ /** The comments found while parsing. */
223
+ using comment_range = detail::next_range<pm_comment_t, pm_comment_next>;
224
+
225
+ /** The magic comments found while parsing. */
226
+ using magic_comment_range = detail::next_range<pm_magic_comment_t, pm_magic_comment_next>;
227
+
228
+ /**
229
+ * The errors found while parsing.
230
+ *
231
+ * @param parser The parser containing the source.
232
+ * @return The range of errors found while parsing.
233
+ */
234
+ [[nodiscard]] inline diagnostic_range
235
+ errors(const pm_parser_t *parser PRISM_LIFETIMEBOUND) noexcept {
236
+ return diagnostic_range(pm_parser_errors_first(parser), pm_parser_errors_size(parser));
237
+ }
238
+
239
+ /**
240
+ * The warnings found while parsing.
241
+ *
242
+ * @param parser The parser containing the source.
243
+ * @return The range of warnings found while parsing.
244
+ */
245
+ [[nodiscard]] inline diagnostic_range
246
+ warnings(const pm_parser_t *parser PRISM_LIFETIMEBOUND) noexcept {
247
+ return diagnostic_range(pm_parser_warnings_first(parser), pm_parser_warnings_size(parser));
248
+ }
249
+
250
+ /**
251
+ * The comments found while parsing, in source order.
252
+ *
253
+ * @param parser The parser containing the source.
254
+ * @return The range of comments found while parsing.
255
+ */
256
+ [[nodiscard]] inline comment_range
257
+ comments(const pm_parser_t *parser PRISM_LIFETIMEBOUND) noexcept {
258
+ return comment_range(pm_parser_comments_first(parser), pm_parser_comments_size(parser));
259
+ }
260
+
261
+ /**
262
+ * The magic comments found while parsing.
263
+ *
264
+ * @param parser The parser containing the source.
265
+ * @return The range of magic comments found while parsing.
266
+ */
267
+ [[nodiscard]] inline magic_comment_range
268
+ magic_comments(const pm_parser_t *parser PRISM_LIFETIMEBOUND) noexcept {
269
+ return magic_comment_range(pm_parser_magic_comments_first(parser), pm_parser_magic_comments_size(parser));
270
+ }
271
+
272
+ }
273
+
274
+ #endif
@@ -17,6 +17,10 @@
17
17
  #include "prism/buffer.h"
18
18
  #include "prism/parser.h"
19
19
 
20
+ #ifdef __cplusplus
21
+ extern "C" {
22
+ #endif
23
+
20
24
  /**
21
25
  * Pretty-prints the AST represented by the given node to the given buffer.
22
26
  *
@@ -26,6 +30,10 @@
26
30
  */
27
31
  PRISM_EXPORTED_FUNCTION void pm_prettyprint(pm_buffer_t *output_buffer, const pm_parser_t *parser, const pm_node_t *node) PRISM_NONNULL(1, 2, 3);
28
32
 
33
+ #ifdef __cplusplus
34
+ }
35
+ #endif
36
+
29
37
  #endif
30
38
 
31
39
  #endif
@@ -22,6 +22,10 @@
22
22
  #include "prism/source.h"
23
23
  #include "prism/stream.h"
24
24
 
25
+ #ifdef __cplusplus
26
+ extern "C" {
27
+ #endif
28
+
25
29
  /**
26
30
  * Serialize the AST represented by the given node to the given buffer.
27
31
  *
@@ -110,6 +114,10 @@ PRISM_EXPORTED_FUNCTION bool pm_serialize_parse_success_p(const uint8_t *source,
110
114
  */
111
115
  PRISM_EXPORTED_FUNCTION int8_t pm_serialize_parse_errors_format(pm_buffer_t *buffer, const uint8_t *source, size_t size, const char *data, pm_errors_format_type_t format_type) PRISM_NONNULL(1, 2);
112
116
 
117
+ #ifdef __cplusplus
118
+ }
119
+ #endif
120
+
113
121
  #endif
114
122
 
115
123
  #endif
@@ -15,6 +15,10 @@
15
15
  #include <stddef.h>
16
16
  #include <stdint.h>
17
17
 
18
+ #ifdef __cplusplus
19
+ extern "C" {
20
+ #endif
21
+
18
22
  /**
19
23
  * An opaque type representing source code being parsed.
20
24
  */
@@ -152,4 +156,8 @@ PRISM_EXPORTED_FUNCTION size_t pm_source_length(const pm_source_t *source) PRISM
152
156
  */
153
157
  PRISM_EXPORTED_FUNCTION const uint8_t * pm_source_source(const pm_source_t *source) PRISM_NONNULL(1);
154
158
 
159
+ #ifdef __cplusplus
160
+ }
161
+ #endif
162
+
155
163
  #endif
@@ -14,6 +14,10 @@
14
14
  #include "prism/parser.h"
15
15
  #include "prism/source.h"
16
16
 
17
+ #ifdef __cplusplus
18
+ extern "C" {
19
+ #endif
20
+
17
21
  /**
18
22
  * Parse a stream of Ruby source and return the tree.
19
23
  *
@@ -25,4 +29,8 @@
25
29
  */
26
30
  PRISM_EXPORTED_FUNCTION pm_node_t * pm_parse_stream(pm_parser_t **parser, pm_arena_t *arena, pm_source_t *source, const pm_options_t *options) PRISM_NONNULL(1, 2, 3);
27
31
 
32
+ #ifdef __cplusplus
33
+ }
34
+ #endif
35
+
28
36
  #endif
@@ -13,6 +13,10 @@
13
13
  #include <stddef.h>
14
14
  #include <stdint.h>
15
15
 
16
+ #ifdef __cplusplus
17
+ extern "C" {
18
+ #endif
19
+
16
20
  /**
17
21
  * Represents the results of a slice query.
18
22
  */
@@ -71,4 +75,8 @@ PRISM_EXPORTED_FUNCTION pm_string_query_t pm_string_query_method_name(const uint
71
75
  */
72
76
  PRISM_EXPORTED_FUNCTION pm_string_query_t pm_string_query_keyword(const uint8_t *source, size_t length, const char *encoding_name) PRISM_NONNULL(1, 3);
73
77
 
78
+ #ifdef __cplusplus
79
+ }
80
+ #endif
81
+
74
82
  #endif
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * @file stringy.h
3
3
  *
4
- * A generic string type that can have various ownership semantics.
4
+ * A view of a sequence of bytes owned by someone else.
5
5
  */
6
6
  #ifndef PRISM_STRINGY_H
7
7
  #define PRISM_STRINGY_H
@@ -12,8 +12,13 @@
12
12
  #include <stddef.h>
13
13
  #include <stdint.h>
14
14
 
15
+ #ifdef __cplusplus
16
+ extern "C" {
17
+ #endif
18
+
15
19
  /**
16
- * A generic string type that can have various ownership semantics.
20
+ * A view of a sequence of bytes. The string does not own the bytes, so they
21
+ * must remain valid for as long as the string is in use.
17
22
  */
18
23
  typedef struct {
19
24
  /** A pointer to the start of the string. */
@@ -21,37 +26,17 @@ typedef struct {
21
26
 
22
27
  /** The length of the string in bytes of memory. */
23
28
  size_t length;
24
-
25
- /** The type of the string. This field determines how the string should be freed. */
26
- enum {
27
- /** This string is a constant string, and should not be freed. */
28
- PM_STRING_CONSTANT,
29
-
30
- /** This is a slice of another string, and should not be freed. */
31
- PM_STRING_SHARED,
32
-
33
- /** This string owns its memory, and should be freed internally. */
34
- PM_STRING_OWNED
35
- } type;
36
29
  } pm_string_t;
37
30
 
38
31
  /**
39
- * Initialize a constant string that doesn't own its memory source.
40
- *
41
- * @param string The string to initialize.
42
- * @param source The source of the string.
43
- * @param length The length of the string.
44
- */
45
- PRISM_EXPORTED_FUNCTION void pm_string_constant_init(pm_string_t *string, const char *source, size_t length) PRISM_NONNULL(1);
46
-
47
- /**
48
- * Initialize an owned string that is responsible for freeing allocated memory.
32
+ * Initialize a string that views the given bytes. The bytes are not copied, so
33
+ * they must remain valid for as long as the string is in use.
49
34
  *
50
35
  * @param string The string to initialize.
51
- * @param source The source of the string.
52
- * @param length The length of the string.
36
+ * @param source The start of the bytes.
37
+ * @param length The number of bytes.
53
38
  */
54
- PRISM_EXPORTED_FUNCTION void pm_string_owned_init(pm_string_t *string, uint8_t *source, size_t length) PRISM_NONNULL(1, 2);
39
+ PRISM_EXPORTED_FUNCTION void pm_string_init(pm_string_t *string, const uint8_t *source, size_t length) PRISM_NONNULL(1);
55
40
 
56
41
  /**
57
42
  * Returns the length associated with the string.
@@ -69,4 +54,8 @@ PRISM_EXPORTED_FUNCTION size_t pm_string_length(const pm_string_t *string) PRISM
69
54
  */
70
55
  PRISM_EXPORTED_FUNCTION const uint8_t * pm_string_source(const pm_string_t *string) PRISM_NONNULL(1);
71
56
 
57
+ #ifdef __cplusplus
58
+ }
59
+ #endif
60
+
72
61
  #endif
@@ -0,0 +1,31 @@
1
+ /**
2
+ * @file stringy.hpp
3
+ *
4
+ * Access to the contents of strings from C++.
5
+ */
6
+ #ifndef PRISM_STRINGY_HPP
7
+ #define PRISM_STRINGY_HPP
8
+
9
+ #include "prism/compiler/cplusplus.hpp"
10
+ #include "prism/compiler/lifetimebound.hpp"
11
+
12
+ #include "prism/stringy.h"
13
+
14
+ #include <string_view>
15
+
16
+ namespace prism {
17
+
18
+ /**
19
+ * The bytes of the given string.
20
+ *
21
+ * @param string The string to view.
22
+ * @return A view of the bytes of the string.
23
+ */
24
+ [[nodiscard]] inline std::string_view
25
+ view(const pm_string_t &string PRISM_LIFETIMEBOUND) noexcept {
26
+ return std::string_view(reinterpret_cast<const char *>(pm_string_source(&string)), pm_string_length(&string));
27
+ }
28
+
29
+ }
30
+
31
+ #endif
@@ -8,6 +8,10 @@
8
8
 
9
9
  #include "prism/compiler/exported.h"
10
10
 
11
+ #ifdef __cplusplus
12
+ extern "C" {
13
+ #endif
14
+
11
15
  /**
12
16
  * The major version of the Prism library as an int.
13
17
  */
@@ -26,7 +30,7 @@
26
30
  /**
27
31
  * The version of the Prism library as a constant string.
28
32
  */
29
- #define PRISM_VERSION "2.0.0.rc2"
33
+ #define PRISM_VERSION "2.0.0"
30
34
 
31
35
  /**
32
36
  * The prism version and the serialization format.
@@ -35,4 +39,8 @@
35
39
  */
36
40
  PRISM_EXPORTED_FUNCTION const char * pm_version(void);
37
41
 
42
+ #ifdef __cplusplus
43
+ }
44
+ #endif
45
+
38
46
  #endif
data/include/prism.h CHANGED
@@ -6,10 +6,6 @@
6
6
  #ifndef PRISM_H
7
7
  #define PRISM_H
8
8
 
9
- #ifdef __cplusplus
10
- extern "C" {
11
- #endif
12
-
13
9
  #include "prism/arena.h"
14
10
  #include "prism/ast.h"
15
11
  #include "prism/buffer.h"
@@ -124,8 +120,4 @@ extern "C" {
124
120
  * ```
125
121
  */
126
122
 
127
- #ifdef __cplusplus
128
- }
129
- #endif
130
-
131
123
  #endif
data/include/prism.hpp ADDED
@@ -0,0 +1,24 @@
1
+ /**
2
+ * @file prism.hpp
3
+ *
4
+ * The main header file for the C++ interface to the prism parser. It adds
5
+ * ownership, checked casts between node types, and callable-based iteration on
6
+ * top of the C API. It never wraps the C structs: every function in it takes
7
+ * and returns the same pm_*_t types that prism.h declares, so the two can be
8
+ * mixed freely. It requires C++17 or later.
9
+ */
10
+ #ifndef PRISM_HPP
11
+ #define PRISM_HPP
12
+
13
+ #include "prism.h"
14
+
15
+ #include "prism/arena.hpp"
16
+ #include "prism/ast.hpp"
17
+ #include "prism/buffer.hpp"
18
+ #include "prism/node.hpp"
19
+ #include "prism/node_type.hpp"
20
+ #include "prism/options.hpp"
21
+ #include "prism/parser.hpp"
22
+ #include "prism/stringy.hpp"
23
+
24
+ #endif