/*----------------------------------------------------------------------------*/
/* This file is generated by the templates/template.rb script and should not  */
/* be modified manually.                                                      */
/* To change the template see                                                 */
/* templates/ext/rbs_extension/ast_translation.c.erb                          */
/*----------------------------------------------------------------------------*/

#include "ast_translation.h"

#include "class_constants.h"
#include "rbs_string_bridging.h"
#include "legacy_location.h"

VALUE EMPTY_ARRAY;
VALUE EMPTY_HASH;

#define RBS_LOCATION_CHILDREN_SIZE(cap) (sizeof(rbs_location_children) + sizeof(rbs_location_entry) * ((cap) - 1))
#define RBS_LOCATION_REQUIRED_P(loc, i) ((loc)->children->required_p & (1 << (i)))
#define RBS_LOCATION_OPTIONAL_P(loc, i) (!RBS_LOCATION_REQUIRED_P((loc), (i)))

rbs_translation_context_t rbs_translation_context_create(rbs_constant_pool_t *constant_pool, VALUE buffer, rb_encoding *ruby_encoding) {
    return (rbs_translation_context_t) {
        .constant_pool = constant_pool,
        .buffer = buffer,
        .encoding = ruby_encoding,
    };
}

VALUE rbs_node_list_to_ruby_array(rbs_translation_context_t ctx, rbs_node_list_t *list) {
    VALUE ruby_array = rb_ary_new();

    for (rbs_node_list_node_t *n = list->head; n != NULL; n = n->next) {
        rb_ary_push(ruby_array, rbs_struct_to_ruby_value(ctx, n->node));
    }

    return ruby_array;
}

VALUE rbs_hash_to_ruby_hash(rbs_translation_context_t ctx, rbs_hash_t *rbs_hash) {
    if (!rbs_hash->head) {
        return EMPTY_HASH;
    }

    VALUE ruby_hash = rb_hash_new();

    for (rbs_hash_node_t *n = rbs_hash->head; n != NULL; n = n->next) {
        VALUE key = rbs_struct_to_ruby_value(ctx, n->key);
        VALUE value = rbs_struct_to_ruby_value(ctx, n->value);
        rb_hash_aset(ruby_hash, key, value);
    }

    return ruby_hash;
}

VALUE rbs_location_range_to_ruby_location(rbs_translation_context_t ctx, rbs_location_range range) {
    if (RBS_LOCATION_NULL_RANGE_P(range)) {
        return Qnil;
    }

    return rbs_new_location2(ctx.buffer, range.start_char, range.end_char);
}

VALUE rbs_location_range_list_to_ruby_array(rbs_translation_context_t ctx, rbs_location_range_list_t *list) {
    if (list == NULL) {
        return EMPTY_ARRAY;
    }

    VALUE ruby_array = rb_ary_new();

    for (rbs_location_range_list_node_t *n = list->head; n != NULL; n = n->next) {
        rb_ary_push(ruby_array, rbs_location_range_to_ruby_location(ctx, n->range));
    }

    return ruby_array;
}

VALUE rbs_attr_ivar_name_to_ruby(rbs_translation_context_t ctx, rbs_attr_ivar_name_t ivar_name) {
    switch (ivar_name.tag) {
    case RBS_ATTR_IVAR_NAME_TAG_NAME: {
        rbs_constant_t *constant = rbs_constant_pool_id_to_constant(ctx.constant_pool, ivar_name.name);
        assert(constant != NULL && "constant is NULL");
        assert(constant->start != NULL && "constant->start is NULL");

        return ID2SYM(rb_intern3((const char *) constant->start, constant->length, ctx.encoding));
    }
    case RBS_ATTR_IVAR_NAME_TAG_UNSPECIFIED:
        return Qnil;
    case RBS_ATTR_IVAR_NAME_TAG_EMPTY:
        return Qfalse;
    default:
        rb_fatal("unknown enum rbs_attr_ivar_name_tag ivar_name.tag: %d", ivar_name.tag);
    }
}

VALUE rbs_attribute_visibility_to_ruby(enum rbs_attribute_visibility value) {
    switch (value) {
    case RBS_ATTRIBUTE_VISIBILITY_UNSPECIFIED:
        return Qnil;
    case RBS_ATTRIBUTE_VISIBILITY_PUBLIC:
        return rb_id2sym(rb_intern("public"));
    case RBS_ATTRIBUTE_VISIBILITY_PRIVATE:
        return rb_id2sym(rb_intern("private"));
    default:
        rb_fatal("unknown enum rbs_attribute_visibility value: %d", value);
    }
}

VALUE rbs_attribute_kind_to_ruby(enum rbs_attribute_kind value) {
    switch (value) {
    case RBS_ATTRIBUTE_KIND_INSTANCE:
        return rb_id2sym(rb_intern("instance"));
    case RBS_ATTRIBUTE_KIND_SINGLETON:
        return rb_id2sym(rb_intern("singleton"));
    default:
        rb_fatal("unknown enum rbs_attribute_kind value: %d", value);
    }
}

VALUE rbs_alias_kind_to_ruby(enum rbs_alias_kind value) {
    switch (value) {
    case RBS_ALIAS_KIND_INSTANCE:
        return rb_id2sym(rb_intern("instance"));
    case RBS_ALIAS_KIND_SINGLETON:
        return rb_id2sym(rb_intern("singleton"));
    default:
        rb_fatal("unknown enum rbs_alias_kind value: %d", value);
    }
}

VALUE rbs_method_definition_kind_to_ruby(enum rbs_method_definition_kind value) {
    switch (value) {
    case RBS_METHOD_DEFINITION_KIND_INSTANCE:
        return rb_id2sym(rb_intern("instance"));
    case RBS_METHOD_DEFINITION_KIND_SINGLETON:
        return rb_id2sym(rb_intern("singleton"));
    case RBS_METHOD_DEFINITION_KIND_SINGLETON_INSTANCE:
        return rb_id2sym(rb_intern("singleton_instance"));
    default:
        rb_fatal("unknown enum rbs_method_definition_kind value: %d", value);
    }
}

VALUE rbs_method_definition_visibility_to_ruby(enum rbs_method_definition_visibility value) {
    switch (value) {
    case RBS_METHOD_DEFINITION_VISIBILITY_UNSPECIFIED:
        return Qnil;
    case RBS_METHOD_DEFINITION_VISIBILITY_PUBLIC:
        return rb_id2sym(rb_intern("public"));
    case RBS_METHOD_DEFINITION_VISIBILITY_PRIVATE:
        return rb_id2sym(rb_intern("private"));
    default:
        rb_fatal("unknown enum rbs_method_definition_visibility value: %d", value);
    }
}

VALUE rbs_type_param_variance_to_ruby(enum rbs_type_param_variance value) {
    switch (value) {
    case RBS_TYPE_PARAM_VARIANCE_INVARIANT:
        return rb_id2sym(rb_intern("invariant"));
    case RBS_TYPE_PARAM_VARIANCE_COVARIANT:
        return rb_id2sym(rb_intern("covariant"));
    case RBS_TYPE_PARAM_VARIANCE_CONTRAVARIANT:
        return rb_id2sym(rb_intern("contravariant"));
    default:
        rb_fatal("unknown enum rbs_type_param_variance value: %d", value);
    }
}

#ifdef RB_PASS_KEYWORDS
// Ruby 2.7 or later
#define CLASS_NEW_INSTANCE(klass, argc, argv) \
    rb_class_new_instance_kw(argc, argv, klass, RB_PASS_KEYWORDS)
#else
// Ruby 2.6
#define CLASS_NEW_INSTANCE(receiver, argc, argv) \
    rb_class_new_instance(argc, argv, receiver)
#endif

VALUE rbs_struct_to_ruby_value(rbs_translation_context_t ctx, rbs_node_t *instance) {
    if (instance == NULL) return Qnil;

    switch (instance->type) {
    case RBS_AST_ANNOTATION: {
        rbs_ast_annotation_t *node = (rbs_ast_annotation_t *) instance;

        VALUE h = rb_hash_new();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
        rb_hash_aset(h, ID2SYM(rb_intern("string")), rbs_string_to_ruby_string(&node->string, ctx.encoding));

        return CLASS_NEW_INSTANCE(
            RBS_AST_Annotation,
            1,
            &h
        );
    }
    case RBS_AST_BOOL: {
        return ((rbs_ast_bool_t *) instance)->value ? Qtrue : Qfalse;
    }
    case RBS_AST_COMMENT: {
        rbs_ast_comment_t *node = (rbs_ast_comment_t *) instance;

        VALUE h = rb_hash_new();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
        rb_hash_aset(h, ID2SYM(rb_intern("string")), rbs_string_to_ruby_string(&node->string, ctx.encoding));

        return CLASS_NEW_INSTANCE(
            RBS_AST_Comment,
            1,
            &h
        );
    }
    case RBS_AST_DECLARATIONS_CLASS: {
        rbs_ast_declarations_class_t *node = (rbs_ast_declarations_class_t *) instance;

        VALUE h = rb_hash_new();
        VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
        rbs_loc *loc = rbs_check_location(location);
        rbs_loc_legacy_alloc_children(loc, 5);
        rbs_loc_legacy_add_required_child(loc, rb_intern("keyword"), (rbs_loc_range) { .start = node->keyword_range.start_char, .end = node->keyword_range.end_char });
        rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
        rbs_loc_legacy_add_required_child(loc, rb_intern("end"), (rbs_loc_range) { .start = node->end_range.start_char, .end = node->end_range.end_char });
        rbs_loc_legacy_add_optional_child(loc, rb_intern("type_params"), (rbs_loc_range) { .start = node->type_params_range.start_char, .end = node->type_params_range.end_char });
        rbs_loc_legacy_add_optional_child(loc, rb_intern("lt"), (rbs_loc_range) { .start = node->lt_range.start_char, .end = node->lt_range.end_char });
        rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
        rb_hash_aset(h, ID2SYM(rb_intern("name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name)); // rbs_type_name
        rb_hash_aset(h, ID2SYM(rb_intern("type_params")), rbs_node_list_to_ruby_array(ctx, node->type_params));
        rb_hash_aset(h, ID2SYM(rb_intern("super_class")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->super_class)); // rbs_ast_declarations_class_super
        rb_hash_aset(h, ID2SYM(rb_intern("members")), rbs_node_list_to_ruby_array(ctx, node->members));
        rb_hash_aset(h, ID2SYM(rb_intern("annotations")), rbs_node_list_to_ruby_array(ctx, node->annotations));
        rb_hash_aset(h, ID2SYM(rb_intern("comment")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->comment)); // rbs_ast_comment

        rb_funcall(
            RBS_AST_TypeParam,
            rb_intern("resolve_variables"),
            1,
            rb_hash_lookup(h, ID2SYM(rb_intern("type_params")))
        );
        return CLASS_NEW_INSTANCE(
            RBS_AST_Declarations_Class,
            1,
            &h
        );
    }
    case RBS_AST_DECLARATIONS_CLASS_SUPER: {
        rbs_ast_declarations_class_super_t *node = (rbs_ast_declarations_class_super_t *) instance;

        VALUE h = rb_hash_new();
        VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
        rbs_loc *loc = rbs_check_location(location);
        rbs_loc_legacy_alloc_children(loc, 2);
        rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
        rbs_loc_legacy_add_optional_child(loc, rb_intern("args"), (rbs_loc_range) { .start = node->args_range.start_char, .end = node->args_range.end_char });
        rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
        rb_hash_aset(h, ID2SYM(rb_intern("name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name)); // rbs_type_name
        rb_hash_aset(h, ID2SYM(rb_intern("args")), rbs_node_list_to_ruby_array(ctx, node->args));

        return CLASS_NEW_INSTANCE(
            RBS_AST_Declarations_Class_Super,
            1,
            &h
        );
    }
    case RBS_AST_DECLARATIONS_CLASS_ALIAS: {
        rbs_ast_declarations_class_alias_t *node = (rbs_ast_declarations_class_alias_t *) instance;

        VALUE h = rb_hash_new();
        VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
        rbs_loc *loc = rbs_check_location(location);
        rbs_loc_legacy_alloc_children(loc, 4);
        rbs_loc_legacy_add_required_child(loc, rb_intern("keyword"), (rbs_loc_range) { .start = node->keyword_range.start_char, .end = node->keyword_range.end_char });
        rbs_loc_legacy_add_required_child(loc, rb_intern("new_name"), (rbs_loc_range) { .start = node->new_name_range.start_char, .end = node->new_name_range.end_char });
        rbs_loc_legacy_add_required_child(loc, rb_intern("eq"), (rbs_loc_range) { .start = node->eq_range.start_char, .end = node->eq_range.end_char });
        rbs_loc_legacy_add_required_child(loc, rb_intern("old_name"), (rbs_loc_range) { .start = node->old_name_range.start_char, .end = node->old_name_range.end_char });
        rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
        rb_hash_aset(h, ID2SYM(rb_intern("new_name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->new_name)); // rbs_type_name
        rb_hash_aset(h, ID2SYM(rb_intern("old_name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->old_name)); // rbs_type_name
        rb_hash_aset(h, ID2SYM(rb_intern("comment")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->comment));   // rbs_ast_comment
        rb_hash_aset(h, ID2SYM(rb_intern("annotations")), rbs_node_list_to_ruby_array(ctx, node->annotations));

        return CLASS_NEW_INSTANCE(
            RBS_AST_Declarations_ClassAlias,
            1,
            &h
        );
    }
    case RBS_AST_DECLARATIONS_CONSTANT: {
        rbs_ast_declarations_constant_t *node = (rbs_ast_declarations_constant_t *) instance;

        VALUE h = rb_hash_new();
        VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
        rbs_loc *loc = rbs_check_location(location);
        rbs_loc_legacy_alloc_children(loc, 2);
        rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
        rbs_loc_legacy_add_required_child(loc, rb_intern("colon"), (rbs_loc_range) { .start = node->colon_range.start_char, .end = node->colon_range.end_char });
        rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
        rb_hash_aset(h, ID2SYM(rb_intern("name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name));       // rbs_type_name
        rb_hash_aset(h, ID2SYM(rb_intern("type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type));       // rbs_node
        rb_hash_aset(h, ID2SYM(rb_intern("comment")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->comment)); // rbs_ast_comment
        rb_hash_aset(h, ID2SYM(rb_intern("annotations")), rbs_node_list_to_ruby_array(ctx, node->annotations));

        return CLASS_NEW_INSTANCE(
            RBS_AST_Declarations_Constant,
            1,
            &h
        );
    }
    case RBS_AST_DECLARATIONS_GLOBAL: {
        rbs_ast_declarations_global_t *node = (rbs_ast_declarations_global_t *) instance;

        VALUE h = rb_hash_new();
        VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
        rbs_loc *loc = rbs_check_location(location);
        rbs_loc_legacy_alloc_children(loc, 2);
        rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
        rbs_loc_legacy_add_required_child(loc, rb_intern("colon"), (rbs_loc_range) { .start = node->colon_range.start_char, .end = node->colon_range.end_char });
        rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
        rb_hash_aset(h, ID2SYM(rb_intern("name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name));       // rbs_ast_symbol
        rb_hash_aset(h, ID2SYM(rb_intern("type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type));       // rbs_node
        rb_hash_aset(h, ID2SYM(rb_intern("comment")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->comment)); // rbs_ast_comment
        rb_hash_aset(h, ID2SYM(rb_intern("annotations")), rbs_node_list_to_ruby_array(ctx, node->annotations));

        return CLASS_NEW_INSTANCE(
            RBS_AST_Declarations_Global,
            1,
            &h
        );
    }
    case RBS_AST_DECLARATIONS_INTERFACE: {
        rbs_ast_declarations_interface_t *node = (rbs_ast_declarations_interface_t *) instance;

        VALUE h = rb_hash_new();
        VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
        rbs_loc *loc = rbs_check_location(location);
        rbs_loc_legacy_alloc_children(loc, 4);
        rbs_loc_legacy_add_required_child(loc, rb_intern("keyword"), (rbs_loc_range) { .start = node->keyword_range.start_char, .end = node->keyword_range.end_char });
        rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
        rbs_loc_legacy_add_required_child(loc, rb_intern("end"), (rbs_loc_range) { .start = node->end_range.start_char, .end = node->end_range.end_char });
        rbs_loc_legacy_add_optional_child(loc, rb_intern("type_params"), (rbs_loc_range) { .start = node->type_params_range.start_char, .end = node->type_params_range.end_char });
        rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
        rb_hash_aset(h, ID2SYM(rb_intern("name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name)); // rbs_type_name
        rb_hash_aset(h, ID2SYM(rb_intern("type_params")), rbs_node_list_to_ruby_array(ctx, node->type_params));
        rb_hash_aset(h, ID2SYM(rb_intern("members")), rbs_node_list_to_ruby_array(ctx, node->members));
        rb_hash_aset(h, ID2SYM(rb_intern("annotations")), rbs_node_list_to_ruby_array(ctx, node->annotations));
        rb_hash_aset(h, ID2SYM(rb_intern("comment")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->comment)); // rbs_ast_comment

        rb_funcall(
            RBS_AST_TypeParam,
            rb_intern("resolve_variables"),
            1,
            rb_hash_lookup(h, ID2SYM(rb_intern("type_params")))
        );
        return CLASS_NEW_INSTANCE(
            RBS_AST_Declarations_Interface,
            1,
            &h
        );
    }
    case RBS_AST_DECLARATIONS_MODULE: {
        rbs_ast_declarations_module_t *node = (rbs_ast_declarations_module_t *) instance;

        VALUE h = rb_hash_new();
        VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
        rbs_loc *loc = rbs_check_location(location);
        rbs_loc_legacy_alloc_children(loc, 6);
        rbs_loc_legacy_add_required_child(loc, rb_intern("keyword"), (rbs_loc_range) { .start = node->keyword_range.start_char, .end = node->keyword_range.end_char });
        rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
        rbs_loc_legacy_add_required_child(loc, rb_intern("end"), (rbs_loc_range) { .start = node->end_range.start_char, .end = node->end_range.end_char });
        rbs_loc_legacy_add_optional_child(loc, rb_intern("type_params"), (rbs_loc_range) { .start = node->type_params_range.start_char, .end = node->type_params_range.end_char });
        rbs_loc_legacy_add_optional_child(loc, rb_intern("colon"), (rbs_loc_range) { .start = node->colon_range.start_char, .end = node->colon_range.end_char });
        rbs_loc_legacy_add_optional_child(loc, rb_intern("self_types"), (rbs_loc_range) { .start = node->self_types_range.start_char, .end = node->self_types_range.end_char });
        rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
        rb_hash_aset(h, ID2SYM(rb_intern("name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name)); // rbs_type_name
        rb_hash_aset(h, ID2SYM(rb_intern("type_params")), rbs_node_list_to_ruby_array(ctx, node->type_params));
        rb_hash_aset(h, ID2SYM(rb_intern("self_types")), rbs_node_list_to_ruby_array(ctx, node->self_types));
        rb_hash_aset(h, ID2SYM(rb_intern("members")), rbs_node_list_to_ruby_array(ctx, node->members));
        rb_hash_aset(h, ID2SYM(rb_intern("annotations")), rbs_node_list_to_ruby_array(ctx, node->annotations));
        rb_hash_aset(h, ID2SYM(rb_intern("comment")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->comment)); // rbs_ast_comment

        rb_funcall(
            RBS_AST_TypeParam,
            rb_intern("resolve_variables"),
            1,
            rb_hash_lookup(h, ID2SYM(rb_intern("type_params")))
        );
        return CLASS_NEW_INSTANCE(
            RBS_AST_Declarations_Module,
            1,
            &h
        );
    }
    case RBS_AST_DECLARATIONS_MODULE_SELF: {
        rbs_ast_declarations_module_self_t *node = (rbs_ast_declarations_module_self_t *) instance;

        VALUE h = rb_hash_new();
        VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
        rbs_loc *loc = rbs_check_location(location);
        rbs_loc_legacy_alloc_children(loc, 2);
        rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
        rbs_loc_legacy_add_optional_child(loc, rb_intern("args"), (rbs_loc_range) { .start = node->args_range.start_char, .end = node->args_range.end_char });
        rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
        rb_hash_aset(h, ID2SYM(rb_intern("name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name)); // rbs_type_name
        rb_hash_aset(h, ID2SYM(rb_intern("args")), rbs_node_list_to_ruby_array(ctx, node->args));

        return CLASS_NEW_INSTANCE(
            RBS_AST_Declarations_Module_Self,
            1,
            &h
        );
    }
    case RBS_AST_DECLARATIONS_MODULE_ALIAS: {
        rbs_ast_declarations_module_alias_t *node = (rbs_ast_declarations_module_alias_t *) instance;

        VALUE h = rb_hash_new();
        VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
        rbs_loc *loc = rbs_check_location(location);
        rbs_loc_legacy_alloc_children(loc, 4);
        rbs_loc_legacy_add_required_child(loc, rb_intern("keyword"), (rbs_loc_range) { .start = node->keyword_range.start_char, .end = node->keyword_range.end_char });
        rbs_loc_legacy_add_required_child(loc, rb_intern("new_name"), (rbs_loc_range) { .start = node->new_name_range.start_char, .end = node->new_name_range.end_char });
        rbs_loc_legacy_add_required_child(loc, rb_intern("eq"), (rbs_loc_range) { .start = node->eq_range.start_char, .end = node->eq_range.end_char });
        rbs_loc_legacy_add_required_child(loc, rb_intern("old_name"), (rbs_loc_range) { .start = node->old_name_range.start_char, .end = node->old_name_range.end_char });
        rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
        rb_hash_aset(h, ID2SYM(rb_intern("new_name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->new_name)); // rbs_type_name
        rb_hash_aset(h, ID2SYM(rb_intern("old_name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->old_name)); // rbs_type_name
        rb_hash_aset(h, ID2SYM(rb_intern("comment")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->comment));   // rbs_ast_comment
        rb_hash_aset(h, ID2SYM(rb_intern("annotations")), rbs_node_list_to_ruby_array(ctx, node->annotations));

        return CLASS_NEW_INSTANCE(
            RBS_AST_Declarations_ModuleAlias,
            1,
            &h
        );
    }
    case RBS_AST_DECLARATIONS_TYPE_ALIAS: {
        rbs_ast_declarations_type_alias_t *node = (rbs_ast_declarations_type_alias_t *) instance;

        VALUE h = rb_hash_new();
        VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
        rbs_loc *loc = rbs_check_location(location);
        rbs_loc_legacy_alloc_children(loc, 4);
        rbs_loc_legacy_add_required_child(loc, rb_intern("keyword"), (rbs_loc_range) { .start = node->keyword_range.start_char, .end = node->keyword_range.end_char });
        rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
        rbs_loc_legacy_add_required_child(loc, rb_intern("eq"), (rbs_loc_range) { .start = node->eq_range.start_char, .end = node->eq_range.end_char });
        rbs_loc_legacy_add_optional_child(loc, rb_intern("type_params"), (rbs_loc_range) { .start = node->type_params_range.start_char, .end = node->type_params_range.end_char });
        rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
        rb_hash_aset(h, ID2SYM(rb_intern("name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name)); // rbs_type_name
        rb_hash_aset(h, ID2SYM(rb_intern("type_params")), rbs_node_list_to_ruby_array(ctx, node->type_params));
        rb_hash_aset(h, ID2SYM(rb_intern("type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type)); // rbs_node
        rb_hash_aset(h, ID2SYM(rb_intern("annotations")), rbs_node_list_to_ruby_array(ctx, node->annotations));
        rb_hash_aset(h, ID2SYM(rb_intern("comment")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->comment)); // rbs_ast_comment

        rb_funcall(
            RBS_AST_TypeParam,
            rb_intern("resolve_variables"),
            1,
            rb_hash_lookup(h, ID2SYM(rb_intern("type_params")))
        );
        return CLASS_NEW_INSTANCE(
            RBS_AST_Declarations_TypeAlias,
            1,
            &h
        );
    }
    case RBS_AST_DIRECTIVES_USE: {
        rbs_ast_directives_use_t *node = (rbs_ast_directives_use_t *) instance;

        VALUE h = rb_hash_new();
        VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
        rbs_loc *loc = rbs_check_location(location);
        rbs_loc_legacy_alloc_children(loc, 1);
        rbs_loc_legacy_add_required_child(loc, rb_intern("keyword"), (rbs_loc_range) { .start = node->keyword_range.start_char, .end = node->keyword_range.end_char });
        rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
        rb_hash_aset(h, ID2SYM(rb_intern("clauses")), rbs_node_list_to_ruby_array(ctx, node->clauses));

        return CLASS_NEW_INSTANCE(
            RBS_AST_Directives_Use,
            1,
            &h
        );
    }
    case RBS_AST_DIRECTIVES_USE_SINGLE_CLAUSE: {
        rbs_ast_directives_use_single_clause_t *node = (rbs_ast_directives_use_single_clause_t *) instance;

        VALUE h = rb_hash_new();
        VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
        rbs_loc *loc = rbs_check_location(location);
        rbs_loc_legacy_alloc_children(loc, 3);
        rbs_loc_legacy_add_required_child(loc, rb_intern("type_name"), (rbs_loc_range) { .start = node->type_name_range.start_char, .end = node->type_name_range.end_char });
        rbs_loc_legacy_add_optional_child(loc, rb_intern("keyword"), (rbs_loc_range) { .start = node->keyword_range.start_char, .end = node->keyword_range.end_char });
        rbs_loc_legacy_add_optional_child(loc, rb_intern("new_name"), (rbs_loc_range) { .start = node->new_name_range.start_char, .end = node->new_name_range.end_char });
        rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
        rb_hash_aset(h, ID2SYM(rb_intern("type_name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type_name)); // rbs_type_name
        rb_hash_aset(h, ID2SYM(rb_intern("new_name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->new_name));   // rbs_ast_symbol

        return CLASS_NEW_INSTANCE(
            RBS_AST_Directives_Use_SingleClause,
            1,
            &h
        );
    }
    case RBS_AST_DIRECTIVES_USE_WILDCARD_CLAUSE: {
        rbs_ast_directives_use_wildcard_clause_t *node = (rbs_ast_directives_use_wildcard_clause_t *) instance;

        VALUE h = rb_hash_new();
        VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
        rbs_loc *loc = rbs_check_location(location);
        rbs_loc_legacy_alloc_children(loc, 2);
        rbs_loc_legacy_add_required_child(loc, rb_intern("namespace"), (rbs_loc_range) { .start = node->namespace_range.start_char, .end = node->namespace_range.end_char });
        rbs_loc_legacy_add_required_child(loc, rb_intern("star"), (rbs_loc_range) { .start = node->star_range.start_char, .end = node->star_range.end_char });
        rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
        rb_hash_aset(h, ID2SYM(rb_intern("namespace")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->rbs_namespace)); // rbs_namespace

        return CLASS_NEW_INSTANCE(
            RBS_AST_Directives_Use_WildcardClause,
            1,
            &h
        );
    }
    case RBS_AST_INTEGER: {
        rbs_ast_integer_t *integer_node = (rbs_ast_integer_t *) instance;
        rbs_string_t string_repr = integer_node->string_representation;

        VALUE str = rb_enc_str_new(string_repr.start, rbs_string_len(string_repr), rb_utf8_encoding());

        return rb_funcall(str, rb_intern("to_i"), 0);
    }
    case RBS_AST_MEMBERS_ALIAS: {
        rbs_ast_members_alias_t *node = (rbs_ast_members_alias_t *) instance;

        VALUE h = rb_hash_new();
        VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
        rbs_loc *loc = rbs_check_location(location);
        rbs_loc_legacy_alloc_children(loc, 5);
        rbs_loc_legacy_add_required_child(loc, rb_intern("keyword"), (rbs_loc_range) { .start = node->keyword_range.start_char, .end = node->keyword_range.end_char });
        rbs_loc_legacy_add_required_child(loc, rb_intern("new_name"), (rbs_loc_range) { .start = node->new_name_range.start_char, .end = node->new_name_range.end_char });
        rbs_loc_legacy_add_required_child(loc, rb_intern("old_name"), (rbs_loc_range) { .start = node->old_name_range.start_char, .end = node->old_name_range.end_char });
        rbs_loc_legacy_add_optional_child(loc, rb_intern("new_kind"), (rbs_loc_range) { .start = node->new_kind_range.start_char, .end = node->new_kind_range.end_char });
        rbs_loc_legacy_add_optional_child(loc, rb_intern("old_kind"), (rbs_loc_range) { .start = node->old_kind_range.start_char, .end = node->old_kind_range.end_char });
        rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
        rb_hash_aset(h, ID2SYM(rb_intern("new_name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->new_name)); // rbs_ast_symbol
        rb_hash_aset(h, ID2SYM(rb_intern("old_name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->old_name)); // rbs_ast_symbol
        rb_hash_aset(h, ID2SYM(rb_intern("kind")), rbs_alias_kind_to_ruby(node->kind));                               // alias_kind
        rb_hash_aset(h, ID2SYM(rb_intern("annotations")), rbs_node_list_to_ruby_array(ctx, node->annotations));
        rb_hash_aset(h, ID2SYM(rb_intern("comment")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->comment)); // rbs_ast_comment

        return CLASS_NEW_INSTANCE(
            RBS_AST_Members_Alias,
            1,
            &h
        );
    }
    case RBS_AST_MEMBERS_ATTR_ACCESSOR: {
        rbs_ast_members_attr_accessor_t *node = (rbs_ast_members_attr_accessor_t *) instance;

        VALUE h = rb_hash_new();
        VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
        rbs_loc *loc = rbs_check_location(location);
        rbs_loc_legacy_alloc_children(loc, 7);
        rbs_loc_legacy_add_required_child(loc, rb_intern("keyword"), (rbs_loc_range) { .start = node->keyword_range.start_char, .end = node->keyword_range.end_char });
        rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
        rbs_loc_legacy_add_required_child(loc, rb_intern("colon"), (rbs_loc_range) { .start = node->colon_range.start_char, .end = node->colon_range.end_char });
        rbs_loc_legacy_add_optional_child(loc, rb_intern("kind"), (rbs_loc_range) { .start = node->kind_range.start_char, .end = node->kind_range.end_char });
        rbs_loc_legacy_add_optional_child(loc, rb_intern("ivar"), (rbs_loc_range) { .start = node->ivar_range.start_char, .end = node->ivar_range.end_char });
        rbs_loc_legacy_add_optional_child(loc, rb_intern("ivar_name"), (rbs_loc_range) { .start = node->ivar_name_range.start_char, .end = node->ivar_name_range.end_char });
        rbs_loc_legacy_add_optional_child(loc, rb_intern("visibility"), (rbs_loc_range) { .start = node->visibility_range.start_char, .end = node->visibility_range.end_char });
        rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
        rb_hash_aset(h, ID2SYM(rb_intern("name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name)); // rbs_ast_symbol
        rb_hash_aset(h, ID2SYM(rb_intern("type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type)); // rbs_node
        rb_hash_aset(h, ID2SYM(rb_intern("ivar_name")), rbs_attr_ivar_name_to_ruby(ctx, node->ivar_name));    // rbs_attr_ivar_name_t
        rb_hash_aset(h, ID2SYM(rb_intern("kind")), rbs_attribute_kind_to_ruby(node->kind));                   // attribute_kind
        rb_hash_aset(h, ID2SYM(rb_intern("annotations")), rbs_node_list_to_ruby_array(ctx, node->annotations));
        rb_hash_aset(h, ID2SYM(rb_intern("comment")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->comment)); // rbs_ast_comment
        rb_hash_aset(h, ID2SYM(rb_intern("visibility")), rbs_attribute_visibility_to_ruby(node->visibility));       // attribute_visibility

        return CLASS_NEW_INSTANCE(
            RBS_AST_Members_AttrAccessor,
            1,
            &h
        );
    }
    case RBS_AST_MEMBERS_ATTR_READER: {
        rbs_ast_members_attr_reader_t *node = (rbs_ast_members_attr_reader_t *) instance;

        VALUE h = rb_hash_new();
        VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
        rbs_loc *loc = rbs_check_location(location);
        rbs_loc_legacy_alloc_children(loc, 7);
        rbs_loc_legacy_add_required_child(loc, rb_intern("keyword"), (rbs_loc_range) { .start = node->keyword_range.start_char, .end = node->keyword_range.end_char });
        rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
        rbs_loc_legacy_add_required_child(loc, rb_intern("colon"), (rbs_loc_range) { .start = node->colon_range.start_char, .end = node->colon_range.end_char });
        rbs_loc_legacy_add_optional_child(loc, rb_intern("kind"), (rbs_loc_range) { .start = node->kind_range.start_char, .end = node->kind_range.end_char });
        rbs_loc_legacy_add_optional_child(loc, rb_intern("ivar"), (rbs_loc_range) { .start = node->ivar_range.start_char, .end = node->ivar_range.end_char });
        rbs_loc_legacy_add_optional_child(loc, rb_intern("ivar_name"), (rbs_loc_range) { .start = node->ivar_name_range.start_char, .end = node->ivar_name_range.end_char });
        rbs_loc_legacy_add_optional_child(loc, rb_intern("visibility"), (rbs_loc_range) { .start = node->visibility_range.start_char, .end = node->visibility_range.end_char });
        rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
        rb_hash_aset(h, ID2SYM(rb_intern("name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name)); // rbs_ast_symbol
        rb_hash_aset(h, ID2SYM(rb_intern("type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type)); // rbs_node
        rb_hash_aset(h, ID2SYM(rb_intern("ivar_name")), rbs_attr_ivar_name_to_ruby(ctx, node->ivar_name));    // rbs_attr_ivar_name_t
        rb_hash_aset(h, ID2SYM(rb_intern("kind")), rbs_attribute_kind_to_ruby(node->kind));                   // attribute_kind
        rb_hash_aset(h, ID2SYM(rb_intern("annotations")), rbs_node_list_to_ruby_array(ctx, node->annotations));
        rb_hash_aset(h, ID2SYM(rb_intern("comment")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->comment)); // rbs_ast_comment
        rb_hash_aset(h, ID2SYM(rb_intern("visibility")), rbs_attribute_visibility_to_ruby(node->visibility));       // attribute_visibility

        return CLASS_NEW_INSTANCE(
            RBS_AST_Members_AttrReader,
            1,
            &h
        );
    }
    case RBS_AST_MEMBERS_ATTR_WRITER: {
        rbs_ast_members_attr_writer_t *node = (rbs_ast_members_attr_writer_t *) instance;

        VALUE h = rb_hash_new();
        VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
        rbs_loc *loc = rbs_check_location(location);
        rbs_loc_legacy_alloc_children(loc, 7);
        rbs_loc_legacy_add_required_child(loc, rb_intern("keyword"), (rbs_loc_range) { .start = node->keyword_range.start_char, .end = node->keyword_range.end_char });
        rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
        rbs_loc_legacy_add_required_child(loc, rb_intern("colon"), (rbs_loc_range) { .start = node->colon_range.start_char, .end = node->colon_range.end_char });
        rbs_loc_legacy_add_optional_child(loc, rb_intern("kind"), (rbs_loc_range) { .start = node->kind_range.start_char, .end = node->kind_range.end_char });
        rbs_loc_legacy_add_optional_child(loc, rb_intern("ivar"), (rbs_loc_range) { .start = node->ivar_range.start_char, .end = node->ivar_range.end_char });
        rbs_loc_legacy_add_optional_child(loc, rb_intern("ivar_name"), (rbs_loc_range) { .start = node->ivar_name_range.start_char, .end = node->ivar_name_range.end_char });
        rbs_loc_legacy_add_optional_child(loc, rb_intern("visibility"), (rbs_loc_range) { .start = node->visibility_range.start_char, .end = node->visibility_range.end_char });
        rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
        rb_hash_aset(h, ID2SYM(rb_intern("name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name)); // rbs_ast_symbol
        rb_hash_aset(h, ID2SYM(rb_intern("type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type)); // rbs_node
        rb_hash_aset(h, ID2SYM(rb_intern("ivar_name")), rbs_attr_ivar_name_to_ruby(ctx, node->ivar_name));    // rbs_attr_ivar_name_t
        rb_hash_aset(h, ID2SYM(rb_intern("kind")), rbs_attribute_kind_to_ruby(node->kind));                   // attribute_kind
        rb_hash_aset(h, ID2SYM(rb_intern("annotations")), rbs_node_list_to_ruby_array(ctx, node->annotations));
        rb_hash_aset(h, ID2SYM(rb_intern("comment")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->comment)); // rbs_ast_comment
        rb_hash_aset(h, ID2SYM(rb_intern("visibility")), rbs_attribute_visibility_to_ruby(node->visibility));       // attribute_visibility

        return CLASS_NEW_INSTANCE(
            RBS_AST_Members_AttrWriter,
            1,
            &h
        );
    }
    case RBS_AST_MEMBERS_CLASS_INSTANCE_VARIABLE: {
        rbs_ast_members_class_instance_variable_t *node = (rbs_ast_members_class_instance_variable_t *) instance;

        VALUE h = rb_hash_new();
        VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
        rbs_loc *loc = rbs_check_location(location);
        rbs_loc_legacy_alloc_children(loc, 3);
        rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
        rbs_loc_legacy_add_required_child(loc, rb_intern("colon"), (rbs_loc_range) { .start = node->colon_range.start_char, .end = node->colon_range.end_char });
        rbs_loc_legacy_add_optional_child(loc, rb_intern("kind"), (rbs_loc_range) { .start = node->kind_range.start_char, .end = node->kind_range.end_char });
        rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
        rb_hash_aset(h, ID2SYM(rb_intern("name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name));       // rbs_ast_symbol
        rb_hash_aset(h, ID2SYM(rb_intern("type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type));       // rbs_node
        rb_hash_aset(h, ID2SYM(rb_intern("comment")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->comment)); // rbs_ast_comment

        return CLASS_NEW_INSTANCE(
            RBS_AST_Members_ClassInstanceVariable,
            1,
            &h
        );
    }
    case RBS_AST_MEMBERS_CLASS_VARIABLE: {
        rbs_ast_members_class_variable_t *node = (rbs_ast_members_class_variable_t *) instance;

        VALUE h = rb_hash_new();
        VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
        rbs_loc *loc = rbs_check_location(location);
        rbs_loc_legacy_alloc_children(loc, 3);
        rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
        rbs_loc_legacy_add_required_child(loc, rb_intern("colon"), (rbs_loc_range) { .start = node->colon_range.start_char, .end = node->colon_range.end_char });
        rbs_loc_legacy_add_optional_child(loc, rb_intern("kind"), (rbs_loc_range) { .start = node->kind_range.start_char, .end = node->kind_range.end_char });
        rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
        rb_hash_aset(h, ID2SYM(rb_intern("name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name));       // rbs_ast_symbol
        rb_hash_aset(h, ID2SYM(rb_intern("type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type));       // rbs_node
        rb_hash_aset(h, ID2SYM(rb_intern("comment")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->comment)); // rbs_ast_comment

        return CLASS_NEW_INSTANCE(
            RBS_AST_Members_ClassVariable,
            1,
            &h
        );
    }
    case RBS_AST_MEMBERS_EXTEND: {
        rbs_ast_members_extend_t *node = (rbs_ast_members_extend_t *) instance;

        VALUE h = rb_hash_new();
        VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
        rbs_loc *loc = rbs_check_location(location);
        rbs_loc_legacy_alloc_children(loc, 3);
        rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
        rbs_loc_legacy_add_required_child(loc, rb_intern("keyword"), (rbs_loc_range) { .start = node->keyword_range.start_char, .end = node->keyword_range.end_char });
        rbs_loc_legacy_add_optional_child(loc, rb_intern("args"), (rbs_loc_range) { .start = node->args_range.start_char, .end = node->args_range.end_char });
        rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
        rb_hash_aset(h, ID2SYM(rb_intern("name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name)); // rbs_type_name
        rb_hash_aset(h, ID2SYM(rb_intern("args")), rbs_node_list_to_ruby_array(ctx, node->args));
        rb_hash_aset(h, ID2SYM(rb_intern("annotations")), rbs_node_list_to_ruby_array(ctx, node->annotations));
        rb_hash_aset(h, ID2SYM(rb_intern("comment")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->comment)); // rbs_ast_comment

        return CLASS_NEW_INSTANCE(
            RBS_AST_Members_Extend,
            1,
            &h
        );
    }
    case RBS_AST_MEMBERS_INCLUDE: {
        rbs_ast_members_include_t *node = (rbs_ast_members_include_t *) instance;

        VALUE h = rb_hash_new();
        VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
        rbs_loc *loc = rbs_check_location(location);
        rbs_loc_legacy_alloc_children(loc, 3);
        rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
        rbs_loc_legacy_add_required_child(loc, rb_intern("keyword"), (rbs_loc_range) { .start = node->keyword_range.start_char, .end = node->keyword_range.end_char });
        rbs_loc_legacy_add_optional_child(loc, rb_intern("args"), (rbs_loc_range) { .start = node->args_range.start_char, .end = node->args_range.end_char });
        rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
        rb_hash_aset(h, ID2SYM(rb_intern("name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name)); // rbs_type_name
        rb_hash_aset(h, ID2SYM(rb_intern("args")), rbs_node_list_to_ruby_array(ctx, node->args));
        rb_hash_aset(h, ID2SYM(rb_intern("annotations")), rbs_node_list_to_ruby_array(ctx, node->annotations));
        rb_hash_aset(h, ID2SYM(rb_intern("comment")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->comment)); // rbs_ast_comment

        return CLASS_NEW_INSTANCE(
            RBS_AST_Members_Include,
            1,
            &h
        );
    }
    case RBS_AST_MEMBERS_INSTANCE_VARIABLE: {
        rbs_ast_members_instance_variable_t *node = (rbs_ast_members_instance_variable_t *) instance;

        VALUE h = rb_hash_new();
        VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
        rbs_loc *loc = rbs_check_location(location);
        rbs_loc_legacy_alloc_children(loc, 3);
        rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
        rbs_loc_legacy_add_required_child(loc, rb_intern("colon"), (rbs_loc_range) { .start = node->colon_range.start_char, .end = node->colon_range.end_char });
        rbs_loc_legacy_add_optional_child(loc, rb_intern("kind"), (rbs_loc_range) { .start = node->kind_range.start_char, .end = node->kind_range.end_char });
        rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
        rb_hash_aset(h, ID2SYM(rb_intern("name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name));       // rbs_ast_symbol
        rb_hash_aset(h, ID2SYM(rb_intern("type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type));       // rbs_node
        rb_hash_aset(h, ID2SYM(rb_intern("comment")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->comment)); // rbs_ast_comment

        return CLASS_NEW_INSTANCE(
            RBS_AST_Members_InstanceVariable,
            1,
            &h
        );
    }
    case RBS_AST_MEMBERS_METHOD_DEFINITION: {
        rbs_ast_members_method_definition_t *node = (rbs_ast_members_method_definition_t *) instance;

        VALUE h = rb_hash_new();
        VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
        rbs_loc *loc = rbs_check_location(location);
        rbs_loc_legacy_alloc_children(loc, 5);
        rbs_loc_legacy_add_required_child(loc, rb_intern("keyword"), (rbs_loc_range) { .start = node->keyword_range.start_char, .end = node->keyword_range.end_char });
        rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
        rbs_loc_legacy_add_optional_child(loc, rb_intern("kind"), (rbs_loc_range) { .start = node->kind_range.start_char, .end = node->kind_range.end_char });
        rbs_loc_legacy_add_optional_child(loc, rb_intern("overloading"), (rbs_loc_range) { .start = node->overloading_range.start_char, .end = node->overloading_range.end_char });
        rbs_loc_legacy_add_optional_child(loc, rb_intern("visibility"), (rbs_loc_range) { .start = node->visibility_range.start_char, .end = node->visibility_range.end_char });
        rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
        rb_hash_aset(h, ID2SYM(rb_intern("name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name)); // rbs_ast_symbol
        rb_hash_aset(h, ID2SYM(rb_intern("kind")), rbs_method_definition_kind_to_ruby(node->kind));           // method_definition_kind
        rb_hash_aset(h, ID2SYM(rb_intern("overloads")), rbs_node_list_to_ruby_array(ctx, node->overloads));
        rb_hash_aset(h, ID2SYM(rb_intern("annotations")), rbs_node_list_to_ruby_array(ctx, node->annotations));
        rb_hash_aset(h, ID2SYM(rb_intern("comment")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->comment)); // rbs_ast_comment
        rb_hash_aset(h, ID2SYM(rb_intern("overloading")), node->overloading ? Qtrue : Qfalse);
        rb_hash_aset(h, ID2SYM(rb_intern("visibility")), rbs_method_definition_visibility_to_ruby(node->visibility)); // method_definition_visibility

        return CLASS_NEW_INSTANCE(
            RBS_AST_Members_MethodDefinition,
            1,
            &h
        );
    }
    case RBS_AST_MEMBERS_METHOD_DEFINITION_OVERLOAD: {
        rbs_ast_members_method_definition_overload_t *node = (rbs_ast_members_method_definition_overload_t *) instance;

        VALUE h = rb_hash_new();
        rb_hash_aset(h, ID2SYM(rb_intern("annotations")), rbs_node_list_to_ruby_array(ctx, node->annotations));
        rb_hash_aset(h, ID2SYM(rb_intern("method_type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->method_type)); // rbs_node

        return CLASS_NEW_INSTANCE(
            RBS_AST_Members_MethodDefinition_Overload,
            1,
            &h
        );
    }
    case RBS_AST_MEMBERS_PREPEND: {
        rbs_ast_members_prepend_t *node = (rbs_ast_members_prepend_t *) instance;

        VALUE h = rb_hash_new();
        VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
        rbs_loc *loc = rbs_check_location(location);
        rbs_loc_legacy_alloc_children(loc, 3);
        rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
        rbs_loc_legacy_add_required_child(loc, rb_intern("keyword"), (rbs_loc_range) { .start = node->keyword_range.start_char, .end = node->keyword_range.end_char });
        rbs_loc_legacy_add_optional_child(loc, rb_intern("args"), (rbs_loc_range) { .start = node->args_range.start_char, .end = node->args_range.end_char });
        rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
        rb_hash_aset(h, ID2SYM(rb_intern("name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name)); // rbs_type_name
        rb_hash_aset(h, ID2SYM(rb_intern("args")), rbs_node_list_to_ruby_array(ctx, node->args));
        rb_hash_aset(h, ID2SYM(rb_intern("annotations")), rbs_node_list_to_ruby_array(ctx, node->annotations));
        rb_hash_aset(h, ID2SYM(rb_intern("comment")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->comment)); // rbs_ast_comment

        return CLASS_NEW_INSTANCE(
            RBS_AST_Members_Prepend,
            1,
            &h
        );
    }
    case RBS_AST_MEMBERS_PRIVATE: {
        rbs_ast_members_private_t *node = (rbs_ast_members_private_t *) instance;

        VALUE h = rb_hash_new();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));

        return CLASS_NEW_INSTANCE(
            RBS_AST_Members_Private,
            1,
            &h
        );
    }
    case RBS_AST_MEMBERS_PUBLIC: {
        rbs_ast_members_public_t *node = (rbs_ast_members_public_t *) instance;

        VALUE h = rb_hash_new();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));

        return CLASS_NEW_INSTANCE(
            RBS_AST_Members_Public,
            1,
            &h
        );
    }
    case RBS_AST_RUBY_ANNOTATIONS_BLOCK_PARAM_TYPE_ANNOTATION: {
        rbs_ast_ruby_annotations_block_param_type_annotation_t *node = (rbs_ast_ruby_annotations_block_param_type_annotation_t *) instance;

        VALUE h = rb_hash_new();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
        rb_hash_aset(h, ID2SYM(rb_intern("prefix_location")), rbs_location_range_to_ruby_location(ctx, node->prefix_location));
        rb_hash_aset(h, ID2SYM(rb_intern("ampersand_location")), rbs_location_range_to_ruby_location(ctx, node->ampersand_location));
        rb_hash_aset(h, ID2SYM(rb_intern("name_location")), rbs_location_range_to_ruby_location(ctx, node->name_location)); // optional
        rb_hash_aset(h, ID2SYM(rb_intern("colon_location")), rbs_location_range_to_ruby_location(ctx, node->colon_location));
        rb_hash_aset(h, ID2SYM(rb_intern("question_location")), rbs_location_range_to_ruby_location(ctx, node->question_location)); // optional
        rb_hash_aset(h, ID2SYM(rb_intern("type_location")), rbs_location_range_to_ruby_location(ctx, node->type_location));
        rb_hash_aset(h, ID2SYM(rb_intern("type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type_));                    // rbs_node
        rb_hash_aset(h, ID2SYM(rb_intern("comment_location")), rbs_location_range_to_ruby_location(ctx, node->comment_location)); // optional

        return CLASS_NEW_INSTANCE(
            RBS_AST_Ruby_Annotations_BlockParamTypeAnnotation,
            1,
            &h
        );
    }
    case RBS_AST_RUBY_ANNOTATIONS_CLASS_ALIAS_ANNOTATION: {
        rbs_ast_ruby_annotations_class_alias_annotation_t *node = (rbs_ast_ruby_annotations_class_alias_annotation_t *) instance;

        VALUE h = rb_hash_new();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
        rb_hash_aset(h, ID2SYM(rb_intern("prefix_location")), rbs_location_range_to_ruby_location(ctx, node->prefix_location));
        rb_hash_aset(h, ID2SYM(rb_intern("keyword_location")), rbs_location_range_to_ruby_location(ctx, node->keyword_location));
        rb_hash_aset(h, ID2SYM(rb_intern("type_name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type_name));               // rbs_type_name
        rb_hash_aset(h, ID2SYM(rb_intern("type_name_location")), rbs_location_range_to_ruby_location(ctx, node->type_name_location)); // optional

        return CLASS_NEW_INSTANCE(
            RBS_AST_Ruby_Annotations_ClassAliasAnnotation,
            1,
            &h
        );
    }
    case RBS_AST_RUBY_ANNOTATIONS_COLON_METHOD_TYPE_ANNOTATION: {
        rbs_ast_ruby_annotations_colon_method_type_annotation_t *node = (rbs_ast_ruby_annotations_colon_method_type_annotation_t *) instance;

        VALUE h = rb_hash_new();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
        rb_hash_aset(h, ID2SYM(rb_intern("prefix_location")), rbs_location_range_to_ruby_location(ctx, node->prefix_location));
        rb_hash_aset(h, ID2SYM(rb_intern("annotations")), rbs_node_list_to_ruby_array(ctx, node->annotations));
        rb_hash_aset(h, ID2SYM(rb_intern("method_type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->method_type)); // rbs_node

        return CLASS_NEW_INSTANCE(
            RBS_AST_Ruby_Annotations_ColonMethodTypeAnnotation,
            1,
            &h
        );
    }
    case RBS_AST_RUBY_ANNOTATIONS_DOUBLE_SPLAT_PARAM_TYPE_ANNOTATION: {
        rbs_ast_ruby_annotations_double_splat_param_type_annotation_t *node = (rbs_ast_ruby_annotations_double_splat_param_type_annotation_t *) instance;

        VALUE h = rb_hash_new();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
        rb_hash_aset(h, ID2SYM(rb_intern("prefix_location")), rbs_location_range_to_ruby_location(ctx, node->prefix_location));
        rb_hash_aset(h, ID2SYM(rb_intern("star2_location")), rbs_location_range_to_ruby_location(ctx, node->star2_location));
        rb_hash_aset(h, ID2SYM(rb_intern("name_location")), rbs_location_range_to_ruby_location(ctx, node->name_location)); // optional
        rb_hash_aset(h, ID2SYM(rb_intern("colon_location")), rbs_location_range_to_ruby_location(ctx, node->colon_location));
        rb_hash_aset(h, ID2SYM(rb_intern("param_type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->param_type));         // rbs_node
        rb_hash_aset(h, ID2SYM(rb_intern("comment_location")), rbs_location_range_to_ruby_location(ctx, node->comment_location)); // optional

        return CLASS_NEW_INSTANCE(
            RBS_AST_Ruby_Annotations_DoubleSplatParamTypeAnnotation,
            1,
            &h
        );
    }
    case RBS_AST_RUBY_ANNOTATIONS_INSTANCE_VARIABLE_ANNOTATION: {
        rbs_ast_ruby_annotations_instance_variable_annotation_t *node = (rbs_ast_ruby_annotations_instance_variable_annotation_t *) instance;

        VALUE h = rb_hash_new();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
        rb_hash_aset(h, ID2SYM(rb_intern("prefix_location")), rbs_location_range_to_ruby_location(ctx, node->prefix_location));
        rb_hash_aset(h, ID2SYM(rb_intern("ivar_name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->ivar_name)); // rbs_ast_symbol
        rb_hash_aset(h, ID2SYM(rb_intern("ivar_name_location")), rbs_location_range_to_ruby_location(ctx, node->ivar_name_location));
        rb_hash_aset(h, ID2SYM(rb_intern("colon_location")), rbs_location_range_to_ruby_location(ctx, node->colon_location));
        rb_hash_aset(h, ID2SYM(rb_intern("type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type));                     // rbs_node
        rb_hash_aset(h, ID2SYM(rb_intern("comment_location")), rbs_location_range_to_ruby_location(ctx, node->comment_location)); // optional

        return CLASS_NEW_INSTANCE(
            RBS_AST_Ruby_Annotations_InstanceVariableAnnotation,
            1,
            &h
        );
    }
    case RBS_AST_RUBY_ANNOTATIONS_METHOD_TYPES_ANNOTATION: {
        rbs_ast_ruby_annotations_method_types_annotation_t *node = (rbs_ast_ruby_annotations_method_types_annotation_t *) instance;

        VALUE h = rb_hash_new();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
        rb_hash_aset(h, ID2SYM(rb_intern("prefix_location")), rbs_location_range_to_ruby_location(ctx, node->prefix_location));
        rb_hash_aset(h, ID2SYM(rb_intern("overloads")), rbs_node_list_to_ruby_array(ctx, node->overloads));
        rb_hash_aset(h, ID2SYM(rb_intern("vertical_bar_locations")), rbs_location_range_list_to_ruby_array(ctx, node->vertical_bar_locations));
        rb_hash_aset(h, ID2SYM(rb_intern("dot3_location")), rbs_location_range_to_ruby_location(ctx, node->dot3_location)); // optional

        return CLASS_NEW_INSTANCE(
            RBS_AST_Ruby_Annotations_MethodTypesAnnotation,
            1,
            &h
        );
    }
    case RBS_AST_RUBY_ANNOTATIONS_MODULE_ALIAS_ANNOTATION: {
        rbs_ast_ruby_annotations_module_alias_annotation_t *node = (rbs_ast_ruby_annotations_module_alias_annotation_t *) instance;

        VALUE h = rb_hash_new();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
        rb_hash_aset(h, ID2SYM(rb_intern("prefix_location")), rbs_location_range_to_ruby_location(ctx, node->prefix_location));
        rb_hash_aset(h, ID2SYM(rb_intern("keyword_location")), rbs_location_range_to_ruby_location(ctx, node->keyword_location));
        rb_hash_aset(h, ID2SYM(rb_intern("type_name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type_name));               // rbs_type_name
        rb_hash_aset(h, ID2SYM(rb_intern("type_name_location")), rbs_location_range_to_ruby_location(ctx, node->type_name_location)); // optional

        return CLASS_NEW_INSTANCE(
            RBS_AST_Ruby_Annotations_ModuleAliasAnnotation,
            1,
            &h
        );
    }
    case RBS_AST_RUBY_ANNOTATIONS_NODE_TYPE_ASSERTION: {
        rbs_ast_ruby_annotations_node_type_assertion_t *node = (rbs_ast_ruby_annotations_node_type_assertion_t *) instance;

        VALUE h = rb_hash_new();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
        rb_hash_aset(h, ID2SYM(rb_intern("prefix_location")), rbs_location_range_to_ruby_location(ctx, node->prefix_location));
        rb_hash_aset(h, ID2SYM(rb_intern("type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type)); // rbs_node

        return CLASS_NEW_INSTANCE(
            RBS_AST_Ruby_Annotations_NodeTypeAssertion,
            1,
            &h
        );
    }
    case RBS_AST_RUBY_ANNOTATIONS_PARAM_TYPE_ANNOTATION: {
        rbs_ast_ruby_annotations_param_type_annotation_t *node = (rbs_ast_ruby_annotations_param_type_annotation_t *) instance;

        VALUE h = rb_hash_new();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
        rb_hash_aset(h, ID2SYM(rb_intern("prefix_location")), rbs_location_range_to_ruby_location(ctx, node->prefix_location));
        rb_hash_aset(h, ID2SYM(rb_intern("name_location")), rbs_location_range_to_ruby_location(ctx, node->name_location));
        rb_hash_aset(h, ID2SYM(rb_intern("colon_location")), rbs_location_range_to_ruby_location(ctx, node->colon_location));
        rb_hash_aset(h, ID2SYM(rb_intern("param_type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->param_type));         // rbs_node
        rb_hash_aset(h, ID2SYM(rb_intern("comment_location")), rbs_location_range_to_ruby_location(ctx, node->comment_location)); // optional

        return CLASS_NEW_INSTANCE(
            RBS_AST_Ruby_Annotations_ParamTypeAnnotation,
            1,
            &h
        );
    }
    case RBS_AST_RUBY_ANNOTATIONS_RETURN_TYPE_ANNOTATION: {
        rbs_ast_ruby_annotations_return_type_annotation_t *node = (rbs_ast_ruby_annotations_return_type_annotation_t *) instance;

        VALUE h = rb_hash_new();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
        rb_hash_aset(h, ID2SYM(rb_intern("prefix_location")), rbs_location_range_to_ruby_location(ctx, node->prefix_location));
        rb_hash_aset(h, ID2SYM(rb_intern("return_location")), rbs_location_range_to_ruby_location(ctx, node->return_location));
        rb_hash_aset(h, ID2SYM(rb_intern("colon_location")), rbs_location_range_to_ruby_location(ctx, node->colon_location));
        rb_hash_aset(h, ID2SYM(rb_intern("return_type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->return_type));       // rbs_node
        rb_hash_aset(h, ID2SYM(rb_intern("comment_location")), rbs_location_range_to_ruby_location(ctx, node->comment_location)); // optional

        return CLASS_NEW_INSTANCE(
            RBS_AST_Ruby_Annotations_ReturnTypeAnnotation,
            1,
            &h
        );
    }
    case RBS_AST_RUBY_ANNOTATIONS_SKIP_ANNOTATION: {
        rbs_ast_ruby_annotations_skip_annotation_t *node = (rbs_ast_ruby_annotations_skip_annotation_t *) instance;

        VALUE h = rb_hash_new();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
        rb_hash_aset(h, ID2SYM(rb_intern("prefix_location")), rbs_location_range_to_ruby_location(ctx, node->prefix_location));
        rb_hash_aset(h, ID2SYM(rb_intern("skip_location")), rbs_location_range_to_ruby_location(ctx, node->skip_location));
        rb_hash_aset(h, ID2SYM(rb_intern("comment_location")), rbs_location_range_to_ruby_location(ctx, node->comment_location)); // optional

        return CLASS_NEW_INSTANCE(
            RBS_AST_Ruby_Annotations_SkipAnnotation,
            1,
            &h
        );
    }
    case RBS_AST_RUBY_ANNOTATIONS_SPLAT_PARAM_TYPE_ANNOTATION: {
        rbs_ast_ruby_annotations_splat_param_type_annotation_t *node = (rbs_ast_ruby_annotations_splat_param_type_annotation_t *) instance;

        VALUE h = rb_hash_new();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
        rb_hash_aset(h, ID2SYM(rb_intern("prefix_location")), rbs_location_range_to_ruby_location(ctx, node->prefix_location));
        rb_hash_aset(h, ID2SYM(rb_intern("star_location")), rbs_location_range_to_ruby_location(ctx, node->star_location));
        rb_hash_aset(h, ID2SYM(rb_intern("name_location")), rbs_location_range_to_ruby_location(ctx, node->name_location)); // optional
        rb_hash_aset(h, ID2SYM(rb_intern("colon_location")), rbs_location_range_to_ruby_location(ctx, node->colon_location));
        rb_hash_aset(h, ID2SYM(rb_intern("param_type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->param_type));         // rbs_node
        rb_hash_aset(h, ID2SYM(rb_intern("comment_location")), rbs_location_range_to_ruby_location(ctx, node->comment_location)); // optional

        return CLASS_NEW_INSTANCE(
            RBS_AST_Ruby_Annotations_SplatParamTypeAnnotation,
            1,
            &h
        );
    }
    case RBS_AST_RUBY_ANNOTATIONS_TYPE_APPLICATION_ANNOTATION: {
        rbs_ast_ruby_annotations_type_application_annotation_t *node = (rbs_ast_ruby_annotations_type_application_annotation_t *) instance;

        VALUE h = rb_hash_new();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
        rb_hash_aset(h, ID2SYM(rb_intern("prefix_location")), rbs_location_range_to_ruby_location(ctx, node->prefix_location));
        rb_hash_aset(h, ID2SYM(rb_intern("type_args")), rbs_node_list_to_ruby_array(ctx, node->type_args));
        rb_hash_aset(h, ID2SYM(rb_intern("close_bracket_location")), rbs_location_range_to_ruby_location(ctx, node->close_bracket_location));
        rb_hash_aset(h, ID2SYM(rb_intern("comma_locations")), rbs_location_range_list_to_ruby_array(ctx, node->comma_locations));

        return CLASS_NEW_INSTANCE(
            RBS_AST_Ruby_Annotations_TypeApplicationAnnotation,
            1,
            &h
        );
    }
    case RBS_AST_STRING: {
        rbs_ast_string_t *string_node = (rbs_ast_string_t *) instance;
        rbs_string_t s = string_node->string;

        return rb_enc_str_new(s.start, rbs_string_len(s), rb_utf8_encoding());
    }
    case RBS_AST_TYPE_PARAM: {
        rbs_ast_type_param_t *node = (rbs_ast_type_param_t *) instance;

        VALUE h = rb_hash_new();
        VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
        rbs_loc *loc = rbs_check_location(location);
        rbs_loc_legacy_alloc_children(loc, 6);
        rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
        rbs_loc_legacy_add_optional_child(loc, rb_intern("variance"), (rbs_loc_range) { .start = node->variance_range.start_char, .end = node->variance_range.end_char });
        rbs_loc_legacy_add_optional_child(loc, rb_intern("unchecked"), (rbs_loc_range) { .start = node->unchecked_range.start_char, .end = node->unchecked_range.end_char });
        rbs_loc_legacy_add_optional_child(loc, rb_intern("upper_bound"), (rbs_loc_range) { .start = node->upper_bound_range.start_char, .end = node->upper_bound_range.end_char });
        rbs_loc_legacy_add_optional_child(loc, rb_intern("lower_bound"), (rbs_loc_range) { .start = node->lower_bound_range.start_char, .end = node->lower_bound_range.end_char });
        rbs_loc_legacy_add_optional_child(loc, rb_intern("default"), (rbs_loc_range) { .start = node->default_range.start_char, .end = node->default_range.end_char });
        rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
        rb_hash_aset(h, ID2SYM(rb_intern("name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name));                 // rbs_ast_symbol
        rb_hash_aset(h, ID2SYM(rb_intern("variance")), rbs_type_param_variance_to_ruby(node->variance));                      // type_param_variance
        rb_hash_aset(h, ID2SYM(rb_intern("upper_bound")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->upper_bound));   // rbs_node
        rb_hash_aset(h, ID2SYM(rb_intern("lower_bound")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->lower_bound));   // rbs_node
        rb_hash_aset(h, ID2SYM(rb_intern("default_type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->default_type)); // rbs_node
        rb_hash_aset(h, ID2SYM(rb_intern("unchecked")), node->unchecked ? Qtrue : Qfalse);

        return CLASS_NEW_INSTANCE(
            RBS_AST_TypeParam,
            1,
            &h
        );
    }
    case RBS_METHOD_TYPE: {
        rbs_method_type_t *node = (rbs_method_type_t *) instance;

        VALUE h = rb_hash_new();
        VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
        rbs_loc *loc = rbs_check_location(location);
        rbs_loc_legacy_alloc_children(loc, 2);
        rbs_loc_legacy_add_required_child(loc, rb_intern("type"), (rbs_loc_range) { .start = node->type_range.start_char, .end = node->type_range.end_char });
        rbs_loc_legacy_add_optional_child(loc, rb_intern("type_params"), (rbs_loc_range) { .start = node->type_params_range.start_char, .end = node->type_params_range.end_char });
        rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
        rb_hash_aset(h, ID2SYM(rb_intern("type_params")), rbs_node_list_to_ruby_array(ctx, node->type_params));
        rb_hash_aset(h, ID2SYM(rb_intern("type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type));   // rbs_node
        rb_hash_aset(h, ID2SYM(rb_intern("block")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->block)); // rbs_types_block

        rb_funcall(
            RBS_AST_TypeParam,
            rb_intern("resolve_variables"),
            1,
            rb_hash_lookup(h, ID2SYM(rb_intern("type_params")))
        );
        return CLASS_NEW_INSTANCE(
            RBS_MethodType,
            1,
            &h
        );
    }
    case RBS_NAMESPACE: {
        rbs_namespace_t *node = (rbs_namespace_t *) instance;

        VALUE h = rb_hash_new();
        rb_hash_aset(h, ID2SYM(rb_intern("path")), rbs_node_list_to_ruby_array(ctx, node->path));
        rb_hash_aset(h, ID2SYM(rb_intern("absolute")), node->absolute ? Qtrue : Qfalse);

        return CLASS_NEW_INSTANCE(
            RBS_Namespace,
            1,
            &h
        );
    }
    case RBS_SIGNATURE: {
        rbs_signature_t *signature = (rbs_signature_t *) instance;

        VALUE array = rb_ary_new();
        rb_ary_push(array, rbs_node_list_to_ruby_array(ctx, signature->directives));
        rb_ary_push(array, rbs_node_list_to_ruby_array(ctx, signature->declarations));
        return array;
    }
    case RBS_TYPE_NAME: {
        rbs_type_name_t *node = (rbs_type_name_t *) instance;

        VALUE h = rb_hash_new();
        rb_hash_aset(h, ID2SYM(rb_intern("namespace")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->rbs_namespace)); // rbs_namespace
        rb_hash_aset(h, ID2SYM(rb_intern("name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name));               // rbs_ast_symbol

        return CLASS_NEW_INSTANCE(
            RBS_TypeName,
            1,
            &h
        );
    }
    case RBS_TYPES_ALIAS: {
        rbs_types_alias_t *node = (rbs_types_alias_t *) instance;

        VALUE h = rb_hash_new();
        VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
        rbs_loc *loc = rbs_check_location(location);
        rbs_loc_legacy_alloc_children(loc, 2);
        rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
        rbs_loc_legacy_add_optional_child(loc, rb_intern("args"), (rbs_loc_range) { .start = node->args_range.start_char, .end = node->args_range.end_char });
        rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
        rb_hash_aset(h, ID2SYM(rb_intern("name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name)); // rbs_type_name
        rb_hash_aset(h, ID2SYM(rb_intern("args")), rbs_node_list_to_ruby_array(ctx, node->args));

        return CLASS_NEW_INSTANCE(
            RBS_Types_Alias,
            1,
            &h
        );
    }
    case RBS_TYPES_BASES_ANY: {
        rbs_types_bases_any_t *node = (rbs_types_bases_any_t *) instance;

        VALUE h = rb_hash_new();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
        rb_hash_aset(h, ID2SYM(rb_intern("todo")), node->todo ? Qtrue : Qfalse);

        return CLASS_NEW_INSTANCE(
            RBS_Types_Bases_Any,
            1,
            &h
        );
    }
    case RBS_TYPES_BASES_BOOL: {
        rbs_types_bases_bool_t *node = (rbs_types_bases_bool_t *) instance;

        VALUE h = rb_hash_new();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));

        return CLASS_NEW_INSTANCE(
            RBS_Types_Bases_Bool,
            1,
            &h
        );
    }
    case RBS_TYPES_BASES_BOTTOM: {
        rbs_types_bases_bottom_t *node = (rbs_types_bases_bottom_t *) instance;

        VALUE h = rb_hash_new();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));

        return CLASS_NEW_INSTANCE(
            RBS_Types_Bases_Bottom,
            1,
            &h
        );
    }
    case RBS_TYPES_BASES_CLASS: {
        rbs_types_bases_class_t *node = (rbs_types_bases_class_t *) instance;

        VALUE h = rb_hash_new();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));

        return CLASS_NEW_INSTANCE(
            RBS_Types_Bases_Class,
            1,
            &h
        );
    }
    case RBS_TYPES_BASES_INSTANCE: {
        rbs_types_bases_instance_t *node = (rbs_types_bases_instance_t *) instance;

        VALUE h = rb_hash_new();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));

        return CLASS_NEW_INSTANCE(
            RBS_Types_Bases_Instance,
            1,
            &h
        );
    }
    case RBS_TYPES_BASES_NIL: {
        rbs_types_bases_nil_t *node = (rbs_types_bases_nil_t *) instance;

        VALUE h = rb_hash_new();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));

        return CLASS_NEW_INSTANCE(
            RBS_Types_Bases_Nil,
            1,
            &h
        );
    }
    case RBS_TYPES_BASES_SELF: {
        rbs_types_bases_self_t *node = (rbs_types_bases_self_t *) instance;

        VALUE h = rb_hash_new();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));

        return CLASS_NEW_INSTANCE(
            RBS_Types_Bases_Self,
            1,
            &h
        );
    }
    case RBS_TYPES_BASES_TOP: {
        rbs_types_bases_top_t *node = (rbs_types_bases_top_t *) instance;

        VALUE h = rb_hash_new();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));

        return CLASS_NEW_INSTANCE(
            RBS_Types_Bases_Top,
            1,
            &h
        );
    }
    case RBS_TYPES_BASES_VOID: {
        rbs_types_bases_void_t *node = (rbs_types_bases_void_t *) instance;

        VALUE h = rb_hash_new();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));

        return CLASS_NEW_INSTANCE(
            RBS_Types_Bases_Void,
            1,
            &h
        );
    }
    case RBS_TYPES_BLOCK: {
        rbs_types_block_t *node = (rbs_types_block_t *) instance;

        VALUE h = rb_hash_new();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
        rb_hash_aset(h, ID2SYM(rb_intern("type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type)); // rbs_node
        rb_hash_aset(h, ID2SYM(rb_intern("required")), node->required ? Qtrue : Qfalse);
        rb_hash_aset(h, ID2SYM(rb_intern("self_type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->self_type)); // rbs_node

        return CLASS_NEW_INSTANCE(
            RBS_Types_Block,
            1,
            &h
        );
    }
    case RBS_TYPES_CLASS_INSTANCE: {
        rbs_types_class_instance_t *node = (rbs_types_class_instance_t *) instance;

        VALUE h = rb_hash_new();
        VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
        rbs_loc *loc = rbs_check_location(location);
        rbs_loc_legacy_alloc_children(loc, 2);
        rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
        rbs_loc_legacy_add_optional_child(loc, rb_intern("args"), (rbs_loc_range) { .start = node->args_range.start_char, .end = node->args_range.end_char });
        rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
        rb_hash_aset(h, ID2SYM(rb_intern("name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name)); // rbs_type_name
        rb_hash_aset(h, ID2SYM(rb_intern("args")), rbs_node_list_to_ruby_array(ctx, node->args));

        return CLASS_NEW_INSTANCE(
            RBS_Types_ClassInstance,
            1,
            &h
        );
    }
    case RBS_TYPES_CLASS_SINGLETON: {
        rbs_types_class_singleton_t *node = (rbs_types_class_singleton_t *) instance;

        VALUE h = rb_hash_new();
        VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
        rbs_loc *loc = rbs_check_location(location);
        rbs_loc_legacy_alloc_children(loc, 2);
        rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
        rbs_loc_legacy_add_optional_child(loc, rb_intern("args"), (rbs_loc_range) { .start = node->args_range.start_char, .end = node->args_range.end_char });
        rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
        rb_hash_aset(h, ID2SYM(rb_intern("name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name)); // rbs_type_name
        rb_hash_aset(h, ID2SYM(rb_intern("args")), rbs_node_list_to_ruby_array(ctx, node->args));

        return CLASS_NEW_INSTANCE(
            RBS_Types_ClassSingleton,
            1,
            &h
        );
    }
    case RBS_TYPES_FUNCTION: {
        rbs_types_function_t *node = (rbs_types_function_t *) instance;

        VALUE h = rb_hash_new();
        rb_hash_aset(h, ID2SYM(rb_intern("required_positionals")), rbs_node_list_to_ruby_array(ctx, node->required_positionals));
        rb_hash_aset(h, ID2SYM(rb_intern("optional_positionals")), rbs_node_list_to_ruby_array(ctx, node->optional_positionals));
        rb_hash_aset(h, ID2SYM(rb_intern("rest_positionals")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->rest_positionals)); // rbs_node
        rb_hash_aset(h, ID2SYM(rb_intern("trailing_positionals")), rbs_node_list_to_ruby_array(ctx, node->trailing_positionals));
        rb_hash_aset(h, ID2SYM(rb_intern("required_keywords")), rbs_hash_to_ruby_hash(ctx, node->required_keywords));
        rb_hash_aset(h, ID2SYM(rb_intern("optional_keywords")), rbs_hash_to_ruby_hash(ctx, node->optional_keywords));
        rb_hash_aset(h, ID2SYM(rb_intern("rest_keywords")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->rest_keywords)); // rbs_node
        rb_hash_aset(h, ID2SYM(rb_intern("return_type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->return_type));     // rbs_node

        return CLASS_NEW_INSTANCE(
            RBS_Types_Function,
            1,
            &h
        );
    }
    case RBS_TYPES_FUNCTION_PARAM: {
        rbs_types_function_param_t *node = (rbs_types_function_param_t *) instance;

        VALUE h = rb_hash_new();
        VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
        rbs_loc *loc = rbs_check_location(location);
        rbs_loc_legacy_alloc_children(loc, 1);
        rbs_loc_legacy_add_optional_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
        rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
        rb_hash_aset(h, ID2SYM(rb_intern("type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type)); // rbs_node
        rb_hash_aset(h, ID2SYM(rb_intern("name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name)); // rbs_ast_symbol

        return CLASS_NEW_INSTANCE(
            RBS_Types_Function_Param,
            1,
            &h
        );
    }
    case RBS_TYPES_INTERFACE: {
        rbs_types_interface_t *node = (rbs_types_interface_t *) instance;

        VALUE h = rb_hash_new();
        VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
        rbs_loc *loc = rbs_check_location(location);
        rbs_loc_legacy_alloc_children(loc, 2);
        rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
        rbs_loc_legacy_add_optional_child(loc, rb_intern("args"), (rbs_loc_range) { .start = node->args_range.start_char, .end = node->args_range.end_char });
        rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
        rb_hash_aset(h, ID2SYM(rb_intern("name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name)); // rbs_type_name
        rb_hash_aset(h, ID2SYM(rb_intern("args")), rbs_node_list_to_ruby_array(ctx, node->args));

        return CLASS_NEW_INSTANCE(
            RBS_Types_Interface,
            1,
            &h
        );
    }
    case RBS_TYPES_INTERSECTION: {
        rbs_types_intersection_t *node = (rbs_types_intersection_t *) instance;

        VALUE h = rb_hash_new();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
        rb_hash_aset(h, ID2SYM(rb_intern("types")), rbs_node_list_to_ruby_array(ctx, node->types));

        return CLASS_NEW_INSTANCE(
            RBS_Types_Intersection,
            1,
            &h
        );
    }
    case RBS_TYPES_LITERAL: {
        rbs_types_literal_t *node = (rbs_types_literal_t *) instance;

        VALUE h = rb_hash_new();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
        rb_hash_aset(h, ID2SYM(rb_intern("literal")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->literal)); // rbs_node

        return CLASS_NEW_INSTANCE(
            RBS_Types_Literal,
            1,
            &h
        );
    }
    case RBS_TYPES_OPTIONAL: {
        rbs_types_optional_t *node = (rbs_types_optional_t *) instance;

        VALUE h = rb_hash_new();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
        rb_hash_aset(h, ID2SYM(rb_intern("type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type)); // rbs_node

        return CLASS_NEW_INSTANCE(
            RBS_Types_Optional,
            1,
            &h
        );
    }
    case RBS_TYPES_PROC: {
        rbs_types_proc_t *node = (rbs_types_proc_t *) instance;

        VALUE h = rb_hash_new();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
        rb_hash_aset(h, ID2SYM(rb_intern("type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type));           // rbs_node
        rb_hash_aset(h, ID2SYM(rb_intern("block")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->block));         // rbs_types_block
        rb_hash_aset(h, ID2SYM(rb_intern("self_type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->self_type)); // rbs_node

        return CLASS_NEW_INSTANCE(
            RBS_Types_Proc,
            1,
            &h
        );
    }
    case RBS_TYPES_RECORD: {
        rbs_types_record_t *node = (rbs_types_record_t *) instance;

        VALUE h = rb_hash_new();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
        rb_hash_aset(h, ID2SYM(rb_intern("all_fields")), rbs_hash_to_ruby_hash(ctx, node->all_fields));

        return CLASS_NEW_INSTANCE(
            RBS_Types_Record,
            1,
            &h
        );
    }
    case RBS_TYPES_RECORD_FIELD_TYPE: {
        rbs_types_record_field_type_t *record_fieldtype = (rbs_types_record_field_type_t *) instance;

        VALUE array = rb_ary_new();
        rb_ary_push(array, rbs_struct_to_ruby_value(ctx, record_fieldtype->type));
        rb_ary_push(array, record_fieldtype->required ? Qtrue : Qfalse);
        return array;
    }
    case RBS_TYPES_TUPLE: {
        rbs_types_tuple_t *node = (rbs_types_tuple_t *) instance;

        VALUE h = rb_hash_new();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
        rb_hash_aset(h, ID2SYM(rb_intern("types")), rbs_node_list_to_ruby_array(ctx, node->types));

        return CLASS_NEW_INSTANCE(
            RBS_Types_Tuple,
            1,
            &h
        );
    }
    case RBS_TYPES_UNION: {
        rbs_types_union_t *node = (rbs_types_union_t *) instance;

        VALUE h = rb_hash_new();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
        rb_hash_aset(h, ID2SYM(rb_intern("types")), rbs_node_list_to_ruby_array(ctx, node->types));

        return CLASS_NEW_INSTANCE(
            RBS_Types_Union,
            1,
            &h
        );
    }
    case RBS_TYPES_UNTYPED_FUNCTION: {
        rbs_types_untyped_function_t *node = (rbs_types_untyped_function_t *) instance;

        VALUE h = rb_hash_new();
        rb_hash_aset(h, ID2SYM(rb_intern("return_type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->return_type)); // rbs_node

        return CLASS_NEW_INSTANCE(
            RBS_Types_UntypedFunction,
            1,
            &h
        );
    }
    case RBS_TYPES_VARIABLE: {
        rbs_types_variable_t *node = (rbs_types_variable_t *) instance;

        VALUE h = rb_hash_new();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
        rb_hash_aset(h, ID2SYM(rb_intern("name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name)); // rbs_ast_symbol

        return CLASS_NEW_INSTANCE(
            RBS_Types_Variable,
            1,
            &h
        );
    }
    case RBS_AST_SYMBOL: {
        rbs_constant_t *constant = rbs_constant_pool_id_to_constant(ctx.constant_pool, ((rbs_ast_symbol_t *) instance)->constant_id);
        assert(constant != NULL && "constant is NULL");
        assert(constant->start != NULL && "constant->start is NULL");

        return ID2SYM(rb_intern3((const char *) constant->start, constant->length, ctx.encoding));
    }
    }

    rb_raise(rb_eRuntimeError, "Unknown node type: %d", instance->type);
}
