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]);
|