Rewriting function calls to have named parameters, default values
This commit is contained in:
@@ -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++;
|
||||
|
||||
@@ -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
|
||||
|
||||
4
main.cpp
4
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
|
||||
|
||||
23
new_ast.cpp
23
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<Ast_Lambda_Arg *> 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->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));
|
||||
|
||||
@@ -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<Ast_Lambda_Arg *> 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;
|
||||
}
|
||||
|
||||
@@ -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<Ast_Call_Item *> 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;
|
||||
|
||||
25
new_type.cpp
25
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<Ast_Resolved_Type*> args;
|
||||
Array<Ast_Resolved_Type *> 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<Ast_Resolved_Type *> args){
|
||||
type_lambda(Ast *ast, Ast_Resolved_Type *ret, Array<Ast_Resolved_Type *> 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<Ast_Resolved_Type *> 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<Ast_Resolved_Type *> 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<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
|
||||
result->agg.members = members.tight_copy(pctx->perm);
|
||||
result->sym = sym;
|
||||
result->ast = ast;
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -218,8 +219,8 @@ test_types(){
|
||||
|
||||
Array<Ast_Resolved_Type*> 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<Ast_Resolved_Type*> 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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user