/*----------------------------------------------------------------------------*/
/* 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_LOC_CHILDREN_SIZE(cap) (sizeof(rbs_loc_children) + sizeof(rbs_loc_entry) * ((cap) - 1))

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_loc_to_ruby_location(rbs_translation_context_t ctx, rbs_location_t *source_loc) {
    if (source_loc == NULL) {
        return Qnil;
    }

    VALUE new_loc = rbs_new_location(ctx.buffer, source_loc->rg);
    rbs_loc *new_loc_struct = rbs_check_location(new_loc);

    if (source_loc->children != NULL) {
        rbs_loc_legacy_alloc_children(new_loc_struct, source_loc->children->cap);
        memcpy(new_loc_struct->children, source_loc->children, RBS_LOC_CHILDREN_SIZE(source_loc->children->cap));
    }

    return new_loc;
}

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

    VALUE ruby_array = rb_ary_new();

    for (rbs_location_list_node_t *n = list->head; n != NULL; n = n->next) {
        rb_ary_push(ruby_array, rbs_loc_to_ruby_location(ctx, n->loc));
    }

    return ruby_array;
}

#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_loc_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_loc_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();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_loc_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_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();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_loc_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_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();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_loc_to_ruby_location(ctx, node->base.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();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_loc_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_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();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_loc_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
        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();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_loc_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_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();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_loc_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_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();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_loc_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_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();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_loc_to_ruby_location(ctx, node->base.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();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_loc_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_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();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_loc_to_ruby_location(ctx, node->base.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();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_loc_to_ruby_location(ctx, node->base.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();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_loc_to_ruby_location(ctx, node->base.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();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_loc_to_ruby_location(ctx, node->base.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_struct_to_ruby_value(ctx, (rbs_node_t *) node->kind));         // rbs_keyword
        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();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_loc_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
        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_struct_to_ruby_value(ctx, (rbs_node_t *) node->ivar_name)); // rbs_node
        rb_hash_aset(h, ID2SYM(rb_intern("kind")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->kind));           // rbs_keyword
        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_struct_to_ruby_value(ctx, (rbs_node_t *) node->visibility)); // rbs_keyword

        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();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_loc_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
        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_struct_to_ruby_value(ctx, (rbs_node_t *) node->ivar_name)); // rbs_node
        rb_hash_aset(h, ID2SYM(rb_intern("kind")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->kind));           // rbs_keyword
        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_struct_to_ruby_value(ctx, (rbs_node_t *) node->visibility)); // rbs_keyword

        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();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_loc_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
        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_struct_to_ruby_value(ctx, (rbs_node_t *) node->ivar_name)); // rbs_node
        rb_hash_aset(h, ID2SYM(rb_intern("kind")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->kind));           // rbs_keyword
        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_struct_to_ruby_value(ctx, (rbs_node_t *) node->visibility)); // rbs_keyword

        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();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_loc_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
        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();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_loc_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
        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();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_loc_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_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();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_loc_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_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();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_loc_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
        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();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_loc_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
        rb_hash_aset(h, ID2SYM(rb_intern("kind")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->kind)); // rbs_keyword
        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_struct_to_ruby_value(ctx, (rbs_node_t *) node->visibility)); // rbs_keyword

        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();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_loc_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_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_loc_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_loc_to_ruby_location(ctx, node->base.location));

        return CLASS_NEW_INSTANCE(
            RBS_AST_Members_Public,
            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();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_loc_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
        rb_hash_aset(h, ID2SYM(rb_intern("variance")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->variance));         // rbs_keyword
        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("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();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_loc_to_ruby_location(ctx, node->base.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();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_loc_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_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_loc_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_loc_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_loc_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_loc_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_loc_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_loc_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_loc_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_loc_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_loc_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_loc_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();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_loc_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_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();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_loc_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_type_name

        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();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_loc_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("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();
        rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_loc_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_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_loc_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_loc_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_loc_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_loc_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_loc_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_loc_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_loc_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_loc_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_KEYWORD: {
        rbs_constant_t *constant = rbs_constant_pool_id_to_constant(RBS_GLOBAL_CONSTANT_POOL, ((rbs_keyword_t *) instance)->constant_id);
        assert(constant != NULL && "constant is NULL");
        assert(constant->start != NULL && "constant->start is NULL");

        return ID2SYM(rb_intern2((const char *) constant->start, constant->length));
    }
    case RBS_AST_SYMBOL: {
        rbs_constant_t *constant = rbs_constant_pool_id_to_constant(ctx.constant_pool, ((rbs_keyword_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);
}
