AST_INT, AST_STR to AST_VALUE

This commit is contained in:
Krzosa Karol
2022-06-02 22:37:42 +02:00
parent 173ef843df
commit a416007bba
6 changed files with 260 additions and 238 deletions

View File

@@ -82,13 +82,11 @@ gen_expr(Ast_Expr *ast){
BREAK(); BREAK();
} }
CASE(INT, Atom){ CASE(VALUE, Atom){
gen("%lld", node->int_val); if(is_int(node->type)) gen("%lld", node->int_val);
BREAK(); else if(is_string(node->type)) gen("LIT(\"%s\")", node->intern_val.str);
} else if(is_bool(node->type)) node->bool_val ? gen("true"):gen("false");
else invalid_codepath;
CASE(STR, Atom){
gen("LIT(\"%s\")", node->intern_val.str);
BREAK(); BREAK();
} }

View File

@@ -80,6 +80,7 @@ For now I don't thing it should be overloadable.
#include "base.cpp" #include "base.cpp"
#include "base_unicode.cpp" #include "base_unicode.cpp"
#include "new_lex.cpp" #include "new_lex.cpp"
#include "types.h"
#include "new_ast.cpp" #include "new_ast.cpp"
#include "new_parse.cpp" #include "new_parse.cpp"
#include "typecheck.h" #include "typecheck.h"

View File

@@ -83,8 +83,7 @@ enum Ast_Kind: U32{
AST_PACKAGE, AST_PACKAGE,
AST_STR, AST_VALUE,
AST_INT,
AST_CAST, AST_CAST,
AST_IDENT, AST_IDENT,
AST_INDEX, AST_INDEX,
@@ -116,9 +115,9 @@ enum{
AST_STMT = 2, AST_STMT = 2,
AST_BINDING = 4, AST_BINDING = 4,
AST_AGGREGATE = 8, AST_AGGREGATE = 8,
AST_ATOM = 16, AST_AGGREGATE_CHILD = 16,
AST_AGGREGATE_CHILD = 32, AST_ITEM_INCLUDED = 32,
AST_ITEM_INCLUDED = 64, AST_ATOM = 64,
}; };
struct Ast{ struct Ast{
@@ -140,6 +139,7 @@ union{ \
F64 f64_val; \ F64 f64_val; \
F32 f32_val; \ F32 f32_val; \
S64 int_val; \ S64 int_val; \
U64 uint_val; \
Intern_String intern_val; \ Intern_String intern_val; \
Ast_Resolved_Type *type_val; \ Ast_Resolved_Type *type_val; \
}; };
@@ -282,21 +282,23 @@ struct Ast_Package:Ast{
function Ast_Atom * function Ast_Atom *
ast_str(Token *pos, Intern_String string){ ast_str(Token *pos, Intern_String string){
AST_NEW(Atom, STR, pos, AST_ATOM | AST_EXPR); AST_NEW(Atom, VALUE, pos, AST_EXPR | AST_ATOM);
result->type = type_string; // @todo untyped
result->intern_val = string; result->intern_val = string;
return result; return result;
} }
function Ast_Atom * function Ast_Atom *
ast_ident(Token *pos, Intern_String string){ ast_ident(Token *pos, Intern_String string){
AST_NEW(Atom, IDENT, pos, AST_ATOM | AST_EXPR); AST_NEW(Atom, IDENT, pos, AST_EXPR | AST_ATOM);
result->intern_val = string; result->intern_val = string;
return result; return result;
} }
function Ast_Atom * function Ast_Atom *
ast_int(Token *pos, S64 integer){ ast_int(Token *pos, S64 integer){
AST_NEW(Atom, INT, pos, AST_ATOM | AST_EXPR); AST_NEW(Atom, VALUE, pos, AST_EXPR | AST_ATOM);
result->type = type_int; // @todo untyped
result->int_val = integer; result->int_val = integer;
return result; return result;
} }

View File

@@ -112,16 +112,8 @@ function void
_rewrite_into_const(Ast *node, U64 ast_size, Sym *sym){ _rewrite_into_const(Ast *node, U64 ast_size, Sym *sym){
auto ast = (Ast_Atom *)node; auto ast = (Ast_Atom *)node;
assert(ast_size >= sizeof(Ast_Atom)); assert(ast_size >= sizeof(Ast_Atom));
if(sym->type == type_int){ ast->kind = AST_VALUE;
ast->kind = AST_INT; ast->value = sym->value;
ast->int_val = sym->int_val;
} else if(sym->type == type_string){
ast->kind = AST_STR;
ast->intern_val = sym->intern_val;
} else if(sym->type == type_bool){
ast->kind = AST_INT;
ast->int_val = sym->int_val;
} else invalid_codepath;
} }
#define rewrite_into_const(ast,T,sym) _rewrite_into_const(ast,sizeof(T),sym) #define rewrite_into_const(ast,T,sym) _rewrite_into_const(ast,sizeof(T),sym)
@@ -176,8 +168,10 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res
assert(is_flag_set(ast->flags, AST_EXPR)); assert(is_flag_set(ast->flags, AST_EXPR));
switch(ast->kind){ switch(ast->kind){
CASE(INT, Atom){return operand_int(node->int_val); BREAK();} CASE(VALUE, Atom){
CASE(STR, Atom){return operand_str(node->intern_val); BREAK();} return operand_rvalue(node->value);
BREAK();
}
CASE(IDENT, Atom){ CASE(IDENT, Atom){
Sym *sym = resolve_name(node->pos, node->intern_val); Sym *sym = resolve_name(node->pos, node->intern_val);

View File

@@ -1,188 +1,3 @@
//-----------------------------------------------------------------------------
// Resolved Types
//-----------------------------------------------------------------------------
enum Ast_Resolved_Type_Kind{
TYPE_NONE,
TYPE_COMPLETING,
TYPE_INCOMPLETE,
TYPE_UNTYPED_BOOL, // FIRST_TYPED_NUMERIC, FIRST_NUMERIC
TYPE_UNTYPED_INT,
TYPE_UNTYPED_FLOAT, // LAST_TYPED_NUMERIC
TYPE_UNTYPED_STRING, // LAST_NUMERIC
TYPE_INT, // FIRST_NUMERIC
TYPE_S64,
TYPE_S32,
TYPE_S16,
TYPE_S8 ,
TYPE_UINT,
TYPE_U64,
TYPE_U32,
TYPE_U16,
TYPE_U8 ,
TYPE_F32,
TYPE_F64,
TYPE_BOOL, // LAST_NUMERIC
TYPE_STRING,
TYPE_VOID,
TYPE_POINTER,
TYPE_ARRAY,
TYPE_LAMBDA,
TYPE_STRUCT,
TYPE_UNION,
TYPE_ENUM,
TYPE_TYPE,
TYPE_UNTYPED_FIRST = TYPE_UNTYPED_BOOL,
TYPE_UNTYPED_LAST = TYPE_UNTYPED_STRING,
TYPE_UNTYPED_FIRST_NUMERIC = TYPE_UNTYPED_BOOL,
TYPE_UNTYPED_LAST_NUMERIC = TYPE_UNTYPED_FLOAT,
TYPE_FIRST_NUMERIC = TYPE_INT,
TYPE_LAST_NUMERIC = TYPE_BOOL,
};
const char *type_names[] = {
"[Invalid Ast_Resolved_Type]",
"[Completing]",
"[Incomplete]",
"[Untyped_Bool]",
"[Untyped_Int]",
"[Untyped_Float]",
"[Untyped_String]",
"[Int]",
"[S64]",
"[S32]",
"[S16]",
"[S8]",
"[UInt]",
"[U64]",
"[U32]",
"[U16]",
"[U8]",
"[Float32]",
"[Float64]",
"[Bool]",
"[String]",
"[Void]",
"[Pointer]",
"[Array]",
"[Lambda]",
"[Struct]",
"[Union]",
"[Enum]",
"[Type]",
};
struct Ast_Resolved_Member{
Ast_Resolved_Type *type;
Intern_String name;
U64 offset;
};
struct Ast_Resolved_Type{
Ast_Resolved_Type_Kind kind;
SizeU size;
SizeU align;
Ast *ast;
union{
Ast_Resolved_Type *base;
struct{
Ast_Resolved_Type *base;
SizeU size;
}arr;
struct{
Array<Ast_Resolved_Member> members;
}agg;
struct{
Ast_Resolved_Type *ret;
Array<Ast_Resolved_Type *> args;
}func;
};
};
function const char *
name(Ast_Resolved_Type *type){
switch(type->kind){
case TYPE_VOID: return "void";
case TYPE_INT: return "Int";
case TYPE_UINT: return "UInt";
case TYPE_BOOL: return "bool";
case TYPE_STRING: return "String";
case TYPE_S8: return "S8";
case TYPE_S16: return "S16";
case TYPE_S32: return "S32";
case TYPE_S64: return "S64";
case TYPE_U8: return "U8";
case TYPE_U16: return "U16";
case TYPE_U32: return "U32";
case TYPE_U64: return "U64";
invalid_default_case;
}
return "<unknown_type>";
}
//-----------------------------------------------------------------------------
// Type globals
//-----------------------------------------------------------------------------
const SizeU pointer_size = sizeof(SizeU);
const SizeU pointer_align = __alignof(SizeU);
global Ast_Resolved_Type type__void = {TYPE_VOID};
global Ast_Resolved_Type type__string = {TYPE_STRING, sizeof(String), __alignof(String)};
global Ast_Resolved_Type type__bool = {TYPE_BOOL, sizeof(bool), __alignof(bool)};
global Ast_Resolved_Type type__type = {TYPE_TYPE};
global Ast_Resolved_Type type__f32 = {TYPE_F32, sizeof(F32), __alignof(F32)};
global Ast_Resolved_Type type__f64 = {TYPE_F64, sizeof(F64), __alignof(F64)};
global Ast_Resolved_Type type__int = {TYPE_INT, sizeof(S64), __alignof(S64)};
global Ast_Resolved_Type type__s8 = {TYPE_S8, sizeof(S8), __alignof(S8)};
global Ast_Resolved_Type type__s16 = {TYPE_S16, sizeof(S16), __alignof(S16)};
global Ast_Resolved_Type type__s32 = {TYPE_S32, sizeof(S32), __alignof(S32)};
global Ast_Resolved_Type type__s64 = {TYPE_S64, sizeof(S64), __alignof(S64)};
global Ast_Resolved_Type type__uint = {TYPE_UINT, sizeof(SizeU), __alignof(SizeU)};
global Ast_Resolved_Type type__u8 = {TYPE_U8, sizeof(U8), __alignof(U8)};
global Ast_Resolved_Type type__u16 = {TYPE_U16, sizeof(U16), __alignof(U16)};
global Ast_Resolved_Type type__u32 = {TYPE_U32, sizeof(U32), __alignof(U32)};
global Ast_Resolved_Type type__u64 = {TYPE_U64, sizeof(U64), __alignof(U64)};
global Ast_Resolved_Type type__untyped_bool = {TYPE_UNTYPED_BOOL, sizeof(bool), __alignof(bool)};
global Ast_Resolved_Type type__untyped_int = {TYPE_UNTYPED_INT, sizeof(S64), __alignof(S64)};
global Ast_Resolved_Type type__untyped_string = {TYPE_UNTYPED_STRING, sizeof(String), __alignof(String)};
global Ast_Resolved_Type type__untyped_float = {TYPE_UNTYPED_FLOAT, sizeof(double), __alignof(double)};
global Ast_Resolved_Type *type_type = &type__type;
global Ast_Resolved_Type *type_void = &type__void;
global Ast_Resolved_Type *type_string = &type__string;
global Ast_Resolved_Type *type_bool = &type__bool;
global Ast_Resolved_Type *type_f32 = &type__f32;
global Ast_Resolved_Type *type_f64 = &type__f64;
global Ast_Resolved_Type *type_int = &type__int;
global Ast_Resolved_Type *type_s8 = &type__s8 ;
global Ast_Resolved_Type *type_s16 = &type__s16;
global Ast_Resolved_Type *type_s32 = &type__s32;
global Ast_Resolved_Type *type_s64 = &type__s64;
global Ast_Resolved_Type *type_uint = &type__uint;
global Ast_Resolved_Type *type_u8 = &type__u8 ;
global Ast_Resolved_Type *type_u16 = &type__u16;
global Ast_Resolved_Type *type_u32 = &type__u32;
global Ast_Resolved_Type *type_u64 = &type__u64;
global Ast_Resolved_Type *untyped_string = &type__untyped_string;
global Ast_Resolved_Type *untyped_bool = &type__untyped_bool;
global Ast_Resolved_Type *untyped_int = &type__untyped_int;
global Ast_Resolved_Type *untyped_float = &type__untyped_float;
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Symbols // Symbols
@@ -353,6 +168,17 @@ sym_insert_builtins(){
sym_insert_builtin_type("Bool"_s , type_bool); sym_insert_builtin_type("Bool"_s , type_bool);
sym_insert_builtin_type("Int"_s , type_int); sym_insert_builtin_type("Int"_s , type_int);
sym_insert_builtin_type("String"_s, type_string); sym_insert_builtin_type("String"_s, type_string);
sym_insert_builtin_type("S8"_s, type_s8);
sym_insert_builtin_type("S16"_s, type_s16);
sym_insert_builtin_type("S32"_s, type_s32);
sym_insert_builtin_type("S64"_s, type_s64);
sym_insert_builtin_type("U8"_s, type_u8);
sym_insert_builtin_type("U16"_s, type_u16);
sym_insert_builtin_type("U32"_s, type_u32);
sym_insert_builtin_type("U64"_s, type_u64);
sym_insert_builtin_type("F32"_s, type_f32);
sym_insert_builtin_type("F64"_s, type_f64);
{ {
Intern_String string = intern_string(&pctx->interns, "true"_s); Intern_String string = intern_string(&pctx->interns, "true"_s);
@@ -425,6 +251,14 @@ operand_lambda(Ast_Resolved_Type *type){
return result; return result;
} }
function Operand
operand_rvalue(Value value){
Operand result = {};
result.is_const = true;
result.value = value;
return result;
}
function Operand function Operand
operand_lvalue(Ast_Resolved_Type *type){ operand_lvalue(Ast_Resolved_Type *type){
Operand result = {}; Operand result = {};
@@ -444,30 +278,8 @@ operand_rvalue(Ast_Resolved_Type *type){
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Type constructors and utillities // Hash consed types
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
force_inline B32 is_struct(Ast_Resolved_Type *a){return a->kind == TYPE_STRUCT;}
force_inline B32 is_array(Ast_Resolved_Type *a){return a->kind == TYPE_ARRAY;}
force_inline B32 is_enum(Ast_Resolved_Type *a){return a->kind == TYPE_ENUM;}
force_inline B32 is_pointer(Ast_Resolved_Type *a){return a->kind == TYPE_POINTER;}
force_inline B32 is_string(Ast_Resolved_Type *a){return a->kind == TYPE_STRING || a->kind == TYPE_UNTYPED_STRING;}
force_inline B32 is_untyped_int(Ast_Resolved_Type *a){return a->kind == TYPE_UNTYPED_INT;}
force_inline B32 is_typed_int(Ast_Resolved_Type *a){return (a->kind >= TYPE_INT && a->kind <= TYPE_U8);}
force_inline B32 is_int(Ast_Resolved_Type *a){return (a->kind >= TYPE_INT && a->kind <= TYPE_U8) || a->kind == TYPE_UNTYPED_INT;}
force_inline B32 is_signed_int(Ast_Resolved_Type *a){return a->kind >= TYPE_INT && a->kind <= TYPE_S8;}
force_inline B32 is_unsigned_int(Ast_Resolved_Type *a){return a->kind >= TYPE_UINT && a->kind <= TYPE_U8;}
force_inline B32 is_float(Ast_Resolved_Type *a){return a->kind == TYPE_F32 || a->kind == TYPE_F64 || a->kind == TYPE_UNTYPED_FLOAT;}
force_inline B32 is_bool(Ast_Resolved_Type *a){return a->kind == TYPE_BOOL || a->kind == TYPE_UNTYPED_BOOL;}
force_inline B32 is_untyped(Ast_Resolved_Type *a){return a->kind >= TYPE_UNTYPED_FIRST && a->kind <= TYPE_UNTYPED_LAST;}
force_inline B32 is_typed(Ast_Resolved_Type *a){return !is_untyped(a);}
force_inline B32
is_numeric(Ast_Resolved_Type *type){
return (type->kind >= TYPE_UNTYPED_FIRST_NUMERIC && type->kind <= TYPE_UNTYPED_LAST_NUMERIC) ||
(type->kind >= TYPE_FIRST_NUMERIC && type->kind <= TYPE_LAST_NUMERIC);
}
function Ast_Resolved_Type * function Ast_Resolved_Type *
type_new(Allocator *allocator, Ast_Resolved_Type_Kind kind, SizeU size, SizeU align){ type_new(Allocator *allocator, Ast_Resolved_Type_Kind kind, SizeU size, SizeU align){
Ast_Resolved_Type *result = exp_alloc_type(allocator, Ast_Resolved_Type, AF_ZeroMemory); Ast_Resolved_Type *result = exp_alloc_type(allocator, Ast_Resolved_Type, AF_ZeroMemory);

215
types.h Normal file
View File

@@ -0,0 +1,215 @@
//-----------------------------------------------------------------------------
// Resolved Types
//-----------------------------------------------------------------------------
enum Ast_Resolved_Type_Kind{
TYPE_NONE,
TYPE_COMPLETING,
TYPE_INCOMPLETE,
TYPE_UNTYPED_BOOL, // FIRST_TYPED_NUMERIC, FIRST_NUMERIC
TYPE_UNTYPED_INT,
TYPE_UNTYPED_FLOAT, // LAST_TYPED_NUMERIC
TYPE_UNTYPED_STRING, // LAST_NUMERIC
TYPE_INT, // FIRST_NUMERIC
TYPE_S64,
TYPE_S32,
TYPE_S16,
TYPE_S8 ,
TYPE_UINT,
TYPE_U64,
TYPE_U32,
TYPE_U16,
TYPE_U8 ,
TYPE_F32,
TYPE_F64,
TYPE_BOOL, // LAST_NUMERIC
TYPE_STRING,
TYPE_VOID,
TYPE_POINTER,
TYPE_ARRAY,
TYPE_LAMBDA,
TYPE_STRUCT,
TYPE_UNION,
TYPE_ENUM,
TYPE_TYPE,
TYPE_UNTYPED_FIRST = TYPE_UNTYPED_BOOL,
TYPE_UNTYPED_LAST = TYPE_UNTYPED_STRING,
TYPE_UNTYPED_FIRST_NUMERIC = TYPE_UNTYPED_BOOL,
TYPE_UNTYPED_LAST_NUMERIC = TYPE_UNTYPED_FLOAT,
TYPE_FIRST_NUMERIC = TYPE_INT,
TYPE_LAST_NUMERIC = TYPE_BOOL,
};
const char *type_names[] = {
"[Invalid Ast_Resolved_Type]",
"[Completing]",
"[Incomplete]",
"[Untyped_Bool]",
"[Untyped_Int]",
"[Untyped_Float]",
"[Untyped_String]",
"[Int]",
"[S64]",
"[S32]",
"[S16]",
"[S8]",
"[UInt]",
"[U64]",
"[U32]",
"[U16]",
"[U8]",
"[Float32]",
"[Float64]",
"[Bool]",
"[String]",
"[Void]",
"[Pointer]",
"[Array]",
"[Lambda]",
"[Struct]",
"[Union]",
"[Enum]",
"[Type]",
};
struct Ast;
struct Ast_Resolved_Type;
struct Ast_Resolved_Member{
Ast_Resolved_Type *type;
Intern_String name;
U64 offset;
};
struct Ast_Resolved_Type{
Ast_Resolved_Type_Kind kind;
SizeU size;
SizeU align;
Ast *ast;
union{
Ast_Resolved_Type *base;
struct{
Ast_Resolved_Type *base;
SizeU size;
}arr;
struct{
Array<Ast_Resolved_Member> members;
}agg;
struct{
Ast_Resolved_Type *ret;
Array<Ast_Resolved_Type *> args;
}func;
};
};
function const char *
name(Ast_Resolved_Type *type){
switch(type->kind){
case TYPE_VOID: return "Void";
case TYPE_INT: return "Int";
case TYPE_UINT: return "UInt";
case TYPE_BOOL: return "Bool";
case TYPE_STRING: return "String";
case TYPE_F32: return "F32";
case TYPE_F64: return "F64";
case TYPE_S8: return "S8";
case TYPE_S16: return "S16";
case TYPE_S32: return "S32";
case TYPE_S64: return "S64";
case TYPE_U8: return "U8";
case TYPE_U16: return "U16";
case TYPE_U32: return "U32";
case TYPE_U64: return "U64";
invalid_default_case;
}
return "<unknown_type>";
}
//-----------------------------------------------------------------------------
// Type globals
//-----------------------------------------------------------------------------
const SizeU pointer_size = sizeof(SizeU);
const SizeU pointer_align = __alignof(SizeU);
global Ast_Resolved_Type type__void = {TYPE_VOID};
global Ast_Resolved_Type type__string = {TYPE_STRING, sizeof(String), __alignof(String)};
global Ast_Resolved_Type type__bool = {TYPE_BOOL, sizeof(bool), __alignof(bool)};
global Ast_Resolved_Type type__type = {TYPE_TYPE};
global Ast_Resolved_Type type__f32 = {TYPE_F32, sizeof(F32), __alignof(F32)};
global Ast_Resolved_Type type__f64 = {TYPE_F64, sizeof(F64), __alignof(F64)};
global Ast_Resolved_Type type__int = {TYPE_INT, sizeof(S64), __alignof(S64)};
global Ast_Resolved_Type type__s8 = {TYPE_S8, sizeof(S8), __alignof(S8)};
global Ast_Resolved_Type type__s16 = {TYPE_S16, sizeof(S16), __alignof(S16)};
global Ast_Resolved_Type type__s32 = {TYPE_S32, sizeof(S32), __alignof(S32)};
global Ast_Resolved_Type type__s64 = {TYPE_S64, sizeof(S64), __alignof(S64)};
global Ast_Resolved_Type type__uint = {TYPE_UINT, sizeof(SizeU), __alignof(SizeU)};
global Ast_Resolved_Type type__u8 = {TYPE_U8, sizeof(U8), __alignof(U8)};
global Ast_Resolved_Type type__u16 = {TYPE_U16, sizeof(U16), __alignof(U16)};
global Ast_Resolved_Type type__u32 = {TYPE_U32, sizeof(U32), __alignof(U32)};
global Ast_Resolved_Type type__u64 = {TYPE_U64, sizeof(U64), __alignof(U64)};
global Ast_Resolved_Type type__untyped_bool = {TYPE_UNTYPED_BOOL, sizeof(bool), __alignof(bool)};
global Ast_Resolved_Type type__untyped_int = {TYPE_UNTYPED_INT, sizeof(S64), __alignof(S64)};
global Ast_Resolved_Type type__untyped_string = {TYPE_UNTYPED_STRING, sizeof(String), __alignof(String)};
global Ast_Resolved_Type type__untyped_float = {TYPE_UNTYPED_FLOAT, sizeof(double), __alignof(double)};
global Ast_Resolved_Type *type_type = &type__type;
global Ast_Resolved_Type *type_void = &type__void;
global Ast_Resolved_Type *type_string = &type__string;
global Ast_Resolved_Type *type_bool = &type__bool;
global Ast_Resolved_Type *type_f32 = &type__f32;
global Ast_Resolved_Type *type_f64 = &type__f64;
global Ast_Resolved_Type *type_int = &type__int;
global Ast_Resolved_Type *type_s8 = &type__s8 ;
global Ast_Resolved_Type *type_s16 = &type__s16;
global Ast_Resolved_Type *type_s32 = &type__s32;
global Ast_Resolved_Type *type_s64 = &type__s64;
global Ast_Resolved_Type *type_uint = &type__uint;
global Ast_Resolved_Type *type_u8 = &type__u8 ;
global Ast_Resolved_Type *type_u16 = &type__u16;
global Ast_Resolved_Type *type_u32 = &type__u32;
global Ast_Resolved_Type *type_u64 = &type__u64;
global Ast_Resolved_Type *untyped_string = &type__untyped_string;
global Ast_Resolved_Type *untyped_bool = &type__untyped_bool;
global Ast_Resolved_Type *untyped_int = &type__untyped_int;
global Ast_Resolved_Type *untyped_float = &type__untyped_float;
//-----------------------------------------------------------------------------
// Type constructors and utillities
//-----------------------------------------------------------------------------
force_inline B32 is_struct(Ast_Resolved_Type *a){return a->kind == TYPE_STRUCT;}
force_inline B32 is_array(Ast_Resolved_Type *a){return a->kind == TYPE_ARRAY;}
force_inline B32 is_enum(Ast_Resolved_Type *a){return a->kind == TYPE_ENUM;}
force_inline B32 is_pointer(Ast_Resolved_Type *a){return a->kind == TYPE_POINTER;}
force_inline B32 is_string(Ast_Resolved_Type *a){return a->kind == TYPE_STRING || a->kind == TYPE_UNTYPED_STRING;}
force_inline B32 is_untyped_int(Ast_Resolved_Type *a){return a->kind == TYPE_UNTYPED_INT;}
force_inline B32 is_typed_int(Ast_Resolved_Type *a){return (a->kind >= TYPE_INT && a->kind <= TYPE_U8);}
force_inline B32 is_int(Ast_Resolved_Type *a){return (a->kind >= TYPE_INT && a->kind <= TYPE_U8) || a->kind == TYPE_UNTYPED_INT;}
force_inline B32 is_signed_int(Ast_Resolved_Type *a){return a->kind >= TYPE_INT && a->kind <= TYPE_S8;}
force_inline B32 is_unsigned_int(Ast_Resolved_Type *a){return a->kind >= TYPE_UINT && a->kind <= TYPE_U8;}
force_inline B32 is_float(Ast_Resolved_Type *a){return a->kind == TYPE_F32 || a->kind == TYPE_F64 || a->kind == TYPE_UNTYPED_FLOAT;}
force_inline B32 is_bool(Ast_Resolved_Type *a){return a->kind == TYPE_BOOL || a->kind == TYPE_UNTYPED_BOOL;}
force_inline B32 is_untyped(Ast_Resolved_Type *a){return a->kind >= TYPE_UNTYPED_FIRST && a->kind <= TYPE_UNTYPED_LAST;}
force_inline B32 is_typed(Ast_Resolved_Type *a){return !is_untyped(a);}
force_inline B32
is_numeric(Ast_Resolved_Type *type){
return (type->kind >= TYPE_UNTYPED_FIRST_NUMERIC && type->kind <= TYPE_UNTYPED_LAST_NUMERIC) ||
(type->kind >= TYPE_FIRST_NUMERIC && type->kind <= TYPE_LAST_NUMERIC);
}