Fixing printing / memory issues, Add stage arena, printing types in errors properly

This commit is contained in:
Krzosa Karol
2022-06-18 09:50:34 +02:00
parent f876b69779
commit 28f89def4b
3 changed files with 48 additions and 42 deletions

View File

@@ -179,6 +179,7 @@ Intern_String intern_flag;
struct Parse_Ctx:Lexer{ struct Parse_Ctx:Lexer{
Allocator *perm; // Stores: AST, tokens, interns Allocator *perm; // Stores: AST, tokens, interns
Allocator *heap; Allocator *heap;
Arena stage_arena;
U64 type_ids; U64 type_ids;
U64 unique_ids; // @Debug U64 unique_ids; // @Debug
@@ -241,6 +242,7 @@ parse_init(Parse_Ctx *ctx, Allocator *perm_allocator, Allocator *heap_allocator)
ctx->ordered_decls = {ctx->heap}; ctx->ordered_decls = {ctx->heap};
ctx->type_map = {ctx->heap}; ctx->type_map = {ctx->heap};
ctx->modules = {ctx->heap}; ctx->modules = {ctx->heap};
ctx->stage_arena = arena_sub(perm_allocator, mib(4), "Compiler stage arena"_s);
bigint_allocator = ctx->perm; bigint_allocator = ctx->perm;
lex_init(ctx->perm, ctx->heap, ctx); lex_init(ctx->perm, ctx->heap, ctx);

View File

@@ -70,6 +70,7 @@ WinMain :: (hInstance: HINSTANCE, hPrevInstance: HINSTANCE, lpCmdLine: LPSTR, nS
assert(RegisterClassW(&w) != 0) assert(RegisterClassW(&w) != 0)
buff: *char = allocate(100) buff: *char = allocate(100)
thing: int = buff
screen_size: Vec2I = {1280, 720} screen_size: Vec2I = {1280, 720}
window := CreateWindowExW( window := CreateWindowExW(

View File

@@ -5,17 +5,6 @@ function String gen_string_simple_decl(Allocator *a, Ast_Type *ast, String name
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Evaluating constant expressions // Evaluating constant expressions
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
function void
check_value_bounds(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);
compiler_error(pos, "Value %s doesn't fit in type %s", string, docname(a->type));
}
}
function void function void
typename_base(String_Builder *sb, Ast_Type *type){ typename_base(String_Builder *sb, Ast_Type *type){
switch(type->kind){ switch(type->kind){
@@ -58,17 +47,30 @@ typename_base(String_Builder *sb, Ast_Type *type){
} }
} }
// @todo: takes too much memory from caller function String
// Caching String_Builder would be cool and then having
// a pass arena or something
function const char *
get_typename(Allocator *a, Ast_Type *type){ get_typename(Allocator *a, Ast_Type *type){
String_Builder sb = {a}; pctx->gen.addf("[");
sb.addf("["); typename_base(&pctx->gen, type);
typename_base(&sb, type); pctx->gen.addf("]");
sb.addf("]"); String result = string_flatten(a, &pctx->gen);
String result = string_flatten(a, &sb); pctx->gen.reset();
return (const char *)result.str; return result;
}
function String
typestring(Ast_Type *type){
return get_typename(&pctx->stage_arena, type);
}
function void
check_value_bounds(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);
compiler_error(pos, "Value %s doesn't fit in type %Q", string, typestring(a->type));
}
} }
function Value function Value
@@ -91,7 +93,7 @@ convert_untyped_to_typed(Token *pos, Value a, Ast_Type *new_type){
; // nothing to do ; // nothing to do
else if(is_string(a.type) && is_string(new_type)) else if(is_string(a.type) && is_string(new_type))
; // nothing to do ; // nothing to do
else compiler_error(pos, "Type mismatch when converting from %s to %s", docname(a.type), docname(new_type)); else compiler_error(pos, "Type mismatch when converting from %Q to %Q", typestring(a.type), typestring(new_type));
a.type = new_type; a.type = new_type;
check_value_bounds(pos, &a); check_value_bounds(pos, &a);
@@ -108,7 +110,7 @@ make_sure_types_are_compatible_for_constant_evaluation(Token *pos, Value *a, Val
} }
else if(is_typed(a->type) && is_typed(b->type)){ else if(is_typed(a->type) && is_typed(b->type)){
if(a->type != b->type){ if(a->type != b->type){
fail: compiler_error(pos, "Type mismatch in make_sure_types_are_compatible_for_constant_evaluation - left: %s right: %s", docname(a->type), docname(b->type)); fail: compiler_error(pos, "Type mismatch in make_sure_types_are_compatible_for_constant_evaluation - left: %Q right: %Q", typestring(a->type), typestring(b->type));
} }
} }
@@ -133,7 +135,7 @@ compare_values(Token *pos, Token_Kind op, Value a, Value b, bool is_const){
if(is_enum(a.type) && (a.type == b.type)) if(is_enum(a.type) && (a.type == b.type))
goto skip_eval; goto skip_eval;
if(!(is_numeric(a.type) && is_numeric(b.type))) if(!(is_numeric(a.type) && is_numeric(b.type)))
compiler_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)); compiler_error(pos, "Constant application of binary %s on values of type %Q and %Q is not allowed", name(op), typestring(a.type), typestring(b.type));
make_sure_types_are_compatible_for_constant_evaluation(pos, &a, &b); make_sure_types_are_compatible_for_constant_evaluation(pos, &a, &b);
@@ -187,7 +189,7 @@ eval_binary(Token *pos, Token_Kind op, Value a, Value b, bool is_const){
return compare_values(pos, op, a, b, is_const); return compare_values(pos, op, a, b, is_const);
if(!(is_numeric(a.type) && is_numeric(b.type))) if(!(is_numeric(a.type) && is_numeric(b.type)))
compiler_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)); compiler_error(pos, "Constant application of binary %s on values of type %Q and %Q is not allowed", name(op), typestring(a.type), typestring(b.type));
make_sure_types_are_compatible_for_constant_evaluation(pos, &a, &b); make_sure_types_are_compatible_for_constant_evaluation(pos, &a, &b);
@@ -253,7 +255,7 @@ eval_unary(Token *pos, Token_Kind op, Operand *operand){
Value *a = &operand->value; Value *a = &operand->value;
Ast_Type *type = a->type; Ast_Type *type = a->type;
if(!is_numeric(type)) if(!is_numeric(type))
compiler_error(pos, "Unary [%s] cant be applied to value of type %s", name(op), docname(type)); compiler_error(pos, "Unary [%s] cant be applied to value of type %Q", name(op), typestring(type));
if(op == TK_Not) if(op == TK_Not)
a->type = untyped_bool; a->type = untyped_bool;
@@ -302,7 +304,7 @@ eval_unary(Token *pos, Token_Kind op, Operand *operand){
default:goto failure; default:goto failure;
} }
} break; } break;
default: failure: compiler_error(pos, "Constant application of unary %s on values of type %s is not allowed", name(op), docname(a->type)); default: failure: compiler_error(pos, "Constant application of unary %s on values of type %Q is not allowed", name(op), typestring(a->type));
} }
} }
@@ -358,8 +360,9 @@ make_sure_value_is_compatible_with_type(Token *pos, Operand *expr, Ast_Type *typ
} }
if(type && expr->type != type){ if(type && expr->type != type){
Scratch scratch; String expr_type_string = typestring(expr->type);
compiler_error(pos, "Assigning but incompatible types, expression: %s expected var type: %s", get_typename(scratch, expr->type), get_typename(scratch, type)); String type_string = typestring(type);
compiler_error(pos, "Assigning but incompatible types, expression: %Q expected var type: %Q", expr_type_string, type_string);
} }
type_complete(expr->type); type_complete(expr->type);
@@ -440,7 +443,7 @@ resolve_typespec(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context =
if(is_flag_set(flags, RESOLVE_TYPESPEC_COMPLETE)) if(is_flag_set(flags, RESOLVE_TYPESPEC_COMPLETE))
type_complete(resolved.type_val); type_complete(resolved.type_val);
if(resolved.type != type_type) if(resolved.type != type_type)
compiler_error(ast->pos, "Expected [Type] got instead %s", get_typename(scratch, resolved.type)); compiler_error(ast->pos, "Expected [Type] got instead %Q", typestring(resolved.type));
return resolved.type_val; return resolved.type_val;
} }
@@ -455,7 +458,7 @@ resolve_and_require_bool(const char *error, Ast_Expr *expr, Resolve_Flag flags,
Scratch scratch; Scratch scratch;
Operand op = resolve_expr(expr, flags, compound_context); Operand op = resolve_expr(expr, flags, compound_context);
if(!is_bool(op.type)){ if(!is_bool(op.type)){
compiler_error(expr->pos, "Expected type [Bool] got instead type %s :: %s", get_typename(scratch, op.type), error); compiler_error(expr->pos, "Expected type [Bool] got instead type %Q :: %s", typestring(op.type), error);
} }
return op; return op;
@@ -473,7 +476,7 @@ require_const_int(Ast_Expr *expr, Resolve_Flag flags, Ast_Type *compound_context
if(!op.is_const) if(!op.is_const)
compiler_error(expr->pos, "Expected a const value"); compiler_error(expr->pos, "Expected a const value");
if(!is_int(op.type)) if(!is_int(op.type))
compiler_error(expr->pos, "Expected a constant integer got instead %s", docname(op.type)); compiler_error(expr->pos, "Expected a constant integer got instead %Q", typestring(op.type));
return op; return op;
} }
@@ -500,7 +503,7 @@ resolve_stmt(Ast *ast, Ast_Type *ret){
Value value = {}; value.type = type; Value value = {}; value.type = type;
value = convert_untyped_to_typed(node->pos, value, ret); value = convert_untyped_to_typed(node->pos, value, ret);
if(value.type && value.type != ret) if(value.type && value.type != ret)
compiler_error(node->pos, "Return statement has different type then returned value, expecting: %s got instead %s", docname(ret), docname(type)); compiler_error(node->pos, "Return statement has different type then returned value, expecting: %Q got instead %Q", typestring(ret), typestring(type));
node->resolved_type = value.type; node->resolved_type = value.type;
BREAK(); BREAK();
} }
@@ -665,7 +668,7 @@ resolve_cast(Ast_Binary *node){
expr.type = type; expr.type = type;
} else goto failure; } else goto failure;
} break; } break;
default: failure: compiler_error(node->pos, "Failed to cast from %s to %s", docname(expr.type), docname(type));; default: failure: compiler_error(node->pos, "Failed to cast from %Q to %Q", typestring(expr.type), typestring(type));;
} }
assert(original_type != type ? expr.type == type : 1); assert(original_type != type ? expr.type == type : 1);
@@ -866,7 +869,7 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context){
Operand left = resolve_expr(node->expr, AST_CANT_BE_NULL); Operand left = resolve_expr(node->expr, AST_CANT_BE_NULL);
Operand index = resolve_expr(node->index, AST_CANT_BE_NULL); Operand index = resolve_expr(node->index, AST_CANT_BE_NULL);
if(!is_int(index.type)){ if(!is_int(index.type)){
compiler_error(node->pos, "Trying to index the array with invalid type, expected [Int] got instead %s", docname(index.type)); compiler_error(node->pos, "Trying to index the array with invalid type, expected [Int] got instead %Q", typestring(index.type));
} }
node->index_original_type = left.type; node->index_original_type = left.type;
@@ -875,7 +878,7 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context){
return operand_lvalue(type_u8); 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)){
compiler_error(node->pos, "Indexing variable that is not an [Array] or [Pointer], it's of type %s instead", docname(left.type)); compiler_error(node->pos, "Indexing variable that is not an [Array] or [Pointer], it's of type %Q instead", typestring(left.type));
} }
return operand_lvalue(left.type->arr.base); return operand_lvalue(left.type->arr.base);
@@ -890,7 +893,7 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context){
Operand right = resolve_expr(node->right, AST_CANT_BE_NULL); Operand right = resolve_expr(node->right, AST_CANT_BE_NULL);
right.value = convert_untyped_to_typed(node->pos, right.value, left.type); right.value = convert_untyped_to_typed(node->pos, right.value, left.type);
if(left.type != right.type) compiler_error(node->pos, "Can't assign value when left is %s and right is %s", docname(left.type), docname(right.type)); if(left.type != right.type) compiler_error(node->pos, "Can't assign value when left is %Q and right is %Q", typestring(left.type), typestring(right.type));
node->resolved_type = right.type; node->resolved_type = right.type;
return {}; return {};
} }
@@ -936,7 +939,7 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context){
node->resolved_type = type_pointer(value.type_val); node->resolved_type = type_pointer(value.type_val);
return operand_type(node->resolved_type); return operand_type(node->resolved_type);
} }
else{ compiler_error(node->pos, "Dereferencing expression %s that is not a [Pointer] or [Type]", docname(value.type)); return {}; } else{ compiler_error(node->pos, "Dereferencing expression %Q that is not a [Pointer] or [Type]", typestring(value.type)); return {}; }
} }
else if(node->op == TK_Dereference){ else if(node->op == TK_Dereference){
node->resolved_type = type_pointer(value.type); node->resolved_type = type_pointer(value.type);
@@ -960,7 +963,7 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context){
Ast_Type *type = op.type; Ast_Type *type = op.type;
if(type){ if(type){
if(type != type_type) if(type != type_type)
compiler_error(node->pos, "Expected type [Type] got instead %s", docname(type)); compiler_error(node->pos, "Expected type [Type] got instead %Q", typestring(type));
type = op.type_val; type = op.type_val;
} }
if(!type) if(!type)
@@ -1010,7 +1013,7 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context){
rewrite_into_const(node, Ast_Builtin, value); rewrite_into_const(node, Ast_Builtin, value);
return operand_const_rvalue(value); return operand_const_rvalue(value);
} }
else compiler_error(node->pos, "Can't get length of type %s", docname(name.type_val)); else compiler_error(node->pos, "Can't get length of type %Q", typestring(name.type_val));
} }
else if(name.type->kind == TYPE_UNTYPED_STRING){ else if(name.type->kind == TYPE_UNTYPED_STRING){
Value value = value_int(name.intern_val.len); Value value = value_int(name.intern_val.len);
@@ -1020,14 +1023,14 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context){
else if(is_array(name.type) || is_slice(name.type) || is_string(name.type)){ else if(is_array(name.type) || is_slice(name.type) || is_string(name.type)){
return operand_rvalue(type_s64); return operand_rvalue(type_s64);
} }
else compiler_error(node->pos, "Can't get length of type %s", docname(name.type)); else compiler_error(node->pos, "Can't get length of type %Q", typestring(name.type));
BREAK(); BREAK();
} }
CASE(CALL, Call){ CASE(CALL, Call){
Operand name = resolve_expr(node->name, AST_CANT_BE_NULL); Operand name = resolve_expr(node->name, AST_CANT_BE_NULL);
if(name.type->kind != TYPE_LAMBDA) if(name.type->kind != TYPE_LAMBDA)
compiler_error(node->pos, "Calling %s which is not a [Lambda]", docname(name.type)); compiler_error(node->pos, "Calling %Q which is not a [Lambda]", typestring(name.type));
Scratch scratch; Scratch scratch;
Array<Ast_Call_Item *> items = {scratch}; Array<Ast_Call_Item *> items = {scratch};