diff --git a/core_codegen_c_language.cpp b/core_codegen_c_language.cpp index 07e3200..2142e45 100644 --- a/core_codegen_c_language.cpp +++ b/core_codegen_c_language.cpp @@ -5,7 +5,7 @@ global S32 global_indent; global S32 is_inside_struct; function void gen_ast(Ast *ast); -function bool gen_expr(Ast_Expr *ast, Ast_Type *type_of_var = 0, bool is_vargs = false); +function bool gen_expr(Ast_Expr *ast); function void gen_indent(){ @@ -270,6 +270,35 @@ enum { DONT_EMIT_VALUE = 1, }; +function void +gen_pointer_to_lvalue(Ast_Expr *expr){ + gen("&("); + gen_simple_decl(expr->resolved_type); + gen(")"); + gen("{"); + gen_expr(expr); + gen("}"); +} + +function void +gen_try_any_or_slice(Ast_Expr *expr, Ast_Type *decl_type){ + + // We want normal values to get boxed as Any pointers + // but other then that we shouldn't box other Any values + if(expr->kind != AST_COMPOUND && is_any(decl_type) && !is_any(expr->resolved_type)){ + gen("(Any){"); + gen_pointer_to_lvalue(expr); + gen(", %d}", expr->resolved_type->type_id); + } + else if(expr->kind == AST_IDENT && is_slice(decl_type)){ + Ast_Atom *atom = (Ast_Atom *)expr; + gen("{%d, ", atom->resolved_type->arr.size); + gen_expr(expr); + gen("}"); + } + else gen_expr(expr); +} + function void gen_var(Ast_Decl *decl, B32 emit_value, B32 scope_names){ if(is_flag_set(decl->flags, AST_FOREIGN)) gen("extern "); @@ -282,7 +311,7 @@ gen_var(Ast_Decl *decl, B32 emit_value, B32 scope_names){ if(decl->expr){ gen(" = "); - gen_expr(decl->expr, decl->type); + gen_try_any_or_slice(decl->expr, decl->type); } else { // Default zero if(is_numeric(decl->type)){ gen(" = 0"); @@ -297,14 +326,9 @@ gen_lambda(Intern_String name, Ast_Lambda *lambda, B32 generate_block = true){ gen_simple_decl(lambda->resolved_type->func.ret, name); gen("("); For(lambda->args){ - if(is_flag_set(it->flags, AST_ANY_VARGS)){ - gen("..."); - } - else{ - gen_var(it, DONT_EMIT_VALUE, true); - if(&it != (lambda->args.end() - 1)) - gen(", "); - } + gen_var(it, DONT_EMIT_VALUE, true); + if(&it != (lambda->args.end() - 1)) + gen(", "); } gen(")"); @@ -315,30 +339,25 @@ gen_lambda(Intern_String name, Ast_Lambda *lambda, B32 generate_block = true){ } function bool -gen_expr(Ast_Expr *ast, Ast_Type *type_of_var, bool is_vargs){ +gen_expr(Ast_Expr *ast){ switch(ast->kind){ CASE(IDENT, Atom){ if(node->resolved_decl->kind == AST_MODULE_NAMESPACE || node->resolved_decl->kind == AST_FILE_NAMESPACE) return false; - if(type_of_var && is_slice(type_of_var) && is_array(node->resolved_decl->type)){ - assert(!is_vargs); - gen("{%d, ", (int)node->resolved_decl->type->arr.size); - gen("%Q}", node->intern_val); - } + /// @edit + // if(type_of_var && is_slice(type_of_var) && is_array(node->resolved_decl->type)){ + // gen("{%d, ", (int)node->resolved_decl->type->arr.size); + // gen("%Q}", node->intern_val); + // } - else if(type_of_var && !is_any(ast->resolved_type) && is_any(type_of_var)){ - if(is_vargs){ - gen_expr(ast, 0, is_vargs); - } - else { - gen("(Any){&"); - gen_expr(ast); - gen(", %d}", ast->resolved_type->type_id); - } - } + // else if(type_of_var && !is_any(ast->resolved_type) && is_any(type_of_var)){ + // gen("(Any){&"); + // gen_expr(ast); + // gen(", %d}", ast->resolved_type->type_id); + // } - else if(node->resolved_decl->kind == AST_LAMBDA){ + if(node->resolved_decl->kind == AST_LAMBDA){ gen("%Q", node->resolved_decl->unique_name); } @@ -351,17 +370,13 @@ gen_expr(Ast_Expr *ast, Ast_Type *type_of_var, bool is_vargs){ } CASE(VALUE, Atom){ - if(is_any(type_of_var)){ - if(is_vargs){ - gen("(Any){&"); - gen("("); gen_simple_decl(node->type); gen("){"); gen_value(node->pos, node->value); gen("}"); - gen(", %d}", node->type->type_id); - } - else{ - gen_value(node->pos, node->value); - } - return true; - } + // @edit + // if(is_any(type_of_var)){ + // gen("(Any){&"); + // gen("("); gen_simple_decl(node->type); gen("){"); gen_value(node->pos, node->value); gen("}"); + // gen(", %d}", node->type->type_id); + // return true; + // } B32 written = gen_value(node->pos, node->value); if(!written) { @@ -377,7 +392,7 @@ gen_expr(Ast_Expr *ast, Ast_Type *type_of_var, bool is_vargs){ CASE(INDEX, Index){ gen("("); - gen_expr(node->expr, 0, is_vargs); + gen_expr(node->expr); if(node->index_original_type == type_string){ gen(".str"); } @@ -398,11 +413,11 @@ gen_expr(Ast_Expr *ast, Ast_Type *type_of_var, bool is_vargs){ CASE(BINARY, Binary){ if(node->op == TK_Dot){ - if(gen_expr(node->left, 0, 0)){ + if(gen_expr(node->left)){ if(node->dot_access_step_resolution && node->dot_access_step_resolution->kind == TYPE_POINTER) gen("->"); else gen("."); } - gen_expr(node->right, 0, 0); + gen_expr(node->right); return true; } @@ -470,7 +485,7 @@ gen_expr(Ast_Expr *ast, Ast_Type *type_of_var, bool is_vargs){ CASE(CALL, Call){ gen("%Q(", node->resolved_decl->unique_name); For(node->exprs){ - gen_expr(it->item, it->resolved_type, is_flag_set(it->flags, AST_ANY_VARGS)); + gen_try_any_or_slice(it->item, it->resolved_type); if(!node->exprs.is_last(&it)) gen(", "); } gen(")"); @@ -478,20 +493,13 @@ gen_expr(Ast_Expr *ast, Ast_Type *type_of_var, bool is_vargs){ } CASE(COMPOUND, Call){ - if(is_vargs){ - For(node->exprs){ - gen_expr(it->item, it->resolved_type, true); - - if(!node->exprs.is_last(&it)) gen(", "); - } - return true; - } - gen("("); gen_simple_decl(node->resolved_type); gen(")"); gen("{"); + // We need to double wrap it because Any is a pointer + // We need to pass it a compound array if(is_slice(node->resolved_type)) { gen(".len = %d, ", node->exprs.len); gen(".data = ("); @@ -506,12 +514,12 @@ gen_expr(Ast_Expr *ast, Ast_Type *type_of_var, bool is_vargs){ gen(".%Q = ", it->resolved_name); else if(is_array(node->resolved_type)) gen("[%d] = ", (int)it->resolved_index); - gen_expr(it->item, it->resolved_type); + gen_try_any_or_slice(it->item, it->resolved_type); if(!node->exprs.is_last(&it)) gen(", "); } - if(is_slice(node->resolved_type)) gen("}"); + if(is_slice(node->resolved_type)) gen("}"); gen("}"); BREAK(); } diff --git a/core_typechecking.cpp b/core_typechecking.cpp index be96ef8..8c01812 100644 --- a/core_typechecking.cpp +++ b/core_typechecking.cpp @@ -1495,7 +1495,6 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context, Ast_ if(is_flag_set(lambda_arg->flags, AST_ANY_VARGS)){ make_sure_value_is_compatible_with_type(item->pos, &expr, lambda_arg->type->base, TYPE_AND_EXPR_REQUIRED); item->resolved_type = expr.type; - set_flag(item->flags, AST_ANY_VARGS); } else{ diff --git a/examples/any_and_variadic_args.core b/examples/any_and_variadic_args.core index b89c5e4..297e5e1 100644 --- a/examples/any_and_variadic_args.core +++ b/examples/any_and_variadic_args.core @@ -1,6 +1,6 @@ -VariadicArguments :: (string: *char, args: ..) - pass +VariadicArguments :: (string: *char, args: ..): Any + return args[0] AnyArguments :: (values: []Any) for values @@ -20,7 +20,11 @@ main :: (): int for values Assert(it.type == S64) AnyArguments({a,b}) - VariadicArguments("Test", args = {a+b,b}) + c := VariadicArguments("Test", args = {a+b,b}) + Assert(*(c.data->*S64) == 30) + d := VariadicArguments("Test", {b,a}) + Assert(*(d.data->*S64) == b) + e := VariadicArguments("Test", {b,a}) Assert(*(values[0].data->*S64) == 10) Assert(*(values[1].data->*S64) == 20) diff --git a/examples/runtime_type_information.core b/examples/runtime_type_information.core index ec802ef..495fe32 100644 --- a/examples/runtime_type_information.core +++ b/examples/runtime_type_information.core @@ -35,15 +35,14 @@ main :: (): int any_value: Any = value_to_be_wrapped if any_value.type == S64 - // Void pointers get implicitly cast - value: *S64 = any_value.data - *value = 20 + *(any_value.data->*S64) = 20 elif any_value.type == int + // Void pointers get implicitly cast value: *int = any_value.data *value = 30 elif any_value.type == char;; Assert(false, "No bueno") - Assert(value_to_be_wrapped == 20) + Assert(*(any_value.data->*S64) == 20) letter := GetFirstLetterOfType(value_to_be_wrapped) Assert(letter == 'I')