diff --git a/base.cpp b/base.cpp index f4ad60c..78b4fef 100644 --- a/base.cpp +++ b/base.cpp @@ -62,12 +62,10 @@ typedef double F64; #define kib(x) ((x)*1024llu) #define mib(x) (kib(x)*1024llu) #define gib(x) (mib(x)*1024llu) -#define JOIN1(X,Y) X##Y // helper macro +#define JOIN1(X,Y) X##Y #define JOIN(X,Y) JOIN1(X,Y) #define string_expand(x) (int)x.len, x.str -#define FLAG32(x) typedef U32 x; enum - #if defined(__clang__) # define COMPILER_CLANG 1 # if defined(_WIN32) diff --git a/core_ast.cpp b/core_ast.cpp index 6bbd43e..888fb46 100644 --- a/core_ast.cpp +++ b/core_ast.cpp @@ -95,7 +95,6 @@ typedef U32 Ast_Call_Item_Flag; enum{ CALL_INDEX = bit_flag(1), CALL_NAME = bit_flag(2), - CALL_DOT_ANY = bit_flag(3), CALL_INCLUDED= bit_flag(4), }; diff --git a/core_compiler.cpp b/core_compiler.cpp index 76913c7..ad9fbaa 100644 --- a/core_compiler.cpp +++ b/core_compiler.cpp @@ -290,7 +290,7 @@ compile_file(String filename, U32 compile_flags = COMPILE_NULL){ Scratch scratch; F64 begin = os_time(); - String compiler_call = string_fmt(scratch, "clang.exe program.c -Wall -Wno-parentheses-equality -g -o a.exe -lgdi32 -luser32 -lwinmm"); + String compiler_call = string_fmt(scratch, "clang.exe program.c -Wall -Wno-unused-function -Wno-parentheses-equality -g -o a.exe -lgdi32 -luser32 -lwinmm"); system((const char *)compiler_call.str); F64 end = os_time(); diff --git a/core_main.cpp b/core_main.cpp index db3e05b..0ba22e9 100644 --- a/core_main.cpp +++ b/core_main.cpp @@ -260,6 +260,7 @@ For modules it's a bit different cause they should be distributed as valid. #include "core_ast.cpp" #include "core_parsing.cpp" #include "core_typechecking.h" +#include "core_types.cpp" #include "core_typechecking.cpp" #include "core_compiler.cpp" #include "core_codegen_c_language.cpp" diff --git a/core_typechecking.cpp b/core_typechecking.cpp index 67b5f21..be96ef8 100644 --- a/core_typechecking.cpp +++ b/core_typechecking.cpp @@ -1,59 +1,4 @@ -function const char * -get_name_of_type(Ast_Type *type){ - switch(type->kind){ - case TYPE_VOID: return "void"; - case TYPE_BOOL: return "Bool"; - case TYPE_STRING: return "String"; - case TYPE_CHAR: return "char"; - case TYPE_F32: return "F32"; - case TYPE_F64: return "F64"; - case TYPE_S8: return "S8"; - case TYPE_INT: return "int"; - 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"; - case TYPE_TUPLE: return "Tuple"; - case TYPE_TYPE: return "Type"; - invalid_default_case; - } - return ""; -} - -//----------------------------------------------------------------------------- -// Type constructors and utillities -//----------------------------------------------------------------------------- -force_inline B32 is_any(Ast_Type *a){return a == type_any;} -force_inline B32 is_struct(Ast_Type *a){return a->kind == TYPE_STRUCT;} -force_inline B32 is_lambda(Ast_Type *a){return a->kind == TYPE_LAMBDA;} -force_inline B32 is_array(Ast_Type *a){return a->kind == TYPE_ARRAY;} -force_inline B32 is_slice(Ast_Type *a){return a->kind == TYPE_SLICE;} -force_inline B32 is_tuple(Ast_Type *a){return a->kind == TYPE_TUPLE;} -force_inline B32 is_enum(Ast_Type *a){return a->kind == TYPE_ENUM;} -force_inline B32 is_pointer(Ast_Type *a){return a->kind == TYPE_POINTER;} -force_inline B32 is_void(Ast_Type *a){return a->kind == TYPE_VOID;} -force_inline B32 is_void_pointer(Ast_Type *a){return a == type_pointer_to_void;} -force_inline B32 is_string(Ast_Type *a){return a->kind == TYPE_STRING || a->kind == TYPE_UNTYPED_STRING || a == type_pointer_to_char;} -force_inline B32 is_untyped_int(Ast_Type *a){return a->kind == TYPE_UNTYPED_INT;} -force_inline B32 is_typed_int(Ast_Type *a){return (a->kind >= TYPE_S64 && a->kind <= TYPE_U8);} -force_inline B32 is_int(Ast_Type *a){return (a->kind >= TYPE_S64 && a->kind <= TYPE_U8) || a->kind == TYPE_UNTYPED_INT;} -force_inline B32 is_signed_int(Ast_Type *a){return !a->is_unsigned;} -force_inline B32 is_unsigned_int(Ast_Type *a){return a->is_unsigned;} -force_inline B32 is_float(Ast_Type *a){return a->kind == TYPE_F32 || a->kind == TYPE_F64 || a->kind == TYPE_UNTYPED_FLOAT;} -force_inline B32 is_f32(Ast_Type *a){return a->kind == TYPE_F32;} -force_inline B32 is_f64(Ast_Type *a){return a->kind == TYPE_F64;} -force_inline B32 is_bool(Ast_Type *a){return a->kind == TYPE_BOOL || a->kind == TYPE_UNTYPED_BOOL;} -force_inline B32 is_untyped(Ast_Type *a){return a->kind >= TYPE_UNTYPED_FIRST && a->kind <= TYPE_UNTYPED_LAST;} -force_inline B32 is_typed(Ast_Type *a){return !is_untyped(a);} -force_inline B32 is_numeric(Ast_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 Resolve_Flag inherit_flag(Resolve_Flag flag, B32 ast_can_be_null){ unset_flag(flag, AST_CAN_BE_NULL); @@ -140,287 +85,6 @@ operand_rvalue(Ast_Type *type){ return result; } -//----------------------------------------------------------------------------- -// Hash consed types -//----------------------------------------------------------------------------- -function Ast_Type * -type_new(Allocator *allocator, Ast_Type_Kind kind, SizeU size, SizeU align){ - Ast_Type *result = exp_alloc_type(allocator, Ast_Type, AF_ZeroMemory); - result->kind = kind; - result->size = size; - result->align = align; - result->type_id = pctx->type_ids++; - add(pctx->perm, &pctx->all_types, result); - return result; -} - -function Ast_Type * -type_copy(Allocator *a, Ast_Type *type){ - // @warning: This changes type id !!!! - Ast_Type *result = exp_alloc_type(a, Ast_Type); - memory_copy(result, type, sizeof(Ast_Type)); - result->type_id = pctx->type_ids++; - add(pctx->perm, &pctx->all_types, result); - return result; -} - -function Ast_Type * -type_pointer(Ast_Type *base){ - Ast_Type *result = (Ast_Type *)map_get(&pctx->type_map, (void *)base); - if(!result){ - result = type_new(pctx->perm, TYPE_POINTER, pointer_size, pointer_align); - result->base = base; - result->is_unsigned = true; - map_insert(&pctx->type_map, base, result); - } - assert(result->kind == TYPE_POINTER); - return result; -} - -function Ast_Type * -type_slice(Ast_Type *base, Ast *ast){ - U64 hash_base = hash_ptr(base); - U64 hash = hash_mix(hash_base, hash_u64(ARRAY_SIZE_SLICE)); - Ast_Type *result = (Ast_Type *)map_get(&pctx->type_map, hash); - if(result){ - assert(result->kind == TYPE_SLICE); - assert(result->arr.base == base); - return result; - } - - struct Slice{void *p; S64 len;}; - result = type_new(pctx->perm, TYPE_SLICE, sizeof(Slice), alignof(Slice)); - result->arr.base = base; - result->arr.slice_hash = hash; - result->ast = ast; - map_insert(&pctx->type_map, hash, result); - return result; -} - -function Ast_Type * -type_try_tupling(Array types, Ast *ast){ - if(types.len == 0) return type_void; - if(types.len == 1) return types[0]; - - U64 hash = 13; - For(types) hash = hash_mix(hash, hash_ptr(it)); - Ast_Type *result = (Ast_Type *)map_get(&pctx->type_map, hash); - if(result){ - assert(result->kind == TYPE_TUPLE); - assert(result->agg.members.len == types.len); - assert(result->agg.members.len > 1); - return result; - } - - // @todo alignment, offsets - result = type_new(pctx->perm, TYPE_TUPLE, 0, pointer_align); - result->agg.members = array_make(pctx->perm, types.len); - For(types){ - Ast_Resolved_Member m = {}; - m.type = it; - m.offset = 0; // @todo - result->size += it->size; - result->agg.members.add(m); - } - map_insert(&pctx->type_map, hash, result); - assert(result->agg.members.len > 1); - - return result; -} - -function Ast_Type * -type_array(Ast_Type *base, S64 size){ - U64 hash_base = hash_ptr(base); - U64 hash = hash_mix(hash_base, hash_u64(size)); - Ast_Type *result = (Ast_Type *)map_get(&pctx->type_map, hash); - if(result){ - assert(result->kind == TYPE_ARRAY); - assert(result->arr.size == size); - assert(result->arr.base == base); - return result; - } - - result = type_new(pctx->perm, TYPE_ARRAY, size*base->size, pointer_align); - result->arr.base = base; - result->arr.size = size; - result->arr.slice_hash = hash_mix(hash_base, hash_u64(ARRAY_SIZE_SLICE)); - map_insert(&pctx->type_map, hash, result); - return result; -} - -inline U64 -calculate_hash_for_arguments(Ast_Type *a, Ast_Type *b){ - U64 result = 13; - result = hash_mix(result, hash_ptr(a)); - result = hash_mix(result, hash_ptr(b)); - return result; -} - -inline U64 -calculate_hash_for_arguments(Ast_Type *a){ - U64 result = 13; - result = hash_mix(result, hash_ptr(a)); - return result; -} - -function Ast_Type * -type_lambda(Ast *ast, Array return_vals, Array args){ - Ast_Type *ret = type_try_tupling(return_vals, ast); - U64 hash_without_ret = 13; - For(args) hash_without_ret = hash_mix(hash_without_ret, hash_ptr(it)); - U64 hash = hash_mix(hash_ptr(ret), hash_without_ret); - Ast_Type *result = (Ast_Type *)map_get(&pctx->type_map, hash); - - if(result){ - assert(result->kind == TYPE_LAMBDA); - assert(result->func.args.len == args.len); - return result; - } - - result = type_new(pctx->perm, TYPE_LAMBDA, pointer_size, pointer_align); - result->ast = ast; - result->func.ret = ret; - result->func.args = args.tight_copy(pctx->perm); - result->func.hash_without_ret = hash_without_ret; // @function_overloading scrap this if we changed course - map_insert(&pctx->type_map, hash, result); - - return result; -} - -function Ast_Type * -type_enum(Ast_Decl *ast, Ast_Type *type){ - if(!type){ - type = type_s64; - } - - Ast_Type *result = type_new(pctx->perm, TYPE_ENUM, type->size, type->align); - result->base = type; - result->ast = ast; - return result; -} - -function Ast_Type * -type_incomplete(Ast *ast){ - Ast_Type *result = type_new(pctx->perm, TYPE_INCOMPLETE, 0, 0); - result->ast = ast; - return result; -} - -function void type_complete(Ast_Type *type); -function void -type_struct_complete(Ast_Type *type, Ast_Decl *node){ - assert(node->kind == AST_STRUCT); - // @todo: compute size, alignement, offset !!! - // @note: resolve all the struct members first - Scratch scratch; - Array members = {scratch}; - type->kind = TYPE_COMPLETING; - size_t members_size = 0; - For(node->scope->decls){ - resolve_decl(it); - assert(it->type->kind != TYPE_INCOMPLETE); - assert(is_pow2(it->type->align)); - - Ast_Resolved_Member m = {}; - m.offset = type->size; - members_size += it->type->size; - type->align = max(type->align, it->type->align); - type->size = it->type->size + align_up(type->size, it->type->align); - - m.name = it->name; - m.value = it->value; - members.add(m); - } - type->size = align_up(type->size, type->align); - type->padding = type->size - members_size; - type->agg.members = members.tight_copy(pctx->perm); - type->kind = TYPE_STRUCT; - node->unique_name = pctx->intern(string_fmt(scratch, "%Q%Q", symbol_prefix, node->name)); -} - -function void -type_complete(Ast_Type *type){ - if(!type) { - return; - } - if(type->kind == TYPE_COMPLETING){ - compiler_error(type->ast->pos, "Cyclic type dependency"); - } - else if(type->kind != TYPE_INCOMPLETE){ - return; - } - - type_struct_complete(type, (Ast_Decl *)type->ast); - add(pctx->perm, &pctx->ordered_decls, (Ast_Decl *)type->ast); -} - -function void -init_type(){ - type_pointer_to_char = type_pointer(type_char); - type_pointer_to_void = type_pointer(type_void); -} - -function void -typename_base(String_Builder *sb, Ast_Type *type){ - switch(type->kind){ - case TYPE_INCOMPLETE: sb->addf("INCOMPLETE"); break; - case TYPE_COMPLETING: sb->addf("COMPLETING"); break; - case TYPE_TYPE: sb->addf("TYPE"); break; - case TYPE_POINTER: - sb->addf("*"); - typename_base(sb, type->base); - break; - case TYPE_LAMBDA: - sb->addf("("); - For(type->func.args) { - typename_base(sb, it); - if(!type->func.args.is_last(&it)) sb->addf(", "); - } - - sb->addf("):"); - typename_base(sb, type->func.ret); - break; - case TYPE_ARRAY: - sb->addf("[%d]", (int)type->arr.size); - typename_base(sb, type->arr.base); - break; - case TYPE_SLICE: - sb->addf("[]"); - typename_base(sb, type->base); - break; - case TYPE_STRUCT: - case TYPE_ENUM:{ - // @todo direct access - auto constant = (Ast_Decl *)type->ast; - auto name = constant->name; - sb->addf("%Q", name); - break; - } - case TYPE_UNTYPED_BOOL: sb->addf("Untyped_Bool"); break; - case TYPE_UNTYPED_INT: sb->addf("Untyped_Int"); break; - case TYPE_UNTYPED_FLOAT: sb->addf("Untyped_Float"); break; - case TYPE_UNTYPED_STRING: sb->addf("Untyped_String"); break; - default: { - sb->addf("%s", get_name_of_type(type)); - } - } -} - -function String -get_typename(Allocator *a, Ast_Type *type){ - pctx->helper_builder.addf("["); - typename_base(&pctx->helper_builder, type); - pctx->helper_builder.addf("]"); - String result = string_flatten(a, &pctx->helper_builder); - pctx->helper_builder.reset(); - return result; -} - -function String -typestring(Ast_Type *type){ - return get_typename(&pctx->stage_arena, type); -} - function void check_value_bounds(Token *pos, Value *a){ if(!is_int(a->type)) return; diff --git a/core_types.cpp b/core_types.cpp new file mode 100644 index 0000000..9f74006 --- /dev/null +++ b/core_types.cpp @@ -0,0 +1,336 @@ + +function const char * +get_name_of_type(Ast_Type *type){ + switch(type->kind){ + case TYPE_VOID: return "void"; + case TYPE_BOOL: return "Bool"; + case TYPE_STRING: return "String"; + case TYPE_CHAR: return "char"; + case TYPE_F32: return "F32"; + case TYPE_F64: return "F64"; + case TYPE_S8: return "S8"; + case TYPE_INT: return "int"; + 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"; + case TYPE_TUPLE: return "Tuple"; + case TYPE_TYPE: return "Type"; + invalid_default_case; + } + return ""; +} + +//----------------------------------------------------------------------------- +// Type constructors and utillities +//----------------------------------------------------------------------------- +force_inline B32 is_any(Ast_Type *a){return a == type_any;} +force_inline B32 is_struct(Ast_Type *a){return a->kind == TYPE_STRUCT;} +force_inline B32 is_lambda(Ast_Type *a){return a->kind == TYPE_LAMBDA;} +force_inline B32 is_array(Ast_Type *a){return a->kind == TYPE_ARRAY;} +force_inline B32 is_slice(Ast_Type *a){return a->kind == TYPE_SLICE;} +force_inline B32 is_tuple(Ast_Type *a){return a->kind == TYPE_TUPLE;} +force_inline B32 is_enum(Ast_Type *a){return a->kind == TYPE_ENUM;} +force_inline B32 is_pointer(Ast_Type *a){return a->kind == TYPE_POINTER;} +force_inline B32 is_void(Ast_Type *a){return a->kind == TYPE_VOID;} +force_inline B32 is_void_pointer(Ast_Type *a){return a == type_pointer_to_void;} +force_inline B32 is_string(Ast_Type *a){return a->kind == TYPE_STRING || a->kind == TYPE_UNTYPED_STRING || a == type_pointer_to_char;} +force_inline B32 is_untyped_int(Ast_Type *a){return a->kind == TYPE_UNTYPED_INT;} +force_inline B32 is_typed_int(Ast_Type *a){return (a->kind >= TYPE_S64 && a->kind <= TYPE_U8);} +force_inline B32 is_int(Ast_Type *a){return (a->kind >= TYPE_S64 && a->kind <= TYPE_U8) || a->kind == TYPE_UNTYPED_INT;} +force_inline B32 is_signed_int(Ast_Type *a){return !a->is_unsigned;} +force_inline B32 is_unsigned_int(Ast_Type *a){return a->is_unsigned;} +force_inline B32 is_float(Ast_Type *a){return a->kind == TYPE_F32 || a->kind == TYPE_F64 || a->kind == TYPE_UNTYPED_FLOAT;} +force_inline B32 is_f32(Ast_Type *a){return a->kind == TYPE_F32;} +force_inline B32 is_f64(Ast_Type *a){return a->kind == TYPE_F64;} +force_inline B32 is_bool(Ast_Type *a){return a->kind == TYPE_BOOL || a->kind == TYPE_UNTYPED_BOOL;} +force_inline B32 is_untyped(Ast_Type *a){return a->kind >= TYPE_UNTYPED_FIRST && a->kind <= TYPE_UNTYPED_LAST;} +force_inline B32 is_typed(Ast_Type *a){return !is_untyped(a);} +force_inline B32 is_numeric(Ast_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); +} + +//----------------------------------------------------------------------------- +// Hash consed types +//----------------------------------------------------------------------------- +function Ast_Type * +type_new(Allocator *allocator, Ast_Type_Kind kind, SizeU size, SizeU align){ + Ast_Type *result = exp_alloc_type(allocator, Ast_Type, AF_ZeroMemory); + result->kind = kind; + result->size = size; + result->align = align; + result->type_id = pctx->type_ids++; + add(pctx->perm, &pctx->all_types, result); + return result; +} + +function Ast_Type * +type_copy(Allocator *a, Ast_Type *type){ + // @warning: This changes type id !!!! + Ast_Type *result = exp_alloc_type(a, Ast_Type); + memory_copy(result, type, sizeof(Ast_Type)); + result->type_id = pctx->type_ids++; + add(pctx->perm, &pctx->all_types, result); + return result; +} + +function Ast_Type * +type_pointer(Ast_Type *base){ + Ast_Type *result = (Ast_Type *)map_get(&pctx->type_map, (void *)base); + if(!result){ + result = type_new(pctx->perm, TYPE_POINTER, pointer_size, pointer_align); + result->base = base; + result->is_unsigned = true; + map_insert(&pctx->type_map, base, result); + } + assert(result->kind == TYPE_POINTER); + return result; +} + +function Ast_Type * +type_slice(Ast_Type *base, Ast *ast){ + U64 hash_base = hash_ptr(base); + U64 hash = hash_mix(hash_base, hash_u64(ARRAY_SIZE_SLICE)); + Ast_Type *result = (Ast_Type *)map_get(&pctx->type_map, hash); + if(result){ + assert(result->kind == TYPE_SLICE); + assert(result->arr.base == base); + return result; + } + + struct Slice{void *p; S64 len;}; + result = type_new(pctx->perm, TYPE_SLICE, sizeof(Slice), alignof(Slice)); + result->arr.base = base; + result->arr.slice_hash = hash; + result->ast = ast; + map_insert(&pctx->type_map, hash, result); + return result; +} + +function Ast_Type * +type_try_tupling(Array types, Ast *ast){ + if(types.len == 0) return type_void; + if(types.len == 1) return types[0]; + + U64 hash = 13; + For(types) hash = hash_mix(hash, hash_ptr(it)); + Ast_Type *result = (Ast_Type *)map_get(&pctx->type_map, hash); + if(result){ + assert(result->kind == TYPE_TUPLE); + assert(result->agg.members.len == types.len); + assert(result->agg.members.len > 1); + return result; + } + + // @todo alignment, offsets + result = type_new(pctx->perm, TYPE_TUPLE, 0, pointer_align); + result->agg.members = array_make(pctx->perm, types.len); + For(types){ + Ast_Resolved_Member m = {}; + m.type = it; + m.offset = 0; // @todo + result->size += it->size; + result->agg.members.add(m); + } + map_insert(&pctx->type_map, hash, result); + assert(result->agg.members.len > 1); + + return result; +} + +function Ast_Type * +type_array(Ast_Type *base, S64 size){ + U64 hash_base = hash_ptr(base); + U64 hash = hash_mix(hash_base, hash_u64(size)); + Ast_Type *result = (Ast_Type *)map_get(&pctx->type_map, hash); + if(result){ + assert(result->kind == TYPE_ARRAY); + assert(result->arr.size == size); + assert(result->arr.base == base); + return result; + } + + result = type_new(pctx->perm, TYPE_ARRAY, size*base->size, pointer_align); + result->arr.base = base; + result->arr.size = size; + result->arr.slice_hash = hash_mix(hash_base, hash_u64(ARRAY_SIZE_SLICE)); + map_insert(&pctx->type_map, hash, result); + return result; +} + +inline U64 +calculate_hash_for_arguments(Ast_Type *a, Ast_Type *b){ + U64 result = 13; + result = hash_mix(result, hash_ptr(a)); + result = hash_mix(result, hash_ptr(b)); + return result; +} + +inline U64 +calculate_hash_for_arguments(Ast_Type *a){ + U64 result = 13; + result = hash_mix(result, hash_ptr(a)); + return result; +} + +function Ast_Type * +type_lambda(Ast *ast, Array return_vals, Array args){ + Ast_Type *ret = type_try_tupling(return_vals, ast); + U64 hash_without_ret = 13; + For(args) hash_without_ret = hash_mix(hash_without_ret, hash_ptr(it)); + U64 hash = hash_mix(hash_ptr(ret), hash_without_ret); + Ast_Type *result = (Ast_Type *)map_get(&pctx->type_map, hash); + + if(result){ + assert(result->kind == TYPE_LAMBDA); + assert(result->func.args.len == args.len); + return result; + } + + result = type_new(pctx->perm, TYPE_LAMBDA, pointer_size, pointer_align); + result->ast = ast; + result->func.ret = ret; + result->func.args = args.tight_copy(pctx->perm); + result->func.hash_without_ret = hash_without_ret; + map_insert(&pctx->type_map, hash, result); + + return result; +} + +function Ast_Type * +type_enum(Ast_Decl *ast, Ast_Type *type){ + if(!type){ + type = type_s64; + } + + Ast_Type *result = type_new(pctx->perm, TYPE_ENUM, type->size, type->align); + result->base = type; + result->ast = ast; + return result; +} + +function Ast_Type * +type_incomplete(Ast *ast){ + Ast_Type *result = type_new(pctx->perm, TYPE_INCOMPLETE, 0, 0); + result->ast = ast; + return result; +} + +function void type_complete(Ast_Type *type); +function void +type_struct_complete(Ast_Type *type, Ast_Decl *node){ + assert(node->kind == AST_STRUCT); + // @todo: compute size, alignement, offset !!! + // @note: resolve all the struct members first + Scratch scratch; + Array members = {scratch}; + type->kind = TYPE_COMPLETING; + size_t members_size = 0; + For(node->scope->decls){ + resolve_decl(it); + assert(it->type->kind != TYPE_INCOMPLETE); + assert(is_pow2(it->type->align)); + + Ast_Resolved_Member m = {}; + m.offset = type->size; + members_size += it->type->size; + type->align = max(type->align, it->type->align); + type->size = it->type->size + align_up(type->size, it->type->align); + + m.name = it->name; + m.value = it->value; + members.add(m); + } + type->size = align_up(type->size, type->align); + type->padding = type->size - members_size; + type->agg.members = members.tight_copy(pctx->perm); + type->kind = TYPE_STRUCT; + node->unique_name = pctx->intern(string_fmt(scratch, "%Q%Q", symbol_prefix, node->name)); +} + +function void +type_complete(Ast_Type *type){ + if(!type) { + return; + } + if(type->kind == TYPE_COMPLETING){ + compiler_error(type->ast->pos, "Cyclic type dependency"); + } + else if(type->kind != TYPE_INCOMPLETE){ + return; + } + + type_struct_complete(type, (Ast_Decl *)type->ast); + add(pctx->perm, &pctx->ordered_decls, (Ast_Decl *)type->ast); +} + +function void +init_type(){ + type_pointer_to_char = type_pointer(type_char); + type_pointer_to_void = type_pointer(type_void); +} + +function void +typename_base(String_Builder *sb, Ast_Type *type){ + switch(type->kind){ + case TYPE_INCOMPLETE: sb->addf("INCOMPLETE"); break; + case TYPE_COMPLETING: sb->addf("COMPLETING"); break; + case TYPE_TYPE: sb->addf("TYPE"); break; + case TYPE_POINTER: + sb->addf("*"); + typename_base(sb, type->base); + break; + case TYPE_LAMBDA: + sb->addf("("); + For(type->func.args) { + typename_base(sb, it); + if(!type->func.args.is_last(&it)) sb->addf(", "); + } + + sb->addf("):"); + typename_base(sb, type->func.ret); + break; + case TYPE_ARRAY: + sb->addf("[%d]", (int)type->arr.size); + typename_base(sb, type->arr.base); + break; + case TYPE_SLICE: + sb->addf("[]"); + typename_base(sb, type->base); + break; + case TYPE_STRUCT: + case TYPE_ENUM:{ + // @todo direct access + auto constant = (Ast_Decl *)type->ast; + auto name = constant->name; + sb->addf("%Q", name); + break; + } + case TYPE_UNTYPED_BOOL: sb->addf("Untyped_Bool"); break; + case TYPE_UNTYPED_INT: sb->addf("Untyped_Int"); break; + case TYPE_UNTYPED_FLOAT: sb->addf("Untyped_Float"); break; + case TYPE_UNTYPED_STRING: sb->addf("Untyped_String"); break; + default: { + sb->addf("%s", get_name_of_type(type)); + } + } +} + +function String +get_typename(Allocator *a, Ast_Type *type){ + pctx->helper_builder.addf("["); + typename_base(&pctx->helper_builder, type); + pctx->helper_builder.addf("]"); + String result = string_flatten(a, &pctx->helper_builder); + pctx->helper_builder.reset(); + return result; +} + +function String +typestring(Ast_Type *type){ + return get_typename(&pctx->stage_arena, type); +} diff --git a/core_types.h b/core_types.h index 89978c4..a10c754 100644 --- a/core_types.h +++ b/core_types.h @@ -102,7 +102,7 @@ struct Ast_Type{ struct{ Ast_Type * ret; Array args; - U64 hash_without_ret; // @function_overloading scrap this if we changed course + U64 hash_without_ret; }func; }; }; diff --git a/examples/using_multimedia.core b/examples/using_multimedia.core index 43e65e7..80ec3f7 100644 --- a/examples/using_multimedia.core +++ b/examples/using_multimedia.core @@ -7,4 +7,6 @@ WinMain :: (hInstance: HINSTANCE, hPrevInstance: HINSTANCE, lpCmdLine: LPSTR, nS for y := 0, y < Mu.window.y, y+=1 for x := 0, x < Mu.window.x, x+=1 - Mu.screen[x + y*Mu.window.x] = 0xFFFFFF00 \ No newline at end of file + Mu.screen[x + y*Mu.window.x] = 0xFFFFFF00 + + return 0 \ No newline at end of file