Rewriting function calls to have named parameters, default values

This commit is contained in:
Krzosa Karol
2022-05-30 11:00:30 +02:00
parent 54e3cb5261
commit 9e24a608cb
7 changed files with 129 additions and 32 deletions

View File

@@ -29,7 +29,8 @@ gen_simple_decl_prefix(Ast_Resolved_Type *ast){
case TYPE_ARRAY: gen_simple_decl_prefix(ast->base); break; case TYPE_ARRAY: gen_simple_decl_prefix(ast->base); break;
case TYPE_LAMBDA:break; case TYPE_LAMBDA:break;
case TYPE_STRUCT: { case TYPE_STRUCT: {
auto name = ast->sym->name; auto constant = (Ast_Const *)ast->ast->parent;
auto name = constant->name;
gen("%s ", name.str); gen("%s ", name.str);
}break; }break;
invalid_default_case; invalid_default_case;
@@ -165,6 +166,7 @@ gen_expr(Ast_Expr *ast){
gen("("); gen("(");
For(node->exprs){ For(node->exprs){
gen_expr(it[0]->item); gen_expr(it[0]->item);
if(!node->exprs.is_last(it)) gen(", ");
} }
gen(")"); gen(")");
} }
@@ -294,7 +296,7 @@ gen_ast(Ast *ast){
} }
else if(sym->type == type_type){ else if(sym->type == type_type){
if(sym->type_val->kind == TYPE_STRUCT){ 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){ if(node->value->kind == AST_STRUCT){
gen("struct %s{", node->name.str); gen("struct %s{", node->name.str);
global_indent++; global_indent++;

View File

@@ -20,8 +20,11 @@ add_10 :: (size: int): int
add_20 :: (new_size: int): int add_20 :: (new_size: int): int
return 20 return 20
add :: (a: int, b: int = 10): int
return a + b
constant :: 20; result := constant + 10 constant :: 20; result := constant + 10
return add_20(result) return add(a = 20)
return_constant :: (): int return_constant :: (): int
constant :: 10 constant :: 10

View File

@@ -37,6 +37,10 @@
/// [x] - Typespecs should probably be expressions so stuff like would be possible :: *[32]int /// [x] - Typespecs should probably be expressions so stuff like would be possible :: *[32]int
/// [x] - Initial order independence algorithm /// [x] - Initial order independence algorithm
/// [ ] - Cleanup the mess with constant bindings /// [ ] - 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 /// [ ] - Structs
/// [ ] - Enums /// [ ] - Enums
/// [ ] - For loop /// [ ] - For loop

View File

@@ -112,6 +112,7 @@ enum{
AST_BINDING = 4, AST_BINDING = 4,
AST_AGGREGATE = 8, AST_AGGREGATE = 8,
AST_ATOM = 16, AST_ATOM = 16,
AST_ITEM_INCLUDED = 32,
}; };
struct Ast{ struct Ast{
@@ -198,6 +199,7 @@ struct Ast_Enum : Ast{
struct Ast_Lambda_Arg: Ast_Expr{ struct Ast_Lambda_Arg: Ast_Expr{
Intern_String name; Intern_String name;
Ast_Expr *typespec; Ast_Expr *typespec;
Ast_Expr *default_value;
}; };
struct Ast_Lambda : Ast_Expr { struct Ast_Lambda : Ast_Expr {
@@ -353,12 +355,14 @@ ast_lambda(Token *pos, Array<Ast_Lambda_Arg *> params, Ast_Expr *ret, Ast_Block
} }
function Ast_Lambda_Arg * 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); AST_NEW(Lambda_Arg, LAMBDA_ARG, pos, AST_EXPR);
result->flags = AST_EXPR; result->flags = AST_EXPR;
result->name = name; result->name = name;
result->typespec = typespec; result->typespec = typespec;
result->default_value = default_value;
result->typespec->parent = result; result->typespec->parent = result;
if(result->default_value) result->default_value->parent = result;
return result; return result;
} }
@@ -487,6 +491,23 @@ const_get_struct(Ast *ast){
return result; 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 function Intern_String
ast_get_name(Ast *ast){ ast_get_name(Ast *ast){
assert(is_flag_set(ast->flags, AST_BINDING)); assert(is_flag_set(ast->flags, AST_BINDING));

View File

@@ -167,6 +167,12 @@ parse_expr_call(Ast_Expr *left){
} }
Ast_Expr *item = parse_expr(); 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); Ast_Call_Item *item_comp = ast_call_item(token, index, name, item);
exprs.add(item_comp); exprs.add(item_comp);
@@ -252,15 +258,21 @@ parse_block(){
function Ast_Lambda * function Ast_Lambda *
parse_lambda(Token *token, B32 is_typespec = false){ parse_lambda(Token *token, B32 is_typespec = false){
Scratch scratch; Scratch scratch;
Array<Ast_Lambda_Arg *> params = {scratch}; Array<Ast_Lambda_Arg *> params = {scratch};
if(!token_is(TK_CloseParen)){ if(!token_is(TK_CloseParen)){
for(;;){ for(;;){
Token *name = token_expect(TK_Identifier); Token *name = token_expect(TK_Identifier);
token_expect(TK_Colon); token_expect(TK_Colon);
Ast_Expr *typespec = parse_expr(); 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)){ if(!token_match(TK_Comma)){
break; break;
} }

View File

@@ -269,7 +269,6 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *const_sym){
result.is_const = true; result.is_const = true;
} }
else if(sym->kind == SYM_CONST || sym->kind == SYM_VAR){ 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.type = sym->type;
result.is_const = sym->kind == SYM_CONST ? true : false; result.is_const = sym->kind == SYM_CONST ? true : false;
result.value = sym->value; 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]"); if(type.type != type_type) parsing_error(it[0]->pos, "Required expression of kind [type]");
args.add(type.type_val); args.add(type.type_val);
} }
lambda_type = type_lambda(ret_type, args); lambda_type = type_lambda(node, ret_type, args);
{ {
assert(lambda_type); assert(lambda_type);
Value val; val.type_val = 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); resolve_type_pair(i->pos, expr.type, item_type);
} }
} }
else if(type->kind == TYPE_STRUCT){
not_implemented;
}
else if(type->kind == TYPE_LAMBDA){ else if(type->kind == TYPE_LAMBDA){
if(type->func.args.len != node->exprs.len) parsing_error(node->pos, "Invalid number of arguments"); auto lambda = (Ast_Lambda *)type->ast;
For(node->exprs){
Ast_Call_Item *i = (Ast_Call_Item *)it[0];
assert(i->kind == AST_CALL_ITEM);
S64 index = node->exprs.get_index(it); Scratch scratch;
Operand expr = resolve_expr(i->item); Array<Ast_Call_Item *> items = {scratch};
if(expr.type != type->func.args[index]) parsing_error(i->pos, "Type is not matching function definition");
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; type = type->func.ret;
} }
else parsing_error(node->pos, "Invalid function call type"); 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]); sym_new_resolved(SYM_VAR, name, op.type, {}, it[0]);
members.add({op.type, name}); 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; Operand result = {type_type, true}; result.type_val = resolved;
return result; return result;
BREAK(); BREAK();
@@ -588,7 +642,7 @@ parse_file(){
sym->kind = SYM_CONST; sym->kind = SYM_CONST;
Ast_Struct *s = const_try_getting_struct(decl); Ast_Struct *s = const_try_getting_struct(decl);
if(s){ if(s){
s->type = type_incomplete(sym); s->type = type_incomplete(decl);
sym->type_val = s->type; sym->type_val = s->type;
sym->type = type_type; sym->type = type_type;
sym->state = SYM_RESOLVED; sym->state = SYM_RESOLVED;

View File

@@ -47,7 +47,7 @@ struct Ast_Resolved_Type{
SizeU size; SizeU size;
SizeU align; SizeU align;
Sym *sym; Ast *ast;
union{ union{
Ast_Resolved_Type *base; Ast_Resolved_Type *base;
struct{ struct{
@@ -130,7 +130,7 @@ type_array(Ast_Resolved_Type *base, SizeU size){
} }
function Ast_Resolved_Type * function Ast_Resolved_Type *
type_lambda(Ast_Resolved_Type *ret, Array<Ast_Resolved_Type *> args){ type_lambda(Ast *ast, Ast_Resolved_Type *ret, Array<Ast_Resolved_Type *> args){
U64 hash = hash_ptr(ret); U64 hash = hash_ptr(ret);
For(args) hash = hash_mix(hash, hash_ptr(*it)); For(args) hash = hash_mix(hash, hash_ptr(*it));
Ast_Resolved_Type *result = (Ast_Resolved_Type *)map_get(&pctx->type_map, hash); Ast_Resolved_Type *result = (Ast_Resolved_Type *)map_get(&pctx->type_map, hash);
@@ -143,6 +143,7 @@ type_lambda(Ast_Resolved_Type *ret, Array<Ast_Resolved_Type *> args){
} }
result = type_new(pctx->perm, TYPE_LAMBDA, pointer_size, pointer_align); result = type_new(pctx->perm, TYPE_LAMBDA, pointer_size, pointer_align);
result->ast = ast;
result->func.ret = ret; result->func.ret = ret;
result->func.args = args.tight_copy(pctx->perm); result->func.args = args.tight_copy(pctx->perm);
map_insert(&pctx->type_map, hash, result); map_insert(&pctx->type_map, hash, result);
@@ -151,9 +152,9 @@ type_lambda(Ast_Resolved_Type *ret, Array<Ast_Resolved_Type *> args){
} }
function Ast_Resolved_Type * function Ast_Resolved_Type *
type_incomplete(Sym *sym){ type_incomplete(Ast *ast){
Ast_Resolved_Type *result = type_new(pctx->perm, TYPE_INCOMPLETE, 0, 0); Ast_Resolved_Type *result = type_new(pctx->perm, TYPE_INCOMPLETE, 0, 0);
result->sym = sym; result->ast = ast;
return result; return result;
} }
@@ -166,7 +167,7 @@ type_complete(Ast_Resolved_Type *type){
else if(type->kind != TYPE_INCOMPLETE){ else if(type->kind != TYPE_INCOMPLETE){
return; return;
} }
Ast_Struct *node = const_get_struct(type->sym->ast); Ast_Struct *node = (Ast_Struct *)type->ast;
// @note: resolve all the struct members // @note: resolve all the struct members
type->kind = TYPE_COMPLETING; type->kind = TYPE_COMPLETING;
@@ -189,10 +190,10 @@ type_complete(Ast_Resolved_Type *type){
} }
function Ast_Resolved_Type * function Ast_Resolved_Type *
type_struct(Sym *sym, Array<Ast_Resolved_Member> members){ type_struct(Ast *ast, Array<Ast_Resolved_Member> members){
Ast_Resolved_Type *result = type_new(pctx->perm, TYPE_STRUCT, 0, 0); // @todo: align,size Ast_Resolved_Type *result = type_new(pctx->perm, TYPE_STRUCT, 0, 0); // @todo: align,size
result->agg.members = members.tight_copy(pctx->perm); result->agg.members = members.tight_copy(pctx->perm);
result->sym = sym; result->ast = ast;
return result; return result;
} }
@@ -218,8 +219,8 @@ test_types(){
Array<Ast_Resolved_Type*> types = {scratch}; Array<Ast_Resolved_Type*> types = {scratch};
types.add(type_array(type_int, 32)); types.add(type_array(type_int, 32));
Ast_Resolved_Type *func_type1 = type_lambda(types[0], types); Ast_Resolved_Type *func_type1 = type_lambda(0, types[0], types);
Ast_Resolved_Type *func_type2 = type_lambda(types[0], types); Ast_Resolved_Type *func_type2 = type_lambda(0, types[0], types);
assert(func_type1 == func_type2); assert(func_type1 == func_type2);
Array<Ast_Resolved_Type*> types2 = {scratch}; Array<Ast_Resolved_Type*> types2 = {scratch};
@@ -228,8 +229,8 @@ test_types(){
types2.add(type_int); types2.add(type_int);
} }
types.add(type_int); types.add(type_int);
Ast_Resolved_Type *func_type3 = type_lambda(types[0], types); Ast_Resolved_Type *func_type3 = type_lambda(0, types[0], types);
Ast_Resolved_Type *func_type4 = type_lambda(types[0], types2); Ast_Resolved_Type *func_type4 = type_lambda(0, types[0], types2);
assert(func_type1 != func_type3); assert(func_type1 != func_type3);
assert(func_type3 == func_type4); assert(func_type3 == func_type4);
} }