diff --git a/ccodegen.cpp b/ccodegen.cpp index 7636140..1986e95 100644 --- a/ccodegen.cpp +++ b/ccodegen.cpp @@ -29,7 +29,8 @@ gen_simple_decl_prefix(Ast_Resolved_Type *ast){ case TYPE_ARRAY: gen_simple_decl_prefix(ast->base); break; case TYPE_LAMBDA:break; case TYPE_STRUCT: { - auto name = ast->sym->name; + auto constant = (Ast_Const *)ast->ast->parent; + auto name = constant->name; gen("%s ", name.str); }break; invalid_default_case; @@ -165,6 +166,7 @@ gen_expr(Ast_Expr *ast){ gen("("); For(node->exprs){ gen_expr(it[0]->item); + if(!node->exprs.is_last(it)) gen(", "); } gen(")"); } @@ -294,7 +296,7 @@ gen_ast(Ast *ast){ } else if(sym->type == type_type){ if(sym->type_val->kind == TYPE_STRUCT){ - Ast_Struct *agg = const_get_struct(sym->type_val->sym->ast); + Ast_Struct *agg = (Ast_Struct *)sym->type_val->ast; if(node->value->kind == AST_STRUCT){ gen("struct %s{", node->name.str); global_indent++; diff --git a/lambdas.kl b/lambdas.kl index 0c1cbb7..9b4c3ea 100644 --- a/lambdas.kl +++ b/lambdas.kl @@ -20,8 +20,11 @@ add_10 :: (size: int): int add_20 :: (new_size: int): int return 20 + add :: (a: int, b: int = 10): int + return a + b + constant :: 20; result := constant + 10 - return add_20(result) + return add(a = 20) return_constant :: (): int constant :: 10 diff --git a/main.cpp b/main.cpp index 3aba088..fffca1e 100644 --- a/main.cpp +++ b/main.cpp @@ -37,6 +37,10 @@ /// [x] - Typespecs should probably be expressions so stuff like would be possible :: *[32]int /// [x] - Initial order independence algorithm /// [ ] - Cleanup the mess with constant bindings +/// [ ] - Struct calls +/// [ ] - Default values in calls +/// [ ] - Resolving calls with default values +/// [ ] - Resolving calls with named args, with indexed args /// [ ] - Structs /// [ ] - Enums /// [ ] - For loop diff --git a/new_ast.cpp b/new_ast.cpp index 55822fc..bf7064f 100644 --- a/new_ast.cpp +++ b/new_ast.cpp @@ -112,6 +112,7 @@ enum{ AST_BINDING = 4, AST_AGGREGATE = 8, AST_ATOM = 16, + AST_ITEM_INCLUDED = 32, }; struct Ast{ @@ -198,6 +199,7 @@ struct Ast_Enum : Ast{ struct Ast_Lambda_Arg: Ast_Expr{ Intern_String name; Ast_Expr *typespec; + Ast_Expr *default_value; }; struct Ast_Lambda : Ast_Expr { @@ -353,12 +355,14 @@ ast_lambda(Token *pos, Array params, Ast_Expr *ret, Ast_Block } function Ast_Lambda_Arg * -ast_expr_lambda_arg(Token *pos, Intern_String name, Ast_Expr *typespec){ +ast_expr_lambda_arg(Token *pos, Intern_String name, Ast_Expr *typespec, Ast_Expr *default_value){ AST_NEW(Lambda_Arg, LAMBDA_ARG, pos, AST_EXPR); - result->flags = AST_EXPR; - result->name = name; - result->typespec = typespec; + result->flags = AST_EXPR; + result->name = name; + result->typespec = typespec; + result->default_value = default_value; result->typespec->parent = result; + if(result->default_value) result->default_value->parent = result; return result; } @@ -487,6 +491,23 @@ const_get_struct(Ast *ast){ return result; } +function Ast_Lambda * +const_try_getting_lambda(Ast *ast){ + assert(ast->kind == AST_CONST); + Ast_Const *constant = (Ast_Const *)ast; + if(constant->value->kind == AST_LAMBDA){ + return (Ast_Lambda *)constant->value; + } + return 0; +} + +function Ast_Lambda * +const_get_lambda(Ast *ast){ + auto result = const_try_getting_lambda(ast); + assert(result); + return result; +} + function Intern_String ast_get_name(Ast *ast){ assert(is_flag_set(ast->flags, AST_BINDING)); diff --git a/new_parse.cpp b/new_parse.cpp index 58e5317..b17a51f 100644 --- a/new_parse.cpp +++ b/new_parse.cpp @@ -167,6 +167,12 @@ parse_expr_call(Ast_Expr *left){ } Ast_Expr *item = parse_expr(); + if(!index && token_match(TK_Assign)){ + assert(is_flag_set(item->flags, AST_ATOM)); + name = (Ast_Atom *)item; + item = parse_expr(); + } + Ast_Call_Item *item_comp = ast_call_item(token, index, name, item); exprs.add(item_comp); @@ -252,15 +258,21 @@ parse_block(){ function Ast_Lambda * parse_lambda(Token *token, B32 is_typespec = false){ Scratch scratch; + Array params = {scratch}; if(!token_is(TK_CloseParen)){ for(;;){ Token *name = token_expect(TK_Identifier); token_expect(TK_Colon); Ast_Expr *typespec = parse_expr(); - Ast_Lambda_Arg *param = ast_expr_lambda_arg(name, name->intern_val, typespec); - params.add(param); + Ast_Expr *default_value = 0; + if(token_match(TK_Assign)) { + default_value = parse_expr(); + } + + Ast_Lambda_Arg *param = ast_expr_lambda_arg(name, name->intern_val, typespec, default_value); + params.add(param); if(!token_match(TK_Comma)){ break; } diff --git a/new_resolve.cpp b/new_resolve.cpp index 17b70b4..627574c 100644 --- a/new_resolve.cpp +++ b/new_resolve.cpp @@ -269,7 +269,6 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *const_sym){ result.is_const = true; } else if(sym->kind == SYM_CONST || sym->kind == SYM_VAR){ - // if(sym->type == type_type) type_complete(sym->type_val); result.type = sym->type; result.is_const = sym->kind == SYM_CONST ? true : false; result.value = sym->value; @@ -305,7 +304,8 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *const_sym){ if(type.type != type_type) parsing_error(it[0]->pos, "Required expression of kind [type]"); args.add(type.type_val); } - lambda_type = type_lambda(ret_type, args); + lambda_type = type_lambda(node, ret_type, args); + { assert(lambda_type); Value val; val.type_val = lambda_type; @@ -377,17 +377,71 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *const_sym){ resolve_type_pair(i->pos, expr.type, item_type); } } + else if(type->kind == TYPE_STRUCT){ + not_implemented; + } else if(type->kind == TYPE_LAMBDA){ - if(type->func.args.len != node->exprs.len) parsing_error(node->pos, "Invalid number of arguments"); - For(node->exprs){ - Ast_Call_Item *i = (Ast_Call_Item *)it[0]; - assert(i->kind == AST_CALL_ITEM); + auto lambda = (Ast_Lambda *)type->ast; - S64 index = node->exprs.get_index(it); - Operand expr = resolve_expr(i->item); - if(expr.type != type->func.args[index]) parsing_error(i->pos, "Type is not matching function definition"); + Scratch scratch; + Array items = {scratch}; + + 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){ + 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){ + // @todo might feel janky + default_iter++; + item = expr[0]; + } + + if(item) break; + } + + if(item){ + item->flags = set_flag(item->flags, AST_ITEM_INCLUDED); + Operand expr = resolve_expr(item->item); + if(expr.type != resolved) parsing_error(item->pos, "Type is not matching function definition"); + items.add(item); + } + else{ + if(arg->default_value){ + // @todo make sure default values have valid types but in lambda definition + Ast_Call_Item *item_default = ast_call_item(arg->default_value->pos, 0, 0, arg->default_value); + items.add(item_default); + } + else parsing_error(arg->pos, "Required value in lambda call was not passed"); + } } + For(node->exprs){ + if(!is_flag_set(it[0]->flags, AST_ITEM_INCLUDED)){ + parsing_error(it[0]->pos, "Invalid argument to function call"); + } + } + + node->exprs = items.tight_copy(pctx->perm); type = type->func.ret; } else parsing_error(node->pos, "Invalid function call type"); @@ -489,7 +543,7 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *const_sym){ sym_new_resolved(SYM_VAR, name, op.type, {}, it[0]); members.add({op.type, name}); } - Ast_Resolved_Type *resolved = type_struct(const_sym, members); + Ast_Resolved_Type *resolved = type_struct(node, members); Operand result = {type_type, true}; result.type_val = resolved; return result; BREAK(); @@ -588,7 +642,7 @@ parse_file(){ sym->kind = SYM_CONST; Ast_Struct *s = const_try_getting_struct(decl); if(s){ - s->type = type_incomplete(sym); + s->type = type_incomplete(decl); sym->type_val = s->type; sym->type = type_type; sym->state = SYM_RESOLVED; diff --git a/new_type.cpp b/new_type.cpp index 6ff6ab7..1fd9db5 100644 --- a/new_type.cpp +++ b/new_type.cpp @@ -47,7 +47,7 @@ struct Ast_Resolved_Type{ SizeU size; SizeU align; - Sym *sym; + Ast *ast; union{ Ast_Resolved_Type *base; struct{ @@ -59,7 +59,7 @@ struct Ast_Resolved_Type{ }agg; struct{ Ast_Resolved_Type *ret; - Array args; + Array args; }func; }; }; @@ -130,7 +130,7 @@ type_array(Ast_Resolved_Type *base, SizeU size){ } function Ast_Resolved_Type * -type_lambda(Ast_Resolved_Type *ret, Array args){ +type_lambda(Ast *ast, Ast_Resolved_Type *ret, Array args){ U64 hash = hash_ptr(ret); For(args) hash = hash_mix(hash, hash_ptr(*it)); Ast_Resolved_Type *result = (Ast_Resolved_Type *)map_get(&pctx->type_map, hash); @@ -143,6 +143,7 @@ type_lambda(Ast_Resolved_Type *ret, Array args){ } result = type_new(pctx->perm, TYPE_LAMBDA, pointer_size, pointer_align); + result->ast = ast; result->func.ret = ret; result->func.args = args.tight_copy(pctx->perm); map_insert(&pctx->type_map, hash, result); @@ -151,9 +152,9 @@ type_lambda(Ast_Resolved_Type *ret, Array args){ } function Ast_Resolved_Type * -type_incomplete(Sym *sym){ +type_incomplete(Ast *ast){ Ast_Resolved_Type *result = type_new(pctx->perm, TYPE_INCOMPLETE, 0, 0); - result->sym = sym; + result->ast = ast; return result; } @@ -166,7 +167,7 @@ type_complete(Ast_Resolved_Type *type){ else if(type->kind != TYPE_INCOMPLETE){ return; } - Ast_Struct *node = const_get_struct(type->sym->ast); + Ast_Struct *node = (Ast_Struct *)type->ast; // @note: resolve all the struct members type->kind = TYPE_COMPLETING; @@ -189,10 +190,10 @@ type_complete(Ast_Resolved_Type *type){ } function Ast_Resolved_Type * -type_struct(Sym *sym, Array members){ +type_struct(Ast *ast, Array members){ Ast_Resolved_Type *result = type_new(pctx->perm, TYPE_STRUCT, 0, 0); // @todo: align,size result->agg.members = members.tight_copy(pctx->perm); - result->sym = sym; + result->ast = ast; return result; } @@ -218,8 +219,8 @@ test_types(){ Array types = {scratch}; types.add(type_array(type_int, 32)); - Ast_Resolved_Type *func_type1 = type_lambda(types[0], types); - Ast_Resolved_Type *func_type2 = type_lambda(types[0], types); + Ast_Resolved_Type *func_type1 = type_lambda(0, types[0], types); + Ast_Resolved_Type *func_type2 = type_lambda(0, types[0], types); assert(func_type1 == func_type2); Array types2 = {scratch}; @@ -228,8 +229,8 @@ test_types(){ types2.add(type_int); } types.add(type_int); - Ast_Resolved_Type *func_type3 = type_lambda(types[0], types); - Ast_Resolved_Type *func_type4 = type_lambda(types[0], types2); + Ast_Resolved_Type *func_type3 = type_lambda(0, types[0], types); + Ast_Resolved_Type *func_type4 = type_lambda(0, types[0], types2); assert(func_type1 != func_type3); assert(func_type3 == func_type4); }