/*----------------------------------------------------------------------------*/
/* This file is generated by the templates/template.rb script and should not  */
/* be modified manually. See                                                  */
/* templates/src/node.c.erb                                                   */
/* if you are looking to modify the                                           */
/* template                                                                   */
/*----------------------------------------------------------------------------*/

#line 2 "prism/templates/src/node.c.erb"
#include "prism/node.h"

/**
 * Attempts to grow the node list to the next size. If there is already
 * capacity in the list, this function does nothing. Otherwise it reallocates
 * the list to be twice as large as it was before. If the reallocation fails,
 * this function returns false, otherwise it returns true.
 */
static bool
pm_node_list_grow(pm_node_list_t *list, size_t size) {
    size_t requested_size = list->size + size;

    // If the requested size caused overflow, return false.
    if (requested_size < list->size) return false;

    // If the requested size is within the existing capacity, return true.
    if (requested_size < list->capacity) return true;

    // Otherwise, reallocate the list to be twice as large as it was before.
    size_t next_capacity = list->capacity == 0 ? 4 : list->capacity * 2;

    // If multiplying by 2 caused overflow, return false.
    if (next_capacity < list->capacity) return false;

    // If we didn't get enough by doubling, keep doubling until we do.
    while (requested_size > next_capacity) {
        size_t double_capacity = next_capacity * 2;

        // Ensure we didn't overflow by multiplying by 2.
        if (double_capacity < next_capacity) return false;
        next_capacity = double_capacity;
    }

    pm_node_t **nodes = (pm_node_t **) xrealloc(list->nodes, sizeof(pm_node_t *) * next_capacity);
    if (nodes == NULL) return false;

    list->nodes = nodes;
    list->capacity = next_capacity;
    return true;
}

/**
 * Append a new node onto the end of the node list.
 */
void
pm_node_list_append(pm_node_list_t *list, pm_node_t *node) {
    if (pm_node_list_grow(list, 1)) {
        list->nodes[list->size++] = node;
    }
}

/**
 * Prepend a new node onto the beginning of the node list.
 */
void
pm_node_list_prepend(pm_node_list_t *list, pm_node_t *node) {
    if (pm_node_list_grow(list, 1)) {
        memmove(list->nodes + 1, list->nodes, list->size * sizeof(pm_node_t *));
        list->nodes[0] = node;
        list->size++;
    }
}

/**
 * Concatenate the given node list onto the end of the other node list.
 */
void
pm_node_list_concat(pm_node_list_t *list, pm_node_list_t *other) {
    if (other->size > 0 && pm_node_list_grow(list, other->size)) {
        memcpy(list->nodes + list->size, other->nodes, other->size * sizeof(pm_node_t *));
        list->size += other->size;
    }
}

/**
 * Free the internal memory associated with the given node list.
 */
void
pm_node_list_free(pm_node_list_t *list) {
    if (list->capacity > 0) {
        xfree(list->nodes);
        *list = (pm_node_list_t) { 0 };
    }
}

PRISM_EXPORTED_FUNCTION void
pm_node_destroy(pm_parser_t *parser, pm_node_t *node);

/**
 * Destroy the nodes that are contained within the given node list.
 */
static void
pm_node_list_destroy(pm_parser_t *parser, pm_node_list_t *list) {
    pm_node_t *node;
    PM_NODE_LIST_FOREACH(list, index, node) pm_node_destroy(parser, node);
    pm_node_list_free(list);
}

/**
 * Deallocate the space for a pm_node_t. Similarly to pm_node_alloc, we're not
 * using the parser argument, but it's there to allow for the future possibility
 * of pre-allocating larger memory pools.
 */
PRISM_EXPORTED_FUNCTION void
pm_node_destroy(pm_parser_t *parser, pm_node_t *node) {
    switch (PM_NODE_TYPE(node)) {
#line 110 "prism/templates/src/node.c.erb"
        case PM_ALIAS_GLOBAL_VARIABLE_NODE: {
            pm_alias_global_variable_node_t *cast = (pm_alias_global_variable_node_t *) node;
            pm_node_destroy(parser, (pm_node_t *)cast->new_name);
            pm_node_destroy(parser, (pm_node_t *)cast->old_name);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_ALIAS_METHOD_NODE: {
            pm_alias_method_node_t *cast = (pm_alias_method_node_t *) node;
            pm_node_destroy(parser, (pm_node_t *)cast->new_name);
            pm_node_destroy(parser, (pm_node_t *)cast->old_name);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_ALTERNATION_PATTERN_NODE: {
            pm_alternation_pattern_node_t *cast = (pm_alternation_pattern_node_t *) node;
            pm_node_destroy(parser, (pm_node_t *)cast->left);
            pm_node_destroy(parser, (pm_node_t *)cast->right);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_AND_NODE: {
            pm_and_node_t *cast = (pm_and_node_t *) node;
            pm_node_destroy(parser, (pm_node_t *)cast->left);
            pm_node_destroy(parser, (pm_node_t *)cast->right);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_ARGUMENTS_NODE: {
            pm_arguments_node_t *cast = (pm_arguments_node_t *) node;
            pm_node_list_destroy(parser, &cast->arguments);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_ARRAY_NODE: {
            pm_array_node_t *cast = (pm_array_node_t *) node;
            pm_node_list_destroy(parser, &cast->elements);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_ARRAY_PATTERN_NODE: {
            pm_array_pattern_node_t *cast = (pm_array_pattern_node_t *) node;
            if (cast->constant != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->constant);
            }
            pm_node_list_destroy(parser, &cast->requireds);
            if (cast->rest != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->rest);
            }
            pm_node_list_destroy(parser, &cast->posts);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_ASSOC_NODE: {
            pm_assoc_node_t *cast = (pm_assoc_node_t *) node;
            pm_node_destroy(parser, (pm_node_t *)cast->key);
            pm_node_destroy(parser, (pm_node_t *)cast->value);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_ASSOC_SPLAT_NODE: {
            pm_assoc_splat_node_t *cast = (pm_assoc_splat_node_t *) node;
            if (cast->value != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->value);
            }
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_BACK_REFERENCE_READ_NODE: {
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_BEGIN_NODE: {
            pm_begin_node_t *cast = (pm_begin_node_t *) node;
            if (cast->statements != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->statements);
            }
            if (cast->rescue_clause != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->rescue_clause);
            }
            if (cast->else_clause != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->else_clause);
            }
            if (cast->ensure_clause != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->ensure_clause);
            }
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_BLOCK_ARGUMENT_NODE: {
            pm_block_argument_node_t *cast = (pm_block_argument_node_t *) node;
            if (cast->expression != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->expression);
            }
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_BLOCK_LOCAL_VARIABLE_NODE: {
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_BLOCK_NODE: {
            pm_block_node_t *cast = (pm_block_node_t *) node;
            pm_constant_id_list_free(&cast->locals);
            if (cast->parameters != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->parameters);
            }
            if (cast->body != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->body);
            }
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_BLOCK_PARAMETER_NODE: {
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_BLOCK_PARAMETERS_NODE: {
            pm_block_parameters_node_t *cast = (pm_block_parameters_node_t *) node;
            if (cast->parameters != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->parameters);
            }
            pm_node_list_destroy(parser, &cast->locals);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_BREAK_NODE: {
            pm_break_node_t *cast = (pm_break_node_t *) node;
            if (cast->arguments != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->arguments);
            }
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_CALL_AND_WRITE_NODE: {
            pm_call_and_write_node_t *cast = (pm_call_and_write_node_t *) node;
            if (cast->receiver != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->receiver);
            }
            pm_node_destroy(parser, (pm_node_t *)cast->value);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_CALL_NODE: {
            pm_call_node_t *cast = (pm_call_node_t *) node;
            if (cast->receiver != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->receiver);
            }
            if (cast->arguments != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->arguments);
            }
            if (cast->block != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->block);
            }
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_CALL_OPERATOR_WRITE_NODE: {
            pm_call_operator_write_node_t *cast = (pm_call_operator_write_node_t *) node;
            if (cast->receiver != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->receiver);
            }
            pm_node_destroy(parser, (pm_node_t *)cast->value);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_CALL_OR_WRITE_NODE: {
            pm_call_or_write_node_t *cast = (pm_call_or_write_node_t *) node;
            if (cast->receiver != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->receiver);
            }
            pm_node_destroy(parser, (pm_node_t *)cast->value);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_CALL_TARGET_NODE: {
            pm_call_target_node_t *cast = (pm_call_target_node_t *) node;
            pm_node_destroy(parser, (pm_node_t *)cast->receiver);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_CAPTURE_PATTERN_NODE: {
            pm_capture_pattern_node_t *cast = (pm_capture_pattern_node_t *) node;
            pm_node_destroy(parser, (pm_node_t *)cast->value);
            pm_node_destroy(parser, (pm_node_t *)cast->target);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_CASE_MATCH_NODE: {
            pm_case_match_node_t *cast = (pm_case_match_node_t *) node;
            if (cast->predicate != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->predicate);
            }
            pm_node_list_destroy(parser, &cast->conditions);
            if (cast->else_clause != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->else_clause);
            }
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_CASE_NODE: {
            pm_case_node_t *cast = (pm_case_node_t *) node;
            if (cast->predicate != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->predicate);
            }
            pm_node_list_destroy(parser, &cast->conditions);
            if (cast->else_clause != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->else_clause);
            }
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_CLASS_NODE: {
            pm_class_node_t *cast = (pm_class_node_t *) node;
            pm_constant_id_list_free(&cast->locals);
            pm_node_destroy(parser, (pm_node_t *)cast->constant_path);
            if (cast->superclass != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->superclass);
            }
            if (cast->body != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->body);
            }
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_CLASS_VARIABLE_AND_WRITE_NODE: {
            pm_class_variable_and_write_node_t *cast = (pm_class_variable_and_write_node_t *) node;
            pm_node_destroy(parser, (pm_node_t *)cast->value);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_CLASS_VARIABLE_OPERATOR_WRITE_NODE: {
            pm_class_variable_operator_write_node_t *cast = (pm_class_variable_operator_write_node_t *) node;
            pm_node_destroy(parser, (pm_node_t *)cast->value);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_CLASS_VARIABLE_OR_WRITE_NODE: {
            pm_class_variable_or_write_node_t *cast = (pm_class_variable_or_write_node_t *) node;
            pm_node_destroy(parser, (pm_node_t *)cast->value);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_CLASS_VARIABLE_READ_NODE: {
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_CLASS_VARIABLE_TARGET_NODE: {
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_CLASS_VARIABLE_WRITE_NODE: {
            pm_class_variable_write_node_t *cast = (pm_class_variable_write_node_t *) node;
            pm_node_destroy(parser, (pm_node_t *)cast->value);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_CONSTANT_AND_WRITE_NODE: {
            pm_constant_and_write_node_t *cast = (pm_constant_and_write_node_t *) node;
            pm_node_destroy(parser, (pm_node_t *)cast->value);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_CONSTANT_OPERATOR_WRITE_NODE: {
            pm_constant_operator_write_node_t *cast = (pm_constant_operator_write_node_t *) node;
            pm_node_destroy(parser, (pm_node_t *)cast->value);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_CONSTANT_OR_WRITE_NODE: {
            pm_constant_or_write_node_t *cast = (pm_constant_or_write_node_t *) node;
            pm_node_destroy(parser, (pm_node_t *)cast->value);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_CONSTANT_PATH_AND_WRITE_NODE: {
            pm_constant_path_and_write_node_t *cast = (pm_constant_path_and_write_node_t *) node;
            pm_node_destroy(parser, (pm_node_t *)cast->target);
            pm_node_destroy(parser, (pm_node_t *)cast->value);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_CONSTANT_PATH_NODE: {
            pm_constant_path_node_t *cast = (pm_constant_path_node_t *) node;
            if (cast->parent != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->parent);
            }
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_CONSTANT_PATH_OPERATOR_WRITE_NODE: {
            pm_constant_path_operator_write_node_t *cast = (pm_constant_path_operator_write_node_t *) node;
            pm_node_destroy(parser, (pm_node_t *)cast->target);
            pm_node_destroy(parser, (pm_node_t *)cast->value);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_CONSTANT_PATH_OR_WRITE_NODE: {
            pm_constant_path_or_write_node_t *cast = (pm_constant_path_or_write_node_t *) node;
            pm_node_destroy(parser, (pm_node_t *)cast->target);
            pm_node_destroy(parser, (pm_node_t *)cast->value);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_CONSTANT_PATH_TARGET_NODE: {
            pm_constant_path_target_node_t *cast = (pm_constant_path_target_node_t *) node;
            if (cast->parent != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->parent);
            }
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_CONSTANT_PATH_WRITE_NODE: {
            pm_constant_path_write_node_t *cast = (pm_constant_path_write_node_t *) node;
            pm_node_destroy(parser, (pm_node_t *)cast->target);
            pm_node_destroy(parser, (pm_node_t *)cast->value);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_CONSTANT_READ_NODE: {
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_CONSTANT_TARGET_NODE: {
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_CONSTANT_WRITE_NODE: {
            pm_constant_write_node_t *cast = (pm_constant_write_node_t *) node;
            pm_node_destroy(parser, (pm_node_t *)cast->value);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_DEF_NODE: {
            pm_def_node_t *cast = (pm_def_node_t *) node;
            if (cast->receiver != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->receiver);
            }
            if (cast->parameters != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->parameters);
            }
            if (cast->body != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->body);
            }
            pm_constant_id_list_free(&cast->locals);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_DEFINED_NODE: {
            pm_defined_node_t *cast = (pm_defined_node_t *) node;
            pm_node_destroy(parser, (pm_node_t *)cast->value);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_ELSE_NODE: {
            pm_else_node_t *cast = (pm_else_node_t *) node;
            if (cast->statements != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->statements);
            }
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_EMBEDDED_STATEMENTS_NODE: {
            pm_embedded_statements_node_t *cast = (pm_embedded_statements_node_t *) node;
            if (cast->statements != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->statements);
            }
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_EMBEDDED_VARIABLE_NODE: {
            pm_embedded_variable_node_t *cast = (pm_embedded_variable_node_t *) node;
            pm_node_destroy(parser, (pm_node_t *)cast->variable);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_ENSURE_NODE: {
            pm_ensure_node_t *cast = (pm_ensure_node_t *) node;
            if (cast->statements != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->statements);
            }
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_FALSE_NODE: {
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_FIND_PATTERN_NODE: {
            pm_find_pattern_node_t *cast = (pm_find_pattern_node_t *) node;
            if (cast->constant != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->constant);
            }
            pm_node_destroy(parser, (pm_node_t *)cast->left);
            pm_node_list_destroy(parser, &cast->requireds);
            pm_node_destroy(parser, (pm_node_t *)cast->right);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_FLIP_FLOP_NODE: {
            pm_flip_flop_node_t *cast = (pm_flip_flop_node_t *) node;
            if (cast->left != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->left);
            }
            if (cast->right != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->right);
            }
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_FLOAT_NODE: {
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_FOR_NODE: {
            pm_for_node_t *cast = (pm_for_node_t *) node;
            pm_node_destroy(parser, (pm_node_t *)cast->index);
            pm_node_destroy(parser, (pm_node_t *)cast->collection);
            if (cast->statements != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->statements);
            }
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_FORWARDING_ARGUMENTS_NODE: {
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_FORWARDING_PARAMETER_NODE: {
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_FORWARDING_SUPER_NODE: {
            pm_forwarding_super_node_t *cast = (pm_forwarding_super_node_t *) node;
            if (cast->block != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->block);
            }
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_GLOBAL_VARIABLE_AND_WRITE_NODE: {
            pm_global_variable_and_write_node_t *cast = (pm_global_variable_and_write_node_t *) node;
            pm_node_destroy(parser, (pm_node_t *)cast->value);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_GLOBAL_VARIABLE_OPERATOR_WRITE_NODE: {
            pm_global_variable_operator_write_node_t *cast = (pm_global_variable_operator_write_node_t *) node;
            pm_node_destroy(parser, (pm_node_t *)cast->value);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_GLOBAL_VARIABLE_OR_WRITE_NODE: {
            pm_global_variable_or_write_node_t *cast = (pm_global_variable_or_write_node_t *) node;
            pm_node_destroy(parser, (pm_node_t *)cast->value);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_GLOBAL_VARIABLE_READ_NODE: {
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_GLOBAL_VARIABLE_TARGET_NODE: {
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_GLOBAL_VARIABLE_WRITE_NODE: {
            pm_global_variable_write_node_t *cast = (pm_global_variable_write_node_t *) node;
            pm_node_destroy(parser, (pm_node_t *)cast->value);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_HASH_NODE: {
            pm_hash_node_t *cast = (pm_hash_node_t *) node;
            pm_node_list_destroy(parser, &cast->elements);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_HASH_PATTERN_NODE: {
            pm_hash_pattern_node_t *cast = (pm_hash_pattern_node_t *) node;
            if (cast->constant != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->constant);
            }
            pm_node_list_destroy(parser, &cast->elements);
            if (cast->rest != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->rest);
            }
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_IF_NODE: {
            pm_if_node_t *cast = (pm_if_node_t *) node;
            pm_node_destroy(parser, (pm_node_t *)cast->predicate);
            if (cast->statements != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->statements);
            }
            if (cast->subsequent != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->subsequent);
            }
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_IMAGINARY_NODE: {
            pm_imaginary_node_t *cast = (pm_imaginary_node_t *) node;
            pm_node_destroy(parser, (pm_node_t *)cast->numeric);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_IMPLICIT_NODE: {
            pm_implicit_node_t *cast = (pm_implicit_node_t *) node;
            pm_node_destroy(parser, (pm_node_t *)cast->value);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_IMPLICIT_REST_NODE: {
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_IN_NODE: {
            pm_in_node_t *cast = (pm_in_node_t *) node;
            pm_node_destroy(parser, (pm_node_t *)cast->pattern);
            if (cast->statements != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->statements);
            }
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_INDEX_AND_WRITE_NODE: {
            pm_index_and_write_node_t *cast = (pm_index_and_write_node_t *) node;
            if (cast->receiver != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->receiver);
            }
            if (cast->arguments != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->arguments);
            }
            if (cast->block != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->block);
            }
            pm_node_destroy(parser, (pm_node_t *)cast->value);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_INDEX_OPERATOR_WRITE_NODE: {
            pm_index_operator_write_node_t *cast = (pm_index_operator_write_node_t *) node;
            if (cast->receiver != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->receiver);
            }
            if (cast->arguments != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->arguments);
            }
            if (cast->block != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->block);
            }
            pm_node_destroy(parser, (pm_node_t *)cast->value);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_INDEX_OR_WRITE_NODE: {
            pm_index_or_write_node_t *cast = (pm_index_or_write_node_t *) node;
            if (cast->receiver != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->receiver);
            }
            if (cast->arguments != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->arguments);
            }
            if (cast->block != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->block);
            }
            pm_node_destroy(parser, (pm_node_t *)cast->value);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_INDEX_TARGET_NODE: {
            pm_index_target_node_t *cast = (pm_index_target_node_t *) node;
            pm_node_destroy(parser, (pm_node_t *)cast->receiver);
            if (cast->arguments != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->arguments);
            }
            if (cast->block != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->block);
            }
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_INSTANCE_VARIABLE_AND_WRITE_NODE: {
            pm_instance_variable_and_write_node_t *cast = (pm_instance_variable_and_write_node_t *) node;
            pm_node_destroy(parser, (pm_node_t *)cast->value);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_INSTANCE_VARIABLE_OPERATOR_WRITE_NODE: {
            pm_instance_variable_operator_write_node_t *cast = (pm_instance_variable_operator_write_node_t *) node;
            pm_node_destroy(parser, (pm_node_t *)cast->value);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_INSTANCE_VARIABLE_OR_WRITE_NODE: {
            pm_instance_variable_or_write_node_t *cast = (pm_instance_variable_or_write_node_t *) node;
            pm_node_destroy(parser, (pm_node_t *)cast->value);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_INSTANCE_VARIABLE_READ_NODE: {
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_INSTANCE_VARIABLE_TARGET_NODE: {
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_INSTANCE_VARIABLE_WRITE_NODE: {
            pm_instance_variable_write_node_t *cast = (pm_instance_variable_write_node_t *) node;
            pm_node_destroy(parser, (pm_node_t *)cast->value);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_INTEGER_NODE: {
            pm_integer_node_t *cast = (pm_integer_node_t *) node;
            pm_integer_free(&cast->value);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_INTERPOLATED_MATCH_LAST_LINE_NODE: {
            pm_interpolated_match_last_line_node_t *cast = (pm_interpolated_match_last_line_node_t *) node;
            pm_node_list_destroy(parser, &cast->parts);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_INTERPOLATED_REGULAR_EXPRESSION_NODE: {
            pm_interpolated_regular_expression_node_t *cast = (pm_interpolated_regular_expression_node_t *) node;
            pm_node_list_destroy(parser, &cast->parts);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_INTERPOLATED_STRING_NODE: {
            pm_interpolated_string_node_t *cast = (pm_interpolated_string_node_t *) node;
            pm_node_list_destroy(parser, &cast->parts);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_INTERPOLATED_SYMBOL_NODE: {
            pm_interpolated_symbol_node_t *cast = (pm_interpolated_symbol_node_t *) node;
            pm_node_list_destroy(parser, &cast->parts);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_INTERPOLATED_X_STRING_NODE: {
            pm_interpolated_x_string_node_t *cast = (pm_interpolated_x_string_node_t *) node;
            pm_node_list_destroy(parser, &cast->parts);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_IT_LOCAL_VARIABLE_READ_NODE: {
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_IT_PARAMETERS_NODE: {
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_KEYWORD_HASH_NODE: {
            pm_keyword_hash_node_t *cast = (pm_keyword_hash_node_t *) node;
            pm_node_list_destroy(parser, &cast->elements);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_KEYWORD_REST_PARAMETER_NODE: {
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_LAMBDA_NODE: {
            pm_lambda_node_t *cast = (pm_lambda_node_t *) node;
            pm_constant_id_list_free(&cast->locals);
            if (cast->parameters != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->parameters);
            }
            if (cast->body != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->body);
            }
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_LOCAL_VARIABLE_AND_WRITE_NODE: {
            pm_local_variable_and_write_node_t *cast = (pm_local_variable_and_write_node_t *) node;
            pm_node_destroy(parser, (pm_node_t *)cast->value);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_LOCAL_VARIABLE_OPERATOR_WRITE_NODE: {
            pm_local_variable_operator_write_node_t *cast = (pm_local_variable_operator_write_node_t *) node;
            pm_node_destroy(parser, (pm_node_t *)cast->value);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_LOCAL_VARIABLE_OR_WRITE_NODE: {
            pm_local_variable_or_write_node_t *cast = (pm_local_variable_or_write_node_t *) node;
            pm_node_destroy(parser, (pm_node_t *)cast->value);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_LOCAL_VARIABLE_READ_NODE: {
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_LOCAL_VARIABLE_TARGET_NODE: {
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_LOCAL_VARIABLE_WRITE_NODE: {
            pm_local_variable_write_node_t *cast = (pm_local_variable_write_node_t *) node;
            pm_node_destroy(parser, (pm_node_t *)cast->value);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_MATCH_LAST_LINE_NODE: {
            pm_match_last_line_node_t *cast = (pm_match_last_line_node_t *) node;
            pm_string_free(&cast->unescaped);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_MATCH_PREDICATE_NODE: {
            pm_match_predicate_node_t *cast = (pm_match_predicate_node_t *) node;
            pm_node_destroy(parser, (pm_node_t *)cast->value);
            pm_node_destroy(parser, (pm_node_t *)cast->pattern);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_MATCH_REQUIRED_NODE: {
            pm_match_required_node_t *cast = (pm_match_required_node_t *) node;
            pm_node_destroy(parser, (pm_node_t *)cast->value);
            pm_node_destroy(parser, (pm_node_t *)cast->pattern);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_MATCH_WRITE_NODE: {
            pm_match_write_node_t *cast = (pm_match_write_node_t *) node;
            pm_node_destroy(parser, (pm_node_t *)cast->call);
            pm_node_list_destroy(parser, &cast->targets);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_MISSING_NODE: {
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_MODULE_NODE: {
            pm_module_node_t *cast = (pm_module_node_t *) node;
            pm_constant_id_list_free(&cast->locals);
            pm_node_destroy(parser, (pm_node_t *)cast->constant_path);
            if (cast->body != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->body);
            }
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_MULTI_TARGET_NODE: {
            pm_multi_target_node_t *cast = (pm_multi_target_node_t *) node;
            pm_node_list_destroy(parser, &cast->lefts);
            if (cast->rest != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->rest);
            }
            pm_node_list_destroy(parser, &cast->rights);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_MULTI_WRITE_NODE: {
            pm_multi_write_node_t *cast = (pm_multi_write_node_t *) node;
            pm_node_list_destroy(parser, &cast->lefts);
            if (cast->rest != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->rest);
            }
            pm_node_list_destroy(parser, &cast->rights);
            pm_node_destroy(parser, (pm_node_t *)cast->value);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_NEXT_NODE: {
            pm_next_node_t *cast = (pm_next_node_t *) node;
            if (cast->arguments != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->arguments);
            }
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_NIL_NODE: {
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_NO_KEYWORDS_PARAMETER_NODE: {
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_NUMBERED_PARAMETERS_NODE: {
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_NUMBERED_REFERENCE_READ_NODE: {
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_OPTIONAL_KEYWORD_PARAMETER_NODE: {
            pm_optional_keyword_parameter_node_t *cast = (pm_optional_keyword_parameter_node_t *) node;
            pm_node_destroy(parser, (pm_node_t *)cast->value);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_OPTIONAL_PARAMETER_NODE: {
            pm_optional_parameter_node_t *cast = (pm_optional_parameter_node_t *) node;
            pm_node_destroy(parser, (pm_node_t *)cast->value);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_OR_NODE: {
            pm_or_node_t *cast = (pm_or_node_t *) node;
            pm_node_destroy(parser, (pm_node_t *)cast->left);
            pm_node_destroy(parser, (pm_node_t *)cast->right);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_PARAMETERS_NODE: {
            pm_parameters_node_t *cast = (pm_parameters_node_t *) node;
            pm_node_list_destroy(parser, &cast->requireds);
            pm_node_list_destroy(parser, &cast->optionals);
            if (cast->rest != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->rest);
            }
            pm_node_list_destroy(parser, &cast->posts);
            pm_node_list_destroy(parser, &cast->keywords);
            if (cast->keyword_rest != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->keyword_rest);
            }
            if (cast->block != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->block);
            }
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_PARENTHESES_NODE: {
            pm_parentheses_node_t *cast = (pm_parentheses_node_t *) node;
            if (cast->body != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->body);
            }
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_PINNED_EXPRESSION_NODE: {
            pm_pinned_expression_node_t *cast = (pm_pinned_expression_node_t *) node;
            pm_node_destroy(parser, (pm_node_t *)cast->expression);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_PINNED_VARIABLE_NODE: {
            pm_pinned_variable_node_t *cast = (pm_pinned_variable_node_t *) node;
            pm_node_destroy(parser, (pm_node_t *)cast->variable);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_POST_EXECUTION_NODE: {
            pm_post_execution_node_t *cast = (pm_post_execution_node_t *) node;
            if (cast->statements != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->statements);
            }
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_PRE_EXECUTION_NODE: {
            pm_pre_execution_node_t *cast = (pm_pre_execution_node_t *) node;
            if (cast->statements != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->statements);
            }
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_PROGRAM_NODE: {
            pm_program_node_t *cast = (pm_program_node_t *) node;
            pm_constant_id_list_free(&cast->locals);
            pm_node_destroy(parser, (pm_node_t *)cast->statements);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_RANGE_NODE: {
            pm_range_node_t *cast = (pm_range_node_t *) node;
            if (cast->left != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->left);
            }
            if (cast->right != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->right);
            }
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_RATIONAL_NODE: {
            pm_rational_node_t *cast = (pm_rational_node_t *) node;
            pm_integer_free(&cast->numerator);
            pm_integer_free(&cast->denominator);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_REDO_NODE: {
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_REGULAR_EXPRESSION_NODE: {
            pm_regular_expression_node_t *cast = (pm_regular_expression_node_t *) node;
            pm_string_free(&cast->unescaped);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_REQUIRED_KEYWORD_PARAMETER_NODE: {
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_REQUIRED_PARAMETER_NODE: {
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_RESCUE_MODIFIER_NODE: {
            pm_rescue_modifier_node_t *cast = (pm_rescue_modifier_node_t *) node;
            pm_node_destroy(parser, (pm_node_t *)cast->expression);
            pm_node_destroy(parser, (pm_node_t *)cast->rescue_expression);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_RESCUE_NODE: {
            pm_rescue_node_t *cast = (pm_rescue_node_t *) node;
            pm_node_list_destroy(parser, &cast->exceptions);
            if (cast->reference != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->reference);
            }
            if (cast->statements != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->statements);
            }
            if (cast->subsequent != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->subsequent);
            }
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_REST_PARAMETER_NODE: {
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_RETRY_NODE: {
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_RETURN_NODE: {
            pm_return_node_t *cast = (pm_return_node_t *) node;
            if (cast->arguments != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->arguments);
            }
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_SELF_NODE: {
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_SHAREABLE_CONSTANT_NODE: {
            pm_shareable_constant_node_t *cast = (pm_shareable_constant_node_t *) node;
            pm_node_destroy(parser, (pm_node_t *)cast->write);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_SINGLETON_CLASS_NODE: {
            pm_singleton_class_node_t *cast = (pm_singleton_class_node_t *) node;
            pm_constant_id_list_free(&cast->locals);
            pm_node_destroy(parser, (pm_node_t *)cast->expression);
            if (cast->body != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->body);
            }
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_SOURCE_ENCODING_NODE: {
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_SOURCE_FILE_NODE: {
            pm_source_file_node_t *cast = (pm_source_file_node_t *) node;
            pm_string_free(&cast->filepath);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_SOURCE_LINE_NODE: {
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_SPLAT_NODE: {
            pm_splat_node_t *cast = (pm_splat_node_t *) node;
            if (cast->expression != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->expression);
            }
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_STATEMENTS_NODE: {
            pm_statements_node_t *cast = (pm_statements_node_t *) node;
            pm_node_list_destroy(parser, &cast->body);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_STRING_NODE: {
            pm_string_node_t *cast = (pm_string_node_t *) node;
            pm_string_free(&cast->unescaped);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_SUPER_NODE: {
            pm_super_node_t *cast = (pm_super_node_t *) node;
            if (cast->arguments != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->arguments);
            }
            if (cast->block != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->block);
            }
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_SYMBOL_NODE: {
            pm_symbol_node_t *cast = (pm_symbol_node_t *) node;
            pm_string_free(&cast->unescaped);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_TRUE_NODE: {
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_UNDEF_NODE: {
            pm_undef_node_t *cast = (pm_undef_node_t *) node;
            pm_node_list_destroy(parser, &cast->names);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_UNLESS_NODE: {
            pm_unless_node_t *cast = (pm_unless_node_t *) node;
            pm_node_destroy(parser, (pm_node_t *)cast->predicate);
            if (cast->statements != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->statements);
            }
            if (cast->else_clause != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->else_clause);
            }
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_UNTIL_NODE: {
            pm_until_node_t *cast = (pm_until_node_t *) node;
            pm_node_destroy(parser, (pm_node_t *)cast->predicate);
            if (cast->statements != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->statements);
            }
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_WHEN_NODE: {
            pm_when_node_t *cast = (pm_when_node_t *) node;
            pm_node_list_destroy(parser, &cast->conditions);
            if (cast->statements != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->statements);
            }
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_WHILE_NODE: {
            pm_while_node_t *cast = (pm_while_node_t *) node;
            pm_node_destroy(parser, (pm_node_t *)cast->predicate);
            if (cast->statements != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->statements);
            }
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_X_STRING_NODE: {
            pm_x_string_node_t *cast = (pm_x_string_node_t *) node;
            pm_string_free(&cast->unescaped);
            break;
        }
#line 110 "prism/templates/src/node.c.erb"
        case PM_YIELD_NODE: {
            pm_yield_node_t *cast = (pm_yield_node_t *) node;
            if (cast->arguments != NULL) {
                pm_node_destroy(parser, (pm_node_t *)cast->arguments);
            }
            break;
        }
#line 139 "prism/templates/src/node.c.erb"
        default:
            assert(false && "unreachable");
            break;
    }
    xfree(node);
}

/**
 * Returns a string representation of the given node type.
 */
PRISM_EXPORTED_FUNCTION const char *
pm_node_type_to_str(pm_node_type_t node_type)
{
    switch (node_type) {
        case PM_ALIAS_GLOBAL_VARIABLE_NODE:
            return "PM_ALIAS_GLOBAL_VARIABLE_NODE";
        case PM_ALIAS_METHOD_NODE:
            return "PM_ALIAS_METHOD_NODE";
        case PM_ALTERNATION_PATTERN_NODE:
            return "PM_ALTERNATION_PATTERN_NODE";
        case PM_AND_NODE:
            return "PM_AND_NODE";
        case PM_ARGUMENTS_NODE:
            return "PM_ARGUMENTS_NODE";
        case PM_ARRAY_NODE:
            return "PM_ARRAY_NODE";
        case PM_ARRAY_PATTERN_NODE:
            return "PM_ARRAY_PATTERN_NODE";
        case PM_ASSOC_NODE:
            return "PM_ASSOC_NODE";
        case PM_ASSOC_SPLAT_NODE:
            return "PM_ASSOC_SPLAT_NODE";
        case PM_BACK_REFERENCE_READ_NODE:
            return "PM_BACK_REFERENCE_READ_NODE";
        case PM_BEGIN_NODE:
            return "PM_BEGIN_NODE";
        case PM_BLOCK_ARGUMENT_NODE:
            return "PM_BLOCK_ARGUMENT_NODE";
        case PM_BLOCK_LOCAL_VARIABLE_NODE:
            return "PM_BLOCK_LOCAL_VARIABLE_NODE";
        case PM_BLOCK_NODE:
            return "PM_BLOCK_NODE";
        case PM_BLOCK_PARAMETER_NODE:
            return "PM_BLOCK_PARAMETER_NODE";
        case PM_BLOCK_PARAMETERS_NODE:
            return "PM_BLOCK_PARAMETERS_NODE";
        case PM_BREAK_NODE:
            return "PM_BREAK_NODE";
        case PM_CALL_AND_WRITE_NODE:
            return "PM_CALL_AND_WRITE_NODE";
        case PM_CALL_NODE:
            return "PM_CALL_NODE";
        case PM_CALL_OPERATOR_WRITE_NODE:
            return "PM_CALL_OPERATOR_WRITE_NODE";
        case PM_CALL_OR_WRITE_NODE:
            return "PM_CALL_OR_WRITE_NODE";
        case PM_CALL_TARGET_NODE:
            return "PM_CALL_TARGET_NODE";
        case PM_CAPTURE_PATTERN_NODE:
            return "PM_CAPTURE_PATTERN_NODE";
        case PM_CASE_MATCH_NODE:
            return "PM_CASE_MATCH_NODE";
        case PM_CASE_NODE:
            return "PM_CASE_NODE";
        case PM_CLASS_NODE:
            return "PM_CLASS_NODE";
        case PM_CLASS_VARIABLE_AND_WRITE_NODE:
            return "PM_CLASS_VARIABLE_AND_WRITE_NODE";
        case PM_CLASS_VARIABLE_OPERATOR_WRITE_NODE:
            return "PM_CLASS_VARIABLE_OPERATOR_WRITE_NODE";
        case PM_CLASS_VARIABLE_OR_WRITE_NODE:
            return "PM_CLASS_VARIABLE_OR_WRITE_NODE";
        case PM_CLASS_VARIABLE_READ_NODE:
            return "PM_CLASS_VARIABLE_READ_NODE";
        case PM_CLASS_VARIABLE_TARGET_NODE:
            return "PM_CLASS_VARIABLE_TARGET_NODE";
        case PM_CLASS_VARIABLE_WRITE_NODE:
            return "PM_CLASS_VARIABLE_WRITE_NODE";
        case PM_CONSTANT_AND_WRITE_NODE:
            return "PM_CONSTANT_AND_WRITE_NODE";
        case PM_CONSTANT_OPERATOR_WRITE_NODE:
            return "PM_CONSTANT_OPERATOR_WRITE_NODE";
        case PM_CONSTANT_OR_WRITE_NODE:
            return "PM_CONSTANT_OR_WRITE_NODE";
        case PM_CONSTANT_PATH_AND_WRITE_NODE:
            return "PM_CONSTANT_PATH_AND_WRITE_NODE";
        case PM_CONSTANT_PATH_NODE:
            return "PM_CONSTANT_PATH_NODE";
        case PM_CONSTANT_PATH_OPERATOR_WRITE_NODE:
            return "PM_CONSTANT_PATH_OPERATOR_WRITE_NODE";
        case PM_CONSTANT_PATH_OR_WRITE_NODE:
            return "PM_CONSTANT_PATH_OR_WRITE_NODE";
        case PM_CONSTANT_PATH_TARGET_NODE:
            return "PM_CONSTANT_PATH_TARGET_NODE";
        case PM_CONSTANT_PATH_WRITE_NODE:
            return "PM_CONSTANT_PATH_WRITE_NODE";
        case PM_CONSTANT_READ_NODE:
            return "PM_CONSTANT_READ_NODE";
        case PM_CONSTANT_TARGET_NODE:
            return "PM_CONSTANT_TARGET_NODE";
        case PM_CONSTANT_WRITE_NODE:
            return "PM_CONSTANT_WRITE_NODE";
        case PM_DEF_NODE:
            return "PM_DEF_NODE";
        case PM_DEFINED_NODE:
            return "PM_DEFINED_NODE";
        case PM_ELSE_NODE:
            return "PM_ELSE_NODE";
        case PM_EMBEDDED_STATEMENTS_NODE:
            return "PM_EMBEDDED_STATEMENTS_NODE";
        case PM_EMBEDDED_VARIABLE_NODE:
            return "PM_EMBEDDED_VARIABLE_NODE";
        case PM_ENSURE_NODE:
            return "PM_ENSURE_NODE";
        case PM_FALSE_NODE:
            return "PM_FALSE_NODE";
        case PM_FIND_PATTERN_NODE:
            return "PM_FIND_PATTERN_NODE";
        case PM_FLIP_FLOP_NODE:
            return "PM_FLIP_FLOP_NODE";
        case PM_FLOAT_NODE:
            return "PM_FLOAT_NODE";
        case PM_FOR_NODE:
            return "PM_FOR_NODE";
        case PM_FORWARDING_ARGUMENTS_NODE:
            return "PM_FORWARDING_ARGUMENTS_NODE";
        case PM_FORWARDING_PARAMETER_NODE:
            return "PM_FORWARDING_PARAMETER_NODE";
        case PM_FORWARDING_SUPER_NODE:
            return "PM_FORWARDING_SUPER_NODE";
        case PM_GLOBAL_VARIABLE_AND_WRITE_NODE:
            return "PM_GLOBAL_VARIABLE_AND_WRITE_NODE";
        case PM_GLOBAL_VARIABLE_OPERATOR_WRITE_NODE:
            return "PM_GLOBAL_VARIABLE_OPERATOR_WRITE_NODE";
        case PM_GLOBAL_VARIABLE_OR_WRITE_NODE:
            return "PM_GLOBAL_VARIABLE_OR_WRITE_NODE";
        case PM_GLOBAL_VARIABLE_READ_NODE:
            return "PM_GLOBAL_VARIABLE_READ_NODE";
        case PM_GLOBAL_VARIABLE_TARGET_NODE:
            return "PM_GLOBAL_VARIABLE_TARGET_NODE";
        case PM_GLOBAL_VARIABLE_WRITE_NODE:
            return "PM_GLOBAL_VARIABLE_WRITE_NODE";
        case PM_HASH_NODE:
            return "PM_HASH_NODE";
        case PM_HASH_PATTERN_NODE:
            return "PM_HASH_PATTERN_NODE";
        case PM_IF_NODE:
            return "PM_IF_NODE";
        case PM_IMAGINARY_NODE:
            return "PM_IMAGINARY_NODE";
        case PM_IMPLICIT_NODE:
            return "PM_IMPLICIT_NODE";
        case PM_IMPLICIT_REST_NODE:
            return "PM_IMPLICIT_REST_NODE";
        case PM_IN_NODE:
            return "PM_IN_NODE";
        case PM_INDEX_AND_WRITE_NODE:
            return "PM_INDEX_AND_WRITE_NODE";
        case PM_INDEX_OPERATOR_WRITE_NODE:
            return "PM_INDEX_OPERATOR_WRITE_NODE";
        case PM_INDEX_OR_WRITE_NODE:
            return "PM_INDEX_OR_WRITE_NODE";
        case PM_INDEX_TARGET_NODE:
            return "PM_INDEX_TARGET_NODE";
        case PM_INSTANCE_VARIABLE_AND_WRITE_NODE:
            return "PM_INSTANCE_VARIABLE_AND_WRITE_NODE";
        case PM_INSTANCE_VARIABLE_OPERATOR_WRITE_NODE:
            return "PM_INSTANCE_VARIABLE_OPERATOR_WRITE_NODE";
        case PM_INSTANCE_VARIABLE_OR_WRITE_NODE:
            return "PM_INSTANCE_VARIABLE_OR_WRITE_NODE";
        case PM_INSTANCE_VARIABLE_READ_NODE:
            return "PM_INSTANCE_VARIABLE_READ_NODE";
        case PM_INSTANCE_VARIABLE_TARGET_NODE:
            return "PM_INSTANCE_VARIABLE_TARGET_NODE";
        case PM_INSTANCE_VARIABLE_WRITE_NODE:
            return "PM_INSTANCE_VARIABLE_WRITE_NODE";
        case PM_INTEGER_NODE:
            return "PM_INTEGER_NODE";
        case PM_INTERPOLATED_MATCH_LAST_LINE_NODE:
            return "PM_INTERPOLATED_MATCH_LAST_LINE_NODE";
        case PM_INTERPOLATED_REGULAR_EXPRESSION_NODE:
            return "PM_INTERPOLATED_REGULAR_EXPRESSION_NODE";
        case PM_INTERPOLATED_STRING_NODE:
            return "PM_INTERPOLATED_STRING_NODE";
        case PM_INTERPOLATED_SYMBOL_NODE:
            return "PM_INTERPOLATED_SYMBOL_NODE";
        case PM_INTERPOLATED_X_STRING_NODE:
            return "PM_INTERPOLATED_X_STRING_NODE";
        case PM_IT_LOCAL_VARIABLE_READ_NODE:
            return "PM_IT_LOCAL_VARIABLE_READ_NODE";
        case PM_IT_PARAMETERS_NODE:
            return "PM_IT_PARAMETERS_NODE";
        case PM_KEYWORD_HASH_NODE:
            return "PM_KEYWORD_HASH_NODE";
        case PM_KEYWORD_REST_PARAMETER_NODE:
            return "PM_KEYWORD_REST_PARAMETER_NODE";
        case PM_LAMBDA_NODE:
            return "PM_LAMBDA_NODE";
        case PM_LOCAL_VARIABLE_AND_WRITE_NODE:
            return "PM_LOCAL_VARIABLE_AND_WRITE_NODE";
        case PM_LOCAL_VARIABLE_OPERATOR_WRITE_NODE:
            return "PM_LOCAL_VARIABLE_OPERATOR_WRITE_NODE";
        case PM_LOCAL_VARIABLE_OR_WRITE_NODE:
            return "PM_LOCAL_VARIABLE_OR_WRITE_NODE";
        case PM_LOCAL_VARIABLE_READ_NODE:
            return "PM_LOCAL_VARIABLE_READ_NODE";
        case PM_LOCAL_VARIABLE_TARGET_NODE:
            return "PM_LOCAL_VARIABLE_TARGET_NODE";
        case PM_LOCAL_VARIABLE_WRITE_NODE:
            return "PM_LOCAL_VARIABLE_WRITE_NODE";
        case PM_MATCH_LAST_LINE_NODE:
            return "PM_MATCH_LAST_LINE_NODE";
        case PM_MATCH_PREDICATE_NODE:
            return "PM_MATCH_PREDICATE_NODE";
        case PM_MATCH_REQUIRED_NODE:
            return "PM_MATCH_REQUIRED_NODE";
        case PM_MATCH_WRITE_NODE:
            return "PM_MATCH_WRITE_NODE";
        case PM_MISSING_NODE:
            return "PM_MISSING_NODE";
        case PM_MODULE_NODE:
            return "PM_MODULE_NODE";
        case PM_MULTI_TARGET_NODE:
            return "PM_MULTI_TARGET_NODE";
        case PM_MULTI_WRITE_NODE:
            return "PM_MULTI_WRITE_NODE";
        case PM_NEXT_NODE:
            return "PM_NEXT_NODE";
        case PM_NIL_NODE:
            return "PM_NIL_NODE";
        case PM_NO_KEYWORDS_PARAMETER_NODE:
            return "PM_NO_KEYWORDS_PARAMETER_NODE";
        case PM_NUMBERED_PARAMETERS_NODE:
            return "PM_NUMBERED_PARAMETERS_NODE";
        case PM_NUMBERED_REFERENCE_READ_NODE:
            return "PM_NUMBERED_REFERENCE_READ_NODE";
        case PM_OPTIONAL_KEYWORD_PARAMETER_NODE:
            return "PM_OPTIONAL_KEYWORD_PARAMETER_NODE";
        case PM_OPTIONAL_PARAMETER_NODE:
            return "PM_OPTIONAL_PARAMETER_NODE";
        case PM_OR_NODE:
            return "PM_OR_NODE";
        case PM_PARAMETERS_NODE:
            return "PM_PARAMETERS_NODE";
        case PM_PARENTHESES_NODE:
            return "PM_PARENTHESES_NODE";
        case PM_PINNED_EXPRESSION_NODE:
            return "PM_PINNED_EXPRESSION_NODE";
        case PM_PINNED_VARIABLE_NODE:
            return "PM_PINNED_VARIABLE_NODE";
        case PM_POST_EXECUTION_NODE:
            return "PM_POST_EXECUTION_NODE";
        case PM_PRE_EXECUTION_NODE:
            return "PM_PRE_EXECUTION_NODE";
        case PM_PROGRAM_NODE:
            return "PM_PROGRAM_NODE";
        case PM_RANGE_NODE:
            return "PM_RANGE_NODE";
        case PM_RATIONAL_NODE:
            return "PM_RATIONAL_NODE";
        case PM_REDO_NODE:
            return "PM_REDO_NODE";
        case PM_REGULAR_EXPRESSION_NODE:
            return "PM_REGULAR_EXPRESSION_NODE";
        case PM_REQUIRED_KEYWORD_PARAMETER_NODE:
            return "PM_REQUIRED_KEYWORD_PARAMETER_NODE";
        case PM_REQUIRED_PARAMETER_NODE:
            return "PM_REQUIRED_PARAMETER_NODE";
        case PM_RESCUE_MODIFIER_NODE:
            return "PM_RESCUE_MODIFIER_NODE";
        case PM_RESCUE_NODE:
            return "PM_RESCUE_NODE";
        case PM_REST_PARAMETER_NODE:
            return "PM_REST_PARAMETER_NODE";
        case PM_RETRY_NODE:
            return "PM_RETRY_NODE";
        case PM_RETURN_NODE:
            return "PM_RETURN_NODE";
        case PM_SELF_NODE:
            return "PM_SELF_NODE";
        case PM_SHAREABLE_CONSTANT_NODE:
            return "PM_SHAREABLE_CONSTANT_NODE";
        case PM_SINGLETON_CLASS_NODE:
            return "PM_SINGLETON_CLASS_NODE";
        case PM_SOURCE_ENCODING_NODE:
            return "PM_SOURCE_ENCODING_NODE";
        case PM_SOURCE_FILE_NODE:
            return "PM_SOURCE_FILE_NODE";
        case PM_SOURCE_LINE_NODE:
            return "PM_SOURCE_LINE_NODE";
        case PM_SPLAT_NODE:
            return "PM_SPLAT_NODE";
        case PM_STATEMENTS_NODE:
            return "PM_STATEMENTS_NODE";
        case PM_STRING_NODE:
            return "PM_STRING_NODE";
        case PM_SUPER_NODE:
            return "PM_SUPER_NODE";
        case PM_SYMBOL_NODE:
            return "PM_SYMBOL_NODE";
        case PM_TRUE_NODE:
            return "PM_TRUE_NODE";
        case PM_UNDEF_NODE:
            return "PM_UNDEF_NODE";
        case PM_UNLESS_NODE:
            return "PM_UNLESS_NODE";
        case PM_UNTIL_NODE:
            return "PM_UNTIL_NODE";
        case PM_WHEN_NODE:
            return "PM_WHEN_NODE";
        case PM_WHILE_NODE:
            return "PM_WHILE_NODE";
        case PM_X_STRING_NODE:
            return "PM_X_STRING_NODE";
        case PM_YIELD_NODE:
            return "PM_YIELD_NODE";
    }
    return "";
}

/**
 * Visit each of the nodes in this subtree using the given visitor callback. The
 * callback function will be called for each node in the subtree. If it returns
 * false, then that node's children will not be visited. If it returns true,
 * then the children will be visited. The data parameter is treated as an opaque
 * pointer and is passed to the visitor callback for consumers to use as they
 * see fit.
 */
PRISM_EXPORTED_FUNCTION void
pm_visit_node(const pm_node_t *node, bool (*visitor)(const pm_node_t *node, void *data), void *data) {
    if (visitor(node, data)) pm_visit_child_nodes(node, visitor, data);
}

/**
 * Visit the children of the given node with the given callback. This is the
 * default behavior for walking the tree that is called from pm_visit_node if
 * the callback returns true.
 */
PRISM_EXPORTED_FUNCTION void
pm_visit_child_nodes(const pm_node_t *node, bool (*visitor)(const pm_node_t *node, void *data), void *data) {
    switch (PM_NODE_TYPE(node)) {
        case PM_ALIAS_GLOBAL_VARIABLE_NODE: {
            const pm_alias_global_variable_node_t *cast = (const pm_alias_global_variable_node_t *) node;

            // Visit the new_name field
            pm_visit_node((const pm_node_t *) cast->new_name, visitor, data);

            // Visit the old_name field
            pm_visit_node((const pm_node_t *) cast->old_name, visitor, data);

            break;
        }
        case PM_ALIAS_METHOD_NODE: {
            const pm_alias_method_node_t *cast = (const pm_alias_method_node_t *) node;

            // Visit the new_name field
            pm_visit_node((const pm_node_t *) cast->new_name, visitor, data);

            // Visit the old_name field
            pm_visit_node((const pm_node_t *) cast->old_name, visitor, data);

            break;
        }
        case PM_ALTERNATION_PATTERN_NODE: {
            const pm_alternation_pattern_node_t *cast = (const pm_alternation_pattern_node_t *) node;

            // Visit the left field
            pm_visit_node((const pm_node_t *) cast->left, visitor, data);

            // Visit the right field
            pm_visit_node((const pm_node_t *) cast->right, visitor, data);

            break;
        }
        case PM_AND_NODE: {
            const pm_and_node_t *cast = (const pm_and_node_t *) node;

            // Visit the left field
            pm_visit_node((const pm_node_t *) cast->left, visitor, data);

            // Visit the right field
            pm_visit_node((const pm_node_t *) cast->right, visitor, data);

            break;
        }
        case PM_ARGUMENTS_NODE: {
            const pm_arguments_node_t *cast = (const pm_arguments_node_t *) node;

            // Visit the arguments field
            const pm_node_list_t *arguments = &cast->arguments;
            for (size_t index = 0; index < arguments->size; index++) {
                pm_visit_node(arguments->nodes[index], visitor, data);
            }

            break;
        }
        case PM_ARRAY_NODE: {
            const pm_array_node_t *cast = (const pm_array_node_t *) node;

            // Visit the elements field
            const pm_node_list_t *elements = &cast->elements;
            for (size_t index = 0; index < elements->size; index++) {
                pm_visit_node(elements->nodes[index], visitor, data);
            }

            break;
        }
        case PM_ARRAY_PATTERN_NODE: {
            const pm_array_pattern_node_t *cast = (const pm_array_pattern_node_t *) node;

            // Visit the constant field
            if (cast->constant != NULL) {
                pm_visit_node((const pm_node_t *) cast->constant, visitor, data);
            }

            // Visit the requireds field
            const pm_node_list_t *requireds = &cast->requireds;
            for (size_t index = 0; index < requireds->size; index++) {
                pm_visit_node(requireds->nodes[index], visitor, data);
            }

            // Visit the rest field
            if (cast->rest != NULL) {
                pm_visit_node((const pm_node_t *) cast->rest, visitor, data);
            }

            // Visit the posts field
            const pm_node_list_t *posts = &cast->posts;
            for (size_t index = 0; index < posts->size; index++) {
                pm_visit_node(posts->nodes[index], visitor, data);
            }

            break;
        }
        case PM_ASSOC_NODE: {
            const pm_assoc_node_t *cast = (const pm_assoc_node_t *) node;

            // Visit the key field
            pm_visit_node((const pm_node_t *) cast->key, visitor, data);

            // Visit the value field
            pm_visit_node((const pm_node_t *) cast->value, visitor, data);

            break;
        }
        case PM_ASSOC_SPLAT_NODE: {
            const pm_assoc_splat_node_t *cast = (const pm_assoc_splat_node_t *) node;

            // Visit the value field
            if (cast->value != NULL) {
                pm_visit_node((const pm_node_t *) cast->value, visitor, data);
            }

            break;
        }
        case PM_BACK_REFERENCE_READ_NODE:
            break;
        case PM_BEGIN_NODE: {
            const pm_begin_node_t *cast = (const pm_begin_node_t *) node;

            // Visit the statements field
            if (cast->statements != NULL) {
                pm_visit_node((const pm_node_t *) cast->statements, visitor, data);
            }

            // Visit the rescue_clause field
            if (cast->rescue_clause != NULL) {
                pm_visit_node((const pm_node_t *) cast->rescue_clause, visitor, data);
            }

            // Visit the else_clause field
            if (cast->else_clause != NULL) {
                pm_visit_node((const pm_node_t *) cast->else_clause, visitor, data);
            }

            // Visit the ensure_clause field
            if (cast->ensure_clause != NULL) {
                pm_visit_node((const pm_node_t *) cast->ensure_clause, visitor, data);
            }

            break;
        }
        case PM_BLOCK_ARGUMENT_NODE: {
            const pm_block_argument_node_t *cast = (const pm_block_argument_node_t *) node;

            // Visit the expression field
            if (cast->expression != NULL) {
                pm_visit_node((const pm_node_t *) cast->expression, visitor, data);
            }

            break;
        }
        case PM_BLOCK_LOCAL_VARIABLE_NODE:
            break;
        case PM_BLOCK_NODE: {
            const pm_block_node_t *cast = (const pm_block_node_t *) node;

            // Visit the parameters field
            if (cast->parameters != NULL) {
                pm_visit_node((const pm_node_t *) cast->parameters, visitor, data);
            }

            // Visit the body field
            if (cast->body != NULL) {
                pm_visit_node((const pm_node_t *) cast->body, visitor, data);
            }

            break;
        }
        case PM_BLOCK_PARAMETER_NODE:
            break;
        case PM_BLOCK_PARAMETERS_NODE: {
            const pm_block_parameters_node_t *cast = (const pm_block_parameters_node_t *) node;

            // Visit the parameters field
            if (cast->parameters != NULL) {
                pm_visit_node((const pm_node_t *) cast->parameters, visitor, data);
            }

            // Visit the locals field
            const pm_node_list_t *locals = &cast->locals;
            for (size_t index = 0; index < locals->size; index++) {
                pm_visit_node(locals->nodes[index], visitor, data);
            }

            break;
        }
        case PM_BREAK_NODE: {
            const pm_break_node_t *cast = (const pm_break_node_t *) node;

            // Visit the arguments field
            if (cast->arguments != NULL) {
                pm_visit_node((const pm_node_t *) cast->arguments, visitor, data);
            }

            break;
        }
        case PM_CALL_AND_WRITE_NODE: {
            const pm_call_and_write_node_t *cast = (const pm_call_and_write_node_t *) node;

            // Visit the receiver field
            if (cast->receiver != NULL) {
                pm_visit_node((const pm_node_t *) cast->receiver, visitor, data);
            }

            // Visit the value field
            pm_visit_node((const pm_node_t *) cast->value, visitor, data);

            break;
        }
        case PM_CALL_NODE: {
            const pm_call_node_t *cast = (const pm_call_node_t *) node;

            // Visit the receiver field
            if (cast->receiver != NULL) {
                pm_visit_node((const pm_node_t *) cast->receiver, visitor, data);
            }

            // Visit the arguments field
            if (cast->arguments != NULL) {
                pm_visit_node((const pm_node_t *) cast->arguments, visitor, data);
            }

            // Visit the block field
            if (cast->block != NULL) {
                pm_visit_node((const pm_node_t *) cast->block, visitor, data);
            }

            break;
        }
        case PM_CALL_OPERATOR_WRITE_NODE: {
            const pm_call_operator_write_node_t *cast = (const pm_call_operator_write_node_t *) node;

            // Visit the receiver field
            if (cast->receiver != NULL) {
                pm_visit_node((const pm_node_t *) cast->receiver, visitor, data);
            }

            // Visit the value field
            pm_visit_node((const pm_node_t *) cast->value, visitor, data);

            break;
        }
        case PM_CALL_OR_WRITE_NODE: {
            const pm_call_or_write_node_t *cast = (const pm_call_or_write_node_t *) node;

            // Visit the receiver field
            if (cast->receiver != NULL) {
                pm_visit_node((const pm_node_t *) cast->receiver, visitor, data);
            }

            // Visit the value field
            pm_visit_node((const pm_node_t *) cast->value, visitor, data);

            break;
        }
        case PM_CALL_TARGET_NODE: {
            const pm_call_target_node_t *cast = (const pm_call_target_node_t *) node;

            // Visit the receiver field
            pm_visit_node((const pm_node_t *) cast->receiver, visitor, data);

            break;
        }
        case PM_CAPTURE_PATTERN_NODE: {
            const pm_capture_pattern_node_t *cast = (const pm_capture_pattern_node_t *) node;

            // Visit the value field
            pm_visit_node((const pm_node_t *) cast->value, visitor, data);

            // Visit the target field
            pm_visit_node((const pm_node_t *) cast->target, visitor, data);

            break;
        }
        case PM_CASE_MATCH_NODE: {
            const pm_case_match_node_t *cast = (const pm_case_match_node_t *) node;

            // Visit the predicate field
            if (cast->predicate != NULL) {
                pm_visit_node((const pm_node_t *) cast->predicate, visitor, data);
            }

            // Visit the conditions field
            const pm_node_list_t *conditions = &cast->conditions;
            for (size_t index = 0; index < conditions->size; index++) {
                pm_visit_node(conditions->nodes[index], visitor, data);
            }

            // Visit the else_clause field
            if (cast->else_clause != NULL) {
                pm_visit_node((const pm_node_t *) cast->else_clause, visitor, data);
            }

            break;
        }
        case PM_CASE_NODE: {
            const pm_case_node_t *cast = (const pm_case_node_t *) node;

            // Visit the predicate field
            if (cast->predicate != NULL) {
                pm_visit_node((const pm_node_t *) cast->predicate, visitor, data);
            }

            // Visit the conditions field
            const pm_node_list_t *conditions = &cast->conditions;
            for (size_t index = 0; index < conditions->size; index++) {
                pm_visit_node(conditions->nodes[index], visitor, data);
            }

            // Visit the else_clause field
            if (cast->else_clause != NULL) {
                pm_visit_node((const pm_node_t *) cast->else_clause, visitor, data);
            }

            break;
        }
        case PM_CLASS_NODE: {
            const pm_class_node_t *cast = (const pm_class_node_t *) node;

            // Visit the constant_path field
            pm_visit_node((const pm_node_t *) cast->constant_path, visitor, data);

            // Visit the superclass field
            if (cast->superclass != NULL) {
                pm_visit_node((const pm_node_t *) cast->superclass, visitor, data);
            }

            // Visit the body field
            if (cast->body != NULL) {
                pm_visit_node((const pm_node_t *) cast->body, visitor, data);
            }

            break;
        }
        case PM_CLASS_VARIABLE_AND_WRITE_NODE: {
            const pm_class_variable_and_write_node_t *cast = (const pm_class_variable_and_write_node_t *) node;

            // Visit the value field
            pm_visit_node((const pm_node_t *) cast->value, visitor, data);

            break;
        }
        case PM_CLASS_VARIABLE_OPERATOR_WRITE_NODE: {
            const pm_class_variable_operator_write_node_t *cast = (const pm_class_variable_operator_write_node_t *) node;

            // Visit the value field
            pm_visit_node((const pm_node_t *) cast->value, visitor, data);

            break;
        }
        case PM_CLASS_VARIABLE_OR_WRITE_NODE: {
            const pm_class_variable_or_write_node_t *cast = (const pm_class_variable_or_write_node_t *) node;

            // Visit the value field
            pm_visit_node((const pm_node_t *) cast->value, visitor, data);

            break;
        }
        case PM_CLASS_VARIABLE_READ_NODE:
            break;
        case PM_CLASS_VARIABLE_TARGET_NODE:
            break;
        case PM_CLASS_VARIABLE_WRITE_NODE: {
            const pm_class_variable_write_node_t *cast = (const pm_class_variable_write_node_t *) node;

            // Visit the value field
            pm_visit_node((const pm_node_t *) cast->value, visitor, data);

            break;
        }
        case PM_CONSTANT_AND_WRITE_NODE: {
            const pm_constant_and_write_node_t *cast = (const pm_constant_and_write_node_t *) node;

            // Visit the value field
            pm_visit_node((const pm_node_t *) cast->value, visitor, data);

            break;
        }
        case PM_CONSTANT_OPERATOR_WRITE_NODE: {
            const pm_constant_operator_write_node_t *cast = (const pm_constant_operator_write_node_t *) node;

            // Visit the value field
            pm_visit_node((const pm_node_t *) cast->value, visitor, data);

            break;
        }
        case PM_CONSTANT_OR_WRITE_NODE: {
            const pm_constant_or_write_node_t *cast = (const pm_constant_or_write_node_t *) node;

            // Visit the value field
            pm_visit_node((const pm_node_t *) cast->value, visitor, data);

            break;
        }
        case PM_CONSTANT_PATH_AND_WRITE_NODE: {
            const pm_constant_path_and_write_node_t *cast = (const pm_constant_path_and_write_node_t *) node;

            // Visit the target field
            pm_visit_node((const pm_node_t *) cast->target, visitor, data);

            // Visit the value field
            pm_visit_node((const pm_node_t *) cast->value, visitor, data);

            break;
        }
        case PM_CONSTANT_PATH_NODE: {
            const pm_constant_path_node_t *cast = (const pm_constant_path_node_t *) node;

            // Visit the parent field
            if (cast->parent != NULL) {
                pm_visit_node((const pm_node_t *) cast->parent, visitor, data);
            }

            break;
        }
        case PM_CONSTANT_PATH_OPERATOR_WRITE_NODE: {
            const pm_constant_path_operator_write_node_t *cast = (const pm_constant_path_operator_write_node_t *) node;

            // Visit the target field
            pm_visit_node((const pm_node_t *) cast->target, visitor, data);

            // Visit the value field
            pm_visit_node((const pm_node_t *) cast->value, visitor, data);

            break;
        }
        case PM_CONSTANT_PATH_OR_WRITE_NODE: {
            const pm_constant_path_or_write_node_t *cast = (const pm_constant_path_or_write_node_t *) node;

            // Visit the target field
            pm_visit_node((const pm_node_t *) cast->target, visitor, data);

            // Visit the value field
            pm_visit_node((const pm_node_t *) cast->value, visitor, data);

            break;
        }
        case PM_CONSTANT_PATH_TARGET_NODE: {
            const pm_constant_path_target_node_t *cast = (const pm_constant_path_target_node_t *) node;

            // Visit the parent field
            if (cast->parent != NULL) {
                pm_visit_node((const pm_node_t *) cast->parent, visitor, data);
            }

            break;
        }
        case PM_CONSTANT_PATH_WRITE_NODE: {
            const pm_constant_path_write_node_t *cast = (const pm_constant_path_write_node_t *) node;

            // Visit the target field
            pm_visit_node((const pm_node_t *) cast->target, visitor, data);

            // Visit the value field
            pm_visit_node((const pm_node_t *) cast->value, visitor, data);

            break;
        }
        case PM_CONSTANT_READ_NODE:
            break;
        case PM_CONSTANT_TARGET_NODE:
            break;
        case PM_CONSTANT_WRITE_NODE: {
            const pm_constant_write_node_t *cast = (const pm_constant_write_node_t *) node;

            // Visit the value field
            pm_visit_node((const pm_node_t *) cast->value, visitor, data);

            break;
        }
        case PM_DEF_NODE: {
            const pm_def_node_t *cast = (const pm_def_node_t *) node;

            // Visit the receiver field
            if (cast->receiver != NULL) {
                pm_visit_node((const pm_node_t *) cast->receiver, visitor, data);
            }

            // Visit the parameters field
            if (cast->parameters != NULL) {
                pm_visit_node((const pm_node_t *) cast->parameters, visitor, data);
            }

            // Visit the body field
            if (cast->body != NULL) {
                pm_visit_node((const pm_node_t *) cast->body, visitor, data);
            }

            break;
        }
        case PM_DEFINED_NODE: {
            const pm_defined_node_t *cast = (const pm_defined_node_t *) node;

            // Visit the value field
            pm_visit_node((const pm_node_t *) cast->value, visitor, data);

            break;
        }
        case PM_ELSE_NODE: {
            const pm_else_node_t *cast = (const pm_else_node_t *) node;

            // Visit the statements field
            if (cast->statements != NULL) {
                pm_visit_node((const pm_node_t *) cast->statements, visitor, data);
            }

            break;
        }
        case PM_EMBEDDED_STATEMENTS_NODE: {
            const pm_embedded_statements_node_t *cast = (const pm_embedded_statements_node_t *) node;

            // Visit the statements field
            if (cast->statements != NULL) {
                pm_visit_node((const pm_node_t *) cast->statements, visitor, data);
            }

            break;
        }
        case PM_EMBEDDED_VARIABLE_NODE: {
            const pm_embedded_variable_node_t *cast = (const pm_embedded_variable_node_t *) node;

            // Visit the variable field
            pm_visit_node((const pm_node_t *) cast->variable, visitor, data);

            break;
        }
        case PM_ENSURE_NODE: {
            const pm_ensure_node_t *cast = (const pm_ensure_node_t *) node;

            // Visit the statements field
            if (cast->statements != NULL) {
                pm_visit_node((const pm_node_t *) cast->statements, visitor, data);
            }

            break;
        }
        case PM_FALSE_NODE:
            break;
        case PM_FIND_PATTERN_NODE: {
            const pm_find_pattern_node_t *cast = (const pm_find_pattern_node_t *) node;

            // Visit the constant field
            if (cast->constant != NULL) {
                pm_visit_node((const pm_node_t *) cast->constant, visitor, data);
            }

            // Visit the left field
            pm_visit_node((const pm_node_t *) cast->left, visitor, data);

            // Visit the requireds field
            const pm_node_list_t *requireds = &cast->requireds;
            for (size_t index = 0; index < requireds->size; index++) {
                pm_visit_node(requireds->nodes[index], visitor, data);
            }

            // Visit the right field
            pm_visit_node((const pm_node_t *) cast->right, visitor, data);

            break;
        }
        case PM_FLIP_FLOP_NODE: {
            const pm_flip_flop_node_t *cast = (const pm_flip_flop_node_t *) node;

            // Visit the left field
            if (cast->left != NULL) {
                pm_visit_node((const pm_node_t *) cast->left, visitor, data);
            }

            // Visit the right field
            if (cast->right != NULL) {
                pm_visit_node((const pm_node_t *) cast->right, visitor, data);
            }

            break;
        }
        case PM_FLOAT_NODE:
            break;
        case PM_FOR_NODE: {
            const pm_for_node_t *cast = (const pm_for_node_t *) node;

            // Visit the index field
            pm_visit_node((const pm_node_t *) cast->index, visitor, data);

            // Visit the collection field
            pm_visit_node((const pm_node_t *) cast->collection, visitor, data);

            // Visit the statements field
            if (cast->statements != NULL) {
                pm_visit_node((const pm_node_t *) cast->statements, visitor, data);
            }

            break;
        }
        case PM_FORWARDING_ARGUMENTS_NODE:
            break;
        case PM_FORWARDING_PARAMETER_NODE:
            break;
        case PM_FORWARDING_SUPER_NODE: {
            const pm_forwarding_super_node_t *cast = (const pm_forwarding_super_node_t *) node;

            // Visit the block field
            if (cast->block != NULL) {
                pm_visit_node((const pm_node_t *) cast->block, visitor, data);
            }

            break;
        }
        case PM_GLOBAL_VARIABLE_AND_WRITE_NODE: {
            const pm_global_variable_and_write_node_t *cast = (const pm_global_variable_and_write_node_t *) node;

            // Visit the value field
            pm_visit_node((const pm_node_t *) cast->value, visitor, data);

            break;
        }
        case PM_GLOBAL_VARIABLE_OPERATOR_WRITE_NODE: {
            const pm_global_variable_operator_write_node_t *cast = (const pm_global_variable_operator_write_node_t *) node;

            // Visit the value field
            pm_visit_node((const pm_node_t *) cast->value, visitor, data);

            break;
        }
        case PM_GLOBAL_VARIABLE_OR_WRITE_NODE: {
            const pm_global_variable_or_write_node_t *cast = (const pm_global_variable_or_write_node_t *) node;

            // Visit the value field
            pm_visit_node((const pm_node_t *) cast->value, visitor, data);

            break;
        }
        case PM_GLOBAL_VARIABLE_READ_NODE:
            break;
        case PM_GLOBAL_VARIABLE_TARGET_NODE:
            break;
        case PM_GLOBAL_VARIABLE_WRITE_NODE: {
            const pm_global_variable_write_node_t *cast = (const pm_global_variable_write_node_t *) node;

            // Visit the value field
            pm_visit_node((const pm_node_t *) cast->value, visitor, data);

            break;
        }
        case PM_HASH_NODE: {
            const pm_hash_node_t *cast = (const pm_hash_node_t *) node;

            // Visit the elements field
            const pm_node_list_t *elements = &cast->elements;
            for (size_t index = 0; index < elements->size; index++) {
                pm_visit_node(elements->nodes[index], visitor, data);
            }

            break;
        }
        case PM_HASH_PATTERN_NODE: {
            const pm_hash_pattern_node_t *cast = (const pm_hash_pattern_node_t *) node;

            // Visit the constant field
            if (cast->constant != NULL) {
                pm_visit_node((const pm_node_t *) cast->constant, visitor, data);
            }

            // Visit the elements field
            const pm_node_list_t *elements = &cast->elements;
            for (size_t index = 0; index < elements->size; index++) {
                pm_visit_node(elements->nodes[index], visitor, data);
            }

            // Visit the rest field
            if (cast->rest != NULL) {
                pm_visit_node((const pm_node_t *) cast->rest, visitor, data);
            }

            break;
        }
        case PM_IF_NODE: {
            const pm_if_node_t *cast = (const pm_if_node_t *) node;

            // Visit the predicate field
            pm_visit_node((const pm_node_t *) cast->predicate, visitor, data);

            // Visit the statements field
            if (cast->statements != NULL) {
                pm_visit_node((const pm_node_t *) cast->statements, visitor, data);
            }

            // Visit the subsequent field
            if (cast->subsequent != NULL) {
                pm_visit_node((const pm_node_t *) cast->subsequent, visitor, data);
            }

            break;
        }
        case PM_IMAGINARY_NODE: {
            const pm_imaginary_node_t *cast = (const pm_imaginary_node_t *) node;

            // Visit the numeric field
            pm_visit_node((const pm_node_t *) cast->numeric, visitor, data);

            break;
        }
        case PM_IMPLICIT_NODE: {
            const pm_implicit_node_t *cast = (const pm_implicit_node_t *) node;

            // Visit the value field
            pm_visit_node((const pm_node_t *) cast->value, visitor, data);

            break;
        }
        case PM_IMPLICIT_REST_NODE:
            break;
        case PM_IN_NODE: {
            const pm_in_node_t *cast = (const pm_in_node_t *) node;

            // Visit the pattern field
            pm_visit_node((const pm_node_t *) cast->pattern, visitor, data);

            // Visit the statements field
            if (cast->statements != NULL) {
                pm_visit_node((const pm_node_t *) cast->statements, visitor, data);
            }

            break;
        }
        case PM_INDEX_AND_WRITE_NODE: {
            const pm_index_and_write_node_t *cast = (const pm_index_and_write_node_t *) node;

            // Visit the receiver field
            if (cast->receiver != NULL) {
                pm_visit_node((const pm_node_t *) cast->receiver, visitor, data);
            }

            // Visit the arguments field
            if (cast->arguments != NULL) {
                pm_visit_node((const pm_node_t *) cast->arguments, visitor, data);
            }

            // Visit the block field
            if (cast->block != NULL) {
                pm_visit_node((const pm_node_t *) cast->block, visitor, data);
            }

            // Visit the value field
            pm_visit_node((const pm_node_t *) cast->value, visitor, data);

            break;
        }
        case PM_INDEX_OPERATOR_WRITE_NODE: {
            const pm_index_operator_write_node_t *cast = (const pm_index_operator_write_node_t *) node;

            // Visit the receiver field
            if (cast->receiver != NULL) {
                pm_visit_node((const pm_node_t *) cast->receiver, visitor, data);
            }

            // Visit the arguments field
            if (cast->arguments != NULL) {
                pm_visit_node((const pm_node_t *) cast->arguments, visitor, data);
            }

            // Visit the block field
            if (cast->block != NULL) {
                pm_visit_node((const pm_node_t *) cast->block, visitor, data);
            }

            // Visit the value field
            pm_visit_node((const pm_node_t *) cast->value, visitor, data);

            break;
        }
        case PM_INDEX_OR_WRITE_NODE: {
            const pm_index_or_write_node_t *cast = (const pm_index_or_write_node_t *) node;

            // Visit the receiver field
            if (cast->receiver != NULL) {
                pm_visit_node((const pm_node_t *) cast->receiver, visitor, data);
            }

            // Visit the arguments field
            if (cast->arguments != NULL) {
                pm_visit_node((const pm_node_t *) cast->arguments, visitor, data);
            }

            // Visit the block field
            if (cast->block != NULL) {
                pm_visit_node((const pm_node_t *) cast->block, visitor, data);
            }

            // Visit the value field
            pm_visit_node((const pm_node_t *) cast->value, visitor, data);

            break;
        }
        case PM_INDEX_TARGET_NODE: {
            const pm_index_target_node_t *cast = (const pm_index_target_node_t *) node;

            // Visit the receiver field
            pm_visit_node((const pm_node_t *) cast->receiver, visitor, data);

            // Visit the arguments field
            if (cast->arguments != NULL) {
                pm_visit_node((const pm_node_t *) cast->arguments, visitor, data);
            }

            // Visit the block field
            if (cast->block != NULL) {
                pm_visit_node((const pm_node_t *) cast->block, visitor, data);
            }

            break;
        }
        case PM_INSTANCE_VARIABLE_AND_WRITE_NODE: {
            const pm_instance_variable_and_write_node_t *cast = (const pm_instance_variable_and_write_node_t *) node;

            // Visit the value field
            pm_visit_node((const pm_node_t *) cast->value, visitor, data);

            break;
        }
        case PM_INSTANCE_VARIABLE_OPERATOR_WRITE_NODE: {
            const pm_instance_variable_operator_write_node_t *cast = (const pm_instance_variable_operator_write_node_t *) node;

            // Visit the value field
            pm_visit_node((const pm_node_t *) cast->value, visitor, data);

            break;
        }
        case PM_INSTANCE_VARIABLE_OR_WRITE_NODE: {
            const pm_instance_variable_or_write_node_t *cast = (const pm_instance_variable_or_write_node_t *) node;

            // Visit the value field
            pm_visit_node((const pm_node_t *) cast->value, visitor, data);

            break;
        }
        case PM_INSTANCE_VARIABLE_READ_NODE:
            break;
        case PM_INSTANCE_VARIABLE_TARGET_NODE:
            break;
        case PM_INSTANCE_VARIABLE_WRITE_NODE: {
            const pm_instance_variable_write_node_t *cast = (const pm_instance_variable_write_node_t *) node;

            // Visit the value field
            pm_visit_node((const pm_node_t *) cast->value, visitor, data);

            break;
        }
        case PM_INTEGER_NODE:
            break;
        case PM_INTERPOLATED_MATCH_LAST_LINE_NODE: {
            const pm_interpolated_match_last_line_node_t *cast = (const pm_interpolated_match_last_line_node_t *) node;

            // Visit the parts field
            const pm_node_list_t *parts = &cast->parts;
            for (size_t index = 0; index < parts->size; index++) {
                pm_visit_node(parts->nodes[index], visitor, data);
            }

            break;
        }
        case PM_INTERPOLATED_REGULAR_EXPRESSION_NODE: {
            const pm_interpolated_regular_expression_node_t *cast = (const pm_interpolated_regular_expression_node_t *) node;

            // Visit the parts field
            const pm_node_list_t *parts = &cast->parts;
            for (size_t index = 0; index < parts->size; index++) {
                pm_visit_node(parts->nodes[index], visitor, data);
            }

            break;
        }
        case PM_INTERPOLATED_STRING_NODE: {
            const pm_interpolated_string_node_t *cast = (const pm_interpolated_string_node_t *) node;

            // Visit the parts field
            const pm_node_list_t *parts = &cast->parts;
            for (size_t index = 0; index < parts->size; index++) {
                pm_visit_node(parts->nodes[index], visitor, data);
            }

            break;
        }
        case PM_INTERPOLATED_SYMBOL_NODE: {
            const pm_interpolated_symbol_node_t *cast = (const pm_interpolated_symbol_node_t *) node;

            // Visit the parts field
            const pm_node_list_t *parts = &cast->parts;
            for (size_t index = 0; index < parts->size; index++) {
                pm_visit_node(parts->nodes[index], visitor, data);
            }

            break;
        }
        case PM_INTERPOLATED_X_STRING_NODE: {
            const pm_interpolated_x_string_node_t *cast = (const pm_interpolated_x_string_node_t *) node;

            // Visit the parts field
            const pm_node_list_t *parts = &cast->parts;
            for (size_t index = 0; index < parts->size; index++) {
                pm_visit_node(parts->nodes[index], visitor, data);
            }

            break;
        }
        case PM_IT_LOCAL_VARIABLE_READ_NODE:
            break;
        case PM_IT_PARAMETERS_NODE:
            break;
        case PM_KEYWORD_HASH_NODE: {
            const pm_keyword_hash_node_t *cast = (const pm_keyword_hash_node_t *) node;

            // Visit the elements field
            const pm_node_list_t *elements = &cast->elements;
            for (size_t index = 0; index < elements->size; index++) {
                pm_visit_node(elements->nodes[index], visitor, data);
            }

            break;
        }
        case PM_KEYWORD_REST_PARAMETER_NODE:
            break;
        case PM_LAMBDA_NODE: {
            const pm_lambda_node_t *cast = (const pm_lambda_node_t *) node;

            // Visit the parameters field
            if (cast->parameters != NULL) {
                pm_visit_node((const pm_node_t *) cast->parameters, visitor, data);
            }

            // Visit the body field
            if (cast->body != NULL) {
                pm_visit_node((const pm_node_t *) cast->body, visitor, data);
            }

            break;
        }
        case PM_LOCAL_VARIABLE_AND_WRITE_NODE: {
            const pm_local_variable_and_write_node_t *cast = (const pm_local_variable_and_write_node_t *) node;

            // Visit the value field
            pm_visit_node((const pm_node_t *) cast->value, visitor, data);

            break;
        }
        case PM_LOCAL_VARIABLE_OPERATOR_WRITE_NODE: {
            const pm_local_variable_operator_write_node_t *cast = (const pm_local_variable_operator_write_node_t *) node;

            // Visit the value field
            pm_visit_node((const pm_node_t *) cast->value, visitor, data);

            break;
        }
        case PM_LOCAL_VARIABLE_OR_WRITE_NODE: {
            const pm_local_variable_or_write_node_t *cast = (const pm_local_variable_or_write_node_t *) node;

            // Visit the value field
            pm_visit_node((const pm_node_t *) cast->value, visitor, data);

            break;
        }
        case PM_LOCAL_VARIABLE_READ_NODE:
            break;
        case PM_LOCAL_VARIABLE_TARGET_NODE:
            break;
        case PM_LOCAL_VARIABLE_WRITE_NODE: {
            const pm_local_variable_write_node_t *cast = (const pm_local_variable_write_node_t *) node;

            // Visit the value field
            pm_visit_node((const pm_node_t *) cast->value, visitor, data);

            break;
        }
        case PM_MATCH_LAST_LINE_NODE:
            break;
        case PM_MATCH_PREDICATE_NODE: {
            const pm_match_predicate_node_t *cast = (const pm_match_predicate_node_t *) node;

            // Visit the value field
            pm_visit_node((const pm_node_t *) cast->value, visitor, data);

            // Visit the pattern field
            pm_visit_node((const pm_node_t *) cast->pattern, visitor, data);

            break;
        }
        case PM_MATCH_REQUIRED_NODE: {
            const pm_match_required_node_t *cast = (const pm_match_required_node_t *) node;

            // Visit the value field
            pm_visit_node((const pm_node_t *) cast->value, visitor, data);

            // Visit the pattern field
            pm_visit_node((const pm_node_t *) cast->pattern, visitor, data);

            break;
        }
        case PM_MATCH_WRITE_NODE: {
            const pm_match_write_node_t *cast = (const pm_match_write_node_t *) node;

            // Visit the call field
            pm_visit_node((const pm_node_t *) cast->call, visitor, data);

            // Visit the targets field
            const pm_node_list_t *targets = &cast->targets;
            for (size_t index = 0; index < targets->size; index++) {
                pm_visit_node(targets->nodes[index], visitor, data);
            }

            break;
        }
        case PM_MISSING_NODE:
            break;
        case PM_MODULE_NODE: {
            const pm_module_node_t *cast = (const pm_module_node_t *) node;

            // Visit the constant_path field
            pm_visit_node((const pm_node_t *) cast->constant_path, visitor, data);

            // Visit the body field
            if (cast->body != NULL) {
                pm_visit_node((const pm_node_t *) cast->body, visitor, data);
            }

            break;
        }
        case PM_MULTI_TARGET_NODE: {
            const pm_multi_target_node_t *cast = (const pm_multi_target_node_t *) node;

            // Visit the lefts field
            const pm_node_list_t *lefts = &cast->lefts;
            for (size_t index = 0; index < lefts->size; index++) {
                pm_visit_node(lefts->nodes[index], visitor, data);
            }

            // Visit the rest field
            if (cast->rest != NULL) {
                pm_visit_node((const pm_node_t *) cast->rest, visitor, data);
            }

            // Visit the rights field
            const pm_node_list_t *rights = &cast->rights;
            for (size_t index = 0; index < rights->size; index++) {
                pm_visit_node(rights->nodes[index], visitor, data);
            }

            break;
        }
        case PM_MULTI_WRITE_NODE: {
            const pm_multi_write_node_t *cast = (const pm_multi_write_node_t *) node;

            // Visit the lefts field
            const pm_node_list_t *lefts = &cast->lefts;
            for (size_t index = 0; index < lefts->size; index++) {
                pm_visit_node(lefts->nodes[index], visitor, data);
            }

            // Visit the rest field
            if (cast->rest != NULL) {
                pm_visit_node((const pm_node_t *) cast->rest, visitor, data);
            }

            // Visit the rights field
            const pm_node_list_t *rights = &cast->rights;
            for (size_t index = 0; index < rights->size; index++) {
                pm_visit_node(rights->nodes[index], visitor, data);
            }

            // Visit the value field
            pm_visit_node((const pm_node_t *) cast->value, visitor, data);

            break;
        }
        case PM_NEXT_NODE: {
            const pm_next_node_t *cast = (const pm_next_node_t *) node;

            // Visit the arguments field
            if (cast->arguments != NULL) {
                pm_visit_node((const pm_node_t *) cast->arguments, visitor, data);
            }

            break;
        }
        case PM_NIL_NODE:
            break;
        case PM_NO_KEYWORDS_PARAMETER_NODE:
            break;
        case PM_NUMBERED_PARAMETERS_NODE:
            break;
        case PM_NUMBERED_REFERENCE_READ_NODE:
            break;
        case PM_OPTIONAL_KEYWORD_PARAMETER_NODE: {
            const pm_optional_keyword_parameter_node_t *cast = (const pm_optional_keyword_parameter_node_t *) node;

            // Visit the value field
            pm_visit_node((const pm_node_t *) cast->value, visitor, data);

            break;
        }
        case PM_OPTIONAL_PARAMETER_NODE: {
            const pm_optional_parameter_node_t *cast = (const pm_optional_parameter_node_t *) node;

            // Visit the value field
            pm_visit_node((const pm_node_t *) cast->value, visitor, data);

            break;
        }
        case PM_OR_NODE: {
            const pm_or_node_t *cast = (const pm_or_node_t *) node;

            // Visit the left field
            pm_visit_node((const pm_node_t *) cast->left, visitor, data);

            // Visit the right field
            pm_visit_node((const pm_node_t *) cast->right, visitor, data);

            break;
        }
        case PM_PARAMETERS_NODE: {
            const pm_parameters_node_t *cast = (const pm_parameters_node_t *) node;

            // Visit the requireds field
            const pm_node_list_t *requireds = &cast->requireds;
            for (size_t index = 0; index < requireds->size; index++) {
                pm_visit_node(requireds->nodes[index], visitor, data);
            }

            // Visit the optionals field
            const pm_node_list_t *optionals = &cast->optionals;
            for (size_t index = 0; index < optionals->size; index++) {
                pm_visit_node(optionals->nodes[index], visitor, data);
            }

            // Visit the rest field
            if (cast->rest != NULL) {
                pm_visit_node((const pm_node_t *) cast->rest, visitor, data);
            }

            // Visit the posts field
            const pm_node_list_t *posts = &cast->posts;
            for (size_t index = 0; index < posts->size; index++) {
                pm_visit_node(posts->nodes[index], visitor, data);
            }

            // Visit the keywords field
            const pm_node_list_t *keywords = &cast->keywords;
            for (size_t index = 0; index < keywords->size; index++) {
                pm_visit_node(keywords->nodes[index], visitor, data);
            }

            // Visit the keyword_rest field
            if (cast->keyword_rest != NULL) {
                pm_visit_node((const pm_node_t *) cast->keyword_rest, visitor, data);
            }

            // Visit the block field
            if (cast->block != NULL) {
                pm_visit_node((const pm_node_t *) cast->block, visitor, data);
            }

            break;
        }
        case PM_PARENTHESES_NODE: {
            const pm_parentheses_node_t *cast = (const pm_parentheses_node_t *) node;

            // Visit the body field
            if (cast->body != NULL) {
                pm_visit_node((const pm_node_t *) cast->body, visitor, data);
            }

            break;
        }
        case PM_PINNED_EXPRESSION_NODE: {
            const pm_pinned_expression_node_t *cast = (const pm_pinned_expression_node_t *) node;

            // Visit the expression field
            pm_visit_node((const pm_node_t *) cast->expression, visitor, data);

            break;
        }
        case PM_PINNED_VARIABLE_NODE: {
            const pm_pinned_variable_node_t *cast = (const pm_pinned_variable_node_t *) node;

            // Visit the variable field
            pm_visit_node((const pm_node_t *) cast->variable, visitor, data);

            break;
        }
        case PM_POST_EXECUTION_NODE: {
            const pm_post_execution_node_t *cast = (const pm_post_execution_node_t *) node;

            // Visit the statements field
            if (cast->statements != NULL) {
                pm_visit_node((const pm_node_t *) cast->statements, visitor, data);
            }

            break;
        }
        case PM_PRE_EXECUTION_NODE: {
            const pm_pre_execution_node_t *cast = (const pm_pre_execution_node_t *) node;

            // Visit the statements field
            if (cast->statements != NULL) {
                pm_visit_node((const pm_node_t *) cast->statements, visitor, data);
            }

            break;
        }
        case PM_PROGRAM_NODE: {
            const pm_program_node_t *cast = (const pm_program_node_t *) node;

            // Visit the statements field
            pm_visit_node((const pm_node_t *) cast->statements, visitor, data);

            break;
        }
        case PM_RANGE_NODE: {
            const pm_range_node_t *cast = (const pm_range_node_t *) node;

            // Visit the left field
            if (cast->left != NULL) {
                pm_visit_node((const pm_node_t *) cast->left, visitor, data);
            }

            // Visit the right field
            if (cast->right != NULL) {
                pm_visit_node((const pm_node_t *) cast->right, visitor, data);
            }

            break;
        }
        case PM_RATIONAL_NODE:
            break;
        case PM_REDO_NODE:
            break;
        case PM_REGULAR_EXPRESSION_NODE:
            break;
        case PM_REQUIRED_KEYWORD_PARAMETER_NODE:
            break;
        case PM_REQUIRED_PARAMETER_NODE:
            break;
        case PM_RESCUE_MODIFIER_NODE: {
            const pm_rescue_modifier_node_t *cast = (const pm_rescue_modifier_node_t *) node;

            // Visit the expression field
            pm_visit_node((const pm_node_t *) cast->expression, visitor, data);

            // Visit the rescue_expression field
            pm_visit_node((const pm_node_t *) cast->rescue_expression, visitor, data);

            break;
        }
        case PM_RESCUE_NODE: {
            const pm_rescue_node_t *cast = (const pm_rescue_node_t *) node;

            // Visit the exceptions field
            const pm_node_list_t *exceptions = &cast->exceptions;
            for (size_t index = 0; index < exceptions->size; index++) {
                pm_visit_node(exceptions->nodes[index], visitor, data);
            }

            // Visit the reference field
            if (cast->reference != NULL) {
                pm_visit_node((const pm_node_t *) cast->reference, visitor, data);
            }

            // Visit the statements field
            if (cast->statements != NULL) {
                pm_visit_node((const pm_node_t *) cast->statements, visitor, data);
            }

            // Visit the subsequent field
            if (cast->subsequent != NULL) {
                pm_visit_node((const pm_node_t *) cast->subsequent, visitor, data);
            }

            break;
        }
        case PM_REST_PARAMETER_NODE:
            break;
        case PM_RETRY_NODE:
            break;
        case PM_RETURN_NODE: {
            const pm_return_node_t *cast = (const pm_return_node_t *) node;

            // Visit the arguments field
            if (cast->arguments != NULL) {
                pm_visit_node((const pm_node_t *) cast->arguments, visitor, data);
            }

            break;
        }
        case PM_SELF_NODE:
            break;
        case PM_SHAREABLE_CONSTANT_NODE: {
            const pm_shareable_constant_node_t *cast = (const pm_shareable_constant_node_t *) node;

            // Visit the write field
            pm_visit_node((const pm_node_t *) cast->write, visitor, data);

            break;
        }
        case PM_SINGLETON_CLASS_NODE: {
            const pm_singleton_class_node_t *cast = (const pm_singleton_class_node_t *) node;

            // Visit the expression field
            pm_visit_node((const pm_node_t *) cast->expression, visitor, data);

            // Visit the body field
            if (cast->body != NULL) {
                pm_visit_node((const pm_node_t *) cast->body, visitor, data);
            }

            break;
        }
        case PM_SOURCE_ENCODING_NODE:
            break;
        case PM_SOURCE_FILE_NODE:
            break;
        case PM_SOURCE_LINE_NODE:
            break;
        case PM_SPLAT_NODE: {
            const pm_splat_node_t *cast = (const pm_splat_node_t *) node;

            // Visit the expression field
            if (cast->expression != NULL) {
                pm_visit_node((const pm_node_t *) cast->expression, visitor, data);
            }

            break;
        }
        case PM_STATEMENTS_NODE: {
            const pm_statements_node_t *cast = (const pm_statements_node_t *) node;

            // Visit the body field
            const pm_node_list_t *body = &cast->body;
            for (size_t index = 0; index < body->size; index++) {
                pm_visit_node(body->nodes[index], visitor, data);
            }

            break;
        }
        case PM_STRING_NODE:
            break;
        case PM_SUPER_NODE: {
            const pm_super_node_t *cast = (const pm_super_node_t *) node;

            // Visit the arguments field
            if (cast->arguments != NULL) {
                pm_visit_node((const pm_node_t *) cast->arguments, visitor, data);
            }

            // Visit the block field
            if (cast->block != NULL) {
                pm_visit_node((const pm_node_t *) cast->block, visitor, data);
            }

            break;
        }
        case PM_SYMBOL_NODE:
            break;
        case PM_TRUE_NODE:
            break;
        case PM_UNDEF_NODE: {
            const pm_undef_node_t *cast = (const pm_undef_node_t *) node;

            // Visit the names field
            const pm_node_list_t *names = &cast->names;
            for (size_t index = 0; index < names->size; index++) {
                pm_visit_node(names->nodes[index], visitor, data);
            }

            break;
        }
        case PM_UNLESS_NODE: {
            const pm_unless_node_t *cast = (const pm_unless_node_t *) node;

            // Visit the predicate field
            pm_visit_node((const pm_node_t *) cast->predicate, visitor, data);

            // Visit the statements field
            if (cast->statements != NULL) {
                pm_visit_node((const pm_node_t *) cast->statements, visitor, data);
            }

            // Visit the else_clause field
            if (cast->else_clause != NULL) {
                pm_visit_node((const pm_node_t *) cast->else_clause, visitor, data);
            }

            break;
        }
        case PM_UNTIL_NODE: {
            const pm_until_node_t *cast = (const pm_until_node_t *) node;

            // Visit the predicate field
            pm_visit_node((const pm_node_t *) cast->predicate, visitor, data);

            // Visit the statements field
            if (cast->statements != NULL) {
                pm_visit_node((const pm_node_t *) cast->statements, visitor, data);
            }

            break;
        }
        case PM_WHEN_NODE: {
            const pm_when_node_t *cast = (const pm_when_node_t *) node;

            // Visit the conditions field
            const pm_node_list_t *conditions = &cast->conditions;
            for (size_t index = 0; index < conditions->size; index++) {
                pm_visit_node(conditions->nodes[index], visitor, data);
            }

            // Visit the statements field
            if (cast->statements != NULL) {
                pm_visit_node((const pm_node_t *) cast->statements, visitor, data);
            }

            break;
        }
        case PM_WHILE_NODE: {
            const pm_while_node_t *cast = (const pm_while_node_t *) node;

            // Visit the predicate field
            pm_visit_node((const pm_node_t *) cast->predicate, visitor, data);

            // Visit the statements field
            if (cast->statements != NULL) {
                pm_visit_node((const pm_node_t *) cast->statements, visitor, data);
            }

            break;
        }
        case PM_X_STRING_NODE:
            break;
        case PM_YIELD_NODE: {
            const pm_yield_node_t *cast = (const pm_yield_node_t *) node;

            // Visit the arguments field
            if (cast->arguments != NULL) {
                pm_visit_node((const pm_node_t *) cast->arguments, visitor, data);
            }

            break;
        }
        case PM_SCOPE_NODE:
            break;
    }
}

// We optionally support dumping to JSON. For systems that don't want or need
// this functionality, it can be turned off with the PRISM_EXCLUDE_JSON define.
#ifndef PRISM_EXCLUDE_JSON

static void
pm_dump_json_constant(pm_buffer_t *buffer, const pm_parser_t *parser, pm_constant_id_t constant_id) {
    const pm_constant_t *constant = pm_constant_pool_id_to_constant(&parser->constant_pool, constant_id);
    pm_buffer_append_byte(buffer, '"');
    pm_buffer_append_source(buffer, constant->start, constant->length, PM_BUFFER_ESCAPING_JSON);
    pm_buffer_append_byte(buffer, '"');
}

static void
pm_dump_json_location(pm_buffer_t *buffer, const pm_parser_t *parser, const pm_location_t *location) {
    uint32_t start = (uint32_t) (location->start - parser->start);
    uint32_t end = (uint32_t) (location->end - parser->start);
    pm_buffer_append_format(buffer, "{\"start\":%" PRIu32 ",\"end\":%" PRIu32 "}", start, end);
}

/**
 * Dump JSON to the given buffer.
 */
PRISM_EXPORTED_FUNCTION void
pm_dump_json(pm_buffer_t *buffer, const pm_parser_t *parser, const pm_node_t *node) {
    switch (PM_NODE_TYPE(node)) {
        case PM_ALIAS_GLOBAL_VARIABLE_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"AliasGlobalVariableNode\",\"location\":", 45);

            const pm_alias_global_variable_node_t *cast = (const pm_alias_global_variable_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the new_name field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"new_name\":", 11);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->new_name);

            // Dump the old_name field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"old_name\":", 11);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->old_name);

            // Dump the keyword_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"keyword_loc\":", 14);
            pm_dump_json_location(buffer, parser, &cast->keyword_loc);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_ALIAS_METHOD_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"AliasMethodNode\",\"location\":", 37);

            const pm_alias_method_node_t *cast = (const pm_alias_method_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the new_name field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"new_name\":", 11);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->new_name);

            // Dump the old_name field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"old_name\":", 11);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->old_name);

            // Dump the keyword_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"keyword_loc\":", 14);
            pm_dump_json_location(buffer, parser, &cast->keyword_loc);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_ALTERNATION_PATTERN_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"AlternationPatternNode\",\"location\":", 44);

            const pm_alternation_pattern_node_t *cast = (const pm_alternation_pattern_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the left field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"left\":", 7);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->left);

            // Dump the right field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"right\":", 8);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->right);

            // Dump the operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"operator_loc\":", 15);
            pm_dump_json_location(buffer, parser, &cast->operator_loc);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_AND_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"AndNode\",\"location\":", 29);

            const pm_and_node_t *cast = (const pm_and_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the left field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"left\":", 7);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->left);

            // Dump the right field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"right\":", 8);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->right);

            // Dump the operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"operator_loc\":", 15);
            pm_dump_json_location(buffer, parser, &cast->operator_loc);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_ARGUMENTS_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"ArgumentsNode\",\"location\":", 35);

            const pm_arguments_node_t *cast = (const pm_arguments_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the ArgumentsNodeFlags field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"ArgumentsNodeFlags\":", 21);
            size_t flags = 0;
            pm_buffer_append_byte(buffer, '[');
            if (PM_NODE_FLAG_P(cast, PM_ARGUMENTS_NODE_FLAGS_CONTAINS_FORWARDING)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"CONTAINS_FORWARDING\"", 21);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_ARGUMENTS_NODE_FLAGS_CONTAINS_KEYWORDS)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"CONTAINS_KEYWORDS\"", 19);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_ARGUMENTS_NODE_FLAGS_CONTAINS_KEYWORD_SPLAT)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"CONTAINS_KEYWORD_SPLAT\"", 24);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_ARGUMENTS_NODE_FLAGS_CONTAINS_SPLAT)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"CONTAINS_SPLAT\"", 16);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_ARGUMENTS_NODE_FLAGS_CONTAINS_MULTIPLE_SPLATS)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"CONTAINS_MULTIPLE_SPLATS\"", 26);
                flags++;
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the arguments field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"arguments\":", 12);
            const pm_node_list_t *arguments = &cast->arguments;
            pm_buffer_append_byte(buffer, '[');

            for (size_t index = 0; index < arguments->size; index++) {
                if (index != 0) pm_buffer_append_byte(buffer, ',');
                pm_dump_json(buffer, parser, arguments->nodes[index]);
            }
            pm_buffer_append_byte(buffer, ']');

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_ARRAY_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"ArrayNode\",\"location\":", 31);

            const pm_array_node_t *cast = (const pm_array_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the ArrayNodeFlags field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"ArrayNodeFlags\":", 17);
            size_t flags = 0;
            pm_buffer_append_byte(buffer, '[');
            if (PM_NODE_FLAG_P(cast, PM_ARRAY_NODE_FLAGS_CONTAINS_SPLAT)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"CONTAINS_SPLAT\"", 16);
                flags++;
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the elements field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"elements\":", 11);
            const pm_node_list_t *elements = &cast->elements;
            pm_buffer_append_byte(buffer, '[');

            for (size_t index = 0; index < elements->size; index++) {
                if (index != 0) pm_buffer_append_byte(buffer, ',');
                pm_dump_json(buffer, parser, elements->nodes[index]);
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the opening_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"opening_loc\":", 14);
            if (cast->opening_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->opening_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the closing_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"closing_loc\":", 14);
            if (cast->closing_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->closing_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_ARRAY_PATTERN_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"ArrayPatternNode\",\"location\":", 38);

            const pm_array_pattern_node_t *cast = (const pm_array_pattern_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the constant field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"constant\":", 11);
            if (cast->constant != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->constant);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the requireds field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"requireds\":", 12);
            const pm_node_list_t *requireds = &cast->requireds;
            pm_buffer_append_byte(buffer, '[');

            for (size_t index = 0; index < requireds->size; index++) {
                if (index != 0) pm_buffer_append_byte(buffer, ',');
                pm_dump_json(buffer, parser, requireds->nodes[index]);
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the rest field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"rest\":", 7);
            if (cast->rest != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->rest);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the posts field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"posts\":", 8);
            const pm_node_list_t *posts = &cast->posts;
            pm_buffer_append_byte(buffer, '[');

            for (size_t index = 0; index < posts->size; index++) {
                if (index != 0) pm_buffer_append_byte(buffer, ',');
                pm_dump_json(buffer, parser, posts->nodes[index]);
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the opening_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"opening_loc\":", 14);
            if (cast->opening_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->opening_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the closing_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"closing_loc\":", 14);
            if (cast->closing_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->closing_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_ASSOC_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"AssocNode\",\"location\":", 31);

            const pm_assoc_node_t *cast = (const pm_assoc_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the key field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"key\":", 6);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->key);

            // Dump the value field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"value\":", 8);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->value);

            // Dump the operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"operator_loc\":", 15);
            if (cast->operator_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->operator_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_ASSOC_SPLAT_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"AssocSplatNode\",\"location\":", 36);

            const pm_assoc_splat_node_t *cast = (const pm_assoc_splat_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the value field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"value\":", 8);
            if (cast->value != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->value);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"operator_loc\":", 15);
            pm_dump_json_location(buffer, parser, &cast->operator_loc);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_BACK_REFERENCE_READ_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"BackReferenceReadNode\",\"location\":", 43);

            const pm_back_reference_read_node_t *cast = (const pm_back_reference_read_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the name field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name\":", 7);
            pm_dump_json_constant(buffer, parser, cast->name);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_BEGIN_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"BeginNode\",\"location\":", 31);

            const pm_begin_node_t *cast = (const pm_begin_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the begin_keyword_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"begin_keyword_loc\":", 20);
            if (cast->begin_keyword_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->begin_keyword_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the statements field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"statements\":", 13);
            if (cast->statements != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->statements);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the rescue_clause field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"rescue_clause\":", 16);
            if (cast->rescue_clause != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->rescue_clause);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the else_clause field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"else_clause\":", 14);
            if (cast->else_clause != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->else_clause);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the ensure_clause field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"ensure_clause\":", 16);
            if (cast->ensure_clause != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->ensure_clause);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the end_keyword_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"end_keyword_loc\":", 18);
            if (cast->end_keyword_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->end_keyword_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_BLOCK_ARGUMENT_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"BlockArgumentNode\",\"location\":", 39);

            const pm_block_argument_node_t *cast = (const pm_block_argument_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the expression field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"expression\":", 13);
            if (cast->expression != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->expression);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"operator_loc\":", 15);
            pm_dump_json_location(buffer, parser, &cast->operator_loc);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_BLOCK_LOCAL_VARIABLE_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"BlockLocalVariableNode\",\"location\":", 44);

            const pm_block_local_variable_node_t *cast = (const pm_block_local_variable_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the ParameterFlags field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"ParameterFlags\":", 17);
            size_t flags = 0;
            pm_buffer_append_byte(buffer, '[');
            if (PM_NODE_FLAG_P(cast, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"REPEATED_PARAMETER\"", 20);
                flags++;
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the name field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name\":", 7);
            pm_dump_json_constant(buffer, parser, cast->name);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_BLOCK_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"BlockNode\",\"location\":", 31);

            const pm_block_node_t *cast = (const pm_block_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the locals field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"locals\":", 9);
            const pm_constant_id_list_t *locals = &cast->locals;
            pm_buffer_append_byte(buffer, '[');

            for (size_t index = 0; index < locals->size; index++) {
                if (index != 0) pm_buffer_append_byte(buffer, ',');
                pm_dump_json_constant(buffer, parser, locals->ids[index]);
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the parameters field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"parameters\":", 13);
            if (cast->parameters != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->parameters);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the body field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"body\":", 7);
            if (cast->body != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->body);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the opening_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"opening_loc\":", 14);
            pm_dump_json_location(buffer, parser, &cast->opening_loc);

            // Dump the closing_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"closing_loc\":", 14);
            pm_dump_json_location(buffer, parser, &cast->closing_loc);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_BLOCK_PARAMETER_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"BlockParameterNode\",\"location\":", 40);

            const pm_block_parameter_node_t *cast = (const pm_block_parameter_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the ParameterFlags field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"ParameterFlags\":", 17);
            size_t flags = 0;
            pm_buffer_append_byte(buffer, '[');
            if (PM_NODE_FLAG_P(cast, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"REPEATED_PARAMETER\"", 20);
                flags++;
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the name field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name\":", 7);
            if (cast->name != PM_CONSTANT_ID_UNSET) {
                pm_dump_json_constant(buffer, parser, cast->name);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the name_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name_loc\":", 11);
            if (cast->name_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->name_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"operator_loc\":", 15);
            pm_dump_json_location(buffer, parser, &cast->operator_loc);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_BLOCK_PARAMETERS_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"BlockParametersNode\",\"location\":", 41);

            const pm_block_parameters_node_t *cast = (const pm_block_parameters_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the parameters field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"parameters\":", 13);
            if (cast->parameters != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->parameters);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the locals field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"locals\":", 9);
            const pm_node_list_t *locals = &cast->locals;
            pm_buffer_append_byte(buffer, '[');

            for (size_t index = 0; index < locals->size; index++) {
                if (index != 0) pm_buffer_append_byte(buffer, ',');
                pm_dump_json(buffer, parser, locals->nodes[index]);
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the opening_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"opening_loc\":", 14);
            if (cast->opening_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->opening_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the closing_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"closing_loc\":", 14);
            if (cast->closing_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->closing_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_BREAK_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"BreakNode\",\"location\":", 31);

            const pm_break_node_t *cast = (const pm_break_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the arguments field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"arguments\":", 12);
            if (cast->arguments != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->arguments);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the keyword_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"keyword_loc\":", 14);
            pm_dump_json_location(buffer, parser, &cast->keyword_loc);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_CALL_AND_WRITE_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"CallAndWriteNode\",\"location\":", 38);

            const pm_call_and_write_node_t *cast = (const pm_call_and_write_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the CallNodeFlags field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"CallNodeFlags\":", 16);
            size_t flags = 0;
            pm_buffer_append_byte(buffer, '[');
            if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_SAFE_NAVIGATION)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"SAFE_NAVIGATION\"", 17);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_VARIABLE_CALL)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"VARIABLE_CALL\"", 15);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"ATTRIBUTE_WRITE\"", 17);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_IGNORE_VISIBILITY)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"IGNORE_VISIBILITY\"", 19);
                flags++;
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the receiver field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"receiver\":", 11);
            if (cast->receiver != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->receiver);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the call_operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"call_operator_loc\":", 20);
            if (cast->call_operator_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->call_operator_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the message_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"message_loc\":", 14);
            if (cast->message_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->message_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the read_name field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"read_name\":", 12);
            pm_dump_json_constant(buffer, parser, cast->read_name);

            // Dump the write_name field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"write_name\":", 13);
            pm_dump_json_constant(buffer, parser, cast->write_name);

            // Dump the operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"operator_loc\":", 15);
            pm_dump_json_location(buffer, parser, &cast->operator_loc);

            // Dump the value field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"value\":", 8);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->value);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_CALL_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"CallNode\",\"location\":", 30);

            const pm_call_node_t *cast = (const pm_call_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the CallNodeFlags field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"CallNodeFlags\":", 16);
            size_t flags = 0;
            pm_buffer_append_byte(buffer, '[');
            if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_SAFE_NAVIGATION)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"SAFE_NAVIGATION\"", 17);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_VARIABLE_CALL)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"VARIABLE_CALL\"", 15);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"ATTRIBUTE_WRITE\"", 17);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_IGNORE_VISIBILITY)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"IGNORE_VISIBILITY\"", 19);
                flags++;
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the receiver field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"receiver\":", 11);
            if (cast->receiver != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->receiver);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the call_operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"call_operator_loc\":", 20);
            if (cast->call_operator_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->call_operator_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the name field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name\":", 7);
            pm_dump_json_constant(buffer, parser, cast->name);

            // Dump the message_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"message_loc\":", 14);
            if (cast->message_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->message_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the opening_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"opening_loc\":", 14);
            if (cast->opening_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->opening_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the arguments field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"arguments\":", 12);
            if (cast->arguments != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->arguments);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the closing_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"closing_loc\":", 14);
            if (cast->closing_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->closing_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the block field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"block\":", 8);
            if (cast->block != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->block);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_CALL_OPERATOR_WRITE_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"CallOperatorWriteNode\",\"location\":", 43);

            const pm_call_operator_write_node_t *cast = (const pm_call_operator_write_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the CallNodeFlags field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"CallNodeFlags\":", 16);
            size_t flags = 0;
            pm_buffer_append_byte(buffer, '[');
            if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_SAFE_NAVIGATION)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"SAFE_NAVIGATION\"", 17);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_VARIABLE_CALL)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"VARIABLE_CALL\"", 15);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"ATTRIBUTE_WRITE\"", 17);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_IGNORE_VISIBILITY)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"IGNORE_VISIBILITY\"", 19);
                flags++;
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the receiver field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"receiver\":", 11);
            if (cast->receiver != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->receiver);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the call_operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"call_operator_loc\":", 20);
            if (cast->call_operator_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->call_operator_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the message_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"message_loc\":", 14);
            if (cast->message_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->message_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the read_name field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"read_name\":", 12);
            pm_dump_json_constant(buffer, parser, cast->read_name);

            // Dump the write_name field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"write_name\":", 13);
            pm_dump_json_constant(buffer, parser, cast->write_name);

            // Dump the binary_operator field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"binary_operator\":", 18);
            pm_dump_json_constant(buffer, parser, cast->binary_operator);

            // Dump the binary_operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"binary_operator_loc\":", 22);
            pm_dump_json_location(buffer, parser, &cast->binary_operator_loc);

            // Dump the value field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"value\":", 8);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->value);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_CALL_OR_WRITE_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"CallOrWriteNode\",\"location\":", 37);

            const pm_call_or_write_node_t *cast = (const pm_call_or_write_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the CallNodeFlags field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"CallNodeFlags\":", 16);
            size_t flags = 0;
            pm_buffer_append_byte(buffer, '[');
            if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_SAFE_NAVIGATION)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"SAFE_NAVIGATION\"", 17);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_VARIABLE_CALL)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"VARIABLE_CALL\"", 15);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"ATTRIBUTE_WRITE\"", 17);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_IGNORE_VISIBILITY)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"IGNORE_VISIBILITY\"", 19);
                flags++;
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the receiver field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"receiver\":", 11);
            if (cast->receiver != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->receiver);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the call_operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"call_operator_loc\":", 20);
            if (cast->call_operator_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->call_operator_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the message_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"message_loc\":", 14);
            if (cast->message_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->message_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the read_name field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"read_name\":", 12);
            pm_dump_json_constant(buffer, parser, cast->read_name);

            // Dump the write_name field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"write_name\":", 13);
            pm_dump_json_constant(buffer, parser, cast->write_name);

            // Dump the operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"operator_loc\":", 15);
            pm_dump_json_location(buffer, parser, &cast->operator_loc);

            // Dump the value field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"value\":", 8);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->value);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_CALL_TARGET_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"CallTargetNode\",\"location\":", 36);

            const pm_call_target_node_t *cast = (const pm_call_target_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the CallNodeFlags field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"CallNodeFlags\":", 16);
            size_t flags = 0;
            pm_buffer_append_byte(buffer, '[');
            if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_SAFE_NAVIGATION)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"SAFE_NAVIGATION\"", 17);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_VARIABLE_CALL)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"VARIABLE_CALL\"", 15);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"ATTRIBUTE_WRITE\"", 17);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_IGNORE_VISIBILITY)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"IGNORE_VISIBILITY\"", 19);
                flags++;
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the receiver field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"receiver\":", 11);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->receiver);

            // Dump the call_operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"call_operator_loc\":", 20);
            pm_dump_json_location(buffer, parser, &cast->call_operator_loc);

            // Dump the name field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name\":", 7);
            pm_dump_json_constant(buffer, parser, cast->name);

            // Dump the message_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"message_loc\":", 14);
            pm_dump_json_location(buffer, parser, &cast->message_loc);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_CAPTURE_PATTERN_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"CapturePatternNode\",\"location\":", 40);

            const pm_capture_pattern_node_t *cast = (const pm_capture_pattern_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the value field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"value\":", 8);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->value);

            // Dump the target field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"target\":", 9);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->target);

            // Dump the operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"operator_loc\":", 15);
            pm_dump_json_location(buffer, parser, &cast->operator_loc);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_CASE_MATCH_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"CaseMatchNode\",\"location\":", 35);

            const pm_case_match_node_t *cast = (const pm_case_match_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the predicate field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"predicate\":", 12);
            if (cast->predicate != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->predicate);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the conditions field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"conditions\":", 13);
            const pm_node_list_t *conditions = &cast->conditions;
            pm_buffer_append_byte(buffer, '[');

            for (size_t index = 0; index < conditions->size; index++) {
                if (index != 0) pm_buffer_append_byte(buffer, ',');
                pm_dump_json(buffer, parser, conditions->nodes[index]);
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the else_clause field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"else_clause\":", 14);
            if (cast->else_clause != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->else_clause);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the case_keyword_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"case_keyword_loc\":", 19);
            pm_dump_json_location(buffer, parser, &cast->case_keyword_loc);

            // Dump the end_keyword_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"end_keyword_loc\":", 18);
            pm_dump_json_location(buffer, parser, &cast->end_keyword_loc);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_CASE_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"CaseNode\",\"location\":", 30);

            const pm_case_node_t *cast = (const pm_case_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the predicate field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"predicate\":", 12);
            if (cast->predicate != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->predicate);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the conditions field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"conditions\":", 13);
            const pm_node_list_t *conditions = &cast->conditions;
            pm_buffer_append_byte(buffer, '[');

            for (size_t index = 0; index < conditions->size; index++) {
                if (index != 0) pm_buffer_append_byte(buffer, ',');
                pm_dump_json(buffer, parser, conditions->nodes[index]);
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the else_clause field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"else_clause\":", 14);
            if (cast->else_clause != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->else_clause);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the case_keyword_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"case_keyword_loc\":", 19);
            pm_dump_json_location(buffer, parser, &cast->case_keyword_loc);

            // Dump the end_keyword_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"end_keyword_loc\":", 18);
            pm_dump_json_location(buffer, parser, &cast->end_keyword_loc);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_CLASS_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"ClassNode\",\"location\":", 31);

            const pm_class_node_t *cast = (const pm_class_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the locals field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"locals\":", 9);
            const pm_constant_id_list_t *locals = &cast->locals;
            pm_buffer_append_byte(buffer, '[');

            for (size_t index = 0; index < locals->size; index++) {
                if (index != 0) pm_buffer_append_byte(buffer, ',');
                pm_dump_json_constant(buffer, parser, locals->ids[index]);
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the class_keyword_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"class_keyword_loc\":", 20);
            pm_dump_json_location(buffer, parser, &cast->class_keyword_loc);

            // Dump the constant_path field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"constant_path\":", 16);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->constant_path);

            // Dump the inheritance_operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"inheritance_operator_loc\":", 27);
            if (cast->inheritance_operator_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->inheritance_operator_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the superclass field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"superclass\":", 13);
            if (cast->superclass != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->superclass);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the body field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"body\":", 7);
            if (cast->body != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->body);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the end_keyword_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"end_keyword_loc\":", 18);
            pm_dump_json_location(buffer, parser, &cast->end_keyword_loc);

            // Dump the name field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name\":", 7);
            pm_dump_json_constant(buffer, parser, cast->name);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_CLASS_VARIABLE_AND_WRITE_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"ClassVariableAndWriteNode\",\"location\":", 47);

            const pm_class_variable_and_write_node_t *cast = (const pm_class_variable_and_write_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the name field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name\":", 7);
            pm_dump_json_constant(buffer, parser, cast->name);

            // Dump the name_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name_loc\":", 11);
            pm_dump_json_location(buffer, parser, &cast->name_loc);

            // Dump the operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"operator_loc\":", 15);
            pm_dump_json_location(buffer, parser, &cast->operator_loc);

            // Dump the value field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"value\":", 8);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->value);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_CLASS_VARIABLE_OPERATOR_WRITE_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"ClassVariableOperatorWriteNode\",\"location\":", 52);

            const pm_class_variable_operator_write_node_t *cast = (const pm_class_variable_operator_write_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the name field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name\":", 7);
            pm_dump_json_constant(buffer, parser, cast->name);

            // Dump the name_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name_loc\":", 11);
            pm_dump_json_location(buffer, parser, &cast->name_loc);

            // Dump the binary_operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"binary_operator_loc\":", 22);
            pm_dump_json_location(buffer, parser, &cast->binary_operator_loc);

            // Dump the value field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"value\":", 8);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->value);

            // Dump the binary_operator field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"binary_operator\":", 18);
            pm_dump_json_constant(buffer, parser, cast->binary_operator);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_CLASS_VARIABLE_OR_WRITE_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"ClassVariableOrWriteNode\",\"location\":", 46);

            const pm_class_variable_or_write_node_t *cast = (const pm_class_variable_or_write_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the name field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name\":", 7);
            pm_dump_json_constant(buffer, parser, cast->name);

            // Dump the name_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name_loc\":", 11);
            pm_dump_json_location(buffer, parser, &cast->name_loc);

            // Dump the operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"operator_loc\":", 15);
            pm_dump_json_location(buffer, parser, &cast->operator_loc);

            // Dump the value field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"value\":", 8);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->value);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_CLASS_VARIABLE_READ_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"ClassVariableReadNode\",\"location\":", 43);

            const pm_class_variable_read_node_t *cast = (const pm_class_variable_read_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the name field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name\":", 7);
            pm_dump_json_constant(buffer, parser, cast->name);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_CLASS_VARIABLE_TARGET_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"ClassVariableTargetNode\",\"location\":", 45);

            const pm_class_variable_target_node_t *cast = (const pm_class_variable_target_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the name field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name\":", 7);
            pm_dump_json_constant(buffer, parser, cast->name);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_CLASS_VARIABLE_WRITE_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"ClassVariableWriteNode\",\"location\":", 44);

            const pm_class_variable_write_node_t *cast = (const pm_class_variable_write_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the name field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name\":", 7);
            pm_dump_json_constant(buffer, parser, cast->name);

            // Dump the name_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name_loc\":", 11);
            pm_dump_json_location(buffer, parser, &cast->name_loc);

            // Dump the value field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"value\":", 8);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->value);

            // Dump the operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"operator_loc\":", 15);
            pm_dump_json_location(buffer, parser, &cast->operator_loc);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_CONSTANT_AND_WRITE_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"ConstantAndWriteNode\",\"location\":", 42);

            const pm_constant_and_write_node_t *cast = (const pm_constant_and_write_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the name field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name\":", 7);
            pm_dump_json_constant(buffer, parser, cast->name);

            // Dump the name_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name_loc\":", 11);
            pm_dump_json_location(buffer, parser, &cast->name_loc);

            // Dump the operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"operator_loc\":", 15);
            pm_dump_json_location(buffer, parser, &cast->operator_loc);

            // Dump the value field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"value\":", 8);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->value);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_CONSTANT_OPERATOR_WRITE_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"ConstantOperatorWriteNode\",\"location\":", 47);

            const pm_constant_operator_write_node_t *cast = (const pm_constant_operator_write_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the name field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name\":", 7);
            pm_dump_json_constant(buffer, parser, cast->name);

            // Dump the name_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name_loc\":", 11);
            pm_dump_json_location(buffer, parser, &cast->name_loc);

            // Dump the binary_operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"binary_operator_loc\":", 22);
            pm_dump_json_location(buffer, parser, &cast->binary_operator_loc);

            // Dump the value field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"value\":", 8);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->value);

            // Dump the binary_operator field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"binary_operator\":", 18);
            pm_dump_json_constant(buffer, parser, cast->binary_operator);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_CONSTANT_OR_WRITE_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"ConstantOrWriteNode\",\"location\":", 41);

            const pm_constant_or_write_node_t *cast = (const pm_constant_or_write_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the name field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name\":", 7);
            pm_dump_json_constant(buffer, parser, cast->name);

            // Dump the name_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name_loc\":", 11);
            pm_dump_json_location(buffer, parser, &cast->name_loc);

            // Dump the operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"operator_loc\":", 15);
            pm_dump_json_location(buffer, parser, &cast->operator_loc);

            // Dump the value field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"value\":", 8);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->value);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_CONSTANT_PATH_AND_WRITE_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"ConstantPathAndWriteNode\",\"location\":", 46);

            const pm_constant_path_and_write_node_t *cast = (const pm_constant_path_and_write_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the target field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"target\":", 9);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->target);

            // Dump the operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"operator_loc\":", 15);
            pm_dump_json_location(buffer, parser, &cast->operator_loc);

            // Dump the value field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"value\":", 8);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->value);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_CONSTANT_PATH_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"ConstantPathNode\",\"location\":", 38);

            const pm_constant_path_node_t *cast = (const pm_constant_path_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the parent field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"parent\":", 9);
            if (cast->parent != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->parent);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the name field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name\":", 7);
            if (cast->name != PM_CONSTANT_ID_UNSET) {
                pm_dump_json_constant(buffer, parser, cast->name);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the delimiter_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"delimiter_loc\":", 16);
            pm_dump_json_location(buffer, parser, &cast->delimiter_loc);

            // Dump the name_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name_loc\":", 11);
            pm_dump_json_location(buffer, parser, &cast->name_loc);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_CONSTANT_PATH_OPERATOR_WRITE_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"ConstantPathOperatorWriteNode\",\"location\":", 51);

            const pm_constant_path_operator_write_node_t *cast = (const pm_constant_path_operator_write_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the target field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"target\":", 9);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->target);

            // Dump the binary_operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"binary_operator_loc\":", 22);
            pm_dump_json_location(buffer, parser, &cast->binary_operator_loc);

            // Dump the value field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"value\":", 8);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->value);

            // Dump the binary_operator field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"binary_operator\":", 18);
            pm_dump_json_constant(buffer, parser, cast->binary_operator);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_CONSTANT_PATH_OR_WRITE_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"ConstantPathOrWriteNode\",\"location\":", 45);

            const pm_constant_path_or_write_node_t *cast = (const pm_constant_path_or_write_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the target field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"target\":", 9);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->target);

            // Dump the operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"operator_loc\":", 15);
            pm_dump_json_location(buffer, parser, &cast->operator_loc);

            // Dump the value field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"value\":", 8);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->value);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_CONSTANT_PATH_TARGET_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"ConstantPathTargetNode\",\"location\":", 44);

            const pm_constant_path_target_node_t *cast = (const pm_constant_path_target_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the parent field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"parent\":", 9);
            if (cast->parent != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->parent);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the name field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name\":", 7);
            if (cast->name != PM_CONSTANT_ID_UNSET) {
                pm_dump_json_constant(buffer, parser, cast->name);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the delimiter_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"delimiter_loc\":", 16);
            pm_dump_json_location(buffer, parser, &cast->delimiter_loc);

            // Dump the name_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name_loc\":", 11);
            pm_dump_json_location(buffer, parser, &cast->name_loc);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_CONSTANT_PATH_WRITE_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"ConstantPathWriteNode\",\"location\":", 43);

            const pm_constant_path_write_node_t *cast = (const pm_constant_path_write_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the target field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"target\":", 9);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->target);

            // Dump the operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"operator_loc\":", 15);
            pm_dump_json_location(buffer, parser, &cast->operator_loc);

            // Dump the value field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"value\":", 8);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->value);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_CONSTANT_READ_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"ConstantReadNode\",\"location\":", 38);

            const pm_constant_read_node_t *cast = (const pm_constant_read_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the name field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name\":", 7);
            pm_dump_json_constant(buffer, parser, cast->name);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_CONSTANT_TARGET_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"ConstantTargetNode\",\"location\":", 40);

            const pm_constant_target_node_t *cast = (const pm_constant_target_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the name field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name\":", 7);
            pm_dump_json_constant(buffer, parser, cast->name);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_CONSTANT_WRITE_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"ConstantWriteNode\",\"location\":", 39);

            const pm_constant_write_node_t *cast = (const pm_constant_write_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the name field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name\":", 7);
            pm_dump_json_constant(buffer, parser, cast->name);

            // Dump the name_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name_loc\":", 11);
            pm_dump_json_location(buffer, parser, &cast->name_loc);

            // Dump the value field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"value\":", 8);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->value);

            // Dump the operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"operator_loc\":", 15);
            pm_dump_json_location(buffer, parser, &cast->operator_loc);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_DEF_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"DefNode\",\"location\":", 29);

            const pm_def_node_t *cast = (const pm_def_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the name field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name\":", 7);
            pm_dump_json_constant(buffer, parser, cast->name);

            // Dump the name_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name_loc\":", 11);
            pm_dump_json_location(buffer, parser, &cast->name_loc);

            // Dump the receiver field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"receiver\":", 11);
            if (cast->receiver != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->receiver);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the parameters field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"parameters\":", 13);
            if (cast->parameters != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->parameters);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the body field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"body\":", 7);
            if (cast->body != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->body);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the locals field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"locals\":", 9);
            const pm_constant_id_list_t *locals = &cast->locals;
            pm_buffer_append_byte(buffer, '[');

            for (size_t index = 0; index < locals->size; index++) {
                if (index != 0) pm_buffer_append_byte(buffer, ',');
                pm_dump_json_constant(buffer, parser, locals->ids[index]);
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the def_keyword_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"def_keyword_loc\":", 18);
            pm_dump_json_location(buffer, parser, &cast->def_keyword_loc);

            // Dump the operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"operator_loc\":", 15);
            if (cast->operator_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->operator_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the lparen_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"lparen_loc\":", 13);
            if (cast->lparen_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->lparen_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the rparen_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"rparen_loc\":", 13);
            if (cast->rparen_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->rparen_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the equal_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"equal_loc\":", 12);
            if (cast->equal_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->equal_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the end_keyword_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"end_keyword_loc\":", 18);
            if (cast->end_keyword_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->end_keyword_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_DEFINED_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"DefinedNode\",\"location\":", 33);

            const pm_defined_node_t *cast = (const pm_defined_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the lparen_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"lparen_loc\":", 13);
            if (cast->lparen_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->lparen_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the value field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"value\":", 8);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->value);

            // Dump the rparen_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"rparen_loc\":", 13);
            if (cast->rparen_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->rparen_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the keyword_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"keyword_loc\":", 14);
            pm_dump_json_location(buffer, parser, &cast->keyword_loc);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_ELSE_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"ElseNode\",\"location\":", 30);

            const pm_else_node_t *cast = (const pm_else_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the else_keyword_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"else_keyword_loc\":", 19);
            pm_dump_json_location(buffer, parser, &cast->else_keyword_loc);

            // Dump the statements field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"statements\":", 13);
            if (cast->statements != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->statements);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the end_keyword_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"end_keyword_loc\":", 18);
            if (cast->end_keyword_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->end_keyword_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_EMBEDDED_STATEMENTS_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"EmbeddedStatementsNode\",\"location\":", 44);

            const pm_embedded_statements_node_t *cast = (const pm_embedded_statements_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the opening_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"opening_loc\":", 14);
            pm_dump_json_location(buffer, parser, &cast->opening_loc);

            // Dump the statements field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"statements\":", 13);
            if (cast->statements != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->statements);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the closing_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"closing_loc\":", 14);
            pm_dump_json_location(buffer, parser, &cast->closing_loc);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_EMBEDDED_VARIABLE_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"EmbeddedVariableNode\",\"location\":", 42);

            const pm_embedded_variable_node_t *cast = (const pm_embedded_variable_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"operator_loc\":", 15);
            pm_dump_json_location(buffer, parser, &cast->operator_loc);

            // Dump the variable field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"variable\":", 11);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->variable);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_ENSURE_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"EnsureNode\",\"location\":", 32);

            const pm_ensure_node_t *cast = (const pm_ensure_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the ensure_keyword_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"ensure_keyword_loc\":", 21);
            pm_dump_json_location(buffer, parser, &cast->ensure_keyword_loc);

            // Dump the statements field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"statements\":", 13);
            if (cast->statements != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->statements);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the end_keyword_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"end_keyword_loc\":", 18);
            pm_dump_json_location(buffer, parser, &cast->end_keyword_loc);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_FALSE_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"FalseNode\",\"location\":", 31);

            const pm_false_node_t *cast = (const pm_false_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_FIND_PATTERN_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"FindPatternNode\",\"location\":", 37);

            const pm_find_pattern_node_t *cast = (const pm_find_pattern_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the constant field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"constant\":", 11);
            if (cast->constant != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->constant);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the left field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"left\":", 7);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->left);

            // Dump the requireds field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"requireds\":", 12);
            const pm_node_list_t *requireds = &cast->requireds;
            pm_buffer_append_byte(buffer, '[');

            for (size_t index = 0; index < requireds->size; index++) {
                if (index != 0) pm_buffer_append_byte(buffer, ',');
                pm_dump_json(buffer, parser, requireds->nodes[index]);
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the right field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"right\":", 8);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->right);

            // Dump the opening_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"opening_loc\":", 14);
            if (cast->opening_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->opening_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the closing_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"closing_loc\":", 14);
            if (cast->closing_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->closing_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_FLIP_FLOP_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"FlipFlopNode\",\"location\":", 34);

            const pm_flip_flop_node_t *cast = (const pm_flip_flop_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the RangeFlags field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"RangeFlags\":", 13);
            size_t flags = 0;
            pm_buffer_append_byte(buffer, '[');
            if (PM_NODE_FLAG_P(cast, PM_RANGE_FLAGS_EXCLUDE_END)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"EXCLUDE_END\"", 13);
                flags++;
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the left field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"left\":", 7);
            if (cast->left != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->left);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the right field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"right\":", 8);
            if (cast->right != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->right);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"operator_loc\":", 15);
            pm_dump_json_location(buffer, parser, &cast->operator_loc);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_FLOAT_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"FloatNode\",\"location\":", 31);

            const pm_float_node_t *cast = (const pm_float_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the value field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"value\":", 8);
            pm_buffer_append_format(buffer, "%f", cast->value);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_FOR_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"ForNode\",\"location\":", 29);

            const pm_for_node_t *cast = (const pm_for_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the index field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"index\":", 8);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->index);

            // Dump the collection field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"collection\":", 13);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->collection);

            // Dump the statements field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"statements\":", 13);
            if (cast->statements != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->statements);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the for_keyword_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"for_keyword_loc\":", 18);
            pm_dump_json_location(buffer, parser, &cast->for_keyword_loc);

            // Dump the in_keyword_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"in_keyword_loc\":", 17);
            pm_dump_json_location(buffer, parser, &cast->in_keyword_loc);

            // Dump the do_keyword_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"do_keyword_loc\":", 17);
            if (cast->do_keyword_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->do_keyword_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the end_keyword_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"end_keyword_loc\":", 18);
            pm_dump_json_location(buffer, parser, &cast->end_keyword_loc);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_FORWARDING_ARGUMENTS_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"ForwardingArgumentsNode\",\"location\":", 45);

            const pm_forwarding_arguments_node_t *cast = (const pm_forwarding_arguments_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_FORWARDING_PARAMETER_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"ForwardingParameterNode\",\"location\":", 45);

            const pm_forwarding_parameter_node_t *cast = (const pm_forwarding_parameter_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_FORWARDING_SUPER_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"ForwardingSuperNode\",\"location\":", 41);

            const pm_forwarding_super_node_t *cast = (const pm_forwarding_super_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the block field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"block\":", 8);
            if (cast->block != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->block);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_GLOBAL_VARIABLE_AND_WRITE_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"GlobalVariableAndWriteNode\",\"location\":", 48);

            const pm_global_variable_and_write_node_t *cast = (const pm_global_variable_and_write_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the name field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name\":", 7);
            pm_dump_json_constant(buffer, parser, cast->name);

            // Dump the name_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name_loc\":", 11);
            pm_dump_json_location(buffer, parser, &cast->name_loc);

            // Dump the operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"operator_loc\":", 15);
            pm_dump_json_location(buffer, parser, &cast->operator_loc);

            // Dump the value field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"value\":", 8);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->value);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_GLOBAL_VARIABLE_OPERATOR_WRITE_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"GlobalVariableOperatorWriteNode\",\"location\":", 53);

            const pm_global_variable_operator_write_node_t *cast = (const pm_global_variable_operator_write_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the name field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name\":", 7);
            pm_dump_json_constant(buffer, parser, cast->name);

            // Dump the name_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name_loc\":", 11);
            pm_dump_json_location(buffer, parser, &cast->name_loc);

            // Dump the binary_operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"binary_operator_loc\":", 22);
            pm_dump_json_location(buffer, parser, &cast->binary_operator_loc);

            // Dump the value field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"value\":", 8);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->value);

            // Dump the binary_operator field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"binary_operator\":", 18);
            pm_dump_json_constant(buffer, parser, cast->binary_operator);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_GLOBAL_VARIABLE_OR_WRITE_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"GlobalVariableOrWriteNode\",\"location\":", 47);

            const pm_global_variable_or_write_node_t *cast = (const pm_global_variable_or_write_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the name field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name\":", 7);
            pm_dump_json_constant(buffer, parser, cast->name);

            // Dump the name_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name_loc\":", 11);
            pm_dump_json_location(buffer, parser, &cast->name_loc);

            // Dump the operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"operator_loc\":", 15);
            pm_dump_json_location(buffer, parser, &cast->operator_loc);

            // Dump the value field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"value\":", 8);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->value);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_GLOBAL_VARIABLE_READ_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"GlobalVariableReadNode\",\"location\":", 44);

            const pm_global_variable_read_node_t *cast = (const pm_global_variable_read_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the name field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name\":", 7);
            pm_dump_json_constant(buffer, parser, cast->name);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_GLOBAL_VARIABLE_TARGET_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"GlobalVariableTargetNode\",\"location\":", 46);

            const pm_global_variable_target_node_t *cast = (const pm_global_variable_target_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the name field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name\":", 7);
            pm_dump_json_constant(buffer, parser, cast->name);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_GLOBAL_VARIABLE_WRITE_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"GlobalVariableWriteNode\",\"location\":", 45);

            const pm_global_variable_write_node_t *cast = (const pm_global_variable_write_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the name field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name\":", 7);
            pm_dump_json_constant(buffer, parser, cast->name);

            // Dump the name_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name_loc\":", 11);
            pm_dump_json_location(buffer, parser, &cast->name_loc);

            // Dump the value field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"value\":", 8);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->value);

            // Dump the operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"operator_loc\":", 15);
            pm_dump_json_location(buffer, parser, &cast->operator_loc);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_HASH_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"HashNode\",\"location\":", 30);

            const pm_hash_node_t *cast = (const pm_hash_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the opening_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"opening_loc\":", 14);
            pm_dump_json_location(buffer, parser, &cast->opening_loc);

            // Dump the elements field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"elements\":", 11);
            const pm_node_list_t *elements = &cast->elements;
            pm_buffer_append_byte(buffer, '[');

            for (size_t index = 0; index < elements->size; index++) {
                if (index != 0) pm_buffer_append_byte(buffer, ',');
                pm_dump_json(buffer, parser, elements->nodes[index]);
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the closing_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"closing_loc\":", 14);
            pm_dump_json_location(buffer, parser, &cast->closing_loc);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_HASH_PATTERN_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"HashPatternNode\",\"location\":", 37);

            const pm_hash_pattern_node_t *cast = (const pm_hash_pattern_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the constant field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"constant\":", 11);
            if (cast->constant != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->constant);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the elements field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"elements\":", 11);
            const pm_node_list_t *elements = &cast->elements;
            pm_buffer_append_byte(buffer, '[');

            for (size_t index = 0; index < elements->size; index++) {
                if (index != 0) pm_buffer_append_byte(buffer, ',');
                pm_dump_json(buffer, parser, elements->nodes[index]);
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the rest field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"rest\":", 7);
            if (cast->rest != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->rest);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the opening_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"opening_loc\":", 14);
            if (cast->opening_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->opening_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the closing_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"closing_loc\":", 14);
            if (cast->closing_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->closing_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_IF_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"IfNode\",\"location\":", 28);

            const pm_if_node_t *cast = (const pm_if_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the if_keyword_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"if_keyword_loc\":", 17);
            if (cast->if_keyword_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->if_keyword_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the predicate field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"predicate\":", 12);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->predicate);

            // Dump the then_keyword_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"then_keyword_loc\":", 19);
            if (cast->then_keyword_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->then_keyword_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the statements field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"statements\":", 13);
            if (cast->statements != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->statements);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the subsequent field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"subsequent\":", 13);
            if (cast->subsequent != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->subsequent);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the end_keyword_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"end_keyword_loc\":", 18);
            if (cast->end_keyword_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->end_keyword_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_IMAGINARY_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"ImaginaryNode\",\"location\":", 35);

            const pm_imaginary_node_t *cast = (const pm_imaginary_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the numeric field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"numeric\":", 10);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->numeric);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_IMPLICIT_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"ImplicitNode\",\"location\":", 34);

            const pm_implicit_node_t *cast = (const pm_implicit_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the value field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"value\":", 8);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->value);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_IMPLICIT_REST_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"ImplicitRestNode\",\"location\":", 38);

            const pm_implicit_rest_node_t *cast = (const pm_implicit_rest_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_IN_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"InNode\",\"location\":", 28);

            const pm_in_node_t *cast = (const pm_in_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the pattern field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"pattern\":", 10);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->pattern);

            // Dump the statements field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"statements\":", 13);
            if (cast->statements != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->statements);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the in_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"in_loc\":", 9);
            pm_dump_json_location(buffer, parser, &cast->in_loc);

            // Dump the then_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"then_loc\":", 11);
            if (cast->then_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->then_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_INDEX_AND_WRITE_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"IndexAndWriteNode\",\"location\":", 39);

            const pm_index_and_write_node_t *cast = (const pm_index_and_write_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the CallNodeFlags field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"CallNodeFlags\":", 16);
            size_t flags = 0;
            pm_buffer_append_byte(buffer, '[');
            if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_SAFE_NAVIGATION)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"SAFE_NAVIGATION\"", 17);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_VARIABLE_CALL)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"VARIABLE_CALL\"", 15);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"ATTRIBUTE_WRITE\"", 17);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_IGNORE_VISIBILITY)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"IGNORE_VISIBILITY\"", 19);
                flags++;
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the receiver field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"receiver\":", 11);
            if (cast->receiver != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->receiver);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the call_operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"call_operator_loc\":", 20);
            if (cast->call_operator_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->call_operator_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the opening_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"opening_loc\":", 14);
            pm_dump_json_location(buffer, parser, &cast->opening_loc);

            // Dump the arguments field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"arguments\":", 12);
            if (cast->arguments != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->arguments);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the closing_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"closing_loc\":", 14);
            pm_dump_json_location(buffer, parser, &cast->closing_loc);

            // Dump the block field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"block\":", 8);
            if (cast->block != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->block);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"operator_loc\":", 15);
            pm_dump_json_location(buffer, parser, &cast->operator_loc);

            // Dump the value field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"value\":", 8);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->value);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_INDEX_OPERATOR_WRITE_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"IndexOperatorWriteNode\",\"location\":", 44);

            const pm_index_operator_write_node_t *cast = (const pm_index_operator_write_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the CallNodeFlags field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"CallNodeFlags\":", 16);
            size_t flags = 0;
            pm_buffer_append_byte(buffer, '[');
            if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_SAFE_NAVIGATION)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"SAFE_NAVIGATION\"", 17);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_VARIABLE_CALL)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"VARIABLE_CALL\"", 15);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"ATTRIBUTE_WRITE\"", 17);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_IGNORE_VISIBILITY)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"IGNORE_VISIBILITY\"", 19);
                flags++;
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the receiver field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"receiver\":", 11);
            if (cast->receiver != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->receiver);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the call_operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"call_operator_loc\":", 20);
            if (cast->call_operator_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->call_operator_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the opening_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"opening_loc\":", 14);
            pm_dump_json_location(buffer, parser, &cast->opening_loc);

            // Dump the arguments field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"arguments\":", 12);
            if (cast->arguments != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->arguments);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the closing_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"closing_loc\":", 14);
            pm_dump_json_location(buffer, parser, &cast->closing_loc);

            // Dump the block field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"block\":", 8);
            if (cast->block != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->block);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the binary_operator field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"binary_operator\":", 18);
            pm_dump_json_constant(buffer, parser, cast->binary_operator);

            // Dump the binary_operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"binary_operator_loc\":", 22);
            pm_dump_json_location(buffer, parser, &cast->binary_operator_loc);

            // Dump the value field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"value\":", 8);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->value);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_INDEX_OR_WRITE_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"IndexOrWriteNode\",\"location\":", 38);

            const pm_index_or_write_node_t *cast = (const pm_index_or_write_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the CallNodeFlags field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"CallNodeFlags\":", 16);
            size_t flags = 0;
            pm_buffer_append_byte(buffer, '[');
            if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_SAFE_NAVIGATION)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"SAFE_NAVIGATION\"", 17);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_VARIABLE_CALL)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"VARIABLE_CALL\"", 15);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"ATTRIBUTE_WRITE\"", 17);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_IGNORE_VISIBILITY)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"IGNORE_VISIBILITY\"", 19);
                flags++;
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the receiver field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"receiver\":", 11);
            if (cast->receiver != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->receiver);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the call_operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"call_operator_loc\":", 20);
            if (cast->call_operator_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->call_operator_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the opening_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"opening_loc\":", 14);
            pm_dump_json_location(buffer, parser, &cast->opening_loc);

            // Dump the arguments field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"arguments\":", 12);
            if (cast->arguments != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->arguments);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the closing_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"closing_loc\":", 14);
            pm_dump_json_location(buffer, parser, &cast->closing_loc);

            // Dump the block field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"block\":", 8);
            if (cast->block != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->block);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"operator_loc\":", 15);
            pm_dump_json_location(buffer, parser, &cast->operator_loc);

            // Dump the value field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"value\":", 8);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->value);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_INDEX_TARGET_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"IndexTargetNode\",\"location\":", 37);

            const pm_index_target_node_t *cast = (const pm_index_target_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the CallNodeFlags field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"CallNodeFlags\":", 16);
            size_t flags = 0;
            pm_buffer_append_byte(buffer, '[');
            if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_SAFE_NAVIGATION)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"SAFE_NAVIGATION\"", 17);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_VARIABLE_CALL)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"VARIABLE_CALL\"", 15);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"ATTRIBUTE_WRITE\"", 17);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_IGNORE_VISIBILITY)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"IGNORE_VISIBILITY\"", 19);
                flags++;
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the receiver field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"receiver\":", 11);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->receiver);

            // Dump the opening_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"opening_loc\":", 14);
            pm_dump_json_location(buffer, parser, &cast->opening_loc);

            // Dump the arguments field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"arguments\":", 12);
            if (cast->arguments != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->arguments);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the closing_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"closing_loc\":", 14);
            pm_dump_json_location(buffer, parser, &cast->closing_loc);

            // Dump the block field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"block\":", 8);
            if (cast->block != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->block);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_INSTANCE_VARIABLE_AND_WRITE_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"InstanceVariableAndWriteNode\",\"location\":", 50);

            const pm_instance_variable_and_write_node_t *cast = (const pm_instance_variable_and_write_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the name field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name\":", 7);
            pm_dump_json_constant(buffer, parser, cast->name);

            // Dump the name_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name_loc\":", 11);
            pm_dump_json_location(buffer, parser, &cast->name_loc);

            // Dump the operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"operator_loc\":", 15);
            pm_dump_json_location(buffer, parser, &cast->operator_loc);

            // Dump the value field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"value\":", 8);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->value);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_INSTANCE_VARIABLE_OPERATOR_WRITE_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"InstanceVariableOperatorWriteNode\",\"location\":", 55);

            const pm_instance_variable_operator_write_node_t *cast = (const pm_instance_variable_operator_write_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the name field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name\":", 7);
            pm_dump_json_constant(buffer, parser, cast->name);

            // Dump the name_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name_loc\":", 11);
            pm_dump_json_location(buffer, parser, &cast->name_loc);

            // Dump the binary_operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"binary_operator_loc\":", 22);
            pm_dump_json_location(buffer, parser, &cast->binary_operator_loc);

            // Dump the value field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"value\":", 8);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->value);

            // Dump the binary_operator field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"binary_operator\":", 18);
            pm_dump_json_constant(buffer, parser, cast->binary_operator);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_INSTANCE_VARIABLE_OR_WRITE_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"InstanceVariableOrWriteNode\",\"location\":", 49);

            const pm_instance_variable_or_write_node_t *cast = (const pm_instance_variable_or_write_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the name field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name\":", 7);
            pm_dump_json_constant(buffer, parser, cast->name);

            // Dump the name_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name_loc\":", 11);
            pm_dump_json_location(buffer, parser, &cast->name_loc);

            // Dump the operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"operator_loc\":", 15);
            pm_dump_json_location(buffer, parser, &cast->operator_loc);

            // Dump the value field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"value\":", 8);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->value);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_INSTANCE_VARIABLE_READ_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"InstanceVariableReadNode\",\"location\":", 46);

            const pm_instance_variable_read_node_t *cast = (const pm_instance_variable_read_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the name field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name\":", 7);
            pm_dump_json_constant(buffer, parser, cast->name);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_INSTANCE_VARIABLE_TARGET_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"InstanceVariableTargetNode\",\"location\":", 48);

            const pm_instance_variable_target_node_t *cast = (const pm_instance_variable_target_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the name field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name\":", 7);
            pm_dump_json_constant(buffer, parser, cast->name);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_INSTANCE_VARIABLE_WRITE_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"InstanceVariableWriteNode\",\"location\":", 47);

            const pm_instance_variable_write_node_t *cast = (const pm_instance_variable_write_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the name field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name\":", 7);
            pm_dump_json_constant(buffer, parser, cast->name);

            // Dump the name_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name_loc\":", 11);
            pm_dump_json_location(buffer, parser, &cast->name_loc);

            // Dump the value field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"value\":", 8);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->value);

            // Dump the operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"operator_loc\":", 15);
            pm_dump_json_location(buffer, parser, &cast->operator_loc);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_INTEGER_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"IntegerNode\",\"location\":", 33);

            const pm_integer_node_t *cast = (const pm_integer_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the IntegerBaseFlags field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"IntegerBaseFlags\":", 19);
            size_t flags = 0;
            pm_buffer_append_byte(buffer, '[');
            if (PM_NODE_FLAG_P(cast, PM_INTEGER_BASE_FLAGS_BINARY)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"BINARY\"", 8);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_INTEGER_BASE_FLAGS_DECIMAL)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"DECIMAL\"", 9);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_INTEGER_BASE_FLAGS_OCTAL)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"OCTAL\"", 7);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_INTEGER_BASE_FLAGS_HEXADECIMAL)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"HEXADECIMAL\"", 13);
                flags++;
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the value field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"value\":", 8);
            pm_integer_string(buffer, &cast->value);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_INTERPOLATED_MATCH_LAST_LINE_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"InterpolatedMatchLastLineNode\",\"location\":", 51);

            const pm_interpolated_match_last_line_node_t *cast = (const pm_interpolated_match_last_line_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the RegularExpressionFlags field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"RegularExpressionFlags\":", 25);
            size_t flags = 0;
            pm_buffer_append_byte(buffer, '[');
            if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_IGNORE_CASE)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"IGNORE_CASE\"", 13);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_EXTENDED)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"EXTENDED\"", 10);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_MULTI_LINE)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"MULTI_LINE\"", 12);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_ONCE)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"ONCE\"", 6);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_EUC_JP)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"EUC_JP\"", 8);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_ASCII_8BIT)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"ASCII_8BIT\"", 12);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_WINDOWS_31J)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"WINDOWS_31J\"", 13);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_UTF_8)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"UTF_8\"", 7);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_FORCED_UTF8_ENCODING)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"FORCED_UTF8_ENCODING\"", 22);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_FORCED_BINARY_ENCODING)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"FORCED_BINARY_ENCODING\"", 24);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_FORCED_US_ASCII_ENCODING)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"FORCED_US_ASCII_ENCODING\"", 26);
                flags++;
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the opening_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"opening_loc\":", 14);
            pm_dump_json_location(buffer, parser, &cast->opening_loc);

            // Dump the parts field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"parts\":", 8);
            const pm_node_list_t *parts = &cast->parts;
            pm_buffer_append_byte(buffer, '[');

            for (size_t index = 0; index < parts->size; index++) {
                if (index != 0) pm_buffer_append_byte(buffer, ',');
                pm_dump_json(buffer, parser, parts->nodes[index]);
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the closing_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"closing_loc\":", 14);
            pm_dump_json_location(buffer, parser, &cast->closing_loc);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_INTERPOLATED_REGULAR_EXPRESSION_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"InterpolatedRegularExpressionNode\",\"location\":", 55);

            const pm_interpolated_regular_expression_node_t *cast = (const pm_interpolated_regular_expression_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the RegularExpressionFlags field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"RegularExpressionFlags\":", 25);
            size_t flags = 0;
            pm_buffer_append_byte(buffer, '[');
            if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_IGNORE_CASE)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"IGNORE_CASE\"", 13);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_EXTENDED)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"EXTENDED\"", 10);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_MULTI_LINE)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"MULTI_LINE\"", 12);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_ONCE)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"ONCE\"", 6);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_EUC_JP)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"EUC_JP\"", 8);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_ASCII_8BIT)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"ASCII_8BIT\"", 12);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_WINDOWS_31J)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"WINDOWS_31J\"", 13);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_UTF_8)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"UTF_8\"", 7);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_FORCED_UTF8_ENCODING)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"FORCED_UTF8_ENCODING\"", 22);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_FORCED_BINARY_ENCODING)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"FORCED_BINARY_ENCODING\"", 24);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_FORCED_US_ASCII_ENCODING)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"FORCED_US_ASCII_ENCODING\"", 26);
                flags++;
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the opening_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"opening_loc\":", 14);
            pm_dump_json_location(buffer, parser, &cast->opening_loc);

            // Dump the parts field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"parts\":", 8);
            const pm_node_list_t *parts = &cast->parts;
            pm_buffer_append_byte(buffer, '[');

            for (size_t index = 0; index < parts->size; index++) {
                if (index != 0) pm_buffer_append_byte(buffer, ',');
                pm_dump_json(buffer, parser, parts->nodes[index]);
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the closing_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"closing_loc\":", 14);
            pm_dump_json_location(buffer, parser, &cast->closing_loc);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_INTERPOLATED_STRING_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"InterpolatedStringNode\",\"location\":", 44);

            const pm_interpolated_string_node_t *cast = (const pm_interpolated_string_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the InterpolatedStringNodeFlags field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"InterpolatedStringNodeFlags\":", 30);
            size_t flags = 0;
            pm_buffer_append_byte(buffer, '[');
            if (PM_NODE_FLAG_P(cast, PM_INTERPOLATED_STRING_NODE_FLAGS_FROZEN)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"FROZEN\"", 8);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_INTERPOLATED_STRING_NODE_FLAGS_MUTABLE)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"MUTABLE\"", 9);
                flags++;
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the opening_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"opening_loc\":", 14);
            if (cast->opening_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->opening_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the parts field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"parts\":", 8);
            const pm_node_list_t *parts = &cast->parts;
            pm_buffer_append_byte(buffer, '[');

            for (size_t index = 0; index < parts->size; index++) {
                if (index != 0) pm_buffer_append_byte(buffer, ',');
                pm_dump_json(buffer, parser, parts->nodes[index]);
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the closing_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"closing_loc\":", 14);
            if (cast->closing_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->closing_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_INTERPOLATED_SYMBOL_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"InterpolatedSymbolNode\",\"location\":", 44);

            const pm_interpolated_symbol_node_t *cast = (const pm_interpolated_symbol_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the opening_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"opening_loc\":", 14);
            if (cast->opening_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->opening_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the parts field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"parts\":", 8);
            const pm_node_list_t *parts = &cast->parts;
            pm_buffer_append_byte(buffer, '[');

            for (size_t index = 0; index < parts->size; index++) {
                if (index != 0) pm_buffer_append_byte(buffer, ',');
                pm_dump_json(buffer, parser, parts->nodes[index]);
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the closing_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"closing_loc\":", 14);
            if (cast->closing_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->closing_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_INTERPOLATED_X_STRING_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"InterpolatedXStringNode\",\"location\":", 45);

            const pm_interpolated_x_string_node_t *cast = (const pm_interpolated_x_string_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the opening_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"opening_loc\":", 14);
            pm_dump_json_location(buffer, parser, &cast->opening_loc);

            // Dump the parts field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"parts\":", 8);
            const pm_node_list_t *parts = &cast->parts;
            pm_buffer_append_byte(buffer, '[');

            for (size_t index = 0; index < parts->size; index++) {
                if (index != 0) pm_buffer_append_byte(buffer, ',');
                pm_dump_json(buffer, parser, parts->nodes[index]);
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the closing_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"closing_loc\":", 14);
            pm_dump_json_location(buffer, parser, &cast->closing_loc);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_IT_LOCAL_VARIABLE_READ_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"ItLocalVariableReadNode\",\"location\":", 45);

            const pm_it_local_variable_read_node_t *cast = (const pm_it_local_variable_read_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_IT_PARAMETERS_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"ItParametersNode\",\"location\":", 38);

            const pm_it_parameters_node_t *cast = (const pm_it_parameters_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_KEYWORD_HASH_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"KeywordHashNode\",\"location\":", 37);

            const pm_keyword_hash_node_t *cast = (const pm_keyword_hash_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the KeywordHashNodeFlags field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"KeywordHashNodeFlags\":", 23);
            size_t flags = 0;
            pm_buffer_append_byte(buffer, '[');
            if (PM_NODE_FLAG_P(cast, PM_KEYWORD_HASH_NODE_FLAGS_SYMBOL_KEYS)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"SYMBOL_KEYS\"", 13);
                flags++;
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the elements field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"elements\":", 11);
            const pm_node_list_t *elements = &cast->elements;
            pm_buffer_append_byte(buffer, '[');

            for (size_t index = 0; index < elements->size; index++) {
                if (index != 0) pm_buffer_append_byte(buffer, ',');
                pm_dump_json(buffer, parser, elements->nodes[index]);
            }
            pm_buffer_append_byte(buffer, ']');

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_KEYWORD_REST_PARAMETER_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"KeywordRestParameterNode\",\"location\":", 46);

            const pm_keyword_rest_parameter_node_t *cast = (const pm_keyword_rest_parameter_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the ParameterFlags field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"ParameterFlags\":", 17);
            size_t flags = 0;
            pm_buffer_append_byte(buffer, '[');
            if (PM_NODE_FLAG_P(cast, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"REPEATED_PARAMETER\"", 20);
                flags++;
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the name field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name\":", 7);
            if (cast->name != PM_CONSTANT_ID_UNSET) {
                pm_dump_json_constant(buffer, parser, cast->name);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the name_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name_loc\":", 11);
            if (cast->name_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->name_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"operator_loc\":", 15);
            pm_dump_json_location(buffer, parser, &cast->operator_loc);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_LAMBDA_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"LambdaNode\",\"location\":", 32);

            const pm_lambda_node_t *cast = (const pm_lambda_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the locals field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"locals\":", 9);
            const pm_constant_id_list_t *locals = &cast->locals;
            pm_buffer_append_byte(buffer, '[');

            for (size_t index = 0; index < locals->size; index++) {
                if (index != 0) pm_buffer_append_byte(buffer, ',');
                pm_dump_json_constant(buffer, parser, locals->ids[index]);
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"operator_loc\":", 15);
            pm_dump_json_location(buffer, parser, &cast->operator_loc);

            // Dump the opening_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"opening_loc\":", 14);
            pm_dump_json_location(buffer, parser, &cast->opening_loc);

            // Dump the closing_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"closing_loc\":", 14);
            pm_dump_json_location(buffer, parser, &cast->closing_loc);

            // Dump the parameters field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"parameters\":", 13);
            if (cast->parameters != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->parameters);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the body field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"body\":", 7);
            if (cast->body != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->body);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_LOCAL_VARIABLE_AND_WRITE_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"LocalVariableAndWriteNode\",\"location\":", 47);

            const pm_local_variable_and_write_node_t *cast = (const pm_local_variable_and_write_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the name_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name_loc\":", 11);
            pm_dump_json_location(buffer, parser, &cast->name_loc);

            // Dump the operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"operator_loc\":", 15);
            pm_dump_json_location(buffer, parser, &cast->operator_loc);

            // Dump the value field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"value\":", 8);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->value);

            // Dump the name field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name\":", 7);
            pm_dump_json_constant(buffer, parser, cast->name);

            // Dump the depth field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"depth\":", 8);
            pm_buffer_append_format(buffer, "%" PRIu32, cast->depth);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_LOCAL_VARIABLE_OPERATOR_WRITE_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"LocalVariableOperatorWriteNode\",\"location\":", 52);

            const pm_local_variable_operator_write_node_t *cast = (const pm_local_variable_operator_write_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the name_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name_loc\":", 11);
            pm_dump_json_location(buffer, parser, &cast->name_loc);

            // Dump the binary_operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"binary_operator_loc\":", 22);
            pm_dump_json_location(buffer, parser, &cast->binary_operator_loc);

            // Dump the value field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"value\":", 8);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->value);

            // Dump the name field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name\":", 7);
            pm_dump_json_constant(buffer, parser, cast->name);

            // Dump the binary_operator field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"binary_operator\":", 18);
            pm_dump_json_constant(buffer, parser, cast->binary_operator);

            // Dump the depth field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"depth\":", 8);
            pm_buffer_append_format(buffer, "%" PRIu32, cast->depth);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_LOCAL_VARIABLE_OR_WRITE_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"LocalVariableOrWriteNode\",\"location\":", 46);

            const pm_local_variable_or_write_node_t *cast = (const pm_local_variable_or_write_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the name_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name_loc\":", 11);
            pm_dump_json_location(buffer, parser, &cast->name_loc);

            // Dump the operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"operator_loc\":", 15);
            pm_dump_json_location(buffer, parser, &cast->operator_loc);

            // Dump the value field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"value\":", 8);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->value);

            // Dump the name field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name\":", 7);
            pm_dump_json_constant(buffer, parser, cast->name);

            // Dump the depth field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"depth\":", 8);
            pm_buffer_append_format(buffer, "%" PRIu32, cast->depth);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_LOCAL_VARIABLE_READ_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"LocalVariableReadNode\",\"location\":", 43);

            const pm_local_variable_read_node_t *cast = (const pm_local_variable_read_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the name field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name\":", 7);
            pm_dump_json_constant(buffer, parser, cast->name);

            // Dump the depth field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"depth\":", 8);
            pm_buffer_append_format(buffer, "%" PRIu32, cast->depth);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_LOCAL_VARIABLE_TARGET_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"LocalVariableTargetNode\",\"location\":", 45);

            const pm_local_variable_target_node_t *cast = (const pm_local_variable_target_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the name field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name\":", 7);
            pm_dump_json_constant(buffer, parser, cast->name);

            // Dump the depth field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"depth\":", 8);
            pm_buffer_append_format(buffer, "%" PRIu32, cast->depth);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_LOCAL_VARIABLE_WRITE_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"LocalVariableWriteNode\",\"location\":", 44);

            const pm_local_variable_write_node_t *cast = (const pm_local_variable_write_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the name field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name\":", 7);
            pm_dump_json_constant(buffer, parser, cast->name);

            // Dump the depth field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"depth\":", 8);
            pm_buffer_append_format(buffer, "%" PRIu32, cast->depth);

            // Dump the name_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name_loc\":", 11);
            pm_dump_json_location(buffer, parser, &cast->name_loc);

            // Dump the value field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"value\":", 8);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->value);

            // Dump the operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"operator_loc\":", 15);
            pm_dump_json_location(buffer, parser, &cast->operator_loc);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_MATCH_LAST_LINE_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"MatchLastLineNode\",\"location\":", 39);

            const pm_match_last_line_node_t *cast = (const pm_match_last_line_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the RegularExpressionFlags field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"RegularExpressionFlags\":", 25);
            size_t flags = 0;
            pm_buffer_append_byte(buffer, '[');
            if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_IGNORE_CASE)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"IGNORE_CASE\"", 13);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_EXTENDED)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"EXTENDED\"", 10);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_MULTI_LINE)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"MULTI_LINE\"", 12);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_ONCE)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"ONCE\"", 6);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_EUC_JP)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"EUC_JP\"", 8);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_ASCII_8BIT)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"ASCII_8BIT\"", 12);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_WINDOWS_31J)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"WINDOWS_31J\"", 13);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_UTF_8)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"UTF_8\"", 7);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_FORCED_UTF8_ENCODING)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"FORCED_UTF8_ENCODING\"", 22);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_FORCED_BINARY_ENCODING)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"FORCED_BINARY_ENCODING\"", 24);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_FORCED_US_ASCII_ENCODING)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"FORCED_US_ASCII_ENCODING\"", 26);
                flags++;
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the opening_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"opening_loc\":", 14);
            pm_dump_json_location(buffer, parser, &cast->opening_loc);

            // Dump the content_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"content_loc\":", 14);
            pm_dump_json_location(buffer, parser, &cast->content_loc);

            // Dump the closing_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"closing_loc\":", 14);
            pm_dump_json_location(buffer, parser, &cast->closing_loc);

            // Dump the unescaped field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"unescaped\":", 12);
            const pm_string_t *unescaped = &cast->unescaped;
            pm_buffer_append_byte(buffer, '"');
            pm_buffer_append_source(buffer, pm_string_source(unescaped), pm_string_length(unescaped), PM_BUFFER_ESCAPING_JSON);
            pm_buffer_append_byte(buffer, '"');

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_MATCH_PREDICATE_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"MatchPredicateNode\",\"location\":", 40);

            const pm_match_predicate_node_t *cast = (const pm_match_predicate_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the value field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"value\":", 8);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->value);

            // Dump the pattern field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"pattern\":", 10);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->pattern);

            // Dump the operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"operator_loc\":", 15);
            pm_dump_json_location(buffer, parser, &cast->operator_loc);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_MATCH_REQUIRED_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"MatchRequiredNode\",\"location\":", 39);

            const pm_match_required_node_t *cast = (const pm_match_required_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the value field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"value\":", 8);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->value);

            // Dump the pattern field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"pattern\":", 10);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->pattern);

            // Dump the operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"operator_loc\":", 15);
            pm_dump_json_location(buffer, parser, &cast->operator_loc);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_MATCH_WRITE_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"MatchWriteNode\",\"location\":", 36);

            const pm_match_write_node_t *cast = (const pm_match_write_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the call field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"call\":", 7);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->call);

            // Dump the targets field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"targets\":", 10);
            const pm_node_list_t *targets = &cast->targets;
            pm_buffer_append_byte(buffer, '[');

            for (size_t index = 0; index < targets->size; index++) {
                if (index != 0) pm_buffer_append_byte(buffer, ',');
                pm_dump_json(buffer, parser, targets->nodes[index]);
            }
            pm_buffer_append_byte(buffer, ']');

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_MISSING_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"MissingNode\",\"location\":", 33);

            const pm_missing_node_t *cast = (const pm_missing_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_MODULE_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"ModuleNode\",\"location\":", 32);

            const pm_module_node_t *cast = (const pm_module_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the locals field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"locals\":", 9);
            const pm_constant_id_list_t *locals = &cast->locals;
            pm_buffer_append_byte(buffer, '[');

            for (size_t index = 0; index < locals->size; index++) {
                if (index != 0) pm_buffer_append_byte(buffer, ',');
                pm_dump_json_constant(buffer, parser, locals->ids[index]);
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the module_keyword_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"module_keyword_loc\":", 21);
            pm_dump_json_location(buffer, parser, &cast->module_keyword_loc);

            // Dump the constant_path field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"constant_path\":", 16);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->constant_path);

            // Dump the body field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"body\":", 7);
            if (cast->body != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->body);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the end_keyword_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"end_keyword_loc\":", 18);
            pm_dump_json_location(buffer, parser, &cast->end_keyword_loc);

            // Dump the name field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name\":", 7);
            pm_dump_json_constant(buffer, parser, cast->name);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_MULTI_TARGET_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"MultiTargetNode\",\"location\":", 37);

            const pm_multi_target_node_t *cast = (const pm_multi_target_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the lefts field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"lefts\":", 8);
            const pm_node_list_t *lefts = &cast->lefts;
            pm_buffer_append_byte(buffer, '[');

            for (size_t index = 0; index < lefts->size; index++) {
                if (index != 0) pm_buffer_append_byte(buffer, ',');
                pm_dump_json(buffer, parser, lefts->nodes[index]);
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the rest field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"rest\":", 7);
            if (cast->rest != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->rest);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the rights field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"rights\":", 9);
            const pm_node_list_t *rights = &cast->rights;
            pm_buffer_append_byte(buffer, '[');

            for (size_t index = 0; index < rights->size; index++) {
                if (index != 0) pm_buffer_append_byte(buffer, ',');
                pm_dump_json(buffer, parser, rights->nodes[index]);
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the lparen_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"lparen_loc\":", 13);
            if (cast->lparen_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->lparen_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the rparen_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"rparen_loc\":", 13);
            if (cast->rparen_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->rparen_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_MULTI_WRITE_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"MultiWriteNode\",\"location\":", 36);

            const pm_multi_write_node_t *cast = (const pm_multi_write_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the lefts field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"lefts\":", 8);
            const pm_node_list_t *lefts = &cast->lefts;
            pm_buffer_append_byte(buffer, '[');

            for (size_t index = 0; index < lefts->size; index++) {
                if (index != 0) pm_buffer_append_byte(buffer, ',');
                pm_dump_json(buffer, parser, lefts->nodes[index]);
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the rest field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"rest\":", 7);
            if (cast->rest != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->rest);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the rights field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"rights\":", 9);
            const pm_node_list_t *rights = &cast->rights;
            pm_buffer_append_byte(buffer, '[');

            for (size_t index = 0; index < rights->size; index++) {
                if (index != 0) pm_buffer_append_byte(buffer, ',');
                pm_dump_json(buffer, parser, rights->nodes[index]);
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the lparen_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"lparen_loc\":", 13);
            if (cast->lparen_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->lparen_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the rparen_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"rparen_loc\":", 13);
            if (cast->rparen_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->rparen_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"operator_loc\":", 15);
            pm_dump_json_location(buffer, parser, &cast->operator_loc);

            // Dump the value field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"value\":", 8);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->value);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_NEXT_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"NextNode\",\"location\":", 30);

            const pm_next_node_t *cast = (const pm_next_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the arguments field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"arguments\":", 12);
            if (cast->arguments != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->arguments);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the keyword_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"keyword_loc\":", 14);
            pm_dump_json_location(buffer, parser, &cast->keyword_loc);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_NIL_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"NilNode\",\"location\":", 29);

            const pm_nil_node_t *cast = (const pm_nil_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_NO_KEYWORDS_PARAMETER_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"NoKeywordsParameterNode\",\"location\":", 45);

            const pm_no_keywords_parameter_node_t *cast = (const pm_no_keywords_parameter_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"operator_loc\":", 15);
            pm_dump_json_location(buffer, parser, &cast->operator_loc);

            // Dump the keyword_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"keyword_loc\":", 14);
            pm_dump_json_location(buffer, parser, &cast->keyword_loc);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_NUMBERED_PARAMETERS_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"NumberedParametersNode\",\"location\":", 44);

            const pm_numbered_parameters_node_t *cast = (const pm_numbered_parameters_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the maximum field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"maximum\":", 10);
            pm_buffer_append_format(buffer, "%" PRIu8, cast->maximum);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_NUMBERED_REFERENCE_READ_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"NumberedReferenceReadNode\",\"location\":", 47);

            const pm_numbered_reference_read_node_t *cast = (const pm_numbered_reference_read_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the number field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"number\":", 9);
            pm_buffer_append_format(buffer, "%" PRIu32, cast->number);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_OPTIONAL_KEYWORD_PARAMETER_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"OptionalKeywordParameterNode\",\"location\":", 50);

            const pm_optional_keyword_parameter_node_t *cast = (const pm_optional_keyword_parameter_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the ParameterFlags field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"ParameterFlags\":", 17);
            size_t flags = 0;
            pm_buffer_append_byte(buffer, '[');
            if (PM_NODE_FLAG_P(cast, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"REPEATED_PARAMETER\"", 20);
                flags++;
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the name field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name\":", 7);
            pm_dump_json_constant(buffer, parser, cast->name);

            // Dump the name_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name_loc\":", 11);
            pm_dump_json_location(buffer, parser, &cast->name_loc);

            // Dump the value field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"value\":", 8);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->value);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_OPTIONAL_PARAMETER_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"OptionalParameterNode\",\"location\":", 43);

            const pm_optional_parameter_node_t *cast = (const pm_optional_parameter_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the ParameterFlags field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"ParameterFlags\":", 17);
            size_t flags = 0;
            pm_buffer_append_byte(buffer, '[');
            if (PM_NODE_FLAG_P(cast, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"REPEATED_PARAMETER\"", 20);
                flags++;
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the name field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name\":", 7);
            pm_dump_json_constant(buffer, parser, cast->name);

            // Dump the name_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name_loc\":", 11);
            pm_dump_json_location(buffer, parser, &cast->name_loc);

            // Dump the operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"operator_loc\":", 15);
            pm_dump_json_location(buffer, parser, &cast->operator_loc);

            // Dump the value field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"value\":", 8);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->value);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_OR_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"OrNode\",\"location\":", 28);

            const pm_or_node_t *cast = (const pm_or_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the left field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"left\":", 7);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->left);

            // Dump the right field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"right\":", 8);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->right);

            // Dump the operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"operator_loc\":", 15);
            pm_dump_json_location(buffer, parser, &cast->operator_loc);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_PARAMETERS_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"ParametersNode\",\"location\":", 36);

            const pm_parameters_node_t *cast = (const pm_parameters_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the requireds field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"requireds\":", 12);
            const pm_node_list_t *requireds = &cast->requireds;
            pm_buffer_append_byte(buffer, '[');

            for (size_t index = 0; index < requireds->size; index++) {
                if (index != 0) pm_buffer_append_byte(buffer, ',');
                pm_dump_json(buffer, parser, requireds->nodes[index]);
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the optionals field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"optionals\":", 12);
            const pm_node_list_t *optionals = &cast->optionals;
            pm_buffer_append_byte(buffer, '[');

            for (size_t index = 0; index < optionals->size; index++) {
                if (index != 0) pm_buffer_append_byte(buffer, ',');
                pm_dump_json(buffer, parser, optionals->nodes[index]);
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the rest field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"rest\":", 7);
            if (cast->rest != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->rest);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the posts field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"posts\":", 8);
            const pm_node_list_t *posts = &cast->posts;
            pm_buffer_append_byte(buffer, '[');

            for (size_t index = 0; index < posts->size; index++) {
                if (index != 0) pm_buffer_append_byte(buffer, ',');
                pm_dump_json(buffer, parser, posts->nodes[index]);
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the keywords field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"keywords\":", 11);
            const pm_node_list_t *keywords = &cast->keywords;
            pm_buffer_append_byte(buffer, '[');

            for (size_t index = 0; index < keywords->size; index++) {
                if (index != 0) pm_buffer_append_byte(buffer, ',');
                pm_dump_json(buffer, parser, keywords->nodes[index]);
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the keyword_rest field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"keyword_rest\":", 15);
            if (cast->keyword_rest != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->keyword_rest);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the block field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"block\":", 8);
            if (cast->block != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->block);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_PARENTHESES_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"ParenthesesNode\",\"location\":", 37);

            const pm_parentheses_node_t *cast = (const pm_parentheses_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the ParenthesesNodeFlags field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"ParenthesesNodeFlags\":", 23);
            size_t flags = 0;
            pm_buffer_append_byte(buffer, '[');
            if (PM_NODE_FLAG_P(cast, PM_PARENTHESES_NODE_FLAGS_MULTIPLE_STATEMENTS)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"MULTIPLE_STATEMENTS\"", 21);
                flags++;
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the body field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"body\":", 7);
            if (cast->body != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->body);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the opening_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"opening_loc\":", 14);
            pm_dump_json_location(buffer, parser, &cast->opening_loc);

            // Dump the closing_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"closing_loc\":", 14);
            pm_dump_json_location(buffer, parser, &cast->closing_loc);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_PINNED_EXPRESSION_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"PinnedExpressionNode\",\"location\":", 42);

            const pm_pinned_expression_node_t *cast = (const pm_pinned_expression_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the expression field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"expression\":", 13);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->expression);

            // Dump the operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"operator_loc\":", 15);
            pm_dump_json_location(buffer, parser, &cast->operator_loc);

            // Dump the lparen_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"lparen_loc\":", 13);
            pm_dump_json_location(buffer, parser, &cast->lparen_loc);

            // Dump the rparen_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"rparen_loc\":", 13);
            pm_dump_json_location(buffer, parser, &cast->rparen_loc);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_PINNED_VARIABLE_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"PinnedVariableNode\",\"location\":", 40);

            const pm_pinned_variable_node_t *cast = (const pm_pinned_variable_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the variable field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"variable\":", 11);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->variable);

            // Dump the operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"operator_loc\":", 15);
            pm_dump_json_location(buffer, parser, &cast->operator_loc);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_POST_EXECUTION_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"PostExecutionNode\",\"location\":", 39);

            const pm_post_execution_node_t *cast = (const pm_post_execution_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the statements field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"statements\":", 13);
            if (cast->statements != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->statements);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the keyword_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"keyword_loc\":", 14);
            pm_dump_json_location(buffer, parser, &cast->keyword_loc);

            // Dump the opening_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"opening_loc\":", 14);
            pm_dump_json_location(buffer, parser, &cast->opening_loc);

            // Dump the closing_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"closing_loc\":", 14);
            pm_dump_json_location(buffer, parser, &cast->closing_loc);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_PRE_EXECUTION_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"PreExecutionNode\",\"location\":", 38);

            const pm_pre_execution_node_t *cast = (const pm_pre_execution_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the statements field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"statements\":", 13);
            if (cast->statements != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->statements);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the keyword_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"keyword_loc\":", 14);
            pm_dump_json_location(buffer, parser, &cast->keyword_loc);

            // Dump the opening_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"opening_loc\":", 14);
            pm_dump_json_location(buffer, parser, &cast->opening_loc);

            // Dump the closing_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"closing_loc\":", 14);
            pm_dump_json_location(buffer, parser, &cast->closing_loc);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_PROGRAM_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"ProgramNode\",\"location\":", 33);

            const pm_program_node_t *cast = (const pm_program_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the locals field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"locals\":", 9);
            const pm_constant_id_list_t *locals = &cast->locals;
            pm_buffer_append_byte(buffer, '[');

            for (size_t index = 0; index < locals->size; index++) {
                if (index != 0) pm_buffer_append_byte(buffer, ',');
                pm_dump_json_constant(buffer, parser, locals->ids[index]);
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the statements field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"statements\":", 13);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->statements);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_RANGE_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"RangeNode\",\"location\":", 31);

            const pm_range_node_t *cast = (const pm_range_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the RangeFlags field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"RangeFlags\":", 13);
            size_t flags = 0;
            pm_buffer_append_byte(buffer, '[');
            if (PM_NODE_FLAG_P(cast, PM_RANGE_FLAGS_EXCLUDE_END)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"EXCLUDE_END\"", 13);
                flags++;
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the left field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"left\":", 7);
            if (cast->left != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->left);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the right field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"right\":", 8);
            if (cast->right != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->right);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"operator_loc\":", 15);
            pm_dump_json_location(buffer, parser, &cast->operator_loc);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_RATIONAL_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"RationalNode\",\"location\":", 34);

            const pm_rational_node_t *cast = (const pm_rational_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the IntegerBaseFlags field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"IntegerBaseFlags\":", 19);
            size_t flags = 0;
            pm_buffer_append_byte(buffer, '[');
            if (PM_NODE_FLAG_P(cast, PM_INTEGER_BASE_FLAGS_BINARY)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"BINARY\"", 8);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_INTEGER_BASE_FLAGS_DECIMAL)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"DECIMAL\"", 9);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_INTEGER_BASE_FLAGS_OCTAL)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"OCTAL\"", 7);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_INTEGER_BASE_FLAGS_HEXADECIMAL)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"HEXADECIMAL\"", 13);
                flags++;
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the numerator field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"numerator\":", 12);
            pm_integer_string(buffer, &cast->numerator);

            // Dump the denominator field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"denominator\":", 14);
            pm_integer_string(buffer, &cast->denominator);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_REDO_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"RedoNode\",\"location\":", 30);

            const pm_redo_node_t *cast = (const pm_redo_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_REGULAR_EXPRESSION_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"RegularExpressionNode\",\"location\":", 43);

            const pm_regular_expression_node_t *cast = (const pm_regular_expression_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the RegularExpressionFlags field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"RegularExpressionFlags\":", 25);
            size_t flags = 0;
            pm_buffer_append_byte(buffer, '[');
            if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_IGNORE_CASE)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"IGNORE_CASE\"", 13);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_EXTENDED)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"EXTENDED\"", 10);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_MULTI_LINE)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"MULTI_LINE\"", 12);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_ONCE)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"ONCE\"", 6);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_EUC_JP)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"EUC_JP\"", 8);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_ASCII_8BIT)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"ASCII_8BIT\"", 12);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_WINDOWS_31J)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"WINDOWS_31J\"", 13);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_UTF_8)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"UTF_8\"", 7);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_FORCED_UTF8_ENCODING)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"FORCED_UTF8_ENCODING\"", 22);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_FORCED_BINARY_ENCODING)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"FORCED_BINARY_ENCODING\"", 24);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_REGULAR_EXPRESSION_FLAGS_FORCED_US_ASCII_ENCODING)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"FORCED_US_ASCII_ENCODING\"", 26);
                flags++;
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the opening_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"opening_loc\":", 14);
            pm_dump_json_location(buffer, parser, &cast->opening_loc);

            // Dump the content_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"content_loc\":", 14);
            pm_dump_json_location(buffer, parser, &cast->content_loc);

            // Dump the closing_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"closing_loc\":", 14);
            pm_dump_json_location(buffer, parser, &cast->closing_loc);

            // Dump the unescaped field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"unescaped\":", 12);
            const pm_string_t *unescaped = &cast->unescaped;
            pm_buffer_append_byte(buffer, '"');
            pm_buffer_append_source(buffer, pm_string_source(unescaped), pm_string_length(unescaped), PM_BUFFER_ESCAPING_JSON);
            pm_buffer_append_byte(buffer, '"');

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_REQUIRED_KEYWORD_PARAMETER_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"RequiredKeywordParameterNode\",\"location\":", 50);

            const pm_required_keyword_parameter_node_t *cast = (const pm_required_keyword_parameter_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the ParameterFlags field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"ParameterFlags\":", 17);
            size_t flags = 0;
            pm_buffer_append_byte(buffer, '[');
            if (PM_NODE_FLAG_P(cast, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"REPEATED_PARAMETER\"", 20);
                flags++;
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the name field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name\":", 7);
            pm_dump_json_constant(buffer, parser, cast->name);

            // Dump the name_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name_loc\":", 11);
            pm_dump_json_location(buffer, parser, &cast->name_loc);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_REQUIRED_PARAMETER_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"RequiredParameterNode\",\"location\":", 43);

            const pm_required_parameter_node_t *cast = (const pm_required_parameter_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the ParameterFlags field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"ParameterFlags\":", 17);
            size_t flags = 0;
            pm_buffer_append_byte(buffer, '[');
            if (PM_NODE_FLAG_P(cast, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"REPEATED_PARAMETER\"", 20);
                flags++;
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the name field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name\":", 7);
            pm_dump_json_constant(buffer, parser, cast->name);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_RESCUE_MODIFIER_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"RescueModifierNode\",\"location\":", 40);

            const pm_rescue_modifier_node_t *cast = (const pm_rescue_modifier_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the expression field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"expression\":", 13);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->expression);

            // Dump the keyword_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"keyword_loc\":", 14);
            pm_dump_json_location(buffer, parser, &cast->keyword_loc);

            // Dump the rescue_expression field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"rescue_expression\":", 20);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->rescue_expression);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_RESCUE_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"RescueNode\",\"location\":", 32);

            const pm_rescue_node_t *cast = (const pm_rescue_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the keyword_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"keyword_loc\":", 14);
            pm_dump_json_location(buffer, parser, &cast->keyword_loc);

            // Dump the exceptions field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"exceptions\":", 13);
            const pm_node_list_t *exceptions = &cast->exceptions;
            pm_buffer_append_byte(buffer, '[');

            for (size_t index = 0; index < exceptions->size; index++) {
                if (index != 0) pm_buffer_append_byte(buffer, ',');
                pm_dump_json(buffer, parser, exceptions->nodes[index]);
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"operator_loc\":", 15);
            if (cast->operator_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->operator_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the reference field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"reference\":", 12);
            if (cast->reference != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->reference);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the then_keyword_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"then_keyword_loc\":", 19);
            if (cast->then_keyword_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->then_keyword_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the statements field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"statements\":", 13);
            if (cast->statements != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->statements);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the subsequent field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"subsequent\":", 13);
            if (cast->subsequent != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->subsequent);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_REST_PARAMETER_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"RestParameterNode\",\"location\":", 39);

            const pm_rest_parameter_node_t *cast = (const pm_rest_parameter_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the ParameterFlags field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"ParameterFlags\":", 17);
            size_t flags = 0;
            pm_buffer_append_byte(buffer, '[');
            if (PM_NODE_FLAG_P(cast, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"REPEATED_PARAMETER\"", 20);
                flags++;
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the name field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name\":", 7);
            if (cast->name != PM_CONSTANT_ID_UNSET) {
                pm_dump_json_constant(buffer, parser, cast->name);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the name_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"name_loc\":", 11);
            if (cast->name_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->name_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"operator_loc\":", 15);
            pm_dump_json_location(buffer, parser, &cast->operator_loc);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_RETRY_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"RetryNode\",\"location\":", 31);

            const pm_retry_node_t *cast = (const pm_retry_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_RETURN_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"ReturnNode\",\"location\":", 32);

            const pm_return_node_t *cast = (const pm_return_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the keyword_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"keyword_loc\":", 14);
            pm_dump_json_location(buffer, parser, &cast->keyword_loc);

            // Dump the arguments field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"arguments\":", 12);
            if (cast->arguments != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->arguments);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_SELF_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"SelfNode\",\"location\":", 30);

            const pm_self_node_t *cast = (const pm_self_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_SHAREABLE_CONSTANT_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"ShareableConstantNode\",\"location\":", 43);

            const pm_shareable_constant_node_t *cast = (const pm_shareable_constant_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the ShareableConstantNodeFlags field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"ShareableConstantNodeFlags\":", 29);
            size_t flags = 0;
            pm_buffer_append_byte(buffer, '[');
            if (PM_NODE_FLAG_P(cast, PM_SHAREABLE_CONSTANT_NODE_FLAGS_LITERAL)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"LITERAL\"", 9);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_SHAREABLE_CONSTANT_NODE_FLAGS_EXPERIMENTAL_EVERYTHING)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"EXPERIMENTAL_EVERYTHING\"", 25);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_SHAREABLE_CONSTANT_NODE_FLAGS_EXPERIMENTAL_COPY)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"EXPERIMENTAL_COPY\"", 19);
                flags++;
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the write field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"write\":", 8);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->write);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_SINGLETON_CLASS_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"SingletonClassNode\",\"location\":", 40);

            const pm_singleton_class_node_t *cast = (const pm_singleton_class_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the locals field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"locals\":", 9);
            const pm_constant_id_list_t *locals = &cast->locals;
            pm_buffer_append_byte(buffer, '[');

            for (size_t index = 0; index < locals->size; index++) {
                if (index != 0) pm_buffer_append_byte(buffer, ',');
                pm_dump_json_constant(buffer, parser, locals->ids[index]);
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the class_keyword_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"class_keyword_loc\":", 20);
            pm_dump_json_location(buffer, parser, &cast->class_keyword_loc);

            // Dump the operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"operator_loc\":", 15);
            pm_dump_json_location(buffer, parser, &cast->operator_loc);

            // Dump the expression field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"expression\":", 13);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->expression);

            // Dump the body field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"body\":", 7);
            if (cast->body != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->body);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the end_keyword_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"end_keyword_loc\":", 18);
            pm_dump_json_location(buffer, parser, &cast->end_keyword_loc);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_SOURCE_ENCODING_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"SourceEncodingNode\",\"location\":", 40);

            const pm_source_encoding_node_t *cast = (const pm_source_encoding_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_SOURCE_FILE_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"SourceFileNode\",\"location\":", 36);

            const pm_source_file_node_t *cast = (const pm_source_file_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the StringFlags field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"StringFlags\":", 14);
            size_t flags = 0;
            pm_buffer_append_byte(buffer, '[');
            if (PM_NODE_FLAG_P(cast, PM_STRING_FLAGS_FORCED_UTF8_ENCODING)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"FORCED_UTF8_ENCODING\"", 22);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_STRING_FLAGS_FORCED_BINARY_ENCODING)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"FORCED_BINARY_ENCODING\"", 24);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_STRING_FLAGS_FROZEN)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"FROZEN\"", 8);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_STRING_FLAGS_MUTABLE)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"MUTABLE\"", 9);
                flags++;
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the filepath field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"filepath\":", 11);
            const pm_string_t *filepath = &cast->filepath;
            pm_buffer_append_byte(buffer, '"');
            pm_buffer_append_source(buffer, pm_string_source(filepath), pm_string_length(filepath), PM_BUFFER_ESCAPING_JSON);
            pm_buffer_append_byte(buffer, '"');

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_SOURCE_LINE_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"SourceLineNode\",\"location\":", 36);

            const pm_source_line_node_t *cast = (const pm_source_line_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_SPLAT_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"SplatNode\",\"location\":", 31);

            const pm_splat_node_t *cast = (const pm_splat_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the operator_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"operator_loc\":", 15);
            pm_dump_json_location(buffer, parser, &cast->operator_loc);

            // Dump the expression field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"expression\":", 13);
            if (cast->expression != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->expression);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_STATEMENTS_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"StatementsNode\",\"location\":", 36);

            const pm_statements_node_t *cast = (const pm_statements_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the body field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"body\":", 7);
            const pm_node_list_t *body = &cast->body;
            pm_buffer_append_byte(buffer, '[');

            for (size_t index = 0; index < body->size; index++) {
                if (index != 0) pm_buffer_append_byte(buffer, ',');
                pm_dump_json(buffer, parser, body->nodes[index]);
            }
            pm_buffer_append_byte(buffer, ']');

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_STRING_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"StringNode\",\"location\":", 32);

            const pm_string_node_t *cast = (const pm_string_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the StringFlags field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"StringFlags\":", 14);
            size_t flags = 0;
            pm_buffer_append_byte(buffer, '[');
            if (PM_NODE_FLAG_P(cast, PM_STRING_FLAGS_FORCED_UTF8_ENCODING)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"FORCED_UTF8_ENCODING\"", 22);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_STRING_FLAGS_FORCED_BINARY_ENCODING)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"FORCED_BINARY_ENCODING\"", 24);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_STRING_FLAGS_FROZEN)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"FROZEN\"", 8);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_STRING_FLAGS_MUTABLE)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"MUTABLE\"", 9);
                flags++;
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the opening_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"opening_loc\":", 14);
            if (cast->opening_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->opening_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the content_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"content_loc\":", 14);
            pm_dump_json_location(buffer, parser, &cast->content_loc);

            // Dump the closing_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"closing_loc\":", 14);
            if (cast->closing_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->closing_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the unescaped field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"unescaped\":", 12);
            const pm_string_t *unescaped = &cast->unescaped;
            pm_buffer_append_byte(buffer, '"');
            pm_buffer_append_source(buffer, pm_string_source(unescaped), pm_string_length(unescaped), PM_BUFFER_ESCAPING_JSON);
            pm_buffer_append_byte(buffer, '"');

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_SUPER_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"SuperNode\",\"location\":", 31);

            const pm_super_node_t *cast = (const pm_super_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the keyword_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"keyword_loc\":", 14);
            pm_dump_json_location(buffer, parser, &cast->keyword_loc);

            // Dump the lparen_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"lparen_loc\":", 13);
            if (cast->lparen_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->lparen_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the arguments field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"arguments\":", 12);
            if (cast->arguments != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->arguments);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the rparen_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"rparen_loc\":", 13);
            if (cast->rparen_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->rparen_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the block field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"block\":", 8);
            if (cast->block != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->block);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_SYMBOL_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"SymbolNode\",\"location\":", 32);

            const pm_symbol_node_t *cast = (const pm_symbol_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the SymbolFlags field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"SymbolFlags\":", 14);
            size_t flags = 0;
            pm_buffer_append_byte(buffer, '[');
            if (PM_NODE_FLAG_P(cast, PM_SYMBOL_FLAGS_FORCED_UTF8_ENCODING)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"FORCED_UTF8_ENCODING\"", 22);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_SYMBOL_FLAGS_FORCED_BINARY_ENCODING)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"FORCED_BINARY_ENCODING\"", 24);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_SYMBOL_FLAGS_FORCED_US_ASCII_ENCODING)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"FORCED_US_ASCII_ENCODING\"", 26);
                flags++;
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the opening_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"opening_loc\":", 14);
            if (cast->opening_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->opening_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the value_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"value_loc\":", 12);
            if (cast->value_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->value_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the closing_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"closing_loc\":", 14);
            if (cast->closing_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->closing_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the unescaped field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"unescaped\":", 12);
            const pm_string_t *unescaped = &cast->unescaped;
            pm_buffer_append_byte(buffer, '"');
            pm_buffer_append_source(buffer, pm_string_source(unescaped), pm_string_length(unescaped), PM_BUFFER_ESCAPING_JSON);
            pm_buffer_append_byte(buffer, '"');

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_TRUE_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"TrueNode\",\"location\":", 30);

            const pm_true_node_t *cast = (const pm_true_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_UNDEF_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"UndefNode\",\"location\":", 31);

            const pm_undef_node_t *cast = (const pm_undef_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the names field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"names\":", 8);
            const pm_node_list_t *names = &cast->names;
            pm_buffer_append_byte(buffer, '[');

            for (size_t index = 0; index < names->size; index++) {
                if (index != 0) pm_buffer_append_byte(buffer, ',');
                pm_dump_json(buffer, parser, names->nodes[index]);
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the keyword_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"keyword_loc\":", 14);
            pm_dump_json_location(buffer, parser, &cast->keyword_loc);

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_UNLESS_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"UnlessNode\",\"location\":", 32);

            const pm_unless_node_t *cast = (const pm_unless_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the keyword_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"keyword_loc\":", 14);
            pm_dump_json_location(buffer, parser, &cast->keyword_loc);

            // Dump the predicate field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"predicate\":", 12);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->predicate);

            // Dump the then_keyword_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"then_keyword_loc\":", 19);
            if (cast->then_keyword_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->then_keyword_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the statements field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"statements\":", 13);
            if (cast->statements != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->statements);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the else_clause field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"else_clause\":", 14);
            if (cast->else_clause != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->else_clause);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the end_keyword_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"end_keyword_loc\":", 18);
            if (cast->end_keyword_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->end_keyword_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_UNTIL_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"UntilNode\",\"location\":", 31);

            const pm_until_node_t *cast = (const pm_until_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the LoopFlags field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"LoopFlags\":", 12);
            size_t flags = 0;
            pm_buffer_append_byte(buffer, '[');
            if (PM_NODE_FLAG_P(cast, PM_LOOP_FLAGS_BEGIN_MODIFIER)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"BEGIN_MODIFIER\"", 16);
                flags++;
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the keyword_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"keyword_loc\":", 14);
            pm_dump_json_location(buffer, parser, &cast->keyword_loc);

            // Dump the do_keyword_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"do_keyword_loc\":", 17);
            if (cast->do_keyword_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->do_keyword_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the closing_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"closing_loc\":", 14);
            if (cast->closing_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->closing_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the predicate field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"predicate\":", 12);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->predicate);

            // Dump the statements field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"statements\":", 13);
            if (cast->statements != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->statements);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_WHEN_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"WhenNode\",\"location\":", 30);

            const pm_when_node_t *cast = (const pm_when_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the keyword_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"keyword_loc\":", 14);
            pm_dump_json_location(buffer, parser, &cast->keyword_loc);

            // Dump the conditions field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"conditions\":", 13);
            const pm_node_list_t *conditions = &cast->conditions;
            pm_buffer_append_byte(buffer, '[');

            for (size_t index = 0; index < conditions->size; index++) {
                if (index != 0) pm_buffer_append_byte(buffer, ',');
                pm_dump_json(buffer, parser, conditions->nodes[index]);
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the then_keyword_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"then_keyword_loc\":", 19);
            if (cast->then_keyword_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->then_keyword_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the statements field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"statements\":", 13);
            if (cast->statements != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->statements);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_WHILE_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"WhileNode\",\"location\":", 31);

            const pm_while_node_t *cast = (const pm_while_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the LoopFlags field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"LoopFlags\":", 12);
            size_t flags = 0;
            pm_buffer_append_byte(buffer, '[');
            if (PM_NODE_FLAG_P(cast, PM_LOOP_FLAGS_BEGIN_MODIFIER)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"BEGIN_MODIFIER\"", 16);
                flags++;
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the keyword_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"keyword_loc\":", 14);
            pm_dump_json_location(buffer, parser, &cast->keyword_loc);

            // Dump the do_keyword_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"do_keyword_loc\":", 17);
            if (cast->do_keyword_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->do_keyword_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the closing_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"closing_loc\":", 14);
            if (cast->closing_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->closing_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the predicate field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"predicate\":", 12);
            pm_dump_json(buffer, parser, (const pm_node_t *) cast->predicate);

            // Dump the statements field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"statements\":", 13);
            if (cast->statements != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->statements);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_X_STRING_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"XStringNode\",\"location\":", 33);

            const pm_x_string_node_t *cast = (const pm_x_string_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the EncodingFlags field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"EncodingFlags\":", 16);
            size_t flags = 0;
            pm_buffer_append_byte(buffer, '[');
            if (PM_NODE_FLAG_P(cast, PM_ENCODING_FLAGS_FORCED_UTF8_ENCODING)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"FORCED_UTF8_ENCODING\"", 22);
                flags++;
            }
            if (PM_NODE_FLAG_P(cast, PM_ENCODING_FLAGS_FORCED_BINARY_ENCODING)) {
                if (flags != 0) pm_buffer_append_byte(buffer, ',');
                pm_buffer_append_string(buffer, "\"FORCED_BINARY_ENCODING\"", 24);
                flags++;
            }
            pm_buffer_append_byte(buffer, ']');

            // Dump the opening_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"opening_loc\":", 14);
            pm_dump_json_location(buffer, parser, &cast->opening_loc);

            // Dump the content_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"content_loc\":", 14);
            pm_dump_json_location(buffer, parser, &cast->content_loc);

            // Dump the closing_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"closing_loc\":", 14);
            pm_dump_json_location(buffer, parser, &cast->closing_loc);

            // Dump the unescaped field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"unescaped\":", 12);
            const pm_string_t *unescaped = &cast->unescaped;
            pm_buffer_append_byte(buffer, '"');
            pm_buffer_append_source(buffer, pm_string_source(unescaped), pm_string_length(unescaped), PM_BUFFER_ESCAPING_JSON);
            pm_buffer_append_byte(buffer, '"');

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_YIELD_NODE: {
            pm_buffer_append_string(buffer, "{\"type\":\"YieldNode\",\"location\":", 31);

            const pm_yield_node_t *cast = (const pm_yield_node_t *) node;
            pm_dump_json_location(buffer, parser, &cast->base.location);

            // Dump the keyword_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"keyword_loc\":", 14);
            pm_dump_json_location(buffer, parser, &cast->keyword_loc);

            // Dump the lparen_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"lparen_loc\":", 13);
            if (cast->lparen_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->lparen_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the arguments field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"arguments\":", 12);
            if (cast->arguments != NULL) {
                pm_dump_json(buffer, parser, (const pm_node_t *) cast->arguments);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            // Dump the rparen_loc field
            pm_buffer_append_byte(buffer, ',');
            pm_buffer_append_string(buffer, "\"rparen_loc\":", 13);
            if (cast->rparen_loc.start != NULL) {
                pm_dump_json_location(buffer, parser, &cast->rparen_loc);
            } else {
                pm_buffer_append_string(buffer, "null", 4);
            }

            pm_buffer_append_byte(buffer, '}');
            break;
        }
        case PM_SCOPE_NODE:
            break;
    }
}

#endif
