diff options
| author | Kevin Newton <kddnewton@gmail.com> | 2024-02-15 13:58:21 -0500 |
|---|---|---|
| committer | git <svn-admin@ruby-lang.org> | 2024-02-16 19:34:38 +0000 |
| commit | 6f4bb638b0182613ca3a4b482a4e31bbb78d0fe4 (patch) | |
| tree | 60eaad560d5a73ecbfbef7b976e25177869a3bbf | |
| parent | bac692f50870b3ede3a152a5b741d1eb22a7df0e (diff) | |
[ruby/prism] Builtins
https://github.com/ruby/prism/commit/851f2571ff
| -rw-r--r-- | prism/prism.h | 10 | ||||
| -rw-r--r-- | prism/templates/src/node.c.erb | 42 | ||||
| -rw-r--r-- | prism/util/pm_buffer.c | 23 | ||||
| -rw-r--r-- | prism/util/pm_buffer.h | 20 | ||||
| -rw-r--r-- | prism/util/pm_string.c | 20 | ||||
| -rw-r--r-- | prism/util/pm_string.h | 12 |
6 files changed, 123 insertions, 4 deletions
diff --git a/prism/prism.h b/prism/prism.h index 08d216cbb5..afd57483fd 100644 --- a/prism/prism.h +++ b/prism/prism.h @@ -188,6 +188,16 @@ const char * pm_token_type_human(pm_token_type_t token_type); PRISM_EXPORTED_FUNCTION void pm_parser_errors_format(const pm_parser_t *parser, pm_buffer_t *buffer, bool colorize); /** + * Visit each of the nodes in this subtree using the given visitor callback. + * + * @param node The node to visit. + * @param visitor The visitor callback to use. It should return `true` if the + * visitor should continue visiting nodes, and `false` if it should stop. + * @param data The optional data to pass to the visitor. + */ +PRISM_EXPORTED_FUNCTION void pm_node_visit(const pm_node_t *node, bool (*visitor)(const pm_node_t *node, void *data), void *data); + +/** * @mainpage * * Prism is a parser for the Ruby programming language. It is designed to be diff --git a/prism/templates/src/node.c.erb b/prism/templates/src/node.c.erb index 0552767f4d..a7135d598e 100644 --- a/prism/templates/src/node.c.erb +++ b/prism/templates/src/node.c.erb @@ -160,3 +160,45 @@ pm_node_type_to_str(pm_node_type_t node_type) } return ""; } + +/** + * Visit each of the nodes in this subtree using the given visitor callback. + */ +PRISM_EXPORTED_FUNCTION void +pm_node_visit(const pm_node_t *node, bool (*visitor)(const pm_node_t *node, void *data), void *data) { + if (!visitor(node, data)) return; + + switch (PM_NODE_TYPE(node)) { + <%- nodes.each do |node| -%> + <%- if (fields = node.fields.select { |field| field.is_a?(Prism::NodeField) || field.is_a?(Prism::OptionalNodeField) || field.is_a?(Prism::NodeListField) }).any? -%> + case <%= node.type %>: { + const pm_<%= node.human %>_t *cast = (const pm_<%= node.human %>_t *) node; + <%- fields.each do |field| -%> + + // Visit the <%= field.name %> field + <%- case field -%> + <%- when Prism::NodeField -%> + pm_node_visit((const pm_node_t *) cast-><%= field.name %>, visitor, data); + <%- when Prism::OptionalNodeField -%> + if (cast-><%= field.name %> != NULL) { + pm_node_visit((const pm_node_t *) cast-><%= field.name %>, visitor, data); + } + <%- when Prism::NodeListField -%> + const pm_node_list_t *<%= field.name %> = &cast-><%= field.name %>; + for (size_t index = 0; index < <%= field.name %>->size; index++) { + pm_node_visit(<%= field.name %>->nodes[index], visitor, data); + } + <%- end -%> + <%- end -%> + + break; + } + <%- else -%> + case <%= node.type %>: + break; + <%- end -%> + <%- end -%> + case PM_SCOPE_NODE: + break; + } +} diff --git a/prism/util/pm_buffer.c b/prism/util/pm_buffer.c index 0ae9445428..129bed52cd 100644 --- a/prism/util/pm_buffer.c +++ b/prism/util/pm_buffer.c @@ -32,7 +32,7 @@ pm_buffer_init(pm_buffer_t *buffer) { * Return the value of the buffer. */ char * -pm_buffer_value(pm_buffer_t *buffer) { +pm_buffer_value(const pm_buffer_t *buffer) { return buffer->value; } @@ -40,7 +40,7 @@ pm_buffer_value(pm_buffer_t *buffer) { * Return the length of the buffer. */ size_t -pm_buffer_length(pm_buffer_t *buffer) { +pm_buffer_length(const pm_buffer_t *buffer) { return buffer->length; } @@ -182,6 +182,25 @@ pm_buffer_concat(pm_buffer_t *destination, const pm_buffer_t *source) { } /** + * Clear the buffer by reducing its size to 0. This does not free the allocated + * memory, but it does allow the buffer to be reused. + */ +void +pm_buffer_clear(pm_buffer_t *buffer) { + buffer->length = 0; +} + +/** + * Strip the whitespace from the end of the buffer. + */ +void +pm_buffer_rstrip(pm_buffer_t *buffer) { + while (buffer->length > 0 && pm_char_is_whitespace((uint8_t) buffer->value[buffer->length - 1])) { + buffer->length--; + } +} + +/** * Free the memory associated with the buffer. */ void diff --git a/prism/util/pm_buffer.h b/prism/util/pm_buffer.h index f0cca84af5..513633baa1 100644 --- a/prism/util/pm_buffer.h +++ b/prism/util/pm_buffer.h @@ -7,6 +7,7 @@ #define PRISM_BUFFER_H #include "prism/defines.h" +#include "prism/util/pm_char.h" #include <assert.h> #include <stdbool.h> @@ -59,7 +60,7 @@ PRISM_EXPORTED_FUNCTION bool pm_buffer_init(pm_buffer_t *buffer); * @param buffer The buffer to get the value of. * @returns The value of the buffer. */ -PRISM_EXPORTED_FUNCTION char * pm_buffer_value(pm_buffer_t *buffer); +PRISM_EXPORTED_FUNCTION char * pm_buffer_value(const pm_buffer_t *buffer); /** * Return the length of the buffer. @@ -67,7 +68,7 @@ PRISM_EXPORTED_FUNCTION char * pm_buffer_value(pm_buffer_t *buffer); * @param buffer The buffer to get the length of. * @returns The length of the buffer. */ -PRISM_EXPORTED_FUNCTION size_t pm_buffer_length(pm_buffer_t *buffer); +PRISM_EXPORTED_FUNCTION size_t pm_buffer_length(const pm_buffer_t *buffer); /** * Append the given amount of space as zeroes to the buffer. @@ -146,6 +147,21 @@ void pm_buffer_prepend_string(pm_buffer_t *buffer, const char *value, size_t len void pm_buffer_concat(pm_buffer_t *destination, const pm_buffer_t *source); /** + * Clear the buffer by reducing its size to 0. This does not free the allocated + * memory, but it does allow the buffer to be reused. + * + * @param buffer The buffer to clear. + */ +void pm_buffer_clear(pm_buffer_t *buffer); + +/** + * Strip the whitespace from the end of the buffer. + * + * @param buffer The buffer to strip. + */ +void pm_buffer_rstrip(pm_buffer_t *buffer); + +/** * Free the memory associated with the buffer. * * @param buffer The buffer to free. diff --git a/prism/util/pm_string.c b/prism/util/pm_string.c index e67fcee0ec..8f3ef92c9b 100644 --- a/prism/util/pm_string.c +++ b/prism/util/pm_string.c @@ -169,6 +169,26 @@ pm_string_ensure_owned(pm_string_t *string) { } /** + * Compare the underlying lengths and bytes of two strings. Returns 0 if the + * strings are equal, a negative number if the left string is less than the + * right string, and a positive number if the left string is greater than the + * right string. + */ +int +pm_string_compare(const pm_string_t *left, const pm_string_t *right) { + size_t left_length = pm_string_length(left); + size_t right_length = pm_string_length(right); + + if (left_length < right_length) { + return -1; + } else if (left_length > right_length) { + return 1; + } + + return memcmp(pm_string_source(left), pm_string_source(right), left_length); +} + +/** * Returns the length associated with the string. */ PRISM_EXPORTED_FUNCTION size_t diff --git a/prism/util/pm_string.h b/prism/util/pm_string.h index ddb153784f..8a568a8238 100644 --- a/prism/util/pm_string.h +++ b/prism/util/pm_string.h @@ -125,6 +125,18 @@ size_t pm_string_memsize(const pm_string_t *string); void pm_string_ensure_owned(pm_string_t *string); /** + * Compare the underlying lengths and bytes of two strings. Returns 0 if the + * strings are equal, a negative number if the left string is less than the + * right string, and a positive number if the left string is greater than the + * right string. + * + * @param left The left string to compare. + * @param right The right string to compare. + * @return The comparison result. + */ +int pm_string_compare(const pm_string_t *left, const pm_string_t *right); + +/** * Returns the length associated with the string. * * @param string The string to get the length of. |
