Var args sort of working, but I feel like all this stuff will need to get yanked out

or tested and refactored
This commit is contained in:
Krzosa Karol
2022-09-30 22:33:47 +02:00
parent 4c6497c5d6
commit 0646ae9279
6 changed files with 75 additions and 25 deletions

View File

@@ -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

View File

@@ -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,10 +271,15 @@ 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(")");
if(generate_block && lambda->scope){
@@ -284,22 +289,28 @@ 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)){
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){
gen("%Q", node->resolved_decl->unique_name);
@@ -315,9 +326,14 @@ gen_expr(Ast_Expr *ast, Ast_Type *type_of_var){
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;
}
@@ -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(")");

View File

@@ -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

View File

@@ -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;

View File

@@ -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{

View File

@@ -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)