From 42699034ae506991c5330d552f23ebbde4970958 Mon Sep 17 00:00:00 2001 From: Krzosa Karol Date: Fri, 3 Jun 2022 17:58:20 +0200 Subject: [PATCH] Got all programs working, now adding unary not and neg --- ccodegen.cpp | 5 +-- main.cpp | 24 ++++++------ new_parse.cpp | 4 ++ new_types.kl | 3 ++ typecheck.cpp | 100 ++++++++++++++++++++++++++++++-------------------- typecheck.h | 3 ++ 6 files changed, 84 insertions(+), 55 deletions(-) diff --git a/ccodegen.cpp b/ccodegen.cpp index 2e0cc36..0504b05 100644 --- a/ccodegen.cpp +++ b/ccodegen.cpp @@ -405,10 +405,7 @@ compile_string(String filecontent, String filename = "default_name"_s){ gen(R"==( -//------------------------------- -#define NULL_POINTER 0 -#define NULL_LAMBDA 0 -//------------------------------- + // Generated )=="); F64 resolve_begin = os_time(); diff --git a/main.cpp b/main.cpp index 05291a4..34eceaa 100644 --- a/main.cpp +++ b/main.cpp @@ -32,10 +32,9 @@ For now I don't thing it should be overloadable. ------------------------------------------------------------------------------- @todo -[ ] - in new typesystem: Fix calls, fix other example programs +[ ] - Operators: Bit negation, Not [ ] - Compiling and running a program [ ] - Passing down program to compile through command line -[ ] - Operators: Bit negation, Not [ ] - More for loop variations [ ] - Fixing access to constants, in C we cant have constants inside of structs / functions so we need to rewrite the tree [ ] - Default values in structs??? Should compound stmts bring values from default values?? Maybe not? Whats the alternative @@ -66,6 +65,7 @@ For now I don't thing it should be overloadable. [x] - Enums [x] - Initial for loop [x] - Enum . access to values +[x] - in new typesystem: Fix calls, fix all example programs [x] - Fix arithmetic operations in new type system [x] - Init statements, different kinds [+=] [-=] etc. [x] - Struct calls @@ -104,20 +104,20 @@ int main(){ test_intern_table(); String result = {}; -#if 1 - // result = compile_file("globals.kl"_s); - // printf("%s", result.str); - // result = compile_file("enums.kl"_s); - // printf("%s", result.str); - // result = compile_file("order1.kl"_s); - // printf("%s", result.str); - // result = compile_file("lambdas.kl"_s); - // printf("%s", result.str); +#if 0 + result = compile_file("globals.kl"_s); + printf("%s", result.str); + result = compile_file("enums.kl"_s); + printf("%s", result.str); + result = compile_file("order1.kl"_s); + printf("%s", result.str); result = compile_file("order2.kl"_s); printf("%s", result.str); - result = compile_file("new_types.kl"_s); + result = compile_file("lambdas.kl"_s); printf("%s", result.str); #endif + result = compile_file("new_types.kl"_s); + printf("%s", result.str); // result = compile_file("lexer.kl"_s); // FILE *f = fopen("program.c", "w"); diff --git a/new_parse.cpp b/new_parse.cpp index 5037783..d39aefe 100644 --- a/new_parse.cpp +++ b/new_parse.cpp @@ -315,6 +315,8 @@ binding_power(Binding binding, Token_Kind kind){ case TK_OpenParen: case TK_Sub: case TK_Add: + case TK_Neg: + case TK_Not: return{-2, 20}; default: return {-1, -1}; } @@ -370,6 +372,8 @@ parse_expr(S64 min_bp){ case TK_Dereference: left = ast_expr_unary(token, TK_Dereference, parse_expr(prefix_bp.right)); break; case TK_Sub : left = ast_expr_unary(token, TK_Sub, parse_expr(prefix_bp.right)); break; case TK_Add : left = ast_expr_unary(token, TK_Add, parse_expr(prefix_bp.right)); break; + case TK_Not : left = ast_expr_unary(token, TK_Not, parse_expr(prefix_bp.right)); break; + case TK_Neg : left = ast_expr_unary(token, TK_Neg, parse_expr(prefix_bp.right)); break; case TK_OpenBracket: { Ast_Array *result = ast_array(token, parse_expr(0)); diff --git a/new_types.kl b/new_types.kl index 230b104..dc48902 100644 --- a/new_types.kl +++ b/new_types.kl @@ -7,6 +7,9 @@ unary_test :: () float2 := -float_val unsigned: Int = -+-+-int_val + not: Bool = !int_val + neg: S64 = ~int_val + // uns: U64 = -int_val // int_float: S64 = float_val // string :: -"Thing" diff --git a/typecheck.cpp b/typecheck.cpp index 8d59e3e..c306965 100644 --- a/typecheck.cpp +++ b/typecheck.cpp @@ -1,6 +1,33 @@ #define CASE(kind,type) case AST_##kind: { Ast_##type *node = (Ast_##type *)ast; #define BREAK() } break +function void +type_error(Token *token, Ast_Resolved_Type *expected, Ast_Resolved_Type *actual, const char *str, ...){ + Scratch scratch; + STRING_FMT(scratch, str, string); + + // @Note(Krzosa): Print nice error message + printf("\nType error :: %s :: ", string.str); + printf("Expected %s, got instead %s", docname(expected), docname(actual)); + if(token){ + printf(" :: %s:%d\n", token->file.str, (S32)token->line + 1); + + // @Note(Krzosa): Print error line + { + int i = 0; + while(token->line_begin[i]!='\n' && token->line_begin[i]!=0) i++; + printf("%.*s\n", i, token->line_begin); + + // @Note(Krzosa): Print error marker + int token_i = token->str - token->line_begin; + for(int i = 0; i < token_i-2; i++) printf(" "); + printf("^^^^^^\n"); + } + } + + __debugbreak(); +} + //----------------------------------------------------------------------------- // Evaluating constant expressions //----------------------------------------------------------------------------- @@ -13,8 +40,10 @@ function Value convert_untyped(Token *pos, Value a, Ast_Resolved_Type *new_type){ - assert(is_untyped(a.type)); + // assert(a.type); assert(new_type); + if(a.type == 0) return a; + if(is_typed(a.type)) return a; assert(a.int_val <= S64MAX); if(is_int(a.type) && is_int(new_type)){ @@ -315,28 +344,6 @@ resolve_typespec(Ast_Expr *ast, B32 ast_can_be_null){ return resolved.type_val; } -function Ast_Resolved_Type * -resolve_type_pair(Token *pos, Ast_Resolved_Type *a, Ast_Resolved_Type *b){ - Ast_Resolved_Type *result = 0; - if(!a && b) result = b; - else if(a && !b) result = a; - else if(!a && !b) parsing_error(pos, "Trying to resolve a type pair where both types are [Null]"); - else{ // a && b - if(a != b) parsing_error(pos, "Expression and type specification are differing %s %s", type_names[a->kind], type_names[b->kind]); - else result = a; // Types are the same - } - - return result; -} - -function Operand -resolve_operand_pair(Token *pos, Operand a, Operand b){ - Operand result = {}; - result.is_const = a.is_const && b.is_const; - result.type = resolve_type_pair(pos, a.type, b.type); - return result; -} - function void resolve_stmt(Ast *ast, Ast_Resolved_Type *ret); function void resolve_stmt_block(Ast_Block *block, Ast_Resolved_Type *ret){ @@ -354,8 +361,9 @@ resolve_stmt(Ast *ast, Ast_Resolved_Type *ret){ switch(ast->kind){ CASE(RETURN, Return){ // @todo: need to check if all paths return a value Operand op = resolve_expr(node->expr); - if(!op.type && ret != type_void) parsing_error(node->pos, "Function expects a void return value but the returned value is [%s]", type_names[op.type->kind]); - if(op.type && op.type != ret) parsing_error(node->pos, "Return statement has different type then returned value"); + if(!op.type && ret != type_void) parsing_error(node->pos, "Function expects a void return value but the returned value is %s", docname(op.type)); + op.value = convert_untyped(node->pos, op.value, ret); + if(op.type && op.type != ret) parsing_error(node->pos, "Return statement has different type then returned value, expecting: %s got instead %s", docname(ret), docname(op.type)); BREAK(); } @@ -409,12 +417,11 @@ require_const_int(Ast_Expr *expr, B32 ast_can_be_null){ if(expr == 0 && ast_can_be_null) return op; else if(expr == 0) parsing_error(expr->pos, "This field cannot be null"); if(!op.is_const) parsing_error(expr->pos, "Expected a const value"); - if(op.type != type_int) parsing_error(expr->pos, "Expected a constant integer"); + if(!is_int(op.type)) parsing_error(expr->pos, "Expected a constant integer got instead %s", docname(op.type)); return op; } - function Operand resolve_lambda(Ast_Lambda *lambda, Sym *sym = 0){ Scratch scratch; @@ -422,11 +429,15 @@ resolve_lambda(Ast_Lambda *lambda, Sym *sym = 0){ Ast_Resolved_Type *ret_type = resolve_typespec(lambda->ret); Array args = {scratch}; For(lambda->args){ - Operand type = resolve_expr(it->typespec); - if(type.type != type_type) parsing_error(it->pos, "Required expression of kind [type]"); - Operand default_value = resolve_expr(it->default_value, type.type_val); - if(default_value.type && default_value.type != type.type_val) parsing_error(it->pos, "Default value type and type declaration differ"); - args.add(type.type_val); + Ast_Resolved_Type *type = resolve_typespec(it->typespec, AST_CANT_BE_NULL); + Operand default_value = resolve_expr(it->default_value, type); + + if(default_value.type){ + default_value.value = convert_untyped(it->pos, default_value.value, type); + if(default_value.type != type) parsing_error(it->pos, "Default value type and type declaration differ, expected %s got instead %s", docname(type), docname(default_value.type)); + } + + args.add(type); } lambda_type = type_lambda(lambda, ret_type, args); @@ -507,8 +518,8 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res CASE(INDEX, Index){ Operand left = resolve_expr(node->expr); Operand index = resolve_expr(node->index); - if(left.type->kind != TYPE_ARRAY) parsing_error(node->pos, "Indexing variable that is not an array"); - if(index.type != type_int) parsing_error(node->pos, "Trying to index the array with invalid type, expected int"); + if(left.type->kind != TYPE_ARRAY) parsing_error(node->pos, "Indexing variable that is not an array, it's of type %s instead", docname(left.type)); + if(!is_int(index.type)) type_error(node->pos, type_int, index.type,"Trying to index the array with invalid type, expected int"); return operand_lvalue(left.type->arr.base); BREAK(); } @@ -536,7 +547,7 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res if(index_op.int_val > (type->arr.size - 1)) parsing_error(i->pos, "Invalid index in compound expression, larger then type can store"); } Operand expr = resolve_expr(i->item, item_type); - resolve_type_pair(i->pos, expr.type, item_type); + expr.value = convert_untyped(i->pos, expr.value, item_type); } } else if(type->kind == TYPE_STRUCT){ @@ -571,10 +582,10 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res if(!found) parsing_error(expr->pos, "Invalid argument in compound constructor"); if(is_flag_set(found->flags, AST_ITEM_INCLUDED)) parsing_error(found->pos, "Item included multiple times in compound constructor"); - found->flags = set_flag(found->flags, AST_ITEM_INCLUDED); + Operand op = resolve_expr(expr->item, found_type->type); - try_untyping(&op); + op.value = convert_untyped(node->pos, op.value, found_type->type); if(found_type->type != op.type) parsing_error(expr->pos, "Invalid type of compound constructor item, expected %s got instead %s", type_names[found_type->type->kind], type_names[op.type->kind]); } @@ -615,7 +626,9 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res if(item){ item->flags = set_flag(item->flags, AST_ITEM_INCLUDED); Operand expr = resolve_expr(item->item); - if(expr.type != resolved) parsing_error(item->pos, "Type is not matching function definition"); + expr.value = convert_untyped(node->pos, expr.value, resolved); + + if(expr.type != resolved) type_error(item->pos, resolved, expr.type, "Type is not matching function definition"); items.add(item); } else{ @@ -809,6 +822,16 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res result = operand_const_rvalue(value); } else{ + if(is_untyped(left.type)){ + assert(is_typed(right.type)); + left.value = convert_untyped(node->pos, left.value, right.type); + } + else if(is_untyped(right.type)){ + assert(is_typed(left.type)); + right.value = convert_untyped(node->pos, right.value, left.type); + } + + if(left.type != right.type){ parsing_error(node->pos, "Type mismatch in binary operation %s - left: %s right: %s", token_kind_string(node->op).str, docname(left.type), docname(right.type)); } @@ -879,7 +902,6 @@ resolve_binding(Ast *ast, Sym *sym){ Operand expr = resolve_expr(node->expr, type); assert(expr.type != 0 || type != 0); - if(!type) try_untyping(&expr); else if(!expr.type) expr.type = type; else if(type == expr.type); diff --git a/typecheck.h b/typecheck.h index 91eb657..dee123d 100644 --- a/typecheck.h +++ b/typecheck.h @@ -400,6 +400,9 @@ type_struct(Ast_Struct *agg){ function void type_complete(Ast_Resolved_Type *type){ + if(!type) { + return; + } if(type->kind == TYPE_COMPLETING){ parsing_error(type->ast->pos, "Cyclic type dependency"); }