prism 2.0.0.rc1-x86_64-linux-gnu → 2.0.0-x86_64-linux-gnu
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 +13 -2
- data/CODE_OF_CONDUCT.md +1 -1
- data/LICENSE.md +1 -1
- data/docs/serialization.md +20 -6
- data/ext/prism/api_node.c +81 -81
- data/ext/prism/extension.c +54 -69
- data/ext/prism/extension.h +1 -1
- data/include/prism/arena.h +8 -0
- data/include/prism/arena.hpp +42 -0
- data/include/prism/ast.h +11 -1
- data/include/prism/ast.hpp +641 -0
- data/include/prism/buffer.h +8 -0
- data/include/prism/buffer.hpp +55 -0
- data/include/prism/comments.h +17 -0
- data/include/prism/compiler/accel.h +3 -1
- data/include/prism/compiler/branch.h +26 -0
- data/include/prism/compiler/bswap.h +46 -0
- data/include/prism/compiler/cplusplus.hpp +16 -0
- data/include/prism/compiler/endianness.h +34 -0
- data/include/prism/compiler/exceptions.hpp +17 -0
- data/include/prism/compiler/format.h +2 -0
- data/include/prism/compiler/lifetimebound.hpp +25 -0
- data/include/prism/constant_pool.h +25 -0
- data/include/prism/diagnostic.h +18 -0
- data/include/prism/errors_format.h +8 -0
- data/include/prism/internal/buffer.h +3 -0
- data/include/prism/internal/node.h +8 -4
- data/include/prism/internal/parser.h +20 -0
- data/include/prism/internal/stringy.h +1 -6
- data/include/prism/internal/xxh3.h +16 -0
- data/include/prism/json.h +8 -0
- data/include/prism/line_offset_list.h +8 -0
- data/include/prism/magic_comments.h +18 -0
- data/include/prism/node.h +55 -10
- data/include/prism/node.hpp +272 -0
- data/include/prism/node_type.hpp +38 -0
- data/include/prism/options.h +10 -1
- data/include/prism/options.hpp +43 -0
- data/include/prism/parser.h +93 -64
- data/include/prism/parser.hpp +274 -0
- data/include/prism/prettyprint.h +8 -0
- data/include/prism/serialize.h +8 -0
- data/include/prism/source.h +8 -0
- data/include/prism/stream.h +8 -0
- data/include/prism/string_query.h +19 -0
- data/include/prism/stringy.h +16 -27
- data/include/prism/stringy.hpp +31 -0
- data/include/prism/version.h +9 -1
- data/include/prism.h +0 -8
- data/include/prism.hpp +24 -0
- data/lib/prism/3.3/prism.so +0 -0
- data/lib/prism/3.4/prism.so +0 -0
- data/lib/prism/4.0/prism.so +0 -0
- data/lib/prism/ffi.rb +6 -0
- data/lib/prism/node.rb +736 -0
- data/lib/prism/parse_result.rb +23 -8
- data/lib/prism/serialize.rb +2567 -3286
- data/lib/prism/string_query.rb +8 -0
- data/prism.gemspec +21 -4
- data/rbi/generated/prism/node.rbi +2430 -968
- data/rbi/generated/prism/parse_result.rbi +16 -4
- data/rbi/generated/prism/serialize.rbi +8 -4
- data/rbi/generated/prism/string_query.rbi +7 -0
- data/sig/generated/prism/node.rbs +2439 -967
- data/sig/generated/prism/parse_result.rbs +16 -4
- data/sig/generated/prism/serialize.rbs +9 -4
- data/sig/generated/prism/string_query.rbs +7 -0
- data/src/buffer.c +9 -0
- data/src/comments.c +2 -2
- data/src/diagnostic.c +8 -0
- data/src/node.c +216 -368
- data/src/options.c +7 -13
- data/src/parser.c +70 -48
- data/src/prism.c +581 -419
- data/src/regexp.c +0 -1
- data/src/serialize.c +2301 -1950
- data/src/source.c +8 -2
- data/src/string_query.c +14 -0
- data/src/stringy.c +3 -33
- data/src/xxh3.c +292 -0
- metadata +20 -3
data/include/prism/node.h
CHANGED
|
@@ -11,6 +11,10 @@
|
|
|
11
11
|
|
|
12
12
|
#include "prism/ast.h"
|
|
13
13
|
|
|
14
|
+
#ifdef __cplusplus
|
|
15
|
+
extern "C" {
|
|
16
|
+
#endif
|
|
17
|
+
|
|
14
18
|
/**
|
|
15
19
|
* Loop through each node in the node list, writing each node to the given
|
|
16
20
|
* pm_node_t pointer.
|
|
@@ -18,6 +22,18 @@
|
|
|
18
22
|
#define PM_NODE_LIST_FOREACH(list, index, node) \
|
|
19
23
|
for (size_t index = 0; index < (list)->size && ((node) = (list)->nodes[index]); index++)
|
|
20
24
|
|
|
25
|
+
/**
|
|
26
|
+
* Append a node to the end of a node list. If the list is full, its storage is
|
|
27
|
+
* grown by allocating from the given arena, so the arena must live as long as
|
|
28
|
+
* the list does. For a list in a parsed tree, that is the arena that was passed
|
|
29
|
+
* to pm_parser_new.
|
|
30
|
+
*
|
|
31
|
+
* @param arena The arena to allocate the list's storage from.
|
|
32
|
+
* @param list The list to append to.
|
|
33
|
+
* @param node The node to append.
|
|
34
|
+
*/
|
|
35
|
+
PRISM_EXPORTED_FUNCTION void pm_node_list_append(pm_arena_t *arena, pm_node_list_t *list, pm_node_t *node) PRISM_NONNULL(1, 2, 3);
|
|
36
|
+
|
|
21
37
|
/**
|
|
22
38
|
* Returns a string representation of the given node type.
|
|
23
39
|
*
|
|
@@ -26,20 +42,41 @@
|
|
|
26
42
|
*/
|
|
27
43
|
PRISM_EXPORTED_FUNCTION const char * pm_node_type(pm_node_type_t node_type);
|
|
28
44
|
|
|
45
|
+
/**
|
|
46
|
+
* The value returned by a visitor callback, which determines where the walk
|
|
47
|
+
* goes next.
|
|
48
|
+
*/
|
|
49
|
+
typedef enum {
|
|
50
|
+
/** Continue the walk without visiting this node's children. */
|
|
51
|
+
PM_VISIT_SKIP,
|
|
52
|
+
|
|
53
|
+
/** Continue the walk by visiting this node's children. */
|
|
54
|
+
PM_VISIT_DESCEND,
|
|
55
|
+
|
|
56
|
+
/** End the walk without visiting any more nodes. */
|
|
57
|
+
PM_VISIT_STOP
|
|
58
|
+
} pm_visit_result_t;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* A callback that is called for each node visited by pm_visit_node and
|
|
62
|
+
* pm_visit_child_nodes. The data parameter is the opaque pointer that was
|
|
63
|
+
* passed to the function that started the walk.
|
|
64
|
+
*/
|
|
65
|
+
typedef pm_visit_result_t (*pm_visit_callback_t)(const pm_node_t *node, void *data);
|
|
66
|
+
|
|
29
67
|
/**
|
|
30
68
|
* Visit each of the nodes in this subtree using the given visitor callback. The
|
|
31
|
-
* callback function will be called for each node in the subtree
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
* see fit.
|
|
69
|
+
* callback function will be called for each node in the subtree, and its
|
|
70
|
+
* return value determines whether the walk visits that node's children, skips
|
|
71
|
+
* them, or stops entirely. The data parameter is treated as an opaque pointer
|
|
72
|
+
* and is passed to the visitor callback for consumers to use as they see fit.
|
|
36
73
|
*
|
|
37
74
|
* As an example:
|
|
38
75
|
*
|
|
39
76
|
* ```c
|
|
40
77
|
* #include "prism.h"
|
|
41
78
|
*
|
|
42
|
-
*
|
|
79
|
+
* pm_visit_result_t visit(const pm_node_t *node, void *data) {
|
|
43
80
|
* size_t *indent = (size_t *) data;
|
|
44
81
|
* for (size_t i = 0; i < *indent * 2; i++) putc(' ', stdout);
|
|
45
82
|
* printf("%s\n", pm_node_type(node->type));
|
|
@@ -48,7 +85,7 @@ PRISM_EXPORTED_FUNCTION const char * pm_node_type(pm_node_type_t node_type);
|
|
|
48
85
|
* size_t *next_data = &next_indent;
|
|
49
86
|
* pm_visit_child_nodes(node, visit, next_data);
|
|
50
87
|
*
|
|
51
|
-
* return
|
|
88
|
+
* return PM_VISIT_SKIP;
|
|
52
89
|
* }
|
|
53
90
|
*
|
|
54
91
|
* int main(void) {
|
|
@@ -77,18 +114,26 @@ PRISM_EXPORTED_FUNCTION const char * pm_node_type(pm_node_type_t node_type);
|
|
|
77
114
|
* @param node The root node to start visiting from.
|
|
78
115
|
* @param visitor The callback to call for each node in the subtree.
|
|
79
116
|
* @param data An opaque pointer that is passed to the visitor callback.
|
|
117
|
+
* @returns false if the visitor stopped the walk by returning PM_VISIT_STOP,
|
|
118
|
+
* true otherwise.
|
|
80
119
|
*/
|
|
81
|
-
PRISM_EXPORTED_FUNCTION
|
|
120
|
+
PRISM_EXPORTED_FUNCTION bool pm_visit_node(const pm_node_t *node, pm_visit_callback_t visitor, void *data) PRISM_NONNULL(1);
|
|
82
121
|
|
|
83
122
|
/**
|
|
84
123
|
* Visit the children of the given node with the given callback. This is the
|
|
85
124
|
* default behavior for walking the tree that is called from pm_visit_node if
|
|
86
|
-
* the callback returns
|
|
125
|
+
* the callback returns PM_VISIT_DESCEND.
|
|
87
126
|
*
|
|
88
127
|
* @param node The node to visit the children of.
|
|
89
128
|
* @param visitor The callback to call for each child node.
|
|
90
129
|
* @param data An opaque pointer that is passed to the visitor callback.
|
|
130
|
+
* @returns false if the visitor stopped the walk by returning PM_VISIT_STOP,
|
|
131
|
+
* true otherwise.
|
|
91
132
|
*/
|
|
92
|
-
PRISM_EXPORTED_FUNCTION
|
|
133
|
+
PRISM_EXPORTED_FUNCTION bool pm_visit_child_nodes(const pm_node_t *node, pm_visit_callback_t visitor, void *data) PRISM_NONNULL(1);
|
|
134
|
+
|
|
135
|
+
#ifdef __cplusplus
|
|
136
|
+
}
|
|
137
|
+
#endif
|
|
93
138
|
|
|
94
139
|
#endif
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file node.hpp
|
|
3
|
+
*
|
|
4
|
+
* Checked casts between node structs, iteration over lists of nodes, and
|
|
5
|
+
* walking the tree from C++.
|
|
6
|
+
*/
|
|
7
|
+
#ifndef PRISM_NODE_HPP
|
|
8
|
+
#define PRISM_NODE_HPP
|
|
9
|
+
|
|
10
|
+
#include "prism/compiler/cplusplus.hpp"
|
|
11
|
+
#include "prism/compiler/exceptions.hpp"
|
|
12
|
+
#include "prism/compiler/lifetimebound.hpp"
|
|
13
|
+
|
|
14
|
+
#include "prism/ast.hpp"
|
|
15
|
+
#include "prism/node.h"
|
|
16
|
+
#include "prism/node_type.hpp"
|
|
17
|
+
|
|
18
|
+
#include <cassert>
|
|
19
|
+
#include <cstddef>
|
|
20
|
+
#include <exception>
|
|
21
|
+
#include <functional>
|
|
22
|
+
#include <memory>
|
|
23
|
+
#include <type_traits>
|
|
24
|
+
|
|
25
|
+
namespace prism {
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Whether the given node, which must not be null, is of the given struct
|
|
29
|
+
*
|
|
30
|
+
* @tparam T The node struct type to check against.
|
|
31
|
+
* @param node The node to check.
|
|
32
|
+
* @return True if the node is of the given struct, false otherwise.
|
|
33
|
+
*/
|
|
34
|
+
template <typename T> [[nodiscard]] bool
|
|
35
|
+
isa(const pm_node_t *node) noexcept {
|
|
36
|
+
static_assert(is_node_v<T>, "isa<T> requires a node struct declared in ast.h");
|
|
37
|
+
assert(node != nullptr);
|
|
38
|
+
return node->type == node_type_v<T>;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Cast the given node, which must not be null and must be of the given struct,
|
|
43
|
+
* to that struct. The type is checked in debug builds.
|
|
44
|
+
*
|
|
45
|
+
* @tparam T The node struct type to cast to.
|
|
46
|
+
* @param node The node to cast.
|
|
47
|
+
* @return The node cast to the given struct.
|
|
48
|
+
*/
|
|
49
|
+
template <typename T> [[nodiscard]] T *
|
|
50
|
+
cast(pm_node_t *node) noexcept {
|
|
51
|
+
assert(isa<T>(node));
|
|
52
|
+
return reinterpret_cast<T *>(node);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Cast the given node, which must not be null and must be of the given struct,
|
|
57
|
+
* to that struct. The type is checked in debug builds.
|
|
58
|
+
*
|
|
59
|
+
* @tparam T The node struct type to cast to.
|
|
60
|
+
* @param node The node to cast.
|
|
61
|
+
* @return The node cast to the given struct.
|
|
62
|
+
*/
|
|
63
|
+
template <typename T> [[nodiscard]] const T *
|
|
64
|
+
cast(const pm_node_t *node) noexcept {
|
|
65
|
+
assert(isa<T>(node));
|
|
66
|
+
return reinterpret_cast<const T *>(node);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Cast the given node to the given struct if it is of that struct, and return
|
|
71
|
+
* null otherwise. The node may be null, in which case this returns null.
|
|
72
|
+
*
|
|
73
|
+
* @tparam T The node struct type to cast to.
|
|
74
|
+
* @param node The node to cast.
|
|
75
|
+
* @return The node cast to the given struct if it is of that struct, or null
|
|
76
|
+
* otherwise.
|
|
77
|
+
*/
|
|
78
|
+
template <typename T> [[nodiscard]] T *
|
|
79
|
+
dyn_cast(pm_node_t *node) noexcept {
|
|
80
|
+
return (node != nullptr && isa<T>(node)) ? reinterpret_cast<T *>(node) : nullptr;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Cast the given node to the given struct if it is of that struct, and return
|
|
85
|
+
* null otherwise. The node may be null, in which case this returns null.
|
|
86
|
+
*
|
|
87
|
+
* @tparam T The node struct type to cast to.
|
|
88
|
+
* @param node The node to cast.
|
|
89
|
+
* @return The node cast to the given struct if it is of that struct, or null
|
|
90
|
+
* otherwise.
|
|
91
|
+
*/
|
|
92
|
+
template <typename T> [[nodiscard]] const T *
|
|
93
|
+
dyn_cast(const pm_node_t *node) noexcept {
|
|
94
|
+
return (node != nullptr && isa<T>(node)) ? reinterpret_cast<const T *>(node) : nullptr;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Return the pm_node_t embedded at the start of the given node struct.
|
|
99
|
+
*
|
|
100
|
+
* @tparam T The node struct type.
|
|
101
|
+
* @param node The node struct to upcast.
|
|
102
|
+
* @return The pm_node_t embedded at the start of the node struct.
|
|
103
|
+
*/
|
|
104
|
+
template <typename T> [[nodiscard]] pm_node_t *
|
|
105
|
+
upcast(T *node) noexcept {
|
|
106
|
+
static_assert(is_node_v<T>, "upcast requires a node struct declared in ast.h");
|
|
107
|
+
return &node->base;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Return the pm_node_t embedded at the start of the given node struct.
|
|
112
|
+
*
|
|
113
|
+
* @tparam T The node struct type.
|
|
114
|
+
* @param node The node struct to upcast.
|
|
115
|
+
* @return The pm_node_t embedded at the start of the node struct.
|
|
116
|
+
*/
|
|
117
|
+
template <typename T> [[nodiscard]] const pm_node_t *
|
|
118
|
+
upcast(const T *node) noexcept {
|
|
119
|
+
static_assert(is_node_v<T>, "upcast requires a node struct declared in ast.h");
|
|
120
|
+
return &node->base;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* The nodes in a list, usable in a range-based for loop. It refers to the list
|
|
125
|
+
* rather than copying it, so the list must outlive it.
|
|
126
|
+
*/
|
|
127
|
+
class node_range {
|
|
128
|
+
public:
|
|
129
|
+
/**
|
|
130
|
+
* Create a range over the nodes in the given list.
|
|
131
|
+
*
|
|
132
|
+
* @param list The list of nodes to create a range for.
|
|
133
|
+
*/
|
|
134
|
+
explicit node_range(const pm_node_list_t &list PRISM_LIFETIMEBOUND) noexcept : list_(&list) {}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* A pointer to the first node.
|
|
138
|
+
*
|
|
139
|
+
* @return A pointer to the first node, or null if the list is empty.
|
|
140
|
+
*/
|
|
141
|
+
pm_node_t *const *begin() const noexcept { return list_->nodes; }
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* A pointer one past the last node.
|
|
145
|
+
*
|
|
146
|
+
* @return A pointer one past the last node, or null if the list is empty.
|
|
147
|
+
*/
|
|
148
|
+
pm_node_t *const *end() const noexcept { return list_->nodes + list_->size; }
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* The number of nodes.
|
|
152
|
+
*
|
|
153
|
+
* @return The number of nodes.
|
|
154
|
+
*/
|
|
155
|
+
std::size_t size() const noexcept { return list_->size; }
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Whether there are no nodes.
|
|
159
|
+
*
|
|
160
|
+
* @return True if there are no nodes, false otherwise.
|
|
161
|
+
*/
|
|
162
|
+
[[nodiscard]] bool empty() const noexcept { return list_->size == 0; }
|
|
163
|
+
|
|
164
|
+
private:
|
|
165
|
+
const pm_node_list_t *list_;
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
namespace detail {
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* The state shared between a walk and its C callback, passed through the C
|
|
172
|
+
* function's void * data parameter.
|
|
173
|
+
*/
|
|
174
|
+
template <typename F> struct visit_context {
|
|
175
|
+
/**
|
|
176
|
+
* The context for a visit, holding the visitor and any exception thrown.
|
|
177
|
+
*
|
|
178
|
+
* @param visitor The visitor callable to be used for each node.
|
|
179
|
+
*/
|
|
180
|
+
explicit visit_context(F *visitor) noexcept : callable(visitor) {}
|
|
181
|
+
|
|
182
|
+
/** The visitor that the walk calls for each node. */
|
|
183
|
+
F *callable;
|
|
184
|
+
|
|
185
|
+
#ifdef PRISM_HAS_EXCEPTIONS
|
|
186
|
+
/** The exception thrown by the visitor, if any. */
|
|
187
|
+
std::exception_ptr exception;
|
|
188
|
+
#endif
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Forwards the C visitor callback to a C++ callable. An exception cannot unwind
|
|
193
|
+
* through the C frames that call this function, so one thrown by the callable
|
|
194
|
+
* is caught here and the walk is stopped. The function that started the walk
|
|
195
|
+
* rethrows it once the C walk has returned. Without exceptions, the callable
|
|
196
|
+
* cannot throw, so it is called directly.
|
|
197
|
+
*
|
|
198
|
+
* @tparam F The type of the visitor callable.
|
|
199
|
+
* @param node The current node being visited.
|
|
200
|
+
* @param data The visit context containing the visitor and exception state.
|
|
201
|
+
* @return The result of the visit, indicating whether to descend, skip, or stop.
|
|
202
|
+
*/
|
|
203
|
+
template <typename F> pm_visit_result_t
|
|
204
|
+
visit_callback(const pm_node_t *node, void *data) noexcept {
|
|
205
|
+
visit_context<F> *context = static_cast<visit_context<F> *>(data);
|
|
206
|
+
|
|
207
|
+
#ifdef PRISM_HAS_EXCEPTIONS
|
|
208
|
+
try {
|
|
209
|
+
return std::invoke(*context->callable, node);
|
|
210
|
+
} catch (...) {
|
|
211
|
+
context->exception = std::current_exception();
|
|
212
|
+
return PM_VISIT_STOP;
|
|
213
|
+
}
|
|
214
|
+
#else
|
|
215
|
+
return std::invoke(*context->callable, node);
|
|
216
|
+
#endif
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Walk the tree rooted at the given node in pre-order, calling the visitor with
|
|
223
|
+
* each node. The visitor returns PM_VISIT_DESCEND to continue into that node's
|
|
224
|
+
* children, PM_VISIT_SKIP to continue past them, or PM_VISIT_STOP to end the
|
|
225
|
+
* walk. Returns false if the walk was stopped. If the visitor throws, the walk
|
|
226
|
+
* stops and the exception propagates from this function.
|
|
227
|
+
*
|
|
228
|
+
* @tparam F The type of the visitor callable.
|
|
229
|
+
* @param node The root node to start the walk from.
|
|
230
|
+
* @param visitor The visitor callable to invoke for each node.
|
|
231
|
+
* @return True if the walk completed, false if it was stopped.
|
|
232
|
+
*/
|
|
233
|
+
template <typename F> bool
|
|
234
|
+
visit_node(const pm_node_t *node, F &&visitor) {
|
|
235
|
+
static_assert(std::is_invocable_r_v<pm_visit_result_t, F &, const pm_node_t *>, "visit_node requires a callable taking const pm_node_t * and returning pm_visit_result_t");
|
|
236
|
+
detail::visit_context<std::remove_reference_t<F>> context(std::addressof(visitor));
|
|
237
|
+
bool completed = pm_visit_node(node, detail::visit_callback<std::remove_reference_t<F>>, &context);
|
|
238
|
+
|
|
239
|
+
#ifdef PRISM_HAS_EXCEPTIONS
|
|
240
|
+
if (context.exception) std::rethrow_exception(context.exception);
|
|
241
|
+
#endif
|
|
242
|
+
|
|
243
|
+
return completed;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Walk the children of the given node, as visit_node does for every node whose
|
|
248
|
+
* visitor returns PM_VISIT_DESCEND. Returns false if the walk was stopped. If
|
|
249
|
+
* the visitor throws, the walk stops and the exception propagates from this
|
|
250
|
+
* function.
|
|
251
|
+
*
|
|
252
|
+
* @tparam F The type of the visitor callable.
|
|
253
|
+
* @param node The node whose children to walk.
|
|
254
|
+
* @param visitor The visitor callable to invoke for each child node.
|
|
255
|
+
* @return True if the walk completed, false if it was stopped.
|
|
256
|
+
*/
|
|
257
|
+
template <typename F> bool
|
|
258
|
+
visit_child_nodes(const pm_node_t *node, F &&visitor) {
|
|
259
|
+
static_assert(std::is_invocable_r_v<pm_visit_result_t, F &, const pm_node_t *>, "visit_child_nodes requires a callable taking const pm_node_t * and returning pm_visit_result_t");
|
|
260
|
+
detail::visit_context<std::remove_reference_t<F>> context(std::addressof(visitor));
|
|
261
|
+
bool completed = pm_visit_child_nodes(node, detail::visit_callback<std::remove_reference_t<F>>, &context);
|
|
262
|
+
|
|
263
|
+
#ifdef PRISM_HAS_EXCEPTIONS
|
|
264
|
+
if (context.exception) std::rethrow_exception(context.exception);
|
|
265
|
+
#endif
|
|
266
|
+
|
|
267
|
+
return completed;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
#endif
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file node_type.hpp
|
|
3
|
+
*
|
|
4
|
+
* The traits that map node structs to node types. The specialization for each
|
|
5
|
+
* node struct is generated into ast.hpp.
|
|
6
|
+
*/
|
|
7
|
+
#ifndef PRISM_NODE_TYPE_HPP
|
|
8
|
+
#define PRISM_NODE_TYPE_HPP
|
|
9
|
+
|
|
10
|
+
#include "prism/compiler/cplusplus.hpp"
|
|
11
|
+
|
|
12
|
+
#include "prism/ast.h"
|
|
13
|
+
|
|
14
|
+
#include <type_traits>
|
|
15
|
+
|
|
16
|
+
namespace prism {
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Maps a node struct to its node type, as in node_type<pm_call_node_t>::value
|
|
20
|
+
* being PM_CALL_NODE. Only the node structs declared in ast.h have a value.
|
|
21
|
+
*/
|
|
22
|
+
template <typename T> struct node_type {};
|
|
23
|
+
|
|
24
|
+
/** The node type of the given node struct. */
|
|
25
|
+
template <typename T> inline constexpr pm_node_type_t node_type_v = node_type<T>::value;
|
|
26
|
+
|
|
27
|
+
/** Whether the given type is one of the node structs declared in ast.h. */
|
|
28
|
+
template <typename T, typename = void> struct is_node : std::false_type {};
|
|
29
|
+
|
|
30
|
+
/** Whether the given type is one of the node structs declared in ast.h. */
|
|
31
|
+
template <typename T> struct is_node<T, std::void_t<decltype(node_type<T>::value)>> : std::true_type {};
|
|
32
|
+
|
|
33
|
+
/** Whether the given type is one of the node structs declared in ast.h. */
|
|
34
|
+
template <typename T> inline constexpr bool is_node_v = is_node<T>::value;
|
|
35
|
+
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
#endif
|
data/include/prism/options.h
CHANGED
|
@@ -15,6 +15,10 @@
|
|
|
15
15
|
#include <stdbool.h>
|
|
16
16
|
#include <stddef.h>
|
|
17
17
|
|
|
18
|
+
#ifdef __cplusplus
|
|
19
|
+
extern "C" {
|
|
20
|
+
#endif
|
|
21
|
+
|
|
18
22
|
/**
|
|
19
23
|
* A scope of locals surrounding the code that is being parsed.
|
|
20
24
|
*/
|
|
@@ -335,7 +339,8 @@ PRISM_EXPORTED_FUNCTION const pm_string_t * pm_options_scope_local(const pm_opti
|
|
|
335
339
|
|
|
336
340
|
/**
|
|
337
341
|
* Return a mutable pointer to the local at the given index within the given
|
|
338
|
-
* scope.
|
|
342
|
+
* scope, for setting the local's name with pm_string_init. The parser copies
|
|
343
|
+
* the name when it is created, so its bytes must remain valid until then.
|
|
339
344
|
*
|
|
340
345
|
* @param scope The scope struct to get the local from.
|
|
341
346
|
* @param index The index of the local to get.
|
|
@@ -351,4 +356,8 @@ PRISM_EXPORTED_FUNCTION pm_string_t * pm_options_scope_local_mut(pm_options_scop
|
|
|
351
356
|
*/
|
|
352
357
|
PRISM_EXPORTED_FUNCTION void pm_options_scope_forwarding_set(pm_options_scope_t *scope, uint8_t forwarding) PRISM_NONNULL(1);
|
|
353
358
|
|
|
359
|
+
#ifdef __cplusplus
|
|
360
|
+
}
|
|
361
|
+
#endif
|
|
362
|
+
|
|
354
363
|
#endif
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file options.hpp
|
|
3
|
+
*
|
|
4
|
+
* Ownership of parse options from C++.
|
|
5
|
+
*/
|
|
6
|
+
#ifndef PRISM_OPTIONS_HPP
|
|
7
|
+
#define PRISM_OPTIONS_HPP
|
|
8
|
+
|
|
9
|
+
#include "prism/compiler/cplusplus.hpp"
|
|
10
|
+
|
|
11
|
+
#include "prism/options.h"
|
|
12
|
+
|
|
13
|
+
#include <memory>
|
|
14
|
+
|
|
15
|
+
namespace prism {
|
|
16
|
+
|
|
17
|
+
/** Frees options with pm_options_free. */
|
|
18
|
+
struct options_deleter {
|
|
19
|
+
/**
|
|
20
|
+
* Free the given options.
|
|
21
|
+
*
|
|
22
|
+
* @param options The options to free.
|
|
23
|
+
*/
|
|
24
|
+
void operator()(pm_options_t *options) const noexcept { pm_options_free(options); }
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/** An owned set of options. */
|
|
28
|
+
using unique_options = std::unique_ptr<pm_options_t, options_deleter>;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Allocate a new set of options with every option at its default. Allocation
|
|
32
|
+
* failure aborts, so this never throws.
|
|
33
|
+
*
|
|
34
|
+
* @return A unique_options owning the newly allocated options.
|
|
35
|
+
*/
|
|
36
|
+
[[nodiscard]] inline unique_options
|
|
37
|
+
make_options() noexcept {
|
|
38
|
+
return unique_options(pm_options_new());
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
#endif
|