Compiling global, work on AST_LAMBDA_EXPR
This commit is contained in:
5
ast.cpp
5
ast.cpp
@@ -152,7 +152,7 @@ struct Ast_Lambda : Ast_Expr {
|
||||
Array<Ast_Decl *> args;
|
||||
Ast_Expr *ret;
|
||||
Ast_Scope *scope;
|
||||
B32 has_var_args;
|
||||
Ast_Resolved_Type *type;
|
||||
};
|
||||
|
||||
struct Ast_Array: Ast_Expr{
|
||||
@@ -327,13 +327,12 @@ ast_expr_index(Token *pos, Ast_Expr *expr, Ast_Expr *index){
|
||||
}
|
||||
|
||||
function Ast_Lambda *
|
||||
ast_lambda(Token *pos, Array<Ast_Decl *> params, B32 has_var_args, Ast_Expr *ret, Ast_Scope *scope){
|
||||
ast_lambda(Token *pos, Array<Ast_Decl *> params, Ast_Expr *ret, Ast_Scope *scope){
|
||||
AST_NEW(Lambda, LAMBDA_EXPR, pos, AST_EXPR);
|
||||
result->flags = AST_EXPR;
|
||||
result->args = params.tight_copy(pctx->perm);
|
||||
result->scope = scope;
|
||||
result->ret = ret;
|
||||
result->has_var_args = has_var_args;
|
||||
if(!ret) result->ret = ast_ident(result->pos, intern_void);
|
||||
|
||||
return result;
|
||||
|
||||
137
ccodegen.cpp
137
ccodegen.cpp
@@ -5,12 +5,19 @@ global S32 global_indent;
|
||||
global S32 is_inside_struct;
|
||||
|
||||
function void gen_ast(Ast *ast);
|
||||
function void gen_expr(Ast_Expr *ast);
|
||||
|
||||
function void
|
||||
gen_indent(){
|
||||
for(S32 i = 0; i < global_indent; i++) gen(" ");
|
||||
}
|
||||
|
||||
function void
|
||||
gen_line(Ast *node){
|
||||
if(emit_line_directives)
|
||||
genln("#line %d", node->pos->line+1);
|
||||
}
|
||||
|
||||
// @todo: Gen complicated decl
|
||||
//array 10 ( pointer (pointer array 5 int a))
|
||||
// int (*(*(a[5])))[10]
|
||||
@@ -91,6 +98,60 @@ gen_value(Value a){
|
||||
return result;
|
||||
}
|
||||
|
||||
function void
|
||||
gen_stmt_scope(Ast_Scope *scope){
|
||||
gen("{");
|
||||
global_indent++;
|
||||
For(scope->stmts) {
|
||||
gen_line(it);
|
||||
genln("");
|
||||
gen_ast(it);
|
||||
}
|
||||
global_indent--;
|
||||
genln("}");
|
||||
}
|
||||
|
||||
enum {
|
||||
ALWAYS_EMIT_VALUE = 0,
|
||||
DONT_EMIT_VALUE = 1,
|
||||
};
|
||||
|
||||
function void
|
||||
gen_var(Intern_String name, Ast_Resolved_Type *type, Ast_Expr *expr, B32 emit_value){
|
||||
gen_simple_decl(type, name);
|
||||
|
||||
if(emit_value == DONT_EMIT_VALUE){
|
||||
return;
|
||||
}
|
||||
|
||||
if(expr){
|
||||
gen(" = ");
|
||||
gen_expr(expr);
|
||||
} else { // Default zero
|
||||
if(is_numeric(type)){
|
||||
gen(" = 0");
|
||||
} else {
|
||||
gen(" = {}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function void
|
||||
gen_lambda(Intern_String name, Ast_Lambda *lambda){
|
||||
gen_simple_decl(lambda->type->func.ret, name);
|
||||
gen("(");
|
||||
For(lambda->args){
|
||||
gen_var(it->name, it->type, 0, DONT_EMIT_VALUE);
|
||||
if(&it != (lambda->args.end() - 1)) gen(", ");
|
||||
}
|
||||
gen(")");
|
||||
|
||||
if(lambda->scope) {
|
||||
gen_stmt_scope(lambda->scope);
|
||||
}
|
||||
else gen(";");
|
||||
}
|
||||
|
||||
function void
|
||||
gen_expr(Ast_Expr *ast){
|
||||
switch(ast->kind){
|
||||
@@ -115,6 +176,11 @@ gen_expr(Ast_Expr *ast){
|
||||
BREAK();
|
||||
}
|
||||
|
||||
CASE(LAMBDA_EXPR, Lambda){
|
||||
gen_lambda({}, node);
|
||||
BREAK();
|
||||
}
|
||||
|
||||
CASE(BINARY, Binary){
|
||||
if(node->op == TK_Dot){
|
||||
gen_expr(node->left);
|
||||
@@ -172,50 +238,6 @@ gen_expr(Ast_Expr *ast){
|
||||
}
|
||||
}
|
||||
|
||||
function void
|
||||
gen_line(Ast *node){
|
||||
if(emit_line_directives)
|
||||
genln("#line %d", node->pos->line+1);
|
||||
}
|
||||
|
||||
function void
|
||||
gen_stmt_scope(Ast_Scope *scope){
|
||||
gen("{");
|
||||
global_indent++;
|
||||
For(scope->stmts) {
|
||||
gen_line(it);
|
||||
genln("");
|
||||
gen_ast(it);
|
||||
}
|
||||
global_indent--;
|
||||
genln("}");
|
||||
}
|
||||
|
||||
enum {
|
||||
ALWAYS_EMIT_VALUE = 0,
|
||||
DONT_EMIT_VALUE = 1,
|
||||
};
|
||||
|
||||
function void
|
||||
gen_var(Intern_String name, Ast_Resolved_Type *type, Ast_Expr *expr, B32 emit_value){
|
||||
gen_simple_decl(type, name);
|
||||
|
||||
if(emit_value == DONT_EMIT_VALUE){
|
||||
return;
|
||||
}
|
||||
|
||||
if(expr){
|
||||
gen(" = ");
|
||||
gen_expr(expr);
|
||||
} else { // Default zero
|
||||
if(is_numeric(type)){
|
||||
gen(" = 0");
|
||||
} else {
|
||||
gen(" = {}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function void
|
||||
gen_ast(Ast *ast){
|
||||
switch(ast->kind){
|
||||
@@ -283,31 +305,10 @@ gen_ast(Ast *ast){
|
||||
}
|
||||
|
||||
CASE(LAMBDA, Decl){
|
||||
if(node->kind == AST_LAMBDA){
|
||||
if(is_flag_set(node->flags, AST_FOREIGN)){
|
||||
return;
|
||||
}
|
||||
Ast_Lambda *lambda = node->lambda;
|
||||
Ast_Resolved_Type *ret = node->type->func.ret;
|
||||
gen_simple_decl(ret, node->name);
|
||||
gen("(");
|
||||
For(lambda->args){
|
||||
gen_var(it->name, it->type, 0, DONT_EMIT_VALUE);
|
||||
if(&it != (lambda->args.end() - 1)) gen(", ");
|
||||
}
|
||||
gen(")");
|
||||
|
||||
if(lambda->scope) {
|
||||
gen_stmt_scope(lambda->scope);
|
||||
}
|
||||
else gen(";");
|
||||
}
|
||||
else{
|
||||
gen_simple_decl(node->type, node->name);
|
||||
gen(" = ");
|
||||
gen_expr((Ast_Expr *)node->expr);
|
||||
gen(";");
|
||||
if(is_flag_set(node->flags, AST_FOREIGN)){
|
||||
gen("/*foreign*/");
|
||||
}
|
||||
gen_lambda(node->name, node->lambda);
|
||||
BREAK();
|
||||
}
|
||||
|
||||
|
||||
11
globals.kl
11
globals.kl
@@ -21,16 +21,7 @@ Boolean: Bool = true
|
||||
//-----------------------------------------------------------------------------
|
||||
// Compound expressions
|
||||
//-----------------------------------------------------------------------------
|
||||
array1: [4]S64 = [4]S64(1,2,3,4)
|
||||
array2 := [32]S64(1,2,3,4)
|
||||
array3 := [32]S64(
|
||||
[0] = 0,
|
||||
[1] = 1,
|
||||
[2] = 2,
|
||||
[31] = 31,
|
||||
)
|
||||
array_item := array1[0]
|
||||
array_item_imp: S64 = array2[2]
|
||||
array1: [4]S64
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Pointers
|
||||
|
||||
11
main.cpp
11
main.cpp
@@ -201,17 +201,7 @@ int main(int argument_count, char **arguments){
|
||||
system((const char *)run_program.str);
|
||||
}
|
||||
else{
|
||||
String result = {};
|
||||
#if 1
|
||||
result = compile_file("globals.kl"_s);
|
||||
printf("%s", result.str);
|
||||
result = compile_file("enums.kl"_s);
|
||||
printf("%s", result.str);
|
||||
|
||||
|
||||
result = compile_file("new_types.kl"_s);
|
||||
printf("%s", result.str);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
Scratch scratch;
|
||||
@@ -221,6 +211,7 @@ int main(int argument_count, char **arguments){
|
||||
files.add("order2.kl"_s);
|
||||
files.add("new_types.kl"_s);
|
||||
files.add("enums.kl"_s);
|
||||
files.add("globals.kl"_s);
|
||||
String result = compile_files(files);
|
||||
printf("%s", result.str);
|
||||
__debugbreak();
|
||||
|
||||
@@ -321,7 +321,7 @@ parse_lambda(Token *token){
|
||||
|
||||
Ast_Expr *ret = parse_optional_type();
|
||||
Ast_Scope *scope = token_is(OPEN_SCOPE) ? parse_stmt_scope() : 0;
|
||||
Ast_Lambda *result = ast_lambda(token, params, has_var_args, ret, scope);
|
||||
Ast_Lambda *result = ast_lambda(token, params, ret, scope);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -496,6 +496,41 @@ resolve_stmt(Ast *ast, Ast_Resolved_Type *ret){
|
||||
}
|
||||
}
|
||||
|
||||
function Ast_Resolved_Type *
|
||||
resolve_lambda_type(Ast_Lambda *lambda){
|
||||
Scratch scratch;
|
||||
Ast_Resolved_Type *ret_type = resolve_typespec(lambda->ret, AST_CANT_BE_NULL);
|
||||
Array<Ast_Resolved_Type *> args = {scratch};
|
||||
|
||||
For(lambda->args){
|
||||
Ast_Resolved_Type *type = resolve_typespec(it->typespec, AST_CANT_BE_NULL);
|
||||
Operand default_value = resolve_expr(it->expr, AST_CAN_BE_NULL);
|
||||
make_sure_value_is_compatible_with_type(it->pos, &default_value, type, EXPR_CAN_BE_NULL);
|
||||
it->type = type;
|
||||
args.add(type);
|
||||
}
|
||||
|
||||
return type_lambda(lambda, ret_type, args);
|
||||
}
|
||||
|
||||
function void
|
||||
try_resolving_lambda_scope(Operand *op, Ast_Lambda *lambda, Ast_Resolved_Type *lambda_type){
|
||||
if(lambda->scope){
|
||||
For(lambda->args){
|
||||
insert_into_scope(lambda->scope, it);
|
||||
}
|
||||
For(lambda->scope->stmts){
|
||||
resolve_stmt(it, lambda_type->func.ret);
|
||||
}
|
||||
|
||||
*op = operand_lambda(lambda_type);
|
||||
}
|
||||
else if(is_flag_set(lambda->flags, AST_FOREIGN)){
|
||||
// @todo: Add foreign
|
||||
*op = operand_lambda(lambda_type);
|
||||
}
|
||||
}
|
||||
|
||||
function Operand
|
||||
resolve_cast(Ast_Cast *node){
|
||||
Operand expr = resolve_expr(node->expr, AST_CANT_BE_NULL);
|
||||
@@ -637,6 +672,14 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags){
|
||||
BREAK();
|
||||
}
|
||||
|
||||
CASE(LAMBDA_EXPR, Lambda){
|
||||
node->type = resolve_lambda_type(node);
|
||||
Operand result = operand_type(node->type);
|
||||
try_resolving_lambda_scope(&result, node, node->type);
|
||||
return result;
|
||||
BREAK();
|
||||
}
|
||||
|
||||
CASE(INDEX, Index){
|
||||
Operand left = resolve_expr(node->expr, AST_CANT_BE_NULL);
|
||||
Operand index = resolve_expr(node->index, AST_CANT_BE_NULL);
|
||||
@@ -811,45 +854,16 @@ resolve_decl(Ast_Decl *ast){
|
||||
switch(ast->kind){
|
||||
CASE(LAMBDA, Decl){
|
||||
Ast_Lambda *lambda = node->lambda;
|
||||
|
||||
Scratch scratch;
|
||||
Ast_Resolved_Type *lambda_type = 0;
|
||||
Ast_Resolved_Type *ret_type = resolve_typespec(lambda->ret, AST_CANT_BE_NULL);
|
||||
Array<Ast_Resolved_Type *> args = {scratch};
|
||||
|
||||
For(lambda->args){
|
||||
Ast_Resolved_Type *type = resolve_typespec(it->typespec, AST_CANT_BE_NULL);
|
||||
Operand default_value = resolve_expr(it->expr, AST_CAN_BE_NULL);
|
||||
make_sure_value_is_compatible_with_type(it->pos, &default_value, type, EXPR_CAN_BE_NULL);
|
||||
it->type = type;
|
||||
args.add(type);
|
||||
}
|
||||
|
||||
lambda_type = type_lambda(lambda, ret_type, args);
|
||||
Operand result = operand_type(lambda_type);
|
||||
lambda->type = resolve_lambda_type(lambda);
|
||||
Operand result = operand_type(lambda->type);
|
||||
|
||||
// @note: top level lambda needs to get marked as resolved
|
||||
// so that the cyclic dependency wont trigger
|
||||
node->type = lambda_type;
|
||||
node->type = lambda->type;
|
||||
node->state = DECL_RESOLVED;
|
||||
|
||||
// @todo: We also need to make sure there is a return value when ret type is not void
|
||||
// @note: then try resolving the block of lambda
|
||||
if(lambda->scope){
|
||||
For(lambda->args){
|
||||
insert_into_scope(lambda->scope, it);
|
||||
}
|
||||
For(lambda->scope->stmts){
|
||||
resolve_stmt(it, ret_type);
|
||||
}
|
||||
|
||||
result = operand_lambda(lambda_type);
|
||||
}
|
||||
else if(is_flag_set(lambda->flags, AST_FOREIGN)){
|
||||
// @todo: Add foreign
|
||||
result = operand_lambda(lambda_type);
|
||||
}
|
||||
|
||||
try_resolving_lambda_scope(&result, lambda, node->type);
|
||||
node->value = result.value;
|
||||
BREAK();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user