diff --git a/ccodegen.cpp b/ccodegen.cpp index 1986e95..e8b8fb9 100644 --- a/ccodegen.cpp +++ b/ccodegen.cpp @@ -136,7 +136,7 @@ gen_expr(Ast_Expr *ast){ } CASE(CALL, Call){ - if(node->type == type_type){ + if(node->type->kind == TYPE_STRUCT){ // @todo: Should this be type_type maybe??? gen("("); gen_simple_decl(node->type, {}); gen(")"); diff --git a/lambdas.kl b/lambdas.kl index 386e21d..4579694 100644 --- a/lambdas.kl +++ b/lambdas.kl @@ -23,18 +23,22 @@ add_10 :: (size: int): int add :: (a: int, b: int = 10): int return a + b + // thing_2 :: (a: int = "String") + // return + constant :: 20; result := constant + 10 - v1 := add(a = 1) + v3 := add(1,2) v2 := add(a = 1, b = 2) - v3 := add([0] = 1) + v1 := add(a = 1) + // v_err := add([0] = 1) v4 := add(b = 1, a = 2) - v5 := add([0] = 1, [1] = 2) + // v_err := add([0] = 1, [1] = 2) // v_err := add([0] = 1, 10) // illegal // v_err := add([1] = 1) // illegal // v_err := add() // illegal - return v3 + return v4 return_constant :: (): int constant :: 10 diff --git a/main.cpp b/main.cpp index 632ae60..31052da 100644 --- a/main.cpp +++ b/main.cpp @@ -65,8 +65,8 @@ int main(){ String result = {}; // result = compile_file("order1.kl"_s); - // result = compile_file("lambdas.kl"_s); - result = compile_file("order2.kl"_s); + result = compile_file("lambdas.kl"_s); + // result = compile_file("order2.kl"_s); // result = compile_file("globals.kl"_s); printf("%s", result.str); diff --git a/new_ast.cpp b/new_ast.cpp index bf7064f..82e94ea 100644 --- a/new_ast.cpp +++ b/new_ast.cpp @@ -213,17 +213,17 @@ struct Ast_Array: Ast_Expr{ Ast_Expr *expr; }; +struct Ast_Named:Ast{ + Intern_String name; +}; + struct Ast_Resolved_Type; struct Ast_Struct: Ast_Expr{ // Required to be Ast_Struct or Ast_Var or Ast_Const - Array members; + Array members; Ast_Resolved_Type *type; }; -struct Ast_Named:Ast{ - Intern_String name; -}; - struct Ast_Var: Ast_Named{ Ast_Expr *typespec; Ast_Expr *expr; @@ -426,11 +426,12 @@ ast_array(Token *pos, Ast_Expr *expr){ } function Ast_Struct * -ast_struct(Token *pos, Array members){ +ast_struct(Token *pos, Array members){ AST_NEW(Struct, STRUCT, pos, AST_AGGREGATE); result->members = members.tight_copy(pctx->perm); For(result->members) { - assert(it[0]->kind == AST_VAR || it[0]->kind == AST_CONST || it[0]->kind == AST_STRUCT); + assert(is_flag_set(it[0]->flags, AST_BINDING)); + assert(it[0]->kind == AST_VAR || it[0]->kind == AST_CONST); it[0]->parent = result; } return result; diff --git a/new_parse.cpp b/new_parse.cpp index b17a51f..d0a0c77 100644 --- a/new_parse.cpp +++ b/new_parse.cpp @@ -406,7 +406,7 @@ parse_assign_expr(){ function Ast_Struct * parse_struct(Token *pos){ Scratch scratch; - Array members = {scratch}; + Array members = {scratch}; token_match(OPEN_SCOPE); do{ diff --git a/new_resolve.cpp b/new_resolve.cpp index 7308fb4..0c67642 100644 --- a/new_resolve.cpp +++ b/new_resolve.cpp @@ -242,6 +242,8 @@ resolve_stmt(Ast *ast, Ast_Resolved_Type *ret){ function Operand resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *const_sym){ + if(!ast) return {}; // @todo: add option for better error prevention + switch(ast->kind){ CASE(INT, Atom){ Operand result = {type_int, true}; @@ -302,6 +304,8 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *const_sym){ For(node->args){ Operand type = resolve_expr(it[0]->typespec); if(type.type != type_type) parsing_error(it[0]->pos, "Required expression of kind [type]"); + Operand default_value = resolve_expr(it[0]->default_value, type.type_val); + if(default_value.type && default_value.type != type.type_val) parsing_error(it[0]->pos, "Default value type and type declaration differ"); args.add(type.type_val); } lambda_type = type_lambda(node, ret_type, args); @@ -378,46 +382,74 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *const_sym){ } } else if(type->kind == TYPE_STRUCT){ - not_implemented; + auto agg = (Ast_Struct *)type->ast; + + S64 default_iter = 0; + For_It(node->exprs, expr){ + if(expr[0]->index) parsing_error(expr[0]->index->pos, "Function call indexing is illegal"); + Ast_Atom *name = expr[0]->name; + S64 expr_index = node->exprs.get_index(expr); + + Ast_Named *found = 0; + Ast_Resolved_Member *found_type = 0; + if(name){ + assert(name->kind == AST_IDENT); + For_It(agg->members, member){ + if(member[0]->name.str == name->intern_val.str){ + found = member[0]; + found_type = &type->agg.members[agg->members.get_index(member)]; + break; + } + } + } + else if(expr_index == default_iter){ + S64 i = default_iter++; + found = agg->members[i]; + found_type = &type->agg.members[i]; + if(i >= agg->members.len) parsing_error(expr[0]->pos, "Too many arguments in compound constructor"); + } + else parsing_error(expr[0]->pos, "Positional argument after named or indexed argument"); + + if(!found) parsing_error(expr[0]->pos, "Invalid argument in compound constructor"); + if(is_flag_set(found->flags, AST_ITEM_INCLUDED)) parsing_error(found->pos, "Item included multiple times in compound constructor"); + + found->flags = set_flag(found->flags, AST_ITEM_INCLUDED); + Operand op = resolve_expr(expr[0]->item, found_type->type); + if(found_type->type != op.type) parsing_error(expr[0]->pos, "Invalid type of compound constructor item"); + } + + // @note: cleanup, required? + For(agg->members){ + it[0]->flags = unset_flag(it[0]->flags, AST_ITEM_INCLUDED); + } } else if(type->kind == TYPE_LAMBDA){ - auto lambda = (Ast_Lambda *)type->ast; - Scratch scratch; Array items = {scratch}; + S64 default_iter = 0; + auto lambda = (Ast_Lambda *)type->ast; For(lambda->args){ S64 i = lambda->args.get_index(it); Ast_Resolved_Type *resolved = type->func.args[i]; Ast_Lambda_Arg *arg = it[0]; - // @note: match any in list of call items, if none matched then we have a problem // there are three kinds of possible matches: indexed, named, default - S64 default_iter = 0; Ast_Call_Item *item = 0; For_It(node->exprs, expr){ + if(expr[0]->index) parsing_error(expr[0]->index->pos, "Function call indexing is illegal"); Ast_Atom *name = expr[0]->name; - Ast_Expr *index = expr[0]->index; - assert(!(name && index)); // Only one of those can be valid if(name){ assert(name->kind == AST_IDENT); if(name->intern_val.str == arg->name.str) item = expr[0]; } - else if(index){ - Operand op = resolve_expr(index); - if(!op.is_const) parsing_error(index->pos, "Function call index is not constant"); - if(op.type != type_int) parsing_error(index->pos, "Function call index is not [Int]"); - if(op.int_val == i) item = expr[0]; - } else if(node->exprs.get_index(expr) == default_iter){ default_iter++; item = expr[0]; } - else{ - parsing_error(expr[0]->pos, "Positional argument after named or indexed argument"); - } + else if(node->exprs.get_index(expr) > default_iter) parsing_error(expr[0]->pos, "Positional argument after named argument"); if(item) break; } @@ -438,10 +470,10 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *const_sym){ } } + // @note: check if all arguments are included and cleanup For(node->exprs){ - if(!is_flag_set(it[0]->flags, AST_ITEM_INCLUDED)){ - parsing_error(it[0]->pos, "Invalid argument to function call"); - } + if(!is_flag_set(it[0]->flags, AST_ITEM_INCLUDED)) parsing_error(it[0]->pos, "Invalid argument to function call"); + else it[0]->flags = unset_flag(it[0]->flags, AST_ITEM_INCLUDED); } node->exprs = items.tight_copy(pctx->perm); diff --git a/order2.kl b/order2.kl index d31e666..288ec2f 100644 --- a/order2.kl +++ b/order2.kl @@ -22,8 +22,8 @@ pointer := &with_type deref := *pointer arena := Arena( - next = 0, - data = 0, + next = null, + data = null, len = 1000, cap = 1000, )