Trying to change untyped to typed in the typechecking phase
This commit is contained in:
@@ -167,13 +167,17 @@ gen_value(Token *pos, Value a){
|
||||
const char *string = bigint_to_error_string(scratch, &a.big_int_val, 10);
|
||||
gen("%s", string);
|
||||
}break;
|
||||
CASE_STRING:
|
||||
if(is_pointer(a.type)){
|
||||
assert(a.type == type_pointer_to_char);
|
||||
case TYPE_POINTER:{
|
||||
if(a.type == type_pointer_to_char){
|
||||
gen("\"%Q\"", a.intern_val);
|
||||
} else{
|
||||
gen("(String){(U8 *)\"%Q\", %d}", a.intern_val, a.intern_val.len);
|
||||
}
|
||||
else{
|
||||
U64 pointer_value = bigint_as_unsigned(&a.big_int_val);
|
||||
gen("0x%llx", pointer_value);
|
||||
}
|
||||
}break;
|
||||
case TYPE_STRING:
|
||||
gen("(String){(U8 *)\"%Q\", %d}", a.intern_val, a.intern_val.len);
|
||||
break;
|
||||
CASE_BOOL: a.bool_val ? gen("true"):gen("false"); break;
|
||||
CASE_FLOAT: gen("%f", a.f64_val); break;
|
||||
|
||||
121
typechecking.cpp
121
typechecking.cpp
@@ -456,6 +456,67 @@ insert_into_scope(Ast_Scope *scope, Ast_Decl *decl){
|
||||
scope->decls.add(decl);
|
||||
}
|
||||
|
||||
//
|
||||
// Booleans are special in that untyped boolean appears from every comparison
|
||||
// and children of that comparison don't have to be booleans so we have to
|
||||
// propagate values of resolved children to each other
|
||||
//
|
||||
// int == untyped_int => bool
|
||||
// need to propagate int to untyped_int
|
||||
//
|
||||
function void
|
||||
try_propagating_resolved_type_to_untyped_literals(Ast *ast, Ast_Type *type, Ast_Type *additional_not_bool_type = 0){
|
||||
if(!ast) return;
|
||||
if(is_untyped(type)) return;
|
||||
|
||||
if(!is_bool(type)){
|
||||
if(ast->kind != AST_VALUE) return;
|
||||
|
||||
auto node = (Ast_Atom *)ast;
|
||||
node->value = convert_untyped_to_typed(ast->pos, node->value, type);// @rename: try and this
|
||||
return;
|
||||
}
|
||||
|
||||
switch(ast->kind){
|
||||
CASE(IDENT, Atom){
|
||||
type = additional_not_bool_type ? additional_not_bool_type : type;
|
||||
node->value = convert_untyped_to_typed(ast->pos, node->value, type);
|
||||
BREAK();
|
||||
}
|
||||
|
||||
CASE(VALUE, Atom){
|
||||
type = additional_not_bool_type ? additional_not_bool_type : type;
|
||||
node->value = convert_untyped_to_typed(ast->pos, node->value, type);
|
||||
BREAK();
|
||||
}
|
||||
|
||||
CASE(BINARY, Binary){
|
||||
Value value = {}; value.type = node->resolved_type; // @cleanup
|
||||
node->resolved_type = convert_untyped_to_typed(ast->pos, value, type).type;
|
||||
|
||||
// memes: int = 10
|
||||
// thing: Bool = int == (20 + 10)
|
||||
|
||||
try_propagating_resolved_type_to_untyped_literals(node->left, type, node->right->resolved_type);
|
||||
try_propagating_resolved_type_to_untyped_literals(node->right, type, node->left->resolved_type);
|
||||
BREAK();
|
||||
}
|
||||
|
||||
CASE(CALL, Call){
|
||||
if(is_untyped(node->resolved_type))
|
||||
compiler_error(node->pos, "Internal compiler error: Resolved type of a call is marked as untyped");
|
||||
BREAK();
|
||||
}
|
||||
|
||||
CASE(UNARY, Unary){
|
||||
Value value = {}; value.type = node->resolved_type; // @cleanup
|
||||
node->resolved_type = convert_untyped_to_typed(ast->pos, value, type).type;
|
||||
try_propagating_resolved_type_to_untyped_literals(node->expr, type);
|
||||
BREAK();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Ast_Type *
|
||||
resolve_typespec(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context = 0){
|
||||
if(!ast && is_flag_set(flags, AST_CAN_BE_NULL))
|
||||
@@ -536,10 +597,12 @@ resolve_stmt(Ast *ast, Ast_Type *ret){
|
||||
compiler_error(node->pos, "Return statement has different type then returned value, expecting: %Q got instead %Q", typestring(ret), typestring(type));
|
||||
node->resolved_type = type;
|
||||
|
||||
// @todo down untyping
|
||||
// For_It(node->expr){
|
||||
// Ast_Type *type =
|
||||
// }
|
||||
For_It(node->expr){
|
||||
Ast_Type *sub_type = type;
|
||||
if(is_tuple(type)) sub_type = type->agg.members[it.i].type;
|
||||
|
||||
try_propagating_resolved_type_to_untyped_literals(*it.it, sub_type);
|
||||
}
|
||||
|
||||
BREAK();
|
||||
}
|
||||
@@ -561,6 +624,7 @@ resolve_stmt(Ast *ast, Ast_Type *ret){
|
||||
|
||||
CASE(RUNTIME_ASSERT, Builtin){
|
||||
resolve_and_require_bool("Assert condition is not boolean", node->expr, AST_CAN_BE_NULL);
|
||||
try_propagating_resolved_type_to_untyped_literals(node->expr, type_bool);
|
||||
BREAK();
|
||||
}
|
||||
|
||||
@@ -597,6 +661,9 @@ resolve_stmt(Ast *ast, Ast_Type *ret){
|
||||
else if(!is_bool(op.type)){
|
||||
compiler_error(node->pos, "Invalid type of for loop condition %Q, required [Bool]", typestring(op.type));
|
||||
}
|
||||
else{
|
||||
try_propagating_resolved_type_to_untyped_literals(node->cond, type_bool);
|
||||
}
|
||||
}
|
||||
|
||||
resolve_expr(node->iter, AST_CAN_BE_NULL);
|
||||
@@ -609,6 +676,7 @@ resolve_stmt(Ast *ast, Ast_Type *ret){
|
||||
resolve_stmt(it->init, ret);
|
||||
// @todo: maybe add else kind ?? and then make sure other then else are AST_CANT_BE_NULL
|
||||
resolve_and_require_bool("Conditional in a if condition", it->expr, AST_CAN_BE_NULL);
|
||||
try_propagating_resolved_type_to_untyped_literals(it->expr, type_bool);
|
||||
For_Named(it->scope->stmts, jt)
|
||||
resolve_stmt(jt, ret);
|
||||
}
|
||||
@@ -684,6 +752,7 @@ resolve_lambda_type(Ast_Lambda *lambda){
|
||||
Operand default_value = resolve_expr(it->expr, AST_CAN_BE_NULL, type);
|
||||
make_sure_value_is_compatible_with_type(it->pos, &default_value, type, EXPR_CAN_BE_NULL);
|
||||
it->type = type;
|
||||
try_propagating_resolved_type_to_untyped_literals(it->expr, it->type);
|
||||
}
|
||||
|
||||
args.add(it->type);
|
||||
@@ -794,6 +863,7 @@ resolve_compound_array(Ast_Call *node, Ast_Type *type){
|
||||
Operand item = resolve_expr(it->item, AST_CANT_BE_NULL, item_type);
|
||||
make_sure_value_is_compatible_with_type(it->pos, &item, item_type, TYPE_AND_EXPR_REQUIRED);
|
||||
it->resolved_type = item_type;
|
||||
try_propagating_resolved_type_to_untyped_literals(it->item, it->resolved_type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -849,6 +919,7 @@ resolve_compound_struct(Ast_Call *node, Ast_Type *type){
|
||||
make_sure_value_is_compatible_with_type(it->pos, &item, item_type, TYPE_AND_EXPR_REQUIRED);
|
||||
|
||||
it->resolved_type = item_type;
|
||||
try_propagating_resolved_type_to_untyped_literals(it->item, it->resolved_type);
|
||||
}
|
||||
|
||||
For(type->agg.members) it.visited = false;
|
||||
@@ -897,15 +968,6 @@ resolve_field_access(Ast_Expr *node, Ast_Scope *context){
|
||||
return resolve_field_access(next, ((Ast_Decl *)type->ast)->scope);
|
||||
}
|
||||
|
||||
function void
|
||||
try_propagating_resolved_type_to_untyped_literals_one_level_deep(Ast *ast, Ast_Type *type){
|
||||
if(ast->kind != AST_VALUE) return;
|
||||
if(is_untyped(type)) return;
|
||||
|
||||
auto node = (Ast_Atom *)ast;
|
||||
convert_untyped_to_typed(ast->pos, node->value, type);// @rename: try and this
|
||||
}
|
||||
|
||||
function Operand
|
||||
resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context){
|
||||
if(!ast && is_flag_set(flags, AST_CAN_BE_NULL)) return {};
|
||||
@@ -978,11 +1040,20 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context){
|
||||
}
|
||||
|
||||
node->index_original_type = left.type;
|
||||
assert(left.type);
|
||||
|
||||
// @todo: type_architecture?
|
||||
try_propagating_resolved_type_to_untyped_literals(node->index, type_s64);
|
||||
|
||||
if(!left.type)
|
||||
compiler_error(node->expr->pos, "Internal compiler error: type of array is null somehow");
|
||||
if(is_untyped(left.type))
|
||||
compiler_error(node->expr->pos, "Internal compiler error: type of array is marked as untyped somehow");
|
||||
|
||||
if(is_string(left.type)){
|
||||
return operand_lvalue(type_u8);
|
||||
}
|
||||
else if(!is_array(left.type) && !is_pointer(left.type) && !is_slice(left.type)){
|
||||
|
||||
if(!is_array(left.type) && !is_pointer(left.type) && !is_slice(left.type)){
|
||||
compiler_error(node->pos, "Indexing variable that is not an [Array] or [Pointer], it's of type %Q instead", typestring(left.type));
|
||||
}
|
||||
|
||||
@@ -999,10 +1070,10 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context){
|
||||
|
||||
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 %Q and right is %Q", typestring(left.type), typestring(right.type));
|
||||
node->resolved_type = right.type;
|
||||
|
||||
try_propagating_resolved_type_to_untyped_literals_one_level_deep(node->left, node->resolved_type);
|
||||
try_propagating_resolved_type_to_untyped_literals_one_level_deep(node->left, node->resolved_type);
|
||||
node->resolved_type = right.type;
|
||||
try_propagating_resolved_type_to_untyped_literals(node->left, node->resolved_type, node->right->resolved_type);
|
||||
try_propagating_resolved_type_to_untyped_literals(node->right, node->resolved_type, node->left->resolved_type);
|
||||
return {};
|
||||
}
|
||||
else if(node->op == TK_Arrow){
|
||||
@@ -1020,12 +1091,18 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context){
|
||||
Operand right = resolve_expr(node->right, AST_CANT_BE_NULL);
|
||||
B32 is_const = left.is_const && right.is_const;
|
||||
Value value = eval_binary(node->pos, node->op, left.value, right.value, is_const);
|
||||
node->resolved_type = value.type;
|
||||
|
||||
if(is_const){
|
||||
// We don't need to propagte deeps for const values cause we are rewritting them
|
||||
rewrite_into_const(node, Ast_Binary, value);
|
||||
return operand_const_rvalue(value);
|
||||
}
|
||||
else return operand_rvalue(value.type);
|
||||
|
||||
else {
|
||||
try_propagating_resolved_type_to_untyped_literals(node->left, value.type);
|
||||
try_propagating_resolved_type_to_untyped_literals(node->right, value.type);
|
||||
return operand_rvalue(value.type);
|
||||
}
|
||||
}
|
||||
BREAK();
|
||||
}
|
||||
@@ -1119,6 +1196,7 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context){
|
||||
|
||||
CASE(LENGTH_OF, Builtin){
|
||||
Operand name = resolve_expr(node->expr, inherit_flag(flags, AST_CANT_BE_NULL));
|
||||
node->resolved_type = type_s64;
|
||||
if(name.type == type_type){
|
||||
if(is_array(name.type_val)){
|
||||
Value value = value_int(name.type_val->arr.size);
|
||||
@@ -1187,6 +1265,7 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context){
|
||||
item->resolved_type = lambda_arg->type;
|
||||
}
|
||||
|
||||
try_propagating_resolved_type_to_untyped_literals(item->item, item->resolved_type);
|
||||
item->resolved_index = lambda->args.get_index(&lambda_arg);
|
||||
items.add(item);
|
||||
}
|
||||
@@ -1206,6 +1285,7 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context){
|
||||
}
|
||||
|
||||
node->exprs = items.tight_copy(pctx->perm);
|
||||
node->resolved_type = name.type->func.ret;
|
||||
|
||||
// @note: check if all arguments are included and cleanup
|
||||
For(node->exprs){
|
||||
@@ -1297,6 +1377,7 @@ resolve_decl(Ast_Decl *ast){
|
||||
if(node->expr) compiler_error(node->pos, "#foreign variable shouldn't have value");
|
||||
}
|
||||
|
||||
try_propagating_resolved_type_to_untyped_literals(node->expr, node->type);
|
||||
BREAK();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user