More work on calls and compound statements
This commit is contained in:
@@ -136,7 +136,7 @@ gen_expr(Ast_Expr *ast){
|
|||||||
}
|
}
|
||||||
|
|
||||||
CASE(CALL, Call){
|
CASE(CALL, Call){
|
||||||
if(node->type == type_type){
|
if(node->type->kind == TYPE_STRUCT){ // @todo: Should this be type_type maybe???
|
||||||
gen("(");
|
gen("(");
|
||||||
gen_simple_decl(node->type, {});
|
gen_simple_decl(node->type, {});
|
||||||
gen(")");
|
gen(")");
|
||||||
|
|||||||
12
lambdas.kl
12
lambdas.kl
@@ -23,18 +23,22 @@ add_10 :: (size: int): int
|
|||||||
add :: (a: int, b: int = 10): int
|
add :: (a: int, b: int = 10): int
|
||||||
return a + b
|
return a + b
|
||||||
|
|
||||||
|
// thing_2 :: (a: int = "String")
|
||||||
|
// return
|
||||||
|
|
||||||
constant :: 20; result := constant + 10
|
constant :: 20; result := constant + 10
|
||||||
|
|
||||||
v1 := add(a = 1)
|
v3 := add(1,2)
|
||||||
v2 := add(a = 1, b = 2)
|
v2 := add(a = 1, b = 2)
|
||||||
v3 := add([0] = 1)
|
v1 := add(a = 1)
|
||||||
|
// v_err := add([0] = 1)
|
||||||
v4 := add(b = 1, a = 2)
|
v4 := add(b = 1, a = 2)
|
||||||
v5 := add([0] = 1, [1] = 2)
|
// v_err := add([0] = 1, [1] = 2)
|
||||||
// v_err := add([0] = 1, 10) // illegal
|
// v_err := add([0] = 1, 10) // illegal
|
||||||
// v_err := add([1] = 1) // illegal
|
// v_err := add([1] = 1) // illegal
|
||||||
// v_err := add() // illegal
|
// v_err := add() // illegal
|
||||||
|
|
||||||
return v3
|
return v4
|
||||||
|
|
||||||
return_constant :: (): int
|
return_constant :: (): int
|
||||||
constant :: 10
|
constant :: 10
|
||||||
|
|||||||
4
main.cpp
4
main.cpp
@@ -65,8 +65,8 @@ int main(){
|
|||||||
|
|
||||||
String result = {};
|
String result = {};
|
||||||
// result = compile_file("order1.kl"_s);
|
// result = compile_file("order1.kl"_s);
|
||||||
// result = compile_file("lambdas.kl"_s);
|
result = compile_file("lambdas.kl"_s);
|
||||||
result = compile_file("order2.kl"_s);
|
// result = compile_file("order2.kl"_s);
|
||||||
// result = compile_file("globals.kl"_s);
|
// result = compile_file("globals.kl"_s);
|
||||||
printf("%s", result.str);
|
printf("%s", result.str);
|
||||||
|
|
||||||
|
|||||||
15
new_ast.cpp
15
new_ast.cpp
@@ -213,17 +213,17 @@ struct Ast_Array: Ast_Expr{
|
|||||||
Ast_Expr *expr;
|
Ast_Expr *expr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Ast_Named:Ast{
|
||||||
|
Intern_String name;
|
||||||
|
};
|
||||||
|
|
||||||
struct Ast_Resolved_Type;
|
struct Ast_Resolved_Type;
|
||||||
struct Ast_Struct: Ast_Expr{
|
struct Ast_Struct: Ast_Expr{
|
||||||
// Required to be Ast_Struct or Ast_Var or Ast_Const
|
// Required to be Ast_Struct or Ast_Var or Ast_Const
|
||||||
Array<Ast *> members;
|
Array<Ast_Named *> members;
|
||||||
Ast_Resolved_Type *type;
|
Ast_Resolved_Type *type;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Ast_Named:Ast{
|
|
||||||
Intern_String name;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Ast_Var: Ast_Named{
|
struct Ast_Var: Ast_Named{
|
||||||
Ast_Expr *typespec;
|
Ast_Expr *typespec;
|
||||||
Ast_Expr *expr;
|
Ast_Expr *expr;
|
||||||
@@ -426,11 +426,12 @@ ast_array(Token *pos, Ast_Expr *expr){
|
|||||||
}
|
}
|
||||||
|
|
||||||
function Ast_Struct *
|
function Ast_Struct *
|
||||||
ast_struct(Token *pos, Array<Ast *> members){
|
ast_struct(Token *pos, Array<Ast_Named *> members){
|
||||||
AST_NEW(Struct, STRUCT, pos, AST_AGGREGATE);
|
AST_NEW(Struct, STRUCT, pos, AST_AGGREGATE);
|
||||||
result->members = members.tight_copy(pctx->perm);
|
result->members = members.tight_copy(pctx->perm);
|
||||||
For(result->members) {
|
For(result->members) {
|
||||||
assert(it[0]->kind == AST_VAR || it[0]->kind == AST_CONST || it[0]->kind == AST_STRUCT);
|
assert(is_flag_set(it[0]->flags, AST_BINDING));
|
||||||
|
assert(it[0]->kind == AST_VAR || it[0]->kind == AST_CONST);
|
||||||
it[0]->parent = result;
|
it[0]->parent = result;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@@ -406,7 +406,7 @@ parse_assign_expr(){
|
|||||||
function Ast_Struct *
|
function Ast_Struct *
|
||||||
parse_struct(Token *pos){
|
parse_struct(Token *pos){
|
||||||
Scratch scratch;
|
Scratch scratch;
|
||||||
Array<Ast *> members = {scratch};
|
Array<Ast_Named *> members = {scratch};
|
||||||
|
|
||||||
token_match(OPEN_SCOPE);
|
token_match(OPEN_SCOPE);
|
||||||
do{
|
do{
|
||||||
|
|||||||
@@ -242,6 +242,8 @@ resolve_stmt(Ast *ast, Ast_Resolved_Type *ret){
|
|||||||
|
|
||||||
function Operand
|
function Operand
|
||||||
resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *const_sym){
|
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){
|
switch(ast->kind){
|
||||||
CASE(INT, Atom){
|
CASE(INT, Atom){
|
||||||
Operand result = {type_int, true};
|
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){
|
For(node->args){
|
||||||
Operand type = resolve_expr(it[0]->typespec);
|
Operand type = resolve_expr(it[0]->typespec);
|
||||||
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]");
|
||||||
|
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);
|
args.add(type.type_val);
|
||||||
}
|
}
|
||||||
lambda_type = type_lambda(node, ret_type, args);
|
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){
|
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){
|
else if(type->kind == TYPE_LAMBDA){
|
||||||
auto lambda = (Ast_Lambda *)type->ast;
|
|
||||||
|
|
||||||
Scratch scratch;
|
Scratch scratch;
|
||||||
Array<Ast_Call_Item *> items = {scratch};
|
Array<Ast_Call_Item *> items = {scratch};
|
||||||
|
|
||||||
|
S64 default_iter = 0;
|
||||||
|
auto lambda = (Ast_Lambda *)type->ast;
|
||||||
For(lambda->args){
|
For(lambda->args){
|
||||||
S64 i = lambda->args.get_index(it);
|
S64 i = lambda->args.get_index(it);
|
||||||
Ast_Resolved_Type *resolved = type->func.args[i];
|
Ast_Resolved_Type *resolved = type->func.args[i];
|
||||||
Ast_Lambda_Arg *arg = it[0];
|
Ast_Lambda_Arg *arg = it[0];
|
||||||
|
|
||||||
|
|
||||||
// @note: match any in list of call items, if none matched then we have a problem
|
// @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
|
// there are three kinds of possible matches: indexed, named, default
|
||||||
S64 default_iter = 0;
|
|
||||||
Ast_Call_Item *item = 0;
|
Ast_Call_Item *item = 0;
|
||||||
For_It(node->exprs, expr){
|
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_Atom *name = expr[0]->name;
|
||||||
Ast_Expr *index = expr[0]->index;
|
|
||||||
assert(!(name && index)); // Only one of those can be valid
|
|
||||||
|
|
||||||
if(name){
|
if(name){
|
||||||
assert(name->kind == AST_IDENT);
|
assert(name->kind == AST_IDENT);
|
||||||
if(name->intern_val.str == arg->name.str) item = expr[0];
|
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){
|
else if(node->exprs.get_index(expr) == default_iter){
|
||||||
default_iter++;
|
default_iter++;
|
||||||
item = expr[0];
|
item = expr[0];
|
||||||
}
|
}
|
||||||
else{
|
else if(node->exprs.get_index(expr) > default_iter) parsing_error(expr[0]->pos, "Positional argument after named argument");
|
||||||
parsing_error(expr[0]->pos, "Positional argument after named or indexed argument");
|
|
||||||
}
|
|
||||||
|
|
||||||
if(item) break;
|
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){
|
For(node->exprs){
|
||||||
if(!is_flag_set(it[0]->flags, AST_ITEM_INCLUDED)){
|
if(!is_flag_set(it[0]->flags, AST_ITEM_INCLUDED)) parsing_error(it[0]->pos, "Invalid argument to function call");
|
||||||
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);
|
node->exprs = items.tight_copy(pctx->perm);
|
||||||
|
|||||||
Reference in New Issue
Block a user