From 0646ae927926d8df2dd87ceb2e7f8134fecc2af5 Mon Sep 17 00:00:00 2001 From: Krzosa Karol Date: Fri, 30 Sep 2022 22:33:47 +0200 Subject: [PATCH] Var args sort of working, but I feel like all this stuff will need to get yanked out or tested and refactored --- README.md | 3 +- core_codegen_c_language.cpp | 55 +++++++++++++++++++++-------- core_main.cpp | 21 ++++++----- core_parsing.cpp | 2 +- core_typechecking.cpp | 4 +++ examples/any_and_variadic_args.core | 15 ++++++++ 6 files changed, 75 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 000c89d..c6e8aed 100644 --- a/README.md +++ b/README.md @@ -126,13 +126,14 @@ Utf8ToUtf32 :: (c: *U8, max_advance: S64): U32, S64 - [x] Order independent declarations - The ordering of functions in code files or modules does not matter, compiler figures all that stuff out for you. "main" can be wherever you want it to be and all functions should be available without problems - [x] Synchronize generated C code with original source using line directives so that debuggers work + - [x] Fix overshoots when debugger goes to brace in c code - [ ] Expressions - [x] Compounds with named fields and numbered fields - [x] Functions calls with named arguments - [x] All the standard binary, unary expressions - [x] Pointer arithmetic and pointer as array - - [ ] Dot access expression needs a redesign because it doesn't handle expressions after the dot it requires names instead + - [x] Dot access expression needs a redesign because it doesn't handle expressions after the dot, requires identifiers - [ ] Casting might need a redesign not sure - [x] Runtime reflection diff --git a/core_codegen_c_language.cpp b/core_codegen_c_language.cpp index d7f7b9e..94f828e 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); +function bool gen_expr(Ast_Expr *ast, Ast_Type *type_of_var = 0, bool is_vargs = false); function void gen_indent(){ @@ -271,9 +271,14 @@ 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){ - gen_var(it, DONT_EMIT_VALUE, true); - if(&it != (lambda->args.end() - 1)) - gen(", "); + 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(")"); @@ -284,21 +289,27 @@ gen_lambda(Intern_String name, Ast_Lambda *lambda, B32 generate_block = true){ } function bool -gen_expr(Ast_Expr *ast, Ast_Type *type_of_var){ +gen_expr(Ast_Expr *ast, Ast_Type *type_of_var, bool is_vargs){ 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); } 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); + if(is_vargs){ + gen_expr(ast, 0, is_vargs); + } + else { + gen("(Any){&"); + gen_expr(ast); + gen(", %d}", ast->resolved_type->type_id); + } } else if(node->resolved_decl->kind == AST_LAMBDA){ @@ -315,9 +326,14 @@ gen_expr(Ast_Expr *ast, Ast_Type *type_of_var){ CASE(VALUE, Atom){ 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); + 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; } @@ -335,7 +351,7 @@ gen_expr(Ast_Expr *ast, Ast_Type *type_of_var){ CASE(INDEX, Index){ gen("("); - gen_expr(node->expr); + gen_expr(node->expr, 0, is_vargs); if(node->index_original_type == type_string){ gen(".str"); } @@ -356,11 +372,11 @@ gen_expr(Ast_Expr *ast, Ast_Type *type_of_var){ CASE(BINARY, Binary){ if(node->op == TK_Dot){ - if(gen_expr(node->left)){ + if(gen_expr(node->left, 0, 0)){ if(node->dot_access_step_resolution && node->dot_access_step_resolution->kind == TYPE_POINTER) gen("->"); else gen("."); } - gen_expr(node->right); + gen_expr(node->right, 0, 0); return true; } @@ -428,7 +444,7 @@ gen_expr(Ast_Expr *ast, Ast_Type *type_of_var){ CASE(CALL, Call){ gen("%Q(", node->resolved_decl->unique_name); For(node->exprs){ - gen_expr(it->item, it->resolved_type); + gen_expr(it->item, it->resolved_type, is_flag_set(it->flags, AST_ANY_VARGS)); if(!node->exprs.is_last(&it)) gen(", "); } gen(")"); @@ -436,6 +452,15 @@ gen_expr(Ast_Expr *ast, Ast_Type *type_of_var){ } 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(")"); diff --git a/core_main.cpp b/core_main.cpp index e13a0a4..3f5cd4b 100644 --- a/core_main.cpp +++ b/core_main.cpp @@ -1,27 +1,31 @@ /* +First doable version: + +- [ ] Any stuff working well +- [ ] Var args working + +In the future + - [ ] Cleanup - [ ] Remove tuple stuff or cleanup, in the future might replace it with a better implementation - - [ ] '.' Operator doesn't handle expressions inside the dot chain, no good, so casts don't work + +- [ ] Conditional compilation +- [ ] Expand macros +- [ ] Defer - [ ] Basic - [ ] Detecting if return was called - [ ] Builtin data structures - - [ ] Strings probably should have len() instead of string.len - [ ] Slices - [ ] Some way to take slice of data - [ ] Tuples - [ ] Dynamic arrays - [ ] Hash tables -- [ ] C Codegen - - [ ] Programming constructs - - [ ] Defer statement - [ ] Using language construct - - [ ] Function polimorphism - - [ ] Operator Overloading - [ ] Named loops and breaking out of them - [ ] Bytecode interpreter @@ -35,7 +39,6 @@ - [ ] Any - [ ] Assigning to any values like ints etc. should work perhaps? But what type they should have? - - [ ] Var args using any - [ ] Slice of Any should work well Maybe later @@ -145,6 +148,8 @@ For modules it's a bit different cause they should be distributed as valid. ## Done +- [x] Operator Overloading +- [x] '.' Operator doesn't handle expressions inside the dot chain, no good, so casts don't work - [x] Introduce List to reduce heap allocations and make it more arena friendly, can we get rid of heap completly? - [x] Function renaming to prevent colissions, we can't really touch other stuff cause I want it to be easily debuggable - [x] Fix Length etc. they should be function calls not operators diff --git a/core_parsing.cpp b/core_parsing.cpp index a114392..0d2a06b 100644 --- a/core_parsing.cpp +++ b/core_parsing.cpp @@ -456,7 +456,7 @@ parse_lambda(Token *token){ params.add(param); } - else compiler_error(name, "Expected [Identifier] or [...] when parsing lambda arguments"); + else compiler_error(name, "Expected [Identifier] or [..] when parsing lambda arguments"); if(!token_match(TK_Comma)) break; diff --git a/core_typechecking.cpp b/core_typechecking.cpp index 86412c1..4f0a38a 100644 --- a/core_typechecking.cpp +++ b/core_typechecking.cpp @@ -1694,6 +1694,9 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context, Ast_ else if(is_struct(type)){ resolve_compound_struct(node, type); } + else { + compiler_error(node->pos, "Internal compiler error: Invalid type was passed to the compound expression, should have been an array, struct or slice"); + } return operand_lvalue(type); @@ -1815,6 +1818,7 @@ 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 64eff74..7a60c05 100644 --- a/examples/any_and_variadic_args.core +++ b/examples/any_and_variadic_args.core @@ -1,11 +1,26 @@ +VariadicArguments :: (string: *char, args: ..) + pass + +AnyArguments :: (values: []Any) + for values + Assert(it.type == S64) + Assert(*(values[0].data->*S64) == 10) + Assert(*(values[1].data->*S64) == 20) + +printf :: #foreign (string: *char, args: ..): int + main :: (): int a := 10 b := 20 values := []Any{a, b} + printf("Test %d", {a}) + for values Assert(it.type == S64) + AnyArguments({a,b}) + VariadicArguments("Test", args = {a+b,b}) Assert(*(values[0].data->*S64) == 10) Assert(*(values[1].data->*S64) == 20)