From 79edfae55b8942ee7d57abf8221bfb45be8c7ff5 Mon Sep 17 00:00:00 2001 From: Krzosa Karol Date: Sun, 19 Jun 2022 15:28:18 +0200 Subject: [PATCH] Lot's of work on Any and Type --- ast.cpp | 4 ++-- ccodegen.cpp | 30 +++++------------------------- main.cpp | 2 +- programs/language.kl | 5 +++++ programs/main.kl | 6 ++++++ typechecking.cpp | 36 +++++++++++++++++++++--------------- typechecking.h | 8 ++++++++ 7 files changed, 48 insertions(+), 43 deletions(-) diff --git a/ast.cpp b/ast.cpp index 964d14f..0c5d094 100644 --- a/ast.cpp +++ b/ast.cpp @@ -113,8 +113,7 @@ struct Ast_Var_Unpack: Ast_Expr{ struct Ast_Unary: Ast_Expr{ Token_Kind op; Ast_Expr *expr; - Ast_Type *resolved_type_val; - U64 padding[1]; // For folding constants into atoms + U64 padding[2]; // For folding constants into atoms }; struct Ast_Index: Ast_Expr{ @@ -175,6 +174,7 @@ struct Ast_Lambda : Ast_Expr { struct Ast_Array: Ast_Expr{ Ast_Expr *base; Ast_Expr *expr; + U64 padding[2]; }; struct Ast_Switch_Case: Ast{ diff --git a/ccodegen.cpp b/ccodegen.cpp index 65d0837..9c3d181 100644 --- a/ccodegen.cpp +++ b/ccodegen.cpp @@ -178,7 +178,7 @@ gen_value(Value a){ assert(a.type == type_pointer_to_char); gen("\"%Q\"", a.intern_val); } else{ - gen("LIT(\"%Q\")", a.intern_val); + gen("(String){(U8 *)\"%Q\", %d}", a.intern_val, a.intern_val.len); } break; CASE_BOOL: a.bool_val ? gen("true"):gen("false"); break; @@ -255,13 +255,6 @@ gen_lambda(Intern_String name, Ast_Lambda *lambda, B32 generate_block = true){ function bool gen_expr(Ast_Expr *ast, Ast_Type *type_of_var){ - if(is_any(type_of_var)){ - gen("(Any){&"); - gen_expr(ast); - gen(", %d}", ast->resolved_type->type_id); - return true; - } - switch(ast->kind){ CASE(IDENT, Atom){ if(node->resolved_decl->kind == AST_MODULE_NAMESPACE || node->resolved_decl->kind == AST_FILE_NAMESPACE) @@ -344,21 +337,9 @@ gen_expr(Ast_Expr *ast, Ast_Type *type_of_var){ CASE(UNARY, Unary){ gen("("); - if(node->op != TK_PostIncrement && node->op != TK_PostDecrement){ - if(node->op == TK_Pointer){ - // Normal types are usually generated with gen_simple_decl - // if they are part of the expression they are a value - // which means we need to shortcircuit here with proper type_id - Ast_Type *base = get_type_base(node->resolved_type); - if(base == type_type){ - gen("%d)", node->resolved_type_val->type_id); - return true; - } - } - gen("%s", name(node->op)); - } + if(node->op != TK_PostIncrement && node->op != TK_PostDecrement) gen("%s", name(node->op)); gen_expr(node->expr); - if(node->op == TK_PostIncrement || node->op == TK_PostDecrement) gen("%s", name(node->op)); + if(node->op == TK_PostIncrement || node->op == TK_PostDecrement) gen("%s", name(node->op)); gen(")"); BREAK(); } @@ -398,7 +379,7 @@ gen_expr(Ast_Expr *ast, Ast_Type *type_of_var){ gen(".%Q = ", it->resolved_name); else if(is_array(node->resolved_type)) gen("[%d] = ", (int)it->resolved_index); - gen_expr(it->item); + gen_expr(it->item, it->resolved_type); if(!node->exprs.is_last(&it)) gen(", "); } gen("}"); @@ -832,7 +813,6 @@ typedef struct String{ U8 *str; S64 len; }String; -#define LIT(x) (String){.str=(U8 *)x, .len=sizeof(x)-1} #define assert(x) do{if(!(x))__debugbreak();}while(0) #define assert_msg(x,...) assert(x) @@ -919,7 +899,7 @@ typedef struct String{ gen(".struct_member_count = %d, ", it->agg.members.len); gen(".struct_members = (Type_Info_Struct_Member[]){"); For_Named(it->agg.members, m){ - gen("{.name = LIT(\"%Q\"), .type = %d, .offset = %d}, ", m.name, m.type->type_id, m.offset); + gen("{.name = (String){(U8 *)\"%Q\", %d}, .type = %d, .offset = %d}, ", m.name, m.name.len, m.type->type_id, m.offset); } gen("}"); diff --git a/main.cpp b/main.cpp index 721ecbc..4e284cd 100644 --- a/main.cpp +++ b/main.cpp @@ -43,7 +43,6 @@ want to export all the symbols, we can namespace them optionally. @todo [ ] - Probably need to give Ast_Expr a Value field, then I can express Type nicely [ ] - I would love for String, slice, Any etc. to have their struct declarations in source files, I also would want for stuff like string.str to work without weird special cases -[ ] - Implementing type Any [ ] - #test construct that would gather all tests and run them on start of program or something [ ] - Foreign import that would link library @@ -81,6 +80,7 @@ want to export all the symbols, we can namespace them optionally. [ ] - Polymorphism - create declaration of a polymorphic thing, when it's called just copy it, replace types and typecheck normally, when someone calls again you just search for the instantiation again @donzo +[x] - Implementing type Any [x] - Runtime TypeInfo [x] - Proper type Type support [x] - Switch diff --git a/programs/language.kl b/programs/language.kl index 6ddef1f..50adef1 100644 --- a/programs/language.kl +++ b/programs/language.kl @@ -10,6 +10,11 @@ Slice :: struct */ +Dynamic_Array :: struct + data: *void + len : S64 + cap : S64 + Any :: struct data: *void type: Type diff --git a/programs/main.kl b/programs/main.kl index 6bb4641..d6fb80f 100644 --- a/programs/main.kl +++ b/programs/main.kl @@ -84,6 +84,10 @@ print :: (a: Any) OutputDebugStringA("Pointer") default;; OutputDebugStringA("Unknown") +// print_array :: (a: []Any) +// for i := 0, i < length_of(a), i+=1 +// print(a[i]) + app_is_running := true window_procedure :: (hwnd: HWND, msg: UINT, wparam: WPARAM, lparam: LPARAM): LRESULT @@ -97,10 +101,12 @@ WinMain :: (hInstance: HINSTANCE, hPrevInstance: HINSTANCE, lpCmdLine: LPSTR, nS if good_scheduling := false, timeBeginPeriod(1) == TIMERR_NOERROR good_scheduling = true + some_type: Type = Vec2 char_info := get_type_info(char) val := 4232.23 thing: Any = val print(val) + // print_array({125.23, 32}) assert(char_info.kind == Type_Info_Kind.CHAR) #assert(int == int) diff --git a/typechecking.cpp b/typechecking.cpp index 2697550..69f6020 100644 --- a/typechecking.cpp +++ b/typechecking.cpp @@ -459,7 +459,7 @@ resolve_typespec(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context = return 0; Scratch scratch; - Operand resolved = resolve_expr(ast, flags, compound_context); + Operand resolved = resolve_expr(ast, flags | RESOLVE_TYPESPEC, compound_context); if(is_flag_set(flags, RESOLVE_TYPESPEC_COMPLETE)) type_complete(resolved.type_val); if(resolved.type != type_type) @@ -723,7 +723,7 @@ resolve_compound_array(Ast_Call *node, Ast_Type *type){ Ast_Type *item_type = type->arr.base; S64 size = type->arr.size; - if(node->exprs.len > size) + if(is_array(type) && node->exprs.len > size) compiler_error(node->pos, "Too many items in compound expression, expected: %lld got: %lld", size, node->exprs.len); S64 default_counter = 0; @@ -886,15 +886,18 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context){ Operand type = resolve_expr(node->base, AST_CANT_BE_NULL); Operand expr = require_const_int(node->expr, AST_CAN_BE_NULL); if(type.type != type_type) compiler_error(node->pos, "Prefix array operator is only allowed on types"); - type_complete(type.type_val); + + if(!is_flag_set(flags, RESOLVE_TYPESPEC)){ + rewrite_into_const(node, Ast_Array, type.value); + } + if(node->expr){ node->resolved_type = type_array(type.type_val, bigint_as_unsigned(&expr.big_int_val)); } else{ node->resolved_type = type_slice(type.type_val, node); } - return operand_type(node->resolved_type); BREAK(); } @@ -919,7 +922,7 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context){ if(is_string(left.type)){ return operand_lvalue(type_u8); } - else if(!is_array(left.type) && !is_pointer(left.type)){ + else if(!is_array(left.type) && !is_pointer(left.type) && !is_slice(left.type)){ compiler_error(node->pos, "Indexing variable that is not an [Array] or [Pointer], it's of type %Q instead", typestring(left.type)); } @@ -971,16 +974,19 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context){ } CASE(UNARY, Unary){ - Operand value = resolve_expr(node->expr, AST_CANT_BE_NULL); + Operand value = resolve_expr(node->expr, inherit_flag(flags, AST_CANT_BE_NULL)); if(node->op == TK_Pointer){ if(value.type->kind == TYPE_POINTER){ node->resolved_type = value.type->base; return operand_lvalue(node->resolved_type); } else if(value.type->kind == TYPE_TYPE){ - node->resolved_type = type_type; - node->resolved_type_val = type_pointer(value.type_val); - return operand_type(node->resolved_type_val); + if(!is_flag_set(flags, RESOLVE_TYPESPEC)){ + rewrite_into_const(node, Ast_Array, value.value); + } + + node->resolved_type = type_pointer(value.type_val); + return operand_type(node->resolved_type); } else{ compiler_error(node->pos, "Dereferencing expression %Q that is not a [Pointer] or [Type]", typestring(value.type)); return {}; } } @@ -1001,7 +1007,7 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context){ } CASE(COMPOUND, Call){ - Operand op = resolve_expr(node->typespec, AST_CAN_BE_NULL); + Operand op = resolve_expr(node->typespec, inherit_flag(flags, AST_CAN_BE_NULL)); Ast_Type *type = op.type; if(type){ @@ -1016,7 +1022,7 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context){ type_complete(type); node->resolved_type = type; - if(is_array(type)){ + if(is_array(type) || is_slice(type)){ resolve_compound_array(node, type); } else if(is_struct(type)){ @@ -1029,7 +1035,7 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context){ } CASE(ALIGN_OF, Builtin){ - Operand name = resolve_expr(node->expr, AST_CANT_BE_NULL); + Operand name = resolve_expr(node->expr, inherit_flag(flags, AST_CANT_BE_NULL)); if(!name.is_const) compiler_error(node->pos, "align_of requires a constant value"); Ast_Type *type = name.type == type_type ? name.type_val : name.type; Value v = value_int(type->align); @@ -1039,7 +1045,7 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context){ } CASE(SIZE_OF, Builtin){ - Operand name = resolve_expr(node->expr, AST_CANT_BE_NULL); + Operand name = resolve_expr(node->expr, inherit_flag(flags, AST_CANT_BE_NULL)); if(!name.is_const) compiler_error(node->pos, "size_of requires a constant value"); Ast_Type *type = name.type == type_type ? name.type_val : name.type; Value v = value_int(type->size); @@ -1049,7 +1055,7 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context){ } CASE(LENGTH_OF, Builtin){ - Operand name = resolve_expr(node->expr, AST_CANT_BE_NULL); + Operand name = resolve_expr(node->expr, inherit_flag(flags, AST_CANT_BE_NULL)); if(name.type == type_type){ if(is_array(name.type_val)){ Value value = value_int(name.type_val->arr.size); @@ -1071,7 +1077,7 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context){ } CASE(CALL, Call){ - Operand name = resolve_expr(node->name, AST_CANT_BE_NULL); + Operand name = resolve_expr(node->name, inherit_flag(flags, AST_CANT_BE_NULL)); if(name.type->kind != TYPE_LAMBDA) compiler_error(node->pos, "Calling %Q which is not a [Lambda]", typestring(name.type)); diff --git a/typechecking.h b/typechecking.h index a02641e..096689b 100644 --- a/typechecking.h +++ b/typechecking.h @@ -10,6 +10,7 @@ FLAG32(Resolve_Flag){ AST_CANT_BE_NULL = bit_flag(0), AST_CAN_BE_NULL = bit_flag(1), RESOLVE_TYPESPEC_COMPLETE = bit_flag(2), + RESOLVE_TYPESPEC = bit_flag(3), }; FLAG32(Search_Flag){ @@ -20,6 +21,13 @@ function Operand resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compo function void resolve_decl(Ast_Decl *ast); function Ast_Decl *resolve_name(Ast_Scope *parent_scope, Token *pos, Intern_String name, Search_Flag search_flags = 0); +function Resolve_Flag +inherit_flag(Resolve_Flag flag, B32 ast_can_be_null){ + unset_flag(flag, AST_CAN_BE_NULL); + set_flag(flag, ast_can_be_null); + return flag; +} + //----------------------------------------------------------------------------- // Operands //-----------------------------------------------------------------------------