From b0077fe9dff39e99b2f5e09361d7e2c94964bd92 Mon Sep 17 00:00:00 2001 From: Krzosa Karol Date: Fri, 10 Jun 2022 10:35:10 +0200 Subject: [PATCH] Basic resolving, codegen with packages --- ast.cpp | 96 ++++++------ ccodegen.cpp | 371 +++++++++++++++++++++++++++-------------------- compiler.h | 2 +- main.cpp | 5 +- order1.kl | 6 +- parsing.cpp | 49 ++++--- typechecking.cpp | 367 ++++++++++++++++++++++++++++++---------------- typechecking.h | 89 +++--------- types.h | 1 + 9 files changed, 553 insertions(+), 433 deletions(-) diff --git a/ast.cpp b/ast.cpp index 044dc53..7bddd37 100644 --- a/ast.cpp +++ b/ast.cpp @@ -17,6 +17,7 @@ enum Ast_Kind: U32{ AST_CALL_ITEM, AST_CALL, + AST_TYPE, AST_VAR, AST_CONST, AST_POINTER, @@ -73,6 +74,7 @@ struct Value{VALUE_FIELDS}; // BigInt big_int_val; struct Ast_Atom: Ast_Expr{ + Ast_Decl *resolved_decl; INLINE_VALUE_FIELDS; }; @@ -91,7 +93,8 @@ struct Ast_Call: Ast_Expr{ struct Ast_Unary: Ast_Expr{ Token_Kind op; Ast_Expr *expr; - U64 padding[3]; // For folding constants into atoms + Ast_Resolved_Type *type; + U64 padding[2]; // For folding constants into atoms }; struct Ast_Cast: Ast_Expr{ @@ -116,19 +119,13 @@ struct Ast_Binary: Ast_Expr{ // look into global scope and to the locals list. // -struct Ast_Block : Ast { - // Stmts for global scope - Array stmts; - // Array members; -}; - struct Ast_Return: Ast{ Ast_Expr *expr; }; struct Ast_If_Node: Ast{ Ast_Expr *expr ; - Ast_Block *block; + Ast_Scope *scope; Ast_Binary*init; }; @@ -142,20 +139,14 @@ struct Ast_For: Ast{ Ast_Expr *init; Ast_Expr *cond; Ast_Expr *iter; - Ast_Block *block; -}; - -struct Ast_Lambda_Arg: Ast_Expr{ - Intern_String name; - Ast_Expr *typespec; - Ast_Expr *default_value; + Ast_Scope *scope; }; struct Ast_Lambda : Ast_Expr { - Array args; - Ast_Expr *ret; - Ast_Block *block; - B32 has_var_args; + Array args; + Ast_Expr *ret; + Ast_Scope *scope; + B32 has_var_args; }; struct Ast_Array: Ast_Expr{ @@ -190,7 +181,6 @@ enum Ast_Decl_State{ struct Ast_Decl; struct Ast_Scope: Ast{ - Array resolved; Array decls; Array stmts; }; @@ -201,8 +191,11 @@ struct Ast_Decl: Ast{ Intern_String name; Ast_Scope *scope; - Ast_Expr *expr; Ast_Expr *typespec; + union{ + Ast_Expr *expr; + Ast_Lambda *lambda; + }; INLINE_VALUE_FIELDS; }; @@ -339,41 +332,21 @@ ast_expr_index(Token *pos, Ast_Expr *expr, Ast_Expr *index){ } function Ast_Lambda * -ast_lambda(Token *pos, Array params, B32 has_var_args, Ast_Expr *ret, Ast_Block *block){ +ast_lambda(Token *pos, Array params, B32 has_var_args, Ast_Expr *ret, Ast_Scope *scope){ AST_NEW(Lambda, LAMBDA, pos, AST_EXPR); result->flags = AST_EXPR; result->args = params.tight_copy(pctx->perm); - result->block = block; + result->scope = scope; result->ret = ret; result->has_var_args = has_var_args; if(!ret) result->ret = ast_ident(result->pos, intern_void); - if(result->block) result->block->parent = result; + if(result->scope) result->scope->parent = result; result->ret->parent = result; For(result->args) it->parent = result; return result; } -function Ast_Lambda_Arg * -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; -} - -function Ast_Block * -ast_block(Token *pos, Array stmts){ - AST_NEW(Block, BLOCK, pos, AST_STMT); - result->stmts = stmts.tight_copy(pctx->perm); - For(result->stmts) it->parent = result; - return result; -} - function Ast_If * ast_if(Token *pos, Array ifs){ AST_NEW(If, IF, pos, AST_STMT); @@ -383,16 +356,16 @@ ast_if(Token *pos, Array ifs){ } function Ast_For * -ast_for(Token *pos, Ast_Expr *init, Ast_Expr *cond, Ast_Expr *iter, Ast_Block *block){ +ast_for(Token *pos, Ast_Expr *init, Ast_Expr *cond, Ast_Expr *iter, Ast_Scope *scope){ AST_NEW(For, FOR, pos, AST_STMT); result->init = init; result->cond = cond; result->iter = iter; - result->block = block; + result->scope = scope; if(result->init) result->init->parent = result; if(result->cond) result->cond->parent = result; if(result->iter) result->iter->parent = result; - result->block->parent = result; + result->scope->parent = result; return result; } @@ -414,15 +387,15 @@ ast_return(Token *pos, Ast_Expr *expr){ } function Ast_If_Node * -ast_if_node(Token *pos, Ast_Expr *init, Ast_Expr *expr, Ast_Block *block){ +ast_if_node(Token *pos, Ast_Expr *init, Ast_Expr *expr, Ast_Scope *scope){ AST_NEW(If_Node, IF_NODE, pos, AST_STMT); - result->block = block; + result->scope = scope; result->expr = expr; result->init = (Ast_Binary *)init; - if(result->block) result->block->parent = result; + if(result->scope) result->scope->parent = result; if(result->expr) result->expr->parent = result; if(result->init) { - assert(init->kind == AST_BINARY); + assert(init->kind == AST_VAR); result->init->parent = result; } return result; @@ -440,7 +413,6 @@ function Ast_Scope * ast_decl_scope(Token *pos, Array decls){ AST_NEW(Scope, SCOPE, pos, AST_DECL); result->decls = decls.tight_copy(pctx->perm); - result->resolved = array_make(pctx->perm, result->decls.len); For(result->decls){ it->parent = result; } @@ -451,6 +423,7 @@ function Ast_Scope * ast_stmt_scope(Token *pos, Array stmts){ AST_NEW(Scope, SCOPE, pos, AST_STMT); result->stmts = stmts.tight_copy(pctx->perm); + result->decls = {pctx->heap}; For(result->stmts){ it->parent = result; } @@ -486,6 +459,14 @@ ast_var(Token *pos, Ast_Expr *typespec, Intern_String name, Ast_Expr *expr){ return result; } +function Ast_Decl * +ast_const(Token *pos, Intern_String name, Value value){ + AST_NEW(Decl, CONST, pos, AST_DECL); + result->value = value; + result->name = name; + return result; +} + function Ast_Decl * ast_const(Token *pos, Intern_String name, Ast_Expr *expr){ AST_NEW(Decl, CONST, pos, AST_DECL); @@ -495,13 +476,22 @@ ast_const(Token *pos, Intern_String name, Ast_Expr *expr){ return result; } +function Ast_Decl * +ast_type(Token *pos, Intern_String name, Ast_Resolved_Type *type){ + AST_NEW(Decl, CONST, pos, AST_DECL); + result->type = type_type; + result->type_val = type; + result->name = name; + return result; +} + function Ast_Package ast_package(Allocator *allocator, Intern_String name, Array decls){ Ast_Package result = {}; result.kind = AST_PACKAGE; result.decls = decls.copy(allocator); - result.resolved = {allocator}; result.name = name; + For(result.decls) it->parent = &result; return result; } diff --git a/ccodegen.cpp b/ccodegen.cpp index 0c54aae..a07f399 100644 --- a/ccodegen.cpp +++ b/ccodegen.cpp @@ -26,7 +26,7 @@ gen_simple_decl_prefix(Ast_Resolved_Type *ast){ case TYPE_LAMBDA:break; case TYPE_ENUM: case TYPE_STRUCT: { - auto constant = (Ast_Const *)ast->ast->parent; + auto constant = (Ast_Decl *)ast->ast; auto name = constant->name; gen("%s ", name.str); }break; @@ -98,60 +98,58 @@ gen_expr(Ast_Expr *ast){ BREAK(); } - CASE(INDEX, Index){ - Sym *sym = resolved_get(node); - if(is_array(sym->type)){ - gen("("); - gen("("); + // CASE(INDEX, Index){ + // Sym *sym = resolved_get(node); + // if(is_array(sym->type)){ + // gen("("); + // gen("("); - gen("("); - gen_simple_decl(sym->type->arr.base, {}); - gen("*)"); - gen_expr(node->expr); - gen(".data)"); + // gen("("); + // gen_simple_decl(sym->type->arr.base, {}); + // gen("*)"); + // gen_expr(node->expr); + // gen(".data)"); - gen("["); - gen_expr(node->index); - gen("]"); - gen(")"); - } else{ - gen("("); - gen_expr(node->expr); - gen("["); - gen_expr(node->index); - gen("]"); - gen(")"); - } - BREAK(); - } + // gen("["); + // gen_expr(node->index); + // gen("]"); + // gen(")"); + // } else{ + // gen("("); + // gen_expr(node->expr); + // gen("["); + // gen_expr(node->index); + // gen("]"); + // gen(")"); + // } + // BREAK(); + // } CASE(BINARY, Binary){ - if(node->op == TK_Dot){ - Sym *sym = resolved_get(node->left); - gen_expr(node->left); - if(sym->type->kind == TYPE_POINTER) gen("->"); - else gen("."); - gen_expr(node->right); - } - else if(node->op == TK_ColonAssign){ + // if(node->op == TK_Dot){ + // Sym *sym = resolved_get(node->left); + // gen_expr(node->left); + // if(sym->type->kind == TYPE_POINTER) gen("->"); + // else gen("."); + // gen_expr(node->right); + // } + // else if(node->op == TK_ColonAssign){ - Sym *sym = resolved_get(node); - Ast_Atom *atom = (Ast_Atom *)node->left; - assert(is_atom(atom)); - gen_simple_decl(sym->type, atom->intern_val); - if(node->right){ - gen(" = "); - gen_expr(node->right); - } - } - else{ - if(!token_is_assign(node->op)) gen("("); - gen_expr(node->left); - gen("%s", name(node->op)); - gen_expr(node->right); - if(!token_is_assign(node->op)) gen(")"); - } + // Sym *sym = resolved_get(node); + // Ast_Atom *atom = (Ast_Atom *)node->left; + // assert(is_atom(atom)); + // gen_simple_decl(sym->type, atom->intern_val); + // if(node->right){ + // gen(" = "); + // gen_expr(node->right); + // } + // } + if(!token_is_assign(node->op)) gen("("); + gen_expr(node->left); + gen("%s", name(node->op)); + gen_expr(node->right); + if(!token_is_assign(node->op)) gen(")"); BREAK(); } @@ -164,15 +162,15 @@ gen_expr(Ast_Expr *ast){ BREAK(); } - CASE(CAST, Cast){ - gen("("); - gen("("); - gen_simple_decl(resolved_type_get(node->typespec), {}); - gen(")"); - gen_expr(node->expr); - gen(")"); - BREAK(); - } + // CASE(CAST, Cast){ + // gen("("); + // gen("("); + // gen_simple_decl(resolved_type_get(node->typespec), {}); + // gen(")"); + // gen_expr(node->expr); + // gen(")"); + // BREAK(); + // } CASE(CALL, Call){ // @todo: Reach into map instead of direct lookup @@ -242,10 +240,10 @@ gen_line(Ast *node){ function void gen_ast(Ast *ast); function void -gen_block(Ast_Block *block){ +gen_stmt_scope(Ast_Scope *scope){ gen("{"); global_indent++; - For(block->stmts) { + For(scope->stmts) { gen_line(it); genln(""); gen_ast(it); @@ -292,17 +290,6 @@ function void gen_ast(Ast *ast){ switch(ast->kind){ - CASE(PACKAGE, Package){ - if(emit_line_directives) - genln("#line 0 \"%s\"", node->name.str); - For(node->ordered) { - gen_line(it); - genln(""); - gen_ast(it); - } - BREAK(); - } - CASE(RETURN, Return){ gen("return"); if(node->expr){ @@ -313,9 +300,8 @@ gen_ast(Ast *ast){ BREAK(); } - CASE(VAR, Var){ - Sym *sym = resolved_get(node); - gen_var(sym->name, sym->type, node->expr, is_inside_struct ? DONT_EMIT_VALUE : ALWAYS_EMIT_VALUE); + CASE(VAR, Decl){ + gen_var(node->name, node->type, node->expr, is_inside_struct ? DONT_EMIT_VALUE : ALWAYS_EMIT_VALUE); gen(";"); BREAK(); } @@ -327,7 +313,7 @@ gen_ast(Ast *ast){ gen("if("); gen_expr(it->expr); gen(")"); - gen_block(it->block); + gen_stmt_scope(it->scope); } else{ genln("else"); @@ -336,7 +322,7 @@ gen_ast(Ast *ast){ gen_expr(it->expr); gen(")"); } - gen_block(it->block); + gen_stmt_scope(it->scope); } } BREAK(); @@ -362,113 +348,116 @@ gen_ast(Ast *ast){ gen(";"); if(node->iter) gen_expr(node->iter); gen(")"); - gen_block(node->block); + gen_stmt_scope(node->scope); BREAK(); } - CASE(CONST, Const){ - Sym *sym = resolved_get(node); + 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(")"); - switch(sym->type->kind){ + if(lambda->scope) { + // gen_stmt_scope(lambda->scope); + // @todo stmts + } + else gen(";"); + } + else{ + gen_simple_decl(node->type, node->name); + gen(" = "); + gen_expr((Ast_Expr *)node->expr); + gen(";"); + } + BREAK(); + } + + CASE(CONST, Decl){ + switch(node->type->kind){ CASE_FLOAT:{ gen("// F64 %s = ", node->name.str); - gen_value(sym->value); + gen_value(node->value); } break; CASE_INT:{ gen("// constant int %s = ", node->name.str); - gen_value(sym->value); + gen_value(node->value); }break; CASE_STRING:{ gen("// const String %s = ", node->name.str); - gen_value(sym->value); + gen_value(node->value); }break; CASE_BOOL:{ gen("// const Bool %s = ", node->name.str); - gen_value(sym->value); + gen_value(node->value); }break; case TYPE_LAMBDA:{ - if(node->value->kind == AST_LAMBDA){ - if(is_flag_set(node->flags, AST_FOREIGN)){ - return; - } - Ast_Lambda *lambda = (Ast_Lambda *)node->value; - Ast_Resolved_Type *ret = resolved_type_get(lambda->ret); - gen_simple_decl(ret, node->name); - gen("("); - For(lambda->args){ - assert(it->kind == AST_LAMBDA_ARG); - Ast_Resolved_Type *type = resolved_type_get(it->typespec); - gen_var(it->name, type, 0, DONT_EMIT_VALUE); - if(&it != (lambda->args.end() - 1)) gen(", "); - } - gen(")"); - if(lambda->block) { - gen_block(lambda->block); - } - else gen(";"); - } - else{ - gen_simple_decl(sym->type, node->name); - gen(" = "); - gen_expr((Ast_Expr *)node->value); - gen(";"); - } }break; case TYPE_TYPE:{ - if(sym->type_val->kind == TYPE_STRUCT){ - Ast_Struct *agg = (Ast_Struct *)sym->type_val->ast; - if(node->value->kind == AST_STRUCT){ - gen("typedef struct %s{", node->name.str); - global_indent++; - is_inside_struct++; - For(agg->members){ - genln(""); - gen_ast(it); - } - - For(agg->const_members){ - genln(""); - gen_ast(it); - } - is_inside_struct--; - global_indent--; - genln("}%s;", node->name.str); - } - else{ - // Type alias - } - } - else if(sym->type_val->kind == TYPE_ENUM){ - Ast_Enum *enu = (Ast_Enum *)sym->type_val->ast; - assert(enu->kind == AST_ENUM); - if(node->value->kind == AST_ENUM){ - gen("/*enum %s{", node->name.str); - // @todo add typespec - global_indent++; - For(enu->members){ - genln("%s", it->name.str); - gen(" = "); - Sym *value_sym = resolved_get(it); - gen("%d", bigint_as_signed(&value_sym->big_int_val)); - gen(","); - } - global_indent--; - genln("};*/"); - } - else{ - // Type alias - } - } - else{ - gen("// typedef "); - gen_simple_decl(sym->type_val, node->name); - gen(";"); - } }break; - default: compiler_error(node->pos, "C_Codegen: Unhandled type %s of constant expression", docname(sym->type)); + // if(sym->type_val->kind == TYPE_STRUCT){ + // Ast_Struct *agg = (Ast_Struct *)sym->type_val->ast; + // if(node->value->kind == AST_STRUCT){ + // gen("typedef struct %s{", node->name.str); + // global_indent++; + // is_inside_struct++; + // For(agg->members){ + // genln(""); + // gen_ast(it); + // } + + // For(agg->const_members){ + // genln(""); + // gen_ast(it); + // } + // is_inside_struct--; + // global_indent--; + // genln("}%s;", node->name.str); + // } + // else{ + // // Type alias + // } + // } + // else if(sym->type_val->kind == TYPE_ENUM){ + // Ast_Enum *enu = (Ast_Enum *)sym->type_val->ast; + // assert(enu->kind == AST_ENUM); + // if(node->value->kind == AST_ENUM){ + // gen("/*enum %s{", node->name.str); + // // @todo add typespec + // global_indent++; + // For(enu->members){ + // genln("%s", it->name.str); + // gen(" = "); + // Sym *value_sym = resolved_get(it); + // gen("%d", bigint_as_signed(&value_sym->big_int_val)); + // gen(","); + // } + // global_indent--; + // genln("};*/"); + // } + // else{ + // // Type alias + // } + // } + // else{ + // gen("// typedef "); + // gen_simple_decl(sym->type_val, node->name); + // gen(";"); + // } + // }break; + default: compiler_error(node->pos, "C_Codegen: Unhandled type %s of constant expression", docname(node->type)); } BREAK(); @@ -482,6 +471,7 @@ gen_ast(Ast *ast){ } } +#if 0 function String compile_string(String filecontent, String filename = "default_name"_s){ F64 total_time = os_time(); @@ -574,3 +564,64 @@ compile_file(String filename){ String result = compile_string(filecontent, filename); return result; } +#endif + + +function String +compile_files(Array filename){ + Scratch scratch(thread_ctx.scratch); + Array files = {scratch}; + + For(filename){ + String filecontent = os_read_file(scratch, it); + assert(filecontent.len); + files.add(ast_file(it, filecontent)); + } + + F64 total_time = os_time(); + OS_Heap heap = win32_os_heap_create(false, mib(16), 0); + + Parse_Ctx ctx = {}; + parse_init(&ctx, scratch, &heap); + + F64 parse_begin = os_time(); + Array packages = {&heap}; + For(files){ + parse_file(&it); + + Ast_Package *package = find_package(it.name, &packages); + if(package){ + package->decls.add(it.decls); + } else { + Ast_Package p = ast_package(&heap, it.name, it.decls); + insert_builtin_types_into_package(&p); + packages.add(p); + } + + } + F64 parse_end = os_time(); + + For(packages){ + resolve_package(&it); + } + + For(pctx->ordered_decls){ + genln(""); + gen_ast(it); + } + + exp_destroy(&heap); + + + F64 flattening_begin = os_time(); + String string_result = string_flatten(scratch, &pctx->gen); + F64 flattening_end = os_time(); + + printf("\n//-------------------------------"); + printf("\n// Parse : %f", parse_end - parse_begin); + printf("\n// Flattening : %f", flattening_end - flattening_begin); + printf("\n// Total : %f", flattening_end - total_time); + printf("\n//-------------------------------"); + + return string_result; +} diff --git a/compiler.h b/compiler.h index cf5c348..0dc6902 100644 --- a/compiler.h +++ b/compiler.h @@ -116,6 +116,7 @@ struct Token{ S32 line; U8 *line_begin; }; +global Token null_token; struct Lex_Stream{ String stream; @@ -179,7 +180,6 @@ struct Parse_Ctx:Lexer{ Ast_Package *resolving_package; Array ordered_decls; - Token empty_token; S64 indent; String_Builder gen; }; diff --git a/main.cpp b/main.cpp index 85acf65..2c5453c 100644 --- a/main.cpp +++ b/main.cpp @@ -164,7 +164,7 @@ Expr: #include "parsing.cpp" #include "typechecking.h" #include "typechecking.cpp" -// #include "ccodegen.cpp" +#include "ccodegen.cpp" #include "tests.cpp" int main(int argument_count, char **arguments){ @@ -221,6 +221,7 @@ int main(int argument_count, char **arguments){ Array files = {scratch}; files.add("lambdas.kl"_s); files.add("order1.kl"_s); - compile_files(files); + String result = compile_files(files); + printf("%s", result.str); __debugbreak(); } diff --git a/order1.kl b/order1.kl index 7f1b96c..b8da11f 100644 --- a/order1.kl +++ b/order1.kl @@ -1,12 +1,12 @@ package lambdas -other_func :: () - a_val := recursive_lambda - recursive_lambda :: (thing: S64) in_val := recursive_lambda some_value := thing + const_in_lambda +other_func :: () + a_val := recursive_lambda + const_in_lambda :: 10 not_const := val + 10 diff --git a/parsing.cpp b/parsing.cpp index b027044..0943982 100644 --- a/parsing.cpp +++ b/parsing.cpp @@ -33,7 +33,7 @@ function Token * token_get(S64 i = 0){ i += pctx->token_iter; if(i >= pctx->tokens.len){ - return &pctx->empty_token; + return &null_token; } Token *result = &pctx->tokens[i]; return result; @@ -122,10 +122,18 @@ parse_init_stmt(Ast_Expr *expr){ if(token->kind == TK_ColonAssign && expr->kind != AST_IDENT) compiler_error(expr->pos, "Binding with [:=] to something that is not an identifier"); - if(token_is_assign(token)){ + + + else if(token_is_assign(token)){ token_next(); - Ast_Expr *value = parse_expr(); - Ast_Expr *result = ast_expr_binary((Ast_Atom *)expr, value, token); + Ast_Expr *value = parse_expr(); + Ast_Expr *result = 0; + if(token->kind == TK_ColonAssign){ + Ast_Atom *name = (Ast_Atom *)expr; + result = (Ast_Expr *)ast_var(token, 0, name->intern_val, value); + } else{ + result = ast_expr_binary((Ast_Atom *)expr, value, token); + } result->flags = set_flag(result->flags, AST_STMT); return result; } @@ -176,9 +184,9 @@ parse_optional_type(){ return result; } -function Ast_Block * -parse_block(){ - Ast_Block *block = 0; +function Ast_Scope * +parse_stmt_scope(){ + Ast_Scope *block = 0; if(token_expect(OPEN_SCOPE)){ // @todo: Fix error message here, it doesn't show proper token context Token *token_block = token_get(); @@ -218,7 +226,7 @@ parse_block(){ } } - Ast_Block *for_block = parse_block(); + Ast_Scope *for_block = parse_stmt_scope(); stmts.add(ast_for(token, init, cond, iter, for_block)); } @@ -232,7 +240,7 @@ parse_block(){ } if(init_val == expr) init_val = 0; - Ast_Block *if_block = parse_block(); + Ast_Scope *if_block = parse_stmt_scope(); Ast_If_Node *if_node = ast_if_node(token, init_val, expr, if_block); if_nodes.add(if_node); @@ -241,12 +249,12 @@ parse_block(){ token = token_next(); if(token_match_keyword(keyword_if)){ Ast_Expr *expr = parse_expr(); - Ast_Block *else_if_block = parse_block(); + Ast_Scope *else_if_block = parse_stmt_scope(); Ast_If_Node *if_node = ast_if_node(token, 0, expr, else_if_block); if_nodes.add(if_node); } else{ - Ast_Block *else_block = parse_block(); + Ast_Scope *else_block = parse_stmt_scope(); Ast_If_Node *if_node = ast_if_node(token, 0, 0, else_block); if_nodes.add(if_node); break; @@ -274,7 +282,7 @@ parse_block(){ } } while(token_match(SAME_SCOPE)); token_expect(CLOSE_SCOPE); - block = ast_block(token_block, stmts); + block = ast_stmt_scope(token_block, stmts); } return block; } @@ -284,7 +292,7 @@ parse_lambda(Token *token){ Scratch scratch; B32 has_var_args = false; - Array params = {scratch}; + Array params = {scratch}; if(!token_is(TK_CloseParen)){ for(;;){ Token *name = token_get(); @@ -297,7 +305,7 @@ parse_lambda(Token *token){ default_value = parse_expr(); } - Ast_Lambda_Arg *param = ast_expr_lambda_arg(name, name->intern_val, typespec, default_value); + Ast_Decl *param = ast_var(name, typespec, name->intern_val, default_value); params.add(param); } else if(token_match(TK_ThreeDots)){ @@ -313,8 +321,8 @@ parse_lambda(Token *token){ token_expect(TK_CloseParen); Ast_Expr *ret = parse_optional_type(); - Ast_Block *block = token_is(OPEN_SCOPE) ? parse_block() : 0; - Ast_Lambda *result = ast_lambda(token, params, has_var_args, ret, block); + Ast_Scope *scope = token_is(OPEN_SCOPE) ? parse_stmt_scope() : 0; + Ast_Lambda *result = ast_lambda(token, params, has_var_args, ret, scope); return result; } @@ -570,10 +578,17 @@ parse_decl(B32 is_global){ result = parse_enum(tname); } - // @note parse constant expression else{ Ast_Expr *expr = parse_expr(); result = ast_const(tname, tname->intern_val, expr); + + if(expr->kind == AST_LAMBDA){ + auto a = (Ast_Lambda *)expr; + if(a->scope){ + result->kind = AST_LAMBDA; + } + } + } } else if(token_match(TK_Identifier, TK_Colon)){ diff --git a/typechecking.cpp b/typechecking.cpp index 91610c7..b16e09b 100644 --- a/typechecking.cpp +++ b/typechecking.cpp @@ -1,7 +1,6 @@ #define CASE(kind,type) case AST_##kind: { Ast_##type *node = (Ast_##type *)ast; #define BREAK() } break - //----------------------------------------------------------------------------- // Evaluating constant expressions //----------------------------------------------------------------------------- @@ -313,16 +312,6 @@ _rewrite_into_const(Ast *node, U64 ast_size, Value value){ } #if 0 -function Ast_Resolved_Type * -resolve_typespec(Ast_Expr *ast, B32 ast_can_be_null){ - if(ast_can_be_null && ast == 0) - return 0; - - Operand resolved = resolve_expr(ast); - if(resolved.type != type_type) - compiler_error(ast->pos, "Expected [Type] got instead %s", type_names[resolved.type->kind]); - return resolved.type_val; -} function Operand require_const_int(Ast_Expr *expr, B32 ast_can_be_null){ @@ -916,18 +905,7 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- - else{ - Operand left = resolve_expr(node->left); - Operand right = resolve_expr(node->right); - B32 is_const = left.is_const && right.is_const; - Value value = eval_binary(node->pos, node->op, left.value, right.value, is_const); - if(is_const){ - rewrite_into_const(node, Ast_Binary, value); - result = operand_const_rvalue(value); - } - else result = operand_rvalue(value.type); - } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- @@ -942,35 +920,6 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res invalid_return; } -function Operand -resolve_const(Ast_Expr *ast, Sym *sym){ - -} - -function Operand -resolve_binding(Ast *ast, Sym *sym){ - switch(ast->kind){ - CASE(VAR, Var){ - Ast_Resolved_Type *type = resolve_typespec(node->typespec, AST_CAN_BE_NULL); - Operand expr = resolve_expr(node->expr, type); - assert(expr.type != 0 || type != 0); - make_sure_value_is_compatible_with_type(node->pos, &expr, type, EXPR_CAN_BE_NULL|TYPE_CAN_BE_NULL); - assert(expr.type); - return expr; - BREAK(); - } - - CASE(CONST, Const){ - Operand expr = resolve_const((Ast_Expr *)node->value, sym); - if(!expr.is_const) compiler_error(node->pos, "Value of constant variable is not a constant expression"); - assert(expr.type); - return expr; - BREAK(); - } - invalid_default_case; return {}; - } -} - #endif #define Enter_Scope(x) Enter_Scope_Defer package_scope(x) @@ -1011,6 +960,178 @@ search_for_decl_in_current_context(Intern_String name){ return result; } +function void +insert_into_scope(Ast_Scope *scope, Ast_Decl *decl){ + scope->decls.add(decl); +} + +function void +insert_into_current_scope(Ast_Decl *decl){ + insert_into_scope(pctx->current_scope, decl); +} + +function void +insert_type_into_package(Ast_Package *p, String name, Ast_Resolved_Type *type){ + Intern_String string = pctx->intern(name); + Ast_Decl *decl = ast_type(&null_token, string, type); + decl->state = DECL_RESOLVED; + insert_into_scope(p, decl); +} + +function void +insert_builtin_types_into_package(Ast_Package *p){ + insert_type_into_package(p, "void"_s , type_void); + insert_type_into_package(p, "Bool"_s , type_bool); + insert_type_into_package(p, "String"_s, type_string); + insert_type_into_package(p, "S8"_s, type_s8); + insert_type_into_package(p, "S16"_s, type_s16); + insert_type_into_package(p, "S32"_s, type_s32); + insert_type_into_package(p, "S64"_s, type_s64); + insert_type_into_package(p, "U8"_s, type_u8); + insert_type_into_package(p, "U16"_s, type_u16); + insert_type_into_package(p, "U32"_s, type_u32); + insert_type_into_package(p, "U64"_s, type_u64); + insert_type_into_package(p, "F32"_s, type_f32); + insert_type_into_package(p, "F64"_s, type_f64); +} + +function Ast_Resolved_Type * +resolve_typespec(Ast_Expr *ast, B32 flags){ + if(!ast && flags == AST_CAN_BE_NULL) + return 0; + + Operand resolved = resolve_expr(ast, flags); + if(resolved.type != type_type) + compiler_error(ast->pos, "Expected [Type] got instead %s", type_names[resolved.type->kind]); + return resolved.type_val; +} + +function Operand +require_const_int(Ast_Expr *expr, B32 flags){ + Operand op = resolve_expr(expr, flags); + + if(expr == 0 && flags) + return op; + else if(expr == 0) + compiler_error(expr->pos, "This field cannot be null"); + + if(!op.is_const) + compiler_error(expr->pos, "Expected a const value"); + if(!is_int(op.type)) + compiler_error(expr->pos, "Expected a constant integer got instead %s", docname(op.type)); + + return op; +} + +function void +resolve_var(Ast_Decl *node){ + Ast_Resolved_Type *type = resolve_typespec(node->typespec, AST_CAN_BE_NULL); + Operand op = resolve_expr(node->expr, AST_CAN_BE_NULL); + assert(op.type != 0 || type != 0); + + make_sure_value_is_compatible_with_type(node->pos, &op, type, EXPR_CAN_BE_NULL|TYPE_CAN_BE_NULL); + node->value = op.value; +} + +function Operand +resolve_expr(Ast_Expr *ast, B32 flags){ + if(!ast && flags == AST_CAN_BE_NULL) return {}; + assert(is_flag_set(ast->flags, AST_EXPR)); + + + switch(ast->kind){ + + CASE(VALUE, Atom){ + return operand_const_rvalue(node->value); + BREAK(); + } + + CASE(IDENT, Atom){ + Ast_Decl *decl = resolve_name(node->pos, node->intern_val); + + node->resolved_decl = decl; + if(decl->kind == AST_CONST){ + // @note + // There might be some problem with types getting rewritten + // I would like decls to be resolved to be of AST_TYPE ?? + // + // assert(decl->value.type != type_type); + // assert(!is_lambda(decl->value.type)); + rewrite_into_const(node, Ast_Atom, decl->value); + } + + + return operand(decl); + BREAK(); + } + + CASE(VAR, Decl){ + resolve_var(node); + insert_into_current_scope(node); + BREAK(); + } + + CASE(BINARY, Binary){ + if(token_is_assign(node->op)){ + assert(is_flag_set(node->flags, AST_STMT)); + Operand left = resolve_expr(node->left, AST_CANT_BE_NULL); + if(!left.is_lvalue) compiler_error(node->pos, "Assigning to rvalue"); + Operand right = resolve_expr(node->right, AST_CANT_BE_NULL); + + right.value = convert_untyped_to_typed(node->pos, right.value, left.type); + if(left.type != right.type) compiler_error(node->pos, "Can't assign value when left is %s and right is %s", docname(left.type), docname(right.type)); + return {}; + } + else{ + Operand left = resolve_expr(node->left, AST_CANT_BE_NULL); + Operand right = resolve_expr(node->right, AST_CANT_BE_NULL); + B32 is_const = left.is_const && right.is_const; + Value value = eval_binary(node->pos, node->op, left.value, right.value, is_const); + if(is_const){ + rewrite_into_const(node, Ast_Binary, value); + return operand_const_rvalue(value); + } + else return operand_rvalue(value.type); + + } + BREAK(); + } + + CASE(UNARY, Unary){ + Operand value = resolve_expr(node->expr, AST_CANT_BE_NULL); + if(node->op == TK_Pointer){ + if(value.type->kind == TYPE_POINTER){ + node->type = value.type->base; + return operand_lvalue(node->type); + } + else if(value.type->kind == TYPE_TYPE){ + node->type = type_pointer(value.type_val); + return operand_type(node->type); + } + else{ compiler_error(node->pos, "Dereferencing expression %s that is not a [Pointer] or [Type]", type_names[value.type->kind]); return {}; } + } + else if(node->op == TK_Dereference){ + node->type = type_pointer(value.type); + return operand_lvalue(node->type); + } + else{ + eval_unary(node->pos, node->op, &value); + if(value.is_const){ + rewrite_into_const(node, Ast_Unary, value.value); + return operand_const_rvalue(value.value); + } + return operand_rvalue(value.value.type); + } + + BREAK(); + } + + invalid_default_case; + } + + invalid_return; +} + function void resolve_decl(Ast_Decl *ast){ if(ast->state == DECL_RESOLVED){ @@ -1024,47 +1145,90 @@ resolve_decl(Ast_Decl *ast){ ast->state = DECL_RESOLVING; { - Operand result = {}; switch(ast->kind){ CASE(LAMBDA, Decl){ - // return resolve_lambda(node, sym); + 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 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); + + // @note: top level lambda needs to get marked as resolved + // so that the cyclic dependency wont trigger + 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){ + Enter_Scope(lambda->scope); + For(lambda->args){ + insert_into_current_scope(it); + } + For(lambda->scope->stmts){ + unused(it); + // resolve_stmt(it, ret_type); + } + + result = operand_lambda(lambda_type); + } + else if(is_flag_set(lambda->parent->flags, AST_FOREIGN)){ + result = operand_lambda(lambda_type); + } + BREAK(); + } + + CASE(CONST, Decl){ + Operand op = resolve_expr(node->expr, AST_CANT_BE_NULL); + if(!op.is_const){ + compiler_error(node->pos, "Assigning a value that is not constant to a constant declaration"); + } + node->value = op.value; + BREAK(); + } + + CASE(VAR, Decl){ + resolve_var(node); BREAK(); } CASE(ENUM, Decl){ - // Ast_Resolved_Type *type = type_enum(node); - // S64 scope_index = scope_open(); - // S64 value = 0; - // For(node->members){ - // Operand op = require_const_int(it->value, AST_CAN_BE_NULL); - // if(op.type){ - // value = bigint_as_signed(&op.big_int_val) + 1; - // } - // else{ - // op.type = untyped_int; - // bigint_init_signed(&op.big_int_val, value++); - // } + node->type = type_enum(node); + Enter_Scope(node->scope); + S64 value = 0; + For(node->scope->decls){ + Operand op = {}; + if(it->expr){ + op = require_const_int(it->expr, AST_CANT_BE_NULL); + value = bigint_as_signed(&op.big_int_val) + 1; + } else{ + op.type = untyped_int; + bigint_init_signed(&op.big_int_val, value++); + } - // sym_const(it->name, op, it, INSERT_INTO_SCOPE); - // } - // scope_close(scope_index); - // return operand_type(type); + it->value = op.value; + } BREAK(); } - CASE(STRUCT, Decl){ - // Ast_Resolved_Type *type = type_struct(node); - // return operand_type(type); - BREAK(); - } invalid_default_case; } - // Operand op = resolve_binding(ast->ast, ast); - // ast->value = op.value; + } ast->state = DECL_RESOLVED; - pctx->resolving_package->resolved.add(ast); + pctx->ordered_decls.add(ast); } function Ast_Decl * @@ -1081,7 +1245,7 @@ resolve_package(Ast_Package *package){ For(package->decls){ resolve_name(it->pos, it->name); if(it->kind == AST_STRUCT){ - // type_complete(it->type); + type_complete(it->type); } } } @@ -1140,50 +1304,3 @@ find_package(Intern_String name, Array *packages){ } return 0; } - -function String -compile_files(Array filename){ - Scratch scratch(thread_ctx.scratch); - Array files = {scratch}; - - For(filename){ - String filecontent = os_read_file(scratch, it); - assert(filecontent.len); - files.add(ast_file(it, filecontent)); - } - - F64 total_time = os_time(); - OS_Heap heap = win32_os_heap_create(false, mib(16), 0); - - Parse_Ctx ctx = {}; - parse_init(&ctx, scratch, &heap); - - F64 parse_begin = os_time(); - Array packages = {&heap}; - For(files){ - parse_file(&it); - - Ast_Package *package = find_package(it.name, &packages); - if(package){ - package->decls.add(it.decls); - } else { - packages.add(ast_package(&heap, it.name, it.decls)); - } - - } - F64 parse_end = os_time(); - - For(packages){ - resolve_package(&it); - } - - exp_destroy(&heap); - F64 flattening_end = os_time(); - printf("\n//-------------------------------"); - printf("\n// Parse : %f", parse_end - parse_begin); - printf("\n// Total : %f", flattening_end - total_time); - printf("\n//-------------------------------"); - - - return {}; -} diff --git a/typechecking.h b/typechecking.h index 769fb23..bc81222 100644 --- a/typechecking.h +++ b/typechecking.h @@ -5,7 +5,11 @@ struct Operand{ U8 is_lvalue: 1; }; - +enum{AST_CANT_BE_NULL = 0, AST_CAN_BE_NULL = 1}; +function Operand resolve_expr(Ast_Expr *ast, B32 flags); +function void resolve_decl(Ast_Decl *ast); +function Ast_Decl *resolve_name(Token *pos, Intern_String name); +function Ast_Resolved_Type *resolve_typespec(Ast_Expr *ast, B32 ast_can_be_null); #if 0 //----------------------------------------------------------------------------- // Symbols @@ -30,7 +34,7 @@ struct Sym{ INLINE_VALUE_FIELDS; }; -enum{AST_CANT_BE_NULL = 0, AST_CAN_BE_NULL = 1}; + function Ast_Resolved_Type *resolve_typespec(Ast_Expr *ast, B32 ast_can_be_null = AST_CANT_BE_NULL); function Sym *resolve_name(Token *pos, Intern_String name); function Operand resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *compound_required_type = 0, Sym *const_sym = 0); @@ -155,39 +159,17 @@ sym_insert(Sym_Kind kind, Intern_String name, Value value, Ast *ast){ return sym; } -function void -sym_insert_builtin_type(String name, Ast_Resolved_Type *type){ - Intern_String string = intern_string(&pctx->interns, name); - Sym *sym = sym_type(type, &empty_decl, string, false); - sym_insert(sym); -} - -function void -sym_insert_builtins(){ - sym_insert_builtin_type("void"_s , type_void); - sym_insert_builtin_type("Bool"_s , type_bool); - sym_insert_builtin_type("String"_s, type_string); - sym_insert_builtin_type("S8"_s, type_s8); - sym_insert_builtin_type("S16"_s, type_s16); - sym_insert_builtin_type("S32"_s, type_s32); - sym_insert_builtin_type("S64"_s, type_s64); - sym_insert_builtin_type("U8"_s, type_u8); - sym_insert_builtin_type("U16"_s, type_u16); - sym_insert_builtin_type("U32"_s, type_u32); - sym_insert_builtin_type("U64"_s, type_u64); - sym_insert_builtin_type("F32"_s, type_f32); - sym_insert_builtin_type("F64"_s, type_f64); -} +#endif //----------------------------------------------------------------------------- // Operands //----------------------------------------------------------------------------- function Operand -operand(Sym *sym){ +operand(Ast_Decl *sym){ Operand result = {}; result.type = sym->type; - result.is_const = sym->kind == SYM_CONST ? true : false; - result.is_lvalue= sym->kind == SYM_CONST ? false : true; // Cant assign to const values + result.is_const = sym->kind == AST_CONST ? true : false; + result.is_lvalue= sym->kind == AST_CONST ? false : true; // Cant assign to const values result.value = sym->value; return result; } @@ -256,7 +238,7 @@ operand_rvalue(Ast_Resolved_Type *type){ result.is_lvalue = false; return result; } -#endif + //----------------------------------------------------------------------------- // Hash consed types //----------------------------------------------------------------------------- @@ -337,8 +319,7 @@ type_lambda(Ast *ast, Ast_Resolved_Type *ret, Array args){ function Ast_Resolved_Type * type_enum(Ast_Decl *ast){ - Ast_Resolved_Type *type = 0; - // Ast_Resolved_Type *type = resolve_typespec(ast->typespec, AST_CAN_BE_NULL); + Ast_Resolved_Type *type = resolve_typespec(ast->typespec, AST_CAN_BE_NULL); if(!type){ type = untyped_int; } @@ -349,24 +330,13 @@ type_enum(Ast_Decl *ast){ return result; } -/* -2022.05.31 - Global scope structs vs nested structs -Structs exist in 2 variants, the global scope structs are a bit different -then scoped structs. They startout incomplete and when some operation -requires the actual struct size, alignment, field access etc. then it -should call complete_type. It resolves all the children, calculates the -size and makes sure there are no cyclic dependencies. This is require for -correct behaviour of order independent structs. If someone just wants a pointer -to that struct we don't need to complete the type, we know how large a pointer is. -This allows us to have cyclic dependency that is a pointer. Cause we know how large pointer is. -*/ function Ast_Resolved_Type * type_incomplete(Ast *ast){ Ast_Resolved_Type *result = type_new(pctx->perm, TYPE_INCOMPLETE, 0, 0); result->ast = ast; return result; } -#if 0 + function void type_struct_complete(Ast_Resolved_Type *type, Ast_Decl *node){ assert(node->kind == AST_STRUCT); @@ -376,34 +346,11 @@ type_struct_complete(Ast_Resolved_Type *type, Ast_Decl *node){ Scratch scratch; Array members = {scratch}; For(node->scope->decls){ - Operand op = resolve_decl(it); - Intern_String name = ast_get_name(it); - sym_var(name, op, it); - members.add({op.type, name}); + resolve_decl(it); + members.add({it->type, it->name}); } type->agg.members = members.tight_copy(pctx->perm); type->kind = TYPE_STRUCT; - - /* - @note: resolve constant members after the struct got resolved - this way we avoid a problem where we start resolving the function - and this function has parameter of type parent struct - which is being resolved right now, cyclic dependency happens. - constants arent required to make struct work - */ - For(node->const_members){ - Operand op = resolve_binding(it); - Intern_String name = ast_get_name(it); - sym_const(name, op, it); - } -} - -function Ast_Resolved_Type * -type_struct(Ast_Struct *agg){ - Ast_Resolved_Type *result = type_new(pctx->perm, TYPE_STRUCT, 0, 0); - result->ast = agg; - type_struct_complete(result, agg); - return result; } function void @@ -418,9 +365,7 @@ type_complete(Ast_Resolved_Type *type){ return; } - Ast_Struct *node = (Ast_Struct *)type->ast; - type_struct_complete(type, node); - pctx->resolving_package->ordered.add((Ast_Named *)node->parent); + type_struct_complete(type, (Ast_Decl *)type->ast); + pctx->ordered_decls.add((Ast_Decl *)type->ast); } -#endif \ No newline at end of file diff --git a/types.h b/types.h index aae98f4..0147886 100644 --- a/types.h +++ b/types.h @@ -227,6 +227,7 @@ global Ast_Resolved_Type *untyped_float = &type__untyped_float; // Type constructors and utillities //----------------------------------------------------------------------------- force_inline B32 is_struct(Ast_Resolved_Type *a){return a->kind == TYPE_STRUCT;} +force_inline B32 is_lambda(Ast_Resolved_Type *a){return a->kind == TYPE_LAMBDA;} force_inline B32 is_array(Ast_Resolved_Type *a){return a->kind == TYPE_ARRAY;} force_inline B32 is_enum(Ast_Resolved_Type *a){return a->kind == TYPE_ENUM;} force_inline B32 is_pointer(Ast_Resolved_Type *a){return a->kind == TYPE_POINTER;}