summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin Newton <kddnewton@gmail.com>2024-02-15 13:58:21 -0500
committergit <svn-admin@ruby-lang.org>2024-02-16 19:34:38 +0000
commit6f4bb638b0182613ca3a4b482a4e31bbb78d0fe4 (patch)
tree60eaad560d5a73ecbfbef7b976e25177869a3bbf
parentbac692f50870b3ede3a152a5b741d1eb22a7df0e (diff)
[ruby/prism] Builtins
https://github.com/ruby/prism/commit/851f2571ff
-rw-r--r--prism/prism.h10
-rw-r--r--prism/templates/src/node.c.erb42
-rw-r--r--prism/util/pm_buffer.c23
-rw-r--r--prism/util/pm_buffer.h20
-rw-r--r--prism/util/pm_string.c20
-rw-r--r--prism/util/pm_string.h12
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.