main
Download
170 lines 5 KiBCModified 2026-02-20 raw
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
// Logic for defining and working with types

#pragma once

#include <stdlib.h>

#include "ast.h"

typedef struct type_s type_t;

typedef struct arg_s {
    const char *name, *alias;
    type_t *type;
    ast_t *default_val;
    Text_t comment;
    struct arg_s *next;
} arg_t;

#define ARG_LIST(...)                                                                                                  \
    ({                                                                                                                 \
        arg_t *args[] = {__VA_ARGS__};                                                                                 \
        for (size_t i = 0; i < sizeof(args) / sizeof(args[0]) - 1; i++)                                                \
            args[i]->next = args[i + 1];                                                                               \
        args[0];                                                                                                       \
    })

typedef struct tag_s {
    const char *name;
    int64_t tag_value;
    type_t *type;
    struct tag_s *next;
} tag_t;

typedef struct type_list_s {
    type_t *type;
    struct type_list_s *next;
} type_list_t;

struct type_s {
    enum {
        UnknownType,
        AbortType,
        ReturnType,
        VoidType,
        MemoryType,
        BoolType,
        ByteType,
        BigIntType,
        IntType,
        NumType,
        CStringType,
        TextType,
        PathType,
        ListType,
        TableType,
        FunctionType,
        ClosureType,
        PointerType,
        StructType,
        EnumType,
        OptionalType,
        TypeInfoType,
        ModuleType,
    } tag;

    union {
        struct {
        } UnknownType, AbortType, VoidType, MemoryType, BoolType, PathType;
        struct {
            type_t *ret;
        } ReturnType;
        struct {
        } BigIntType;
        struct {
            enum { TYPE_IBITS8 = 8, TYPE_IBITS16 = 16, TYPE_IBITS32 = 32, TYPE_IBITS64 = 64 } bits;
        } IntType;
        struct {
        } ByteType;
        struct {
            enum { TYPE_NBITS32 = 32, TYPE_NBITS64 = 64 } bits;
        } NumType;
        struct {
        } CStringType;
        struct {
            const char *lang;
            struct env_s *env;
        } TextType;
        struct {
            type_t *item_type;
        } ListType;
        struct {
            type_t *key_type, *value_type;
            struct env_s *env;
            ast_t *default_value;
        } TableType;
        struct {
            arg_t *args;
            type_t *ret;
        } FunctionType;
        struct {
            type_t *fn;
        } ClosureType;
        struct {
            type_t *pointed;
            bool is_stack : 1;
        } PointerType;
        struct {
            const char *name;
            arg_t *fields;
            struct env_s *env;
            bool opaque : 1, external : 1;
        } StructType;
        struct {
            const char *name;
            tag_t *tags;
            struct env_s *env;
            bool opaque;
        } EnumType;
        struct {
            type_t *type;
        } OptionalType;
        struct {
            const char *name;
            type_t *type;
            struct env_s *env;
        } TypeInfoType;
        struct {
            const char *name;
        } ModuleType;
    } __data;
};

#define Type(typetag, ...) new (type_t, .tag = typetag, .__data.typetag = {__VA_ARGS__})
#define INT_TYPE Type(BigIntType)
#define NUM_TYPE Type(NumType, .bits = TYPE_NBITS64)
#define NewFunctionType(ret, ...)                                                                                      \
    _make_function_type(ret, sizeof((arg_t[]){__VA_ARGS__}) / sizeof(arg_t), (arg_t[]){__VA_ARGS__})

Text_t type_to_text(type_t *t);
Text_t arg_types_to_text(arg_t *args, const char *separator);
const char *get_type_name(type_t *t);
PUREFUNC bool type_eq(type_t *a, type_t *b);
PUREFUNC bool type_is_a(type_t *t, type_t *req);
type_t *type_or_type(type_t *a, type_t *b);
type_t *value_type(type_t *a);
PUREFUNC bool is_discardable_type(type_t *t);
typedef enum {
    NUM_PRECISION_EQUAL,
    NUM_PRECISION_LESS,
    NUM_PRECISION_MORE,
    NUM_PRECISION_INCOMPARABLE
} precision_cmp_e;
PUREFUNC precision_cmp_e compare_precision(type_t *a, type_t *b);
bool has_heap_memory(type_t *t);
bool has_refcounts(type_t *t);
bool has_stack_memory(type_t *t);
PUREFUNC bool can_promote(type_t *actual, type_t *needed);
PUREFUNC const char *enum_single_value_tag(type_t *enum_type, type_t *t);
PUREFUNC bool is_int_type(type_t *t);
PUREFUNC bool is_numeric_type(type_t *t);
PUREFUNC bool is_packed_data(type_t *t);
CONSTFUNC bool is_incomplete_type(type_t *t);
CONSTFUNC type_t *most_complete_type(type_t *t1, type_t *t2);
PUREFUNC size_t type_size(type_t *t);
PUREFUNC size_t type_align(type_t *t);
PUREFUNC size_t unpadded_struct_size(type_t *t);
PUREFUNC type_t *non_optional(type_t *t);
type_t *get_field_type(type_t *t, const char *field_name);
PUREFUNC type_t *get_iterated_type(type_t *t);
type_t *_make_function_type(type_t *ret, int n, arg_t args[n]);