diff --git a/c_codegen.cpp b/c_codegen.cpp index d44870e..7757db8 100644 --- a/c_codegen.cpp +++ b/c_codegen.cpp @@ -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; diff --git a/typechecking.cpp b/typechecking.cpp index 3e65271..67c1ae8 100644 --- a/typechecking.cpp +++ b/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(); }