From 06d6ec752534cae9a0e4b4bc1607a0b9d230a213 Mon Sep 17 00:00:00 2001 From: Krzosa Karol Date: Mon, 6 Jun 2022 13:24:01 +0200 Subject: [PATCH] Working on casts --- big_int_c3.cpp | 8 +- ccodegen.cpp | 166 ++++++++++++++++---------------- big_int.cpp => int128_tests.cpp | 0 main.cpp | 2 + new_lex.cpp | 4 +- new_types.kl | 2 + typecheck.cpp | 62 +++++++++--- types.h | 1 + 8 files changed, 145 insertions(+), 100 deletions(-) rename big_int.cpp => int128_tests.cpp (100%) diff --git a/big_int_c3.cpp b/big_int_c3.cpp index 6a5fca4..43a691e 100644 --- a/big_int_c3.cpp +++ b/big_int_c3.cpp @@ -3,8 +3,9 @@ // a copy of which can be found in the LICENSE file. struct Token; +global S64 bigint_allocation_count; function void parsing_error(Token *token, const char *str, ...); -#define malloc_arena(x) exp_alloc(&pernament_arena, x) +#define malloc_arena(x) (bigint_allocation_count++, exp_alloc(&pernament_arena, x)) #define ALLOC_DIGITS(_digits) (uint64_t *)((_digits) ? malloc_arena(sizeof(uint64_t) * (_digits)) : NULL) #define FATAL_ERROR(x) parsing_error(0, x) @@ -18,7 +19,6 @@ struct BigInt }; }; - #include enum CmpRes { @@ -74,14 +74,14 @@ size_t bigint_popcount_unsigned(const BigInt *big_int); //----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- -static BigInt +function BigInt bigint_u64(U64 value){ BigInt result; bigint_init_unsigned(&result, value); return result; } -static BigInt +function BigInt bigint_s64(S64 value){ BigInt result; bigint_init_signed(&result, value); diff --git a/ccodegen.cpp b/ccodegen.cpp index 30d5324..4d83373 100644 --- a/ccodegen.cpp +++ b/ccodegen.cpp @@ -292,99 +292,101 @@ gen_ast(Ast *ast){ CASE(CONST, Const){ Sym *sym = resolved_get(node); - if(sym->type->kind == TYPE_LAMBDA){ - if(node->value->kind == AST_LAMBDA){ - Ast_Lambda *lambda = (Ast_Lambda *)node->value; - Ast_Resolved_Type *ret = resolved_type_get(lambda->ret); - gen_simple_decl(ret, node->name); - gen("("); - For(lambda->args){ - assert(it->kind == AST_LAMBDA_ARG); - Ast_Resolved_Type *type = resolved_type_get(it->typespec); - gen_simple_decl(type, it->name); - if(&it != (lambda->args.end() - 1)) gen(", "); - } - gen(")"); + switch(sym->type->kind){ + CASE_FLOAT:{ + gen("// F64 %s = ", node->name.str); + gen_value(sym->value); + } break; + CASE_INT:{ + gen("// constant int %s = ", node->name.str); + gen_value(sym->value); + }break; + CASE_STRING:{ + gen("// const String %s = ", node->name.str); + gen_value(sym->value); + }break; + CASE_BOOL:{ + gen("// const Bool %s = ", node->name.str); + gen_value(sym->value); + }break; - if(lambda->block) { - gen_block(lambda->block); - } - else gen(";"); - } - else{ - gen_simple_decl(sym->type, node->name); - gen(" = "); - gen_expr((Ast_Expr *)node->value); - gen(";"); - } - } - else if(sym->type == untyped_float){ - gen("// F64 %s = ", node->name.str); - gen_value(sym->value); - } - else if(sym->type == untyped_int){ - gen("// constant int %s = ", node->name.str); - gen_value(sym->value); - } - else if(sym->type == untyped_string){ - gen("// const String %s = ", node->name.str); - gen_value(sym->value); - } - else if(sym->type == untyped_bool){ - gen("// const Bool %s = ", node->name.str); - gen_value(sym->value); - } - else if(sym->type == type_type){ - if(sym->type_val->kind == TYPE_STRUCT){ - Ast_Struct *agg = (Ast_Struct *)sym->type_val->ast; - if(node->value->kind == AST_STRUCT){ - gen("struct %s{", node->name.str); - global_indent++; - For(agg->members){ - genln(""); - gen_ast(it); + case TYPE_LAMBDA:{ + if(node->value->kind == AST_LAMBDA){ + Ast_Lambda *lambda = (Ast_Lambda *)node->value; + Ast_Resolved_Type *ret = resolved_type_get(lambda->ret); + gen_simple_decl(ret, node->name); + gen("("); + For(lambda->args){ + assert(it->kind == AST_LAMBDA_ARG); + Ast_Resolved_Type *type = resolved_type_get(it->typespec); + gen_simple_decl(type, it->name); + if(&it != (lambda->args.end() - 1)) gen(", "); } + gen(")"); - For(agg->const_members){ - genln(""); - gen_ast(it); + if(lambda->block) { + gen_block(lambda->block); } - global_indent--; - genln("};"); + else gen(";"); } else{ - // Type alias + gen_simple_decl(sym->type, node->name); + gen(" = "); + gen_expr((Ast_Expr *)node->value); + gen(";"); } - } - else if(sym->type_val->kind == TYPE_ENUM){ - Ast_Enum *enu = (Ast_Enum *)sym->type_val->ast; - assert(enu->kind == AST_ENUM); - if(node->value->kind == AST_ENUM){ - gen("/*enum %s{", node->name.str); - // @todo add typespec - global_indent++; - For(enu->members){ - genln("%s", it->name.str); - gen(" = "); - Sym *value_sym = resolved_get(it); - gen("%d", bigint_as_signed(&value_sym->big_int_val)); - gen(","); + }break; + + case TYPE_TYPE:{ + if(sym->type_val->kind == TYPE_STRUCT){ + Ast_Struct *agg = (Ast_Struct *)sym->type_val->ast; + if(node->value->kind == AST_STRUCT){ + gen("struct %s{", node->name.str); + global_indent++; + For(agg->members){ + genln(""); + gen_ast(it); + } + + For(agg->const_members){ + genln(""); + gen_ast(it); + } + global_indent--; + genln("};"); + } + else{ + // Type alias + } + } + else if(sym->type_val->kind == TYPE_ENUM){ + Ast_Enum *enu = (Ast_Enum *)sym->type_val->ast; + assert(enu->kind == AST_ENUM); + if(node->value->kind == AST_ENUM){ + gen("/*enum %s{", node->name.str); + // @todo add typespec + global_indent++; + For(enu->members){ + genln("%s", it->name.str); + gen(" = "); + Sym *value_sym = resolved_get(it); + gen("%d", bigint_as_signed(&value_sym->big_int_val)); + gen(","); + } + global_indent--; + genln("};*/"); + } + else{ + // Type alias } - global_indent--; - genln("};*/"); } else{ - // Type alias + gen("// typedef "); + gen_simple_decl(sym->type_val, node->name); + gen(";"); } - } - else{ - gen("// typedef "); - gen_simple_decl(sym->type_val, node->name); - gen(";"); - } - } - else{ - parsing_error(node->pos, "C_Codegen: Unhandled type of constant expression"); + }break; + default: parsing_error(node->pos, "C_Codegen: Unhandled type %s of constant expression", docname(sym->type)); } BREAK(); diff --git a/big_int.cpp b/int128_tests.cpp similarity index 100% rename from big_int.cpp rename to int128_tests.cpp diff --git a/main.cpp b/main.cpp index b52e356..2955b17 100644 --- a/main.cpp +++ b/main.cpp @@ -32,6 +32,7 @@ For now I don't thing it should be overloadable. ------------------------------------------------------------------------------- @todo +[ ] - Fix casting [ ] - Passing down program to compile through command line [ ] - More for loop variations [ ] - Write up on order independent declarations @@ -43,6 +44,7 @@ For now I don't thing it should be overloadable. [ ] - Ternary operator [ ] - Remodel compound from call to {} +[ ] - Scope [ ] - Field access rewrite [ ] - Constants embeded in structs should be able to refer to other constants in that namespace without prefix [ ] - Order independent constants in structs diff --git a/new_lex.cpp b/new_lex.cpp index bf0fabc..95e841f 100644 --- a/new_lex.cpp +++ b/new_lex.cpp @@ -86,9 +86,7 @@ enum Token_Kind{ TK_Pointer = TK_Mul, TK_Dereference = TK_BitAnd, - - // These are not produced by lexer - // but identified by parser + OPEN_SCOPE = 128, CLOSE_SCOPE, SAME_SCOPE, diff --git a/new_types.kl b/new_types.kl index c381a56..4a9c3ca 100644 --- a/new_types.kl +++ b/new_types.kl @@ -33,6 +33,8 @@ binary_test :: () boolean_equals :: true == false boolean_var: Bool = boolean_equals + cast_value :: cast(4242: S32) + bvar2 := int_val > 1 if int_val < 1 if int_val > 1 diff --git a/typecheck.cpp b/typecheck.cpp index cfe5d3a..b30a4fe 100644 --- a/typecheck.cpp +++ b/typecheck.cpp @@ -71,21 +71,25 @@ value_float(BigInt a){ return value; } +function void +check_value_boundaries(Token *pos, Value *a){ + if(!is_int(a->type)) return; + + Scratch scratch; + if(!bigint_fits_in_bits(&a->big_int_val, a->type->size*8, is_signed_int(a->type))){ + const char *string = bigint_to_error_string(scratch, &a->big_int_val, 10); + parsing_error(pos, "Value %s doesn't fit in type %s", string, docname(a->type)); + } +} + function Value convert_untyped(Token *pos, Value a, Ast_Resolved_Type *new_type){ assert(new_type); if(a.type == 0) return a; if(is_typed(a.type)) return a; - if(is_int(a.type) && is_int(new_type)){ + if(is_int(a.type) && is_int(new_type)) assert(a.type == untyped_int); - if(!bigint_fits_in_bits(&a.big_int_val, new_type->size*8, is_signed_int(new_type))){ - Scratch scratch; - const char *string = bigint_to_error_string(scratch, &a.big_int_val, 10); - parsing_error(pos, "Value %s doesn't fit in type %s", string, docname(new_type)); - } - } - else if(is_int(a.type) && is_float(new_type)) a.f64_val = bigint_as_float(&a.big_int_val); // @leak bigint else if(is_float(a.type) && is_float(new_type)) @@ -97,11 +101,15 @@ convert_untyped(Token *pos, Value a, Ast_Resolved_Type *new_type){ else parsing_error(pos, "Type mismatch when converting from %s to %s", docname(a.type), docname(new_type)); a.type = new_type; + check_value_boundaries(pos, &a); return a; } function void match_values(Value *a, Value *b){ + // @todo: We want match values to convert when int and float => float + // but also we want to unify types when one of them is typed and other untyped??? + // Lastly maybe check if typed types are the same if(is_int(a->type) && is_float(b->type)) *a = value_float(a->big_int_val); else if(is_float(a->type) && is_int(b->type)) @@ -630,9 +638,41 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res CASE(CAST, Cast){ Operand expr = resolve_expr(node->expr); Ast_Resolved_Type *type = resolve_typespec(node->typespec); - unused(expr); - // @todo - return operand_rvalue(type); + Ast_Resolved_Type *original_type = expr.type; + + switch(expr.type->kind){ + case TYPE_POINTER:{ + if(is_pointer(type)) + expr = operand_rvalue(type); + else goto failure; + } break; + CASE_UNTYPED: { + expr.value = convert_untyped(node->pos, expr.value, type); + } break; + CASE_UINT: + CASE_SINT:{ + if(is_int(type)) + expr.type = type; + else if(is_float(type)){ + expr.value.type = type; + expr.value.f64_val = bigint_as_float(&expr.big_int_val); // @leak + } else goto failure; + } break; + case TYPE_F32: case TYPE_F64: { + if(is_float(type)){ + expr.type = type; + } + else if(is_int(type)){ + expr.value.big_int_val = bigint_s64((S64)expr.value.f64_val); // @todo: What to do here??? + expr.type = type; + } else goto failure; + } + default: failure: parsing_error(node->pos, "Failed to cast from %s to %s", docname(expr.type), docname(type));; + } + + if(original_type != type) assert(expr.type == type); + check_value_boundaries(node->pos, &expr.value); + return expr; BREAK(); } diff --git a/types.h b/types.h index 7030f5d..a1e93e6 100644 --- a/types.h +++ b/types.h @@ -46,6 +46,7 @@ enum Ast_Resolved_Type_Kind{ #define CASE_BOOL case TYPE_UNTYPED_BOOL: case TYPE_BOOL #define CASE_FLOAT case TYPE_UNTYPED_FLOAT: case TYPE_F32: case TYPE_F64 #define CASE_STRING case TYPE_UNTYPED_STRING: case TYPE_STRING +#define CASE_UNTYPED case TYPE_UNTYPED_INT: case TYPE_UNTYPED_BOOL: case TYPE_UNTYPED_FLOAT: case TYPE_UNTYPED_STRING const char *type_names[] = { "[Invalid Ast_Resolved_Type]",