Skip to content

Commit

Permalink
Builtins
Browse files Browse the repository at this point in the history
  • Loading branch information
kddnewton committed Feb 16, 2024
1 parent 40059d3 commit 851f257
Show file tree
Hide file tree
Showing 6 changed files with 123 additions and 4 deletions.
10 changes: 10 additions & 0 deletions include/prism.h
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,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
*
Expand Down
20 changes: 18 additions & 2 deletions include/prism/util/pm_buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#define PRISM_BUFFER_H

#include "prism/defines.h"
#include "prism/util/pm_char.h"

#include <assert.h>
#include <stdbool.h>
Expand Down Expand Up @@ -59,15 +60,15 @@ 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.
*
* @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.
Expand Down Expand Up @@ -145,6 +146,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.
*
Expand Down
12 changes: 12 additions & 0 deletions include/prism/util/pm_string.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,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.
*
Expand Down
23 changes: 21 additions & 2 deletions src/util/pm_buffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,15 @@ 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;
}

/**
* 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;
}

Expand Down Expand Up @@ -181,6 +181,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.
*/
Expand Down
20 changes: 20 additions & 0 deletions src/util/pm_string.c
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,26 @@ pm_string_ensure_owned(pm_string_t *string) {
memcpy((void *) string->source, source, length);
}

/**
* 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.
*/
Expand Down
42 changes: 42 additions & 0 deletions templates/src/node.c.erb
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}

0 comments on commit 851f257

Please sign in to comment.