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_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++;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
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] - 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
|
||||||
|
|||||||
23
new_ast.cpp
23
new_ast.cpp
@@ -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));
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
25
new_type.cpp
25
new_type.cpp
@@ -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{
|
||||||
@@ -59,7 +59,7 @@ struct Ast_Resolved_Type{
|
|||||||
}agg;
|
}agg;
|
||||||
struct{
|
struct{
|
||||||
Ast_Resolved_Type *ret;
|
Ast_Resolved_Type *ret;
|
||||||
Array<Ast_Resolved_Type*> args;
|
Array<Ast_Resolved_Type *> args;
|
||||||
}func;
|
}func;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user