More work on calls and compound statements

This commit is contained in:
Krzosa Karol
2022-05-30 13:22:57 +02:00
parent b2d3e9d8e1
commit 3a97e739a8
7 changed files with 73 additions and 36 deletions

View File

@@ -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<Ast_Call_Item *> 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);