From f852a23fcb6471c0ea57eaf51a8e3ff9daa747b8 Mon Sep 17 00:00:00 2001 From: Krzosa Karol Date: Mon, 6 Jun 2022 23:50:38 +0200 Subject: [PATCH] Fixing bugs, pointer arithmetic checking, better for, working on first program --- ccodegen.cpp | 14 ++++++-- main.cpp | 9 ++--- new_parse.cpp | 6 ++-- new_types.kl | 3 ++ program.c | 28 ++++++++++++---- program.kl | 22 ++++++++---- typecheck.cpp | 93 +++++++++++++++++++++++++++++++++++---------------- types.h | 2 +- 8 files changed, 127 insertions(+), 50 deletions(-) diff --git a/ccodegen.cpp b/ccodegen.cpp index 061f910..90f1155 100644 --- a/ccodegen.cpp +++ b/ccodegen.cpp @@ -66,7 +66,7 @@ gen_simple_decl(Ast_Resolved_Type *ast, Intern_String name){ function void gen_value(Value a){ - gen("%s", docname(a.type)); + // gen("%s", docname(a.type)); switch(a.type->kind){ CASE_INT: { Scratch scratch; @@ -94,10 +94,12 @@ gen_expr(Ast_Expr *ast){ } CASE(INDEX, Index){ + gen("("); gen_expr(node->expr); gen("["); gen_expr(node->index); gen("]"); + gen(")"); BREAK(); } @@ -335,7 +337,7 @@ gen_ast(Ast *ast){ 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); + gen("typedef struct %s{", node->name.str); global_indent++; For(agg->members){ genln(""); @@ -347,7 +349,7 @@ gen_ast(Ast *ast){ gen_ast(it); } global_indent--; - genln("};"); + genln("}%s;", node->name.str); } else{ // Type alias @@ -428,12 +430,18 @@ typedef U64 SizeU; typedef S64 SizeS; typedef float F32; typedef double F64; +typedef S32 Bool; typedef struct String{ U8 *str; S64 len; }String; #define LIT(x) (String){.str=(U8 *)x, .len=sizeof(x)-1} + +void entry(); +int main(){ + entry(); +} )=="); F64 resolve_begin = os_time(); diff --git a/main.cpp b/main.cpp index 01579a2..4376a12 100644 --- a/main.cpp +++ b/main.cpp @@ -77,7 +77,6 @@ Expr: @todo -[ ] - Fix casting [ ] - Make sure pointer arithmetic works [ ] - Passing down program to compile through command line [ ] - More for loop variations @@ -108,10 +107,12 @@ Expr: [ ] - Compound that zeros values - .{} , Compound that assumes defaults from struct definition - {} @donzo +[x] - We are parsing wrong here: (t.str=(&string_to_lex.str)[i]); [x] - Test new operators, add constant eval for them [x] - lvalue, rvalue concept so we cant assign value to some arbitrary weird expression [x] - More basic types [x] - Implementing required operations int128 +[x] - Fix casting [x] - Add basic support for floats [x] - Converting from U64 token to S64 Atom introduces unnanounced error (negates) - probably need big int [x] - Add basic setup for new type system @@ -167,7 +168,7 @@ int main(){ String result = {}; -#if 1 +#if 0 result = compile_file("globals.kl"_s); printf("%s", result.str); result = compile_file("enums.kl"_s); @@ -178,12 +179,12 @@ int main(){ printf("%s", result.str); result = compile_file("lambdas.kl"_s); printf("%s", result.str); -#endif result = compile_file("new_types.kl"_s); printf("%s", result.str); +#endif -#if 0 +#if 1 result = compile_file("program.kl"_s); FILE *f = fopen("program.c", "w"); assert(f); diff --git a/new_parse.cpp b/new_parse.cpp index e1b991e..b61f297 100644 --- a/new_parse.cpp +++ b/new_parse.cpp @@ -118,7 +118,9 @@ function Ast_Expr *parse_expr(S64 minbp = 0); function Ast_Expr * parse_init_stmt(Ast_Expr *expr){ Token *token = token_get(); - if(token->kind == TK_ColonAssign && expr->kind != AST_IDENT) parsing_error(expr->pos, "Binding with [:=] to something that is not an identifier"); + if(token->kind == TK_ColonAssign && expr->kind != AST_IDENT) + parsing_error(expr->pos, "Binding with [:=] to something that is not an identifier"); + if(token_is_assign(token)){ token_next(); Ast_Expr *value = parse_expr(); @@ -359,7 +361,7 @@ binding_power(Binding binding, Token_Kind kind){ Postfix: switch(kind){ case TK_OpenBracket: case TK_OpenParen: - return {20, -2}; + return {21, -2}; default: return{-1,-1}; } } diff --git a/new_types.kl b/new_types.kl index 0110d2f..5d14131 100644 --- a/new_types.kl +++ b/new_types.kl @@ -18,6 +18,9 @@ unary_test :: () var2: S64 = 20 var_bool: Bool = !var1 == !var2 + pointer: *S64 + pointer += 10 + // pointer = pointer + pointer // uns: U64 = -int_val // int_float: S64 = float_val diff --git a/program.c b/program.c index df0c593..ab27355 100644 --- a/program.c +++ b/program.c @@ -16,20 +16,36 @@ typedef U64 SizeU; typedef S64 SizeS; typedef float F32; typedef double F64; +typedef S32 Bool; typedef struct String{ U8 *str; S64 len; }String; #define LIT(x) (String){.str=(U8 *)x, .len=sizeof(x)-1} - -struct Lex_Stream{ - U8 *stream; - U8 *end; -}; + +void entry(); int main(){ + entry(); +} + +typedef struct Token{ + U8 *str; + S64 len; +}Token; +Bool is_numeric(U8 c){ + Bool result = ((c>=48)&&(c<=57)); + return result; +} +void entry(){ String string_to_lex = LIT("Identifier 2425525 Not_Number"); + Token t; for(S64 i = 0;(i= '0 && c <= '9 + return result + +entry :: () string_to_lex := "Identifier 2425525 Not_Number" - + t: Token for i := 0, i < string_to_lex.len, i+=1 - string_to_lex.str[0] = 64 + if is_numeric(string_to_lex.str[i]) + t.str = &string_to_lex.str[i] + for is_numeric(string_to_lex.str[i]) + i+=1 + + diff --git a/typecheck.cpp b/typecheck.cpp index 660114c..747fcf3 100644 --- a/typecheck.cpp +++ b/typecheck.cpp @@ -52,6 +52,8 @@ convert_untyped_to_typed(Token *pos, Value a, Ast_Resolved_Type *new_type){ assert(a.type == untyped_int); 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_int(a.type) && is_pointer(new_type)) + ; else if(is_float(a.type) && is_float(new_type)) ; // nothing to do else if(is_bool(a.type) && is_bool(new_type)) @@ -67,11 +69,18 @@ convert_untyped_to_typed(Token *pos, Value a, Ast_Resolved_Type *new_type){ function void make_sure_types_are_compatible(Token *pos, Value *a, Value *b){ - if(is_typed(a->type) && is_typed(b->type)){ + if((is_pointer(a->type) && is_int(b->type)) || (is_pointer(b->type) && is_int(a->type))){ + return; + } + else if(is_pointer(a->type) && is_pointer(b->type)){ + goto fail; + } + else if(is_typed(a->type) && is_typed(b->type)){ if(a->type != b->type){ - parsing_error(pos, "Type mismatch in make_sure_types_are_compatible - left: %s right: %s", docname(a->type), docname(b->type)); + fail: parsing_error(pos, "Type mismatch in make_sure_types_are_compatible - left: %s right: %s", docname(a->type), docname(b->type)); } } + if(is_untyped(a->type) && is_typed(b->type)){ assert(is_typed(b->type)); *a = convert_untyped_to_typed(pos, *a, b->type); @@ -80,7 +89,6 @@ make_sure_types_are_compatible(Token *pos, Value *a, Value *b){ assert(is_typed(a->type)); *b = convert_untyped_to_typed(pos, *b, a->type); } - else if(is_int(a->type) && is_float(b->type)){ *a = value_float(a->big_int_val); } @@ -92,7 +100,7 @@ make_sure_types_are_compatible(Token *pos, Value *a, Value *b){ function Value compare_values(Token *pos, Token_Kind op, Value a, Value b, bool is_const){ 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", name(op), docname(a.type), docname(a.type)); + parsing_error(pos, "Constant application of binary %s on values of type %s and %s is not allowed", name(op), docname(a.type), docname(b.type)); make_sure_types_are_compatible(pos, &a, &b); @@ -146,7 +154,7 @@ eval_binary(Token *pos, Token_Kind op, Value a, Value b, bool is_const){ return compare_values(pos, op, a, b, is_const); 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", name(op), docname(a.type), docname(a.type)); + parsing_error(pos, "Constant application of binary %s on values of type %s and %s is not allowed", name(op), docname(a.type), docname(b.type)); make_sure_types_are_compatible(pos, &a, &b); @@ -261,30 +269,45 @@ eval_unary(Token *pos, Token_Kind op, Value *a, bool is_const){ } function void -convert_untyped_to_typed_default(Operand *op){ - if(!op) return; +try_converting_untyped_to_typed(Operand *op){ if(is_untyped(op->type)){ - if(op->type->kind == TYPE_UNTYPED_INT) op->type = type_s64; - 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; + switch(op->type->kind){ + case TYPE_UNTYPED_INT: op->type = type_s64; break; + case TYPE_UNTYPED_BOOL: op->type = type_bool; break; + case TYPE_UNTYPED_STRING: op->type = type_string; break; + case TYPE_UNTYPED_FLOAT: op->type = type_f64; break; + default: invalid_codepath; + } } } +enum{ + TYPE_AND_EXPR_REQUIRED = 0, + TYPE_CAN_BE_NULL = 1, + EXPR_CAN_BE_NULL = 2 +}; + function void -make_sure_types_are_compatible_for_assignment(Token *pos, Operand *expr, Ast_Resolved_Type *type = 0){ +make_sure_value_is_compatible_with_type(Token *pos, Operand *expr, Ast_Resolved_Type *type, U64 debug_flag){ if(type == expr->type){ + assert(type); assert(expr->type); return; } - if(!type) - convert_untyped_to_typed_default(expr); - else if(!expr->type) + if(!type){ + assert(is_flag_set(debug_flag, TYPE_CAN_BE_NULL)); + assert(expr->type); + try_converting_untyped_to_typed(expr); + } + else if(!expr->type){ + assert(is_flag_set(debug_flag, EXPR_CAN_BE_NULL)); + assert(type); expr->type = type; - else if(is_untyped(expr->type)) + } + else if(is_untyped(expr->type)){ expr->value = convert_untyped_to_typed(pos, expr->value, type); + } if(type && expr->type != type){ parsing_error(pos, "Assigning but incompatible types, expression: %s expected var type: %s", docname(expr->type), docname(type)); @@ -362,10 +385,16 @@ resolve_stmt(Ast *ast, Ast_Resolved_Type *ret){ } CASE(FOR, For){ + if(node->init && node->cond == 0 && node->iter == 0){ + if(!is_flag_set(node->init->flags, AST_STMT)){ + node->cond = node->init; + node->init = 0; + } + } + resolve_expr(node->init, ret); - Operand cond = resolve_expr(node->cond); // @todo: typechecking + resolve_expr(node->cond, ret); resolve_expr(node->iter, ret); - unused(cond); resolve_stmt_block(node->block, ret); BREAK(); } @@ -392,10 +421,16 @@ resolve_stmt(Ast *ast, Ast_Resolved_Type *ret){ function Operand require_const_int(Ast_Expr *expr, B32 ast_can_be_null){ Operand op = resolve_expr(expr); - 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(!is_int(op.type)) parsing_error(expr->pos, "Expected a constant integer got instead %s", docname(op.type)); + + 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(!is_int(op.type)) + parsing_error(expr->pos, "Expected a constant integer got instead %s", docname(op.type)); return op; } @@ -410,7 +445,7 @@ resolve_lambda(Ast_Lambda *lambda, Sym *sym = 0){ Ast_Resolved_Type *type = resolve_typespec(it->typespec, AST_CANT_BE_NULL); Operand default_value = resolve_expr(it->default_value, type); - make_sure_types_are_compatible_for_assignment(it->pos, &default_value, type); + make_sure_value_is_compatible_with_type(it->pos, &default_value, type, EXPR_CAN_BE_NULL); args.add(type); } @@ -700,7 +735,9 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res } else{ parsing_error(node->pos, "Dereferencing expression %s that is not a [Pointer] or [Type]", type_names[value.type->kind]); return {}; } }break; - case TK_Dereference:{return operand_lvalue(type_pointer(value.type));}break; + case TK_Dereference:{ + return operand_lvalue(type_pointer(value.type)); + }break; case TK_Neg:case TK_Not:case TK_Add:case TK_Sub:{ Operand op = resolve_expr(node->expr); eval_unary(node->pos, node->op, &op.value, op.is_const); @@ -724,7 +761,7 @@ 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); - make_sure_types_are_compatible_for_assignment(node->pos, &right); + make_sure_value_is_compatible_with_type(node->pos, &right, 0, TYPE_CAN_BE_NULL); assert(right.type); auto atom = (Ast_Atom *)node->left; @@ -840,7 +877,7 @@ 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 result = operand_rvalue(left.type); + else result = operand_rvalue(value.type); } //----------------------------------------------------------------------------- @@ -903,7 +940,7 @@ resolve_binding(Ast *ast, Sym *sym){ Ast_Resolved_Type *type = resolve_typespec(node->typespec, AST_CAN_BE_NULL); Operand expr = resolve_expr(node->expr, type); assert(expr.type != 0 || type != 0); - make_sure_types_are_compatible_for_assignment(node->pos, &expr, type); + make_sure_value_is_compatible_with_type(node->pos, &expr, type, EXPR_CAN_BE_NULL|TYPE_CAN_BE_NULL); assert(expr.type); return expr; BREAK(); diff --git a/types.h b/types.h index a1e93e6..cf70b57 100644 --- a/types.h +++ b/types.h @@ -19,10 +19,10 @@ enum Ast_Resolved_Type_Kind{ TYPE_U8 , TYPE_F32, TYPE_F64, + TYPE_POINTER, TYPE_BOOL, // LAST_NUMERIC TYPE_STRING, TYPE_VOID, - TYPE_POINTER, TYPE_ARRAY, TYPE_LAMBDA, TYPE_STRUCT,