From 25820a0c5b4dc1aa844bb16cb3d3d0ce004e5a4c Mon Sep 17 00:00:00 2001 From: Krzosa Karol Date: Fri, 3 Jun 2022 16:06:33 +0200 Subject: [PATCH] More work on types --- main.cpp | 10 ++++---- order2.kl | 4 ++-- typecheck.cpp | 65 +++++++++++++++++++++++++++++++++++---------------- types.h | 12 ---------- 4 files changed, 53 insertions(+), 38 deletions(-) diff --git a/main.cpp b/main.cpp index 63d0c55..05291a4 100644 --- a/main.cpp +++ b/main.cpp @@ -32,10 +32,10 @@ For now I don't thing it should be overloadable. ------------------------------------------------------------------------------- @todo -[ ] - Test new operators, add constant eval for them +[ ] - in new typesystem: Fix calls, fix other example programs [ ] - Compiling and running a program [ ] - Passing down program to compile through command line -[ ] - More operators +[ ] - 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 @@ -58,6 +58,7 @@ For now I don't thing it should be overloadable. [ ] - Rust like enum where you associate values(other structs) with keys @donzo +[x] - Test new operators, add constant eval for them [x] - lvalue, rvalue concept so we cant assign value to some arbitrary weird expression [x] - Add basic support for floats [x] - Add basic setup for new type system @@ -65,6 +66,7 @@ For now I don't thing it should be overloadable. [x] - Enums [x] - Initial for loop [x] - Enum . access to values +[x] - Fix arithmetic operations in new type system [x] - Init statements, different kinds [+=] [-=] etc. [x] - Struct calls [x] - Default values in calls @@ -111,8 +113,8 @@ int main(){ // printf("%s", result.str); // result = compile_file("lambdas.kl"_s); // printf("%s", result.str); - // result = compile_file("order2.kl"_s); - // printf("%s", result.str); + result = compile_file("order2.kl"_s); + printf("%s", result.str); result = compile_file("new_types.kl"_s); printf("%s", result.str); #endif diff --git a/order2.kl b/order2.kl index 8618b28..decbaee 100644 --- a/order2.kl +++ b/order2.kl @@ -18,7 +18,7 @@ Arena :: struct // arena: Arena next: *Arena data: *Int - len : Int + len : S64 cap : Int Sub :: struct @@ -26,7 +26,7 @@ Arena :: struct Sub_Sub :: struct len: Int - get_len :: (s: *Arena): Int // @todo + get_len :: (s: *Arena): S64 // @todo return s.next.len constant_inside :: 10000 diff --git a/typecheck.cpp b/typecheck.cpp index b0b4879..8d59e3e 100644 --- a/typecheck.cpp +++ b/typecheck.cpp @@ -1,5 +1,6 @@ #define CASE(kind,type) case AST_##kind: { Ast_##type *node = (Ast_##type *)ast; #define BREAK() } break + //----------------------------------------------------------------------------- // Evaluating constant expressions //----------------------------------------------------------------------------- @@ -33,6 +34,7 @@ convert_untyped(Token *pos, Value a, Ast_Resolved_Type *new_type){ invalid_default_case; } } + else if(is_int(a.type) && is_float(new_type)){ assert(a.type == untyped_int); switch(new_type->kind){ @@ -92,7 +94,7 @@ value_get_float(Value value){ return result; } -#include +#include // fmod function Value eval_binary(Token *pos, Token_Kind op, Value a, Value b){ if(!(is_numeric(a.type) && is_numeric(b.type))) parsing_error(pos, "Constant application of binary %s on values of type %s and %s is not allowed", token_kind_string(op).str, docname(a.type), docname(a.type)); @@ -142,55 +144,56 @@ eval_binary(Token *pos, Token_Kind op, Value a, Value b){ S64 right_int = value_get_int(b); F64 left_float = value_get_float(a); F64 right_float = value_get_float(b); - // @WARNING: When introducing big ints & | ^ will be problematic - Value c; - c.type = untyped_bool; + assert(before_conversion.type == untyped_float || before_conversion.type == untyped_int); + // @note: for returning early with bools + Value c; c.type = untyped_bool; switch(op){ // @note: These return early, they don't need type evaluation // always should return untyped bool case TK_And: { if(final_type == untyped_int) c.bool_val = left_int && right_int; - else c.bool_val = left_float && right_float; + else c.bool_val = left_float && right_float; return c; }break; case TK_Or: { if(final_type == untyped_int) c.bool_val = left_int || right_int; - else c.bool_val = left_float || right_float; + else c.bool_val = left_float || right_float; return c; }break; case TK_GreaterThen: { if(final_type == untyped_int) c.bool_val = left_int > right_int; - else c.bool_val = left_float > right_float; + else c.bool_val = left_float > right_float; return c; }break; case TK_GreaterThenOrEqual: { if(final_type == untyped_int) c.bool_val = left_int >= right_int; - else c.bool_val = left_float >= right_float; + else c.bool_val = left_float >= right_float; return c; }break; case TK_LesserThen: { if(final_type == untyped_int) c.bool_val = left_int < right_int; - else c.bool_val = left_float < right_float; + else c.bool_val = left_float < right_float; return c; }break; case TK_LesserThenOrEqual: { if(final_type == untyped_int) c.bool_val = left_int <= right_int; - else c.bool_val = left_float <= right_float; + else c.bool_val = left_float <= right_float; return c; }break; case TK_Equals: { if(final_type == untyped_int) c.bool_val = left_int == right_int; - else c.bool_val = left_float == right_float; + else c.bool_val = left_float == right_float; return c; }break; case TK_NotEquals: { if(final_type == untyped_int) c.bool_val = left_int != right_int; - else c.bool_val = left_float != right_float; + else c.bool_val = left_float != right_float; return c; }break; + // @note: These return at the end cause need type evaluation case TK_Add: { left_int = left_int + right_int; left_float = left_float + right_float; @@ -211,6 +214,8 @@ eval_binary(Token *pos, Token_Kind op, Value a, Value b){ left_int = left_int % right_int; left_float = fmod(left_float, right_float); } break; + + // @WARNING: When introducing big ints & | ^ will be problematic case TK_BitAnd: { left_int = left_int & right_int; if(before_conversion.type == untyped_float) parsing_error(pos, "%s cant be performed on [Untyped_Float]", token_kind_string(op).str); @@ -223,6 +228,7 @@ eval_binary(Token *pos, Token_Kind op, Value a, Value b){ left_int = left_int ^ right_int; if(before_conversion.type == untyped_float) parsing_error(pos, "%s cant be performed on [Untyped_Float]", token_kind_string(op).str); } break; + default: parsing_error(pos, "Binary operation %s is not allowed on types: left: %s right: %s", token_kind_string(op).str, docname(a.type), docname(b.type)); } @@ -237,6 +243,18 @@ eval_binary(Token *pos, Token_Kind op, Value a, Value b){ return result; } +function void +try_untyping(Operand *op){ + if(!op) return; + if(is_untyped(op->type)){ + if(op->type->kind == TYPE_UNTYPED_INT) op->type = type_int; + else if(op->type->kind == TYPE_UNTYPED_BOOL) op->type = type_bool; + else if(op->type->kind == TYPE_UNTYPED_STRING) op->type = type_string; + else if(op->type->kind == TYPE_UNTYPED_FLOAT) op->type = type_f64; + else invalid_codepath; + } +} + function Value eval_unary(Token *pos, Token_Kind op, Value a){ if(!is_numeric(a.type)) parsing_error(pos, "Constant application of binary %s on values of type %s is not allowed", token_kind_string(op).str, docname(a.type)); @@ -556,7 +574,8 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res found->flags = set_flag(found->flags, AST_ITEM_INCLUDED); Operand op = resolve_expr(expr->item, 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[op.type->kind], type_names[found_type->type->kind]); + try_untyping(&op); + 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]); } // @note: cleanup, required? @@ -601,7 +620,6 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res } else{ if(arg->default_value){ - // @todo make sure default values have valid types but in lambda definition Ast_Call_Item *item_default = ast_call_item(arg->default_value->pos, 0, 0, arg->default_value); items.add(item_default); } @@ -683,6 +701,8 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res assert(node->left->kind == AST_IDENT); Operand right = resolve_expr(node->right); + try_untyping(&right); + Ast_Atom *atom = (Ast_Atom *)node->left; sym_var(atom->intern_val, right, node, INSERT_INTO_SCOPE); } @@ -694,7 +714,8 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res Operand left = resolve_expr(node->left); if(!left.is_lvalue) parsing_error(node->pos, "Assigning to rvalue"); Operand right = resolve_expr(node->right); - if(left.type != right.type) parsing_error(node->pos, "Different types"); + try_untyping(&right); + if(left.type != right.type) parsing_error(node->pos, "Can't assign value when left is %s and right is %s", docname(left.type), docname(right.type)); } //----------------------------------------------------------------------------- @@ -787,12 +808,15 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res rewrite_into_const(node, Ast_Binary, value); result = operand_const_rvalue(value); } - else 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)); - } else{ - result = operand_rvalue(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)); + } + else{ + result = operand_rvalue(left.type); + } } + } //----------------------------------------------------------------------------- @@ -855,7 +879,8 @@ resolve_binding(Ast *ast, Sym *sym){ Operand expr = resolve_expr(node->expr, type); assert(expr.type != 0 || type != 0); - if(!type) expr.type = if_untyped_get_default_conversion(expr.type); + + if(!type) try_untyping(&expr); else if(!expr.type) expr.type = type; else if(type == expr.type); else if(is_untyped(expr.type)) expr.value = convert_untyped(node->pos, expr.value, type); diff --git a/types.h b/types.h index f924cc0..f6b2213 100644 --- a/types.h +++ b/types.h @@ -251,15 +251,3 @@ 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 * -if_untyped_get_default_conversion(Ast_Resolved_Type *type){ - if(is_untyped(type)){ - if(type->kind == TYPE_UNTYPED_INT) return type_int; - else if(type->kind == TYPE_UNTYPED_BOOL) return type_bool; - else if(type->kind == TYPE_UNTYPED_STRING) return type_string; - else if(type->kind == TYPE_UNTYPED_FLOAT) return type_f64; - invalid_return; - } - return type; -}