14#include "prism/ast.hpp"
34template <
typename T> [[nodiscard]]
bool
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>;
49template <
typename T> [[nodiscard]] T *
52 return reinterpret_cast<T *
>(node);
63template <
typename T> [[nodiscard]]
const T *
66 return reinterpret_cast<const T *
>(node);
78template <
typename T> [[nodiscard]] T *
80 return (node !=
nullptr && isa<T>(node)) ?
reinterpret_cast<T *
>(node) :
nullptr;
92template <
typename T> [[nodiscard]]
const T *
94 return (node !=
nullptr && isa<T>(node)) ?
reinterpret_cast<const T *
>(node) :
nullptr;
104template <
typename T> [[nodiscard]]
pm_node_t *
106 static_assert(is_node_v<T>,
"upcast requires a node struct declared in ast.h");
117template <
typename T> [[nodiscard]]
const pm_node_t *
119 static_assert(is_node_v<T>,
"upcast requires a node struct declared in ast.h");
155 std::size_t
size() const noexcept {
return list_->
size; }
162 [[nodiscard]]
bool empty() const noexcept {
return list_->
size == 0; }
174template <
typename F>
struct visit_context {
180 explicit visit_context(F *visitor) noexcept : callable(visitor) {}
185#ifdef PRISM_HAS_EXCEPTIONS
187 std::exception_ptr exception;
204visit_callback(
const pm_node_t *node,
void *data)
noexcept {
205 visit_context<F> *context =
static_cast<visit_context<F> *
>(data);
207#ifdef PRISM_HAS_EXCEPTIONS
209 return std::invoke(*context->callable, node);
211 context->exception = std::current_exception();
215 return std::invoke(*context->callable, node);
233template <
typename F>
bool
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);
239#ifdef PRISM_HAS_EXCEPTIONS
240 if (context.exception) std::rethrow_exception(context.exception);
257template <
typename F>
bool
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);
263#ifdef PRISM_HAS_EXCEPTIONS
264 if (context.exception) std::rethrow_exception(context.exception);
The nodes in a list, usable in a range-based for loop.
bool empty() const noexcept
Whether there are no nodes.
pm_node_t *const * end() const noexcept
A pointer one past the last node.
node_range(const pm_node_list_t &list PRISM_LIFETIMEBOUND) noexcept
Create a range over the nodes in the given list.
std::size_t size() const noexcept
The number of nodes.
pm_node_t *const * begin() const noexcept
A pointer to the first node.
#define PRISM_LIFETIMEBOUND
Mark a parameter that the return value points into, so that the compiler warns if a temporary is pass...
bool isa(const pm_node_t *node) noexcept
Whether the given node, which must not be null, is of the given struct.
T * dyn_cast(pm_node_t *node) noexcept
Cast the given node to the given struct if it is of that struct, and return null otherwise.
bool visit_node(const pm_node_t *node, F &&visitor)
Walk the tree rooted at the given node in pre-order, calling the visitor with each node.
bool visit_child_nodes(const pm_node_t *node, F &&visitor)
Walk the children of the given node, as visit_node does for every node whose visitor returns PM_VISIT...
T * cast(pm_node_t *node) noexcept
Cast the given node, which must not be null and must be of the given struct, to that struct.
pm_node_t * upcast(T *node) noexcept
Return the pm_node_t embedded at the start of the given node struct.
The traits that map node structs to node types.
Functions related to nodes in the AST.
pm_visit_result_t
The value returned by a visitor callback, which determines where the walk goes next.
@ PM_VISIT_STOP
End the walk without visiting any more nodes.
A list of nodes in the source, most often used for lists of children.
size_t size
The number of nodes in the list.
struct pm_node ** nodes
The nodes in the list.
This is the base structure that represents a node in the syntax tree.