From fbe911d267facead53a6d300c2b7f461dc58f4c7 Mon Sep 17 00:00:00 2001 From: Krzosa Karol Date: Thu, 9 Jun 2022 21:30:52 +0200 Subject: [PATCH] Complete rework, adding packages --- ast.cpp | 288 +++++++++---------------------- big_int_c3.cpp | 4 +- ccodegen.cpp | 14 +- compiler.h | 31 ++-- lambdas.kl | 2 + lexing.cpp | 4 +- main.cpp | 16 +- order1.kl | 1 + parsing.cpp | 68 ++++---- typechecking.cpp | 431 ++++++++++++++++++++++++++--------------------- typechecking.h | 37 ++-- 11 files changed, 399 insertions(+), 497 deletions(-) diff --git a/ast.cpp b/ast.cpp index 6c0db21..044dc53 100644 --- a/ast.cpp +++ b/ast.cpp @@ -7,6 +7,7 @@ enum Ast_Kind: U32{ AST_PACKAGE, + AST_SCOPE, AST_VALUE, AST_CAST, AST_IDENT, @@ -16,6 +17,8 @@ enum Ast_Kind: U32{ AST_CALL_ITEM, AST_CALL, + AST_VAR, + AST_CONST, AST_POINTER, AST_ARRAY, AST_FOR, @@ -29,8 +32,6 @@ enum Ast_Kind: U32{ AST_ENUM, AST_ENUM_MEMBER, AST_STRUCT, - AST_CONST, - AST_VAR, }; typedef U32 Ast_Flag; @@ -43,6 +44,7 @@ enum{ AST_ITEM_INCLUDED = bit_flag(6), AST_ATOM = bit_flag(7), AST_FOREIGN = bit_flag(8), + AST_DECL = bit_flag(9), }; struct Ast{ @@ -161,16 +163,6 @@ struct Ast_Array: Ast_Expr{ Ast_Expr *expr; }; -struct Ast_Named:Ast{ - Intern_String name; -}; - -enum Ast_Decl_State{ - DECL_NOT_RESOLVED, - DECL_RESOLVED, - DECL_RESOLVING, -}; - /* How does current declaration order resolver works: * First we put all the global declarations into the global scope (when parsing) all unresolved @@ -188,81 +180,43 @@ How does current declaration order resolver works: resolving, we got a circular dependency. That might happen when we have that struct without pointer inside itself. - - -We need a new algorithm to process structs -we probably want default values so constants -can be evaluated first, also it's pretty weird that -only top scope gets special treatment - -Idea 1 -New algorithm, at some point in a constant we might -see the struct inside which is the constant. struct is -unresolved so we probably call resolve_name on struct -and struct continues resolving omitting already resolved and -declaration that requires the struct size. Problem is what happens -when we meet a member that references a constant and that constant -has reference to struct. - -Idea 2 -We resolve first members without default values, we add to queue dependencies -then we resolve constants. And at the end we resolve the queued values. */ -struct Ast_Scope{ - Array resolved; - Array children; - Array constants; +enum Ast_Decl_State{ + DECL_NOT_RESOLVED, + DECL_RESOLVED, + DECL_RESOLVING, +}; +struct Ast_Decl; +struct Ast_Scope: Ast{ + Array resolved; + Array decls; + Array stmts; }; struct Ast_Decl: Ast{ Ast_Decl_State state; - // kind:AST_CONST: subkind:AST_STRUCT, AST_ENUM, AST_EXPR(can be TYPE_TYPE), AST_LAMBDA - // kind:AST_VAR : subkind:AST_EXPR, AST_LAMBDA + // Kind: AST_STRUCT implied AST_DECL (should flag AST_CONST AST_DECL) Intern_String name; - Ast_Kind sub_kind; + Ast_Scope *scope; - Ast_Resolved_Type *type; -}; - -struct Ast_Var: Ast_Named{ - Ast_Expr *typespec; Ast_Expr *expr; -}; - -struct Ast_Const; -struct Ast_Resolved_Type; -struct Ast_Struct: Ast{ - // Required to be Ast_Struct or Ast_Var or Ast_Const - Array members; - Array const_members; - Ast_Resolved_Type *type; -}; - -struct Ast_Enum_Member: Ast{ - Intern_String name; - Ast_Expr *value; -}; - -struct Ast_Enum: Ast{ Ast_Expr *typespec; - Array members; + + INLINE_VALUE_FIELDS; }; -struct Ast_Const: Ast_Named{ - union{ - Ast *ast; - Ast_Expr *value; - Ast_Struct *agg; - Ast_Enum *enu; - }; -}; +struct Ast_File{ + String filename; + String filecontent; -struct Ast_Package:Ast{ Intern_String name; - Array decls; - Array ordered; + Array decls; +}; + +struct Ast_Package : Ast_Scope{ + Intern_String name; }; //----------------------------------------------------------------------------- @@ -482,76 +436,72 @@ ast_array(Token *pos, Ast_Expr *expr){ return result; } -function Ast_Enum_Member * -ast_enum_member(Token *pos, Intern_String name, Ast_Expr *default_value){ - AST_NEW(Enum_Member, ENUM_MEMBER, pos, AST_AGGREGATE_CHILD); - result->name = name; - result->value = default_value; - if(result->value) result->value->parent = result; +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; + } return result; } -function Ast_Enum * -ast_enum(Token *pos, Ast_Expr *typespec, Array members){ - AST_NEW(Enum, ENUM, pos, AST_AGGREGATE); - result->members = members.tight_copy(pctx->perm); +function Ast_Scope * +ast_stmt_scope(Token *pos, Array stmts){ + AST_NEW(Scope, SCOPE, pos, AST_STMT); + result->stmts = stmts.tight_copy(pctx->perm); + For(result->stmts){ + it->parent = result; + } + return result; +} + +function Ast_Decl * +ast_struct(Token *pos, Array decls){ + AST_NEW(Decl, STRUCT, pos, AST_DECL | AST_AGGREGATE); + result->scope = ast_decl_scope(pos, decls); + result->scope->parent = result; + return result; +} + +function Ast_Decl * +ast_enum(Token *pos, Ast_Expr *typespec, Array decls){ + AST_NEW(Decl, ENUM, pos, AST_DECL | AST_AGGREGATE); + result->scope = ast_decl_scope(pos, decls); result->typespec = typespec; + result->scope->parent = result; if(result->typespec) result->typespec->parent = result; - For(result->members){ - it->parent = result; - } return result; } -function Ast_Struct * -ast_struct(Token *pos, Array members, Array const_members){ - AST_NEW(Struct, STRUCT, pos, AST_AGGREGATE); - result->members = members.tight_copy(pctx->perm); - result->const_members = const_members.tight_copy(pctx->perm); - For(result->members) { - assert(is_flag_set(it->flags, AST_BINDING)); - assert(it->kind == AST_VAR); - it->parent = result; - } - For(result->const_members) { - assert(is_flag_set(it->flags, AST_BINDING)); - assert(it->kind == AST_CONST); - it->parent = result; - } - return result; -} - -//----------------------------------------------------------------------------- -// Declarations -//----------------------------------------------------------------------------- -function Ast_Var * +function Ast_Decl * ast_var(Token *pos, Ast_Expr *typespec, Intern_String name, Ast_Expr *expr){ - AST_NEW(Var, VAR, pos, AST_BINDING); - result->expr = expr; - result->typespec = typespec; - result->name = name; - if(result->expr) result->expr->parent = result; - if(result->typespec) result->typespec->parent = result; - return result; -} - -function Ast_Const * -ast_const(Token *pos, Intern_String name, Ast_Expr *value){ - assert(is_flag_set(value->flags, AST_AGGREGATE) || is_flag_set(value->flags, AST_EXPR) ); - AST_NEW(Const, CONST, pos, AST_BINDING); - result->value = value; + AST_NEW(Decl, VAR, pos, AST_DECL); result->name = name; - result->value->parent = result; + result->typespec = typespec; + result->expr = expr; + if(result->typespec) result->typespec->parent = result; + if(result->expr) result->expr->parent = result; return result; } -function Ast_Package * -ast_package(Token *pos, String name, Array decls){ - AST_NEW(Package, PACKAGE, pos, 0); - result->decls = decls.tight_copy(pctx->perm); - result->ordered = array_make(pctx->perm, decls.len); - result->name = intern_string(&pctx->interns, name); - For(result->decls) it->parent = result; +function Ast_Decl * +ast_const(Token *pos, Intern_String name, Ast_Expr *expr){ + AST_NEW(Decl, CONST, pos, AST_DECL); + result->expr = expr; + result->name = name; + if(result->expr) result->expr->parent = result; + 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; return result; } @@ -598,61 +548,6 @@ value_float(BigInt a){ return value; } - -//----------------------------------------------------------------------------- -// Utillities -//----------------------------------------------------------------------------- -function Ast_Struct * -const_try_getting_struct(Ast *ast){ - assert(ast->kind == AST_CONST); - Ast_Const *constant = (Ast_Const *)ast; - if(constant->value->kind == AST_STRUCT){ - return (Ast_Struct *)constant->value; - } - return 0; -} - -function Ast_Struct * -const_get_struct(Ast *ast){ - auto result = const_try_getting_struct(ast); - assert(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 -ast_get_name(Ast *ast){ - assert(is_flag_set(ast->flags, AST_BINDING)); - auto constant = (Ast_Named *)ast; - return constant->name; -} - -function B32 -ast_is_struct(Ast *ast){ - if(ast->kind == AST_CONST){ - auto a = (Ast_Const *)ast; - B32 result = a->agg->kind == AST_STRUCT; - return result; - } - return false; -} - function B32 is_ident(Ast *ast){ B32 result = ast->kind == AST_IDENT; @@ -670,28 +565,3 @@ is_atom(Ast *ast){ B32 result = is_flag_set(ast->flags, AST_ATOM); return result; } - -function Ast * -query_struct(Ast_Struct *agg, Intern_String string){ - For(agg->members){ - if(it->name == string){ - return it; - } - } - For(agg->const_members){ - if(it->name == string){ - return it; - } - } - return 0; -} - -function Ast_Enum_Member * -query_enum(Ast_Enum *enu, Intern_String string){ - For(enu->members){ - if(it->name == string){ - return it; - } - } - return 0; -} \ No newline at end of file diff --git a/big_int_c3.cpp b/big_int_c3.cpp index ebc20b3..bc2b8d4 100644 --- a/big_int_c3.cpp +++ b/big_int_c3.cpp @@ -5,7 +5,7 @@ struct Token; Allocator *bigint_allocator; global S64 bigint_allocation_count; -function void parsing_error(Token *token, const char *str, ...); +function void compiler_error(Token *token, const char *str, ...); #define Set_BigInt_Allocator(x) BigInt_Allocator bigint_allocator(x) struct BigInt_Allocator{ @@ -17,7 +17,7 @@ struct BigInt_Allocator{ #define count_bigint_alloc() (bigint_allocator != thread_ctx.scratch ? bigint_allocation_count++ : 0) #define malloc_arena(x) (count_bigint_alloc(), exp_alloc(bigint_allocator, x, AF_ZeroMemory)) #define ALLOC_DIGITS(_digits) (uint64_t *)((_digits) ? malloc_arena(sizeof(uint64_t) * (_digits)) : NULL) -#define FATAL_ERROR(x) parsing_error(0, x) +#define FATAL_ERROR(x) compiler_error(0, x) struct BigInt { diff --git a/ccodegen.cpp b/ccodegen.cpp index b3eed63..0c54aae 100644 --- a/ccodegen.cpp +++ b/ccodegen.cpp @@ -468,7 +468,7 @@ gen_ast(Ast *ast){ gen(";"); } }break; - default: parsing_error(node->pos, "C_Codegen: Unhandled type %s of constant expression", docname(sym->type)); + default: compiler_error(node->pos, "C_Codegen: Unhandled type %s of constant expression", docname(sym->type)); } BREAK(); @@ -574,15 +574,3 @@ compile_file(String filename){ String result = compile_string(filecontent, filename); return result; } - -typedef struct Custom_Data{ - S32 thing; -}Custom_Data; - - -typedef struct Slice{ - S64 len; - void *data; -}Slice; - -Slice thing = (Slice){2, (Custom_Data []){(Custom_Data ){1}, (Custom_Data ){2}}}; \ No newline at end of file diff --git a/compiler.h b/compiler.h index 8266bb1..cf5c348 100644 --- a/compiler.h +++ b/compiler.h @@ -112,19 +112,19 @@ struct Token{ S64 indent; }; - String file; - S32 line; - U8 *line_begin; + Intern_String file; + S32 line; + U8 *line_begin; }; struct Lex_Stream{ String stream; S64 iter; - U8 *line_begin; - String file; - S32 line; - S32 inside_brace_paren; + U8 *line_begin; + Intern_String file; + S32 line; + S32 inside_brace_paren; Array indent_stack; }; @@ -154,6 +154,7 @@ Intern_String keyword_if; Intern_String keyword_else; Intern_String keyword_true; Intern_String keyword_false; +Intern_String keyword_package; Intern_String keyword_for; Intern_String keyword_pass; Intern_String keyword_cast; @@ -163,8 +164,10 @@ Intern_String intern_void; Intern_String intern_foreign; Intern_String intern_printf; + +struct Ast_Scope; +struct Ast_Decl; struct Ast_Package; -struct Sym; struct Parse_Ctx:Lexer{ Allocator *perm; // Stores: AST, tokens, interns Allocator *heap; @@ -172,15 +175,12 @@ struct Parse_Ctx:Lexer{ U64 unique_ids; Map type_map; + Ast_Scope *current_scope; Ast_Package *resolving_package; - Map resolved; - Map syms; - S32 scope; - Array local_syms; + Array ordered_decls; Token empty_token; S64 indent; - String_Builder gen; }; @@ -201,6 +201,7 @@ lex_init(Allocator *token_string_arena, Allocator *map_allocator, Lexer *l){ keyword_cast = l->intern("cast"_s); keyword_true = l->intern("true"_s); keyword_false = l->intern("false"_s); + keyword_package = l->intern("package"_s); keyword_return = l->intern("return"_s); keyword_if = l->intern("if"_s); keyword_pass = l->intern("pass"_s); @@ -220,10 +221,8 @@ parse_init(Parse_Ctx *ctx, Allocator *perm_allocator, Allocator *heap_allocator) ctx->perm = perm_allocator; ctx->heap = heap_allocator; ctx->gen = {ctx->perm}; - ctx->resolved = {ctx->heap}; - ctx->syms = {ctx->heap}; + ctx->ordered_decls = {ctx->heap}; ctx->type_map = {ctx->heap}; - ctx->local_syms = {ctx->heap}; bigint_allocator = ctx->perm; lex_init(ctx->perm, ctx->heap, ctx); diff --git a/lambdas.kl b/lambdas.kl index f6d3303..4b96c0d 100644 --- a/lambdas.kl +++ b/lambdas.kl @@ -1,3 +1,5 @@ +package lambdas + a_type :: S64 pointer_type :: *S64 // null_pointer: pointer_type = null diff --git a/lexing.cpp b/lexing.cpp index 513cf5b..76cd08a 100644 --- a/lexing.cpp +++ b/lexing.cpp @@ -165,7 +165,7 @@ lex_parse_ident(Intern_Table *table, Lex_Stream *s, Token *t){ break function Token -token_make(Lexer *lexer, U8 *str, String file, int line, U8 *line_begin){ +token_make(Lexer *lexer, U8 *str, Intern_String file, int line, U8 *line_begin){ Token t = {}; t.str = str; t.file = file; @@ -540,7 +540,7 @@ lex_restream(Lexer *lexer, String istream, String file){ lexer->stream = {}; lexer->stream.stream = istream; lexer->stream.line_begin = istream.str; - lexer->stream.file = file; + lexer->stream.file = lexer->intern(file); lexer->tokens.clear(); diff --git a/main.cpp b/main.cpp index c21ebb0..85acf65 100644 --- a/main.cpp +++ b/main.cpp @@ -164,10 +164,10 @@ 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){ - // test_big_int(); test_os_memory(); thread_ctx_init(); @@ -180,7 +180,7 @@ int main(int argument_count, char **arguments){ test_intern_table(); - +#if 0 emit_line_directives = true; if(argument_count > 1){ Scratch scratch; @@ -211,12 +211,16 @@ int main(int argument_count, char **arguments){ printf("%s", result.str); result = compile_file("order2.kl"_s); printf("%s", result.str); - result = compile_file("lambdas.kl"_s); - printf("%s", result.str); + result = compile_file("new_types.kl"_s); printf("%s", result.str); #endif } - +#endif + Scratch scratch; + Array files = {scratch}; + files.add("lambdas.kl"_s); + files.add("order1.kl"_s); + compile_files(files); __debugbreak(); } diff --git a/order1.kl b/order1.kl index fabae8c..7f1b96c 100644 --- a/order1.kl +++ b/order1.kl @@ -1,3 +1,4 @@ +package lambdas other_func :: () a_val := recursive_lambda diff --git a/parsing.cpp b/parsing.cpp index 1d8775f..b027044 100644 --- a/parsing.cpp +++ b/parsing.cpp @@ -1,6 +1,7 @@ +function Ast_Decl *parse_decl(B32 is_global); function void -parsing_error(Token *token, const char *str, ...){ +compiler_error(Token *token, const char *str, ...){ Scratch scratch; STRING_FMT(scratch, str, string); @@ -109,7 +110,7 @@ function Token * token_expect(Token_Kind kind){ Token *token = token_get(); if(token->kind == kind) return token_next(); - parsing_error(token, "Expected token of kind: [%s], got instead token of kind: [%s]", name(kind), name(token->kind)); + compiler_error(token, "Expected token of kind: [%s], got instead token of kind: [%s]", name(kind), name(token->kind)); return 0; } @@ -119,7 +120,7 @@ function Ast_Expr * parse_init_stmt(Ast_Expr *expr){ Token *token = token_get(); if(token->kind == TK_ColonAssign && expr->kind != AST_IDENT) - parsing_error(expr->pos, "Binding with [:=] to something that is not an identifier"); + compiler_error(expr->pos, "Binding with [:=] to something that is not an identifier"); if(token_is_assign(token)){ token_next(); @@ -175,7 +176,6 @@ parse_optional_type(){ return result; } -function Ast_Named *parse_named(B32); function Ast_Block * parse_block(){ Ast_Block *block = 0; @@ -257,7 +257,7 @@ parse_block(){ } else{ - Ast *result = parse_named(false); + Ast *result = parse_decl(false); if(!result){ result = parse_expr(); result = parse_init_stmt((Ast_Expr *)result); @@ -268,7 +268,7 @@ parse_block(){ stmts.add(result); } else { - parsing_error(token, "Unexpected token [%s] while parsing statement", name(token->kind)); + compiler_error(token, "Unexpected token [%s] while parsing statement", name(token->kind)); } } @@ -304,7 +304,7 @@ parse_lambda(Token *token){ has_var_args = true; break; } - else parsing_error(name, "Expected [Identifier] or [...] when parsing lambda arguments"); + else compiler_error(name, "Expected [Identifier] or [...] when parsing lambda arguments"); if(!token_match(TK_Comma)) break; @@ -412,7 +412,7 @@ parse_expr(S64 min_bp){ Ast_Expr *expr = 0; if(!token_is(TK_CloseBracket)) expr = parse_expr(0); - + Ast_Array *result = ast_array(token, expr); token_expect(TK_CloseBracket); result->base = parse_expr(prefix_bp.right); @@ -430,7 +430,7 @@ parse_expr(S64 min_bp){ token_expect(TK_CloseParen); left = ast_expr_cast(token, expr, typespec); } - else parsing_error(token, "Unexpected keyword: [%s], expected keyword [cast]", token->intern_val.str); + else compiler_error(token, "Unexpected keyword: [%s], expected keyword [cast]", token->intern_val.str); }break; case TK_OpenParen: { @@ -441,7 +441,7 @@ parse_expr(S64 min_bp){ token_expect(TK_CloseParen); } }break; - default: parsing_error(token, "Unexpected token of kind: [%s] in expression", name(token->kind)); return 0; + default: compiler_error(token, "Unexpected token of kind: [%s] in expression", name(token->kind)); return 0; } for(;;){ @@ -497,51 +497,45 @@ parse_assign_expr(){ return result; } -function Ast_Struct * +function Ast_Decl * parse_struct(Token *pos){ Scratch scratch; - Array members = {scratch}; - Array members_const = {scratch}; + Array members = {scratch}; token_match(OPEN_SCOPE); do{ Token *token = token_get(); - Ast_Named *named = parse_named(false); - if(!named) parsing_error(token, "Failed to parse struct member"); - named->flags = set_flag(named->flags, AST_AGGREGATE_CHILD); + Ast_Decl *decl = parse_decl(false); + if(!decl) compiler_error(token, "Failed to parse struct member"); - if(named->kind == AST_CONST){ - members_const.add((Ast_Const *)named); - } - else { - assert(named->kind == AST_VAR); - members.add((Ast_Var *)named); - } + decl->flags = set_flag(decl->flags, AST_AGGREGATE_CHILD); + members.add(decl); }while(token_match(SAME_SCOPE)); token_expect(CLOSE_SCOPE); - Ast_Struct *result = ast_struct(pos, members, members_const); + Ast_Decl *result = ast_struct(pos, members); return result; } -function Ast_Enum * +function Ast_Decl * parse_enum(Token *pos){ Scratch scratch; - Array members = {scratch}; + Array members = {scratch}; Ast_Expr *typespec = parse_optional_type(); token_match(OPEN_SCOPE); do{ Token *name = token_expect(TK_Identifier); Ast_Expr *value = parse_assign_expr(); - Ast_Enum_Member *member = ast_enum_member(name, name->intern_val, value); + Ast_Decl *member = ast_const(name, name->intern_val, value); + member->flags = set_flag(member->flags, AST_AGGREGATE_CHILD); members.add(member); }while(token_match(SAME_SCOPE)); token_expect(CLOSE_SCOPE); - Ast_Enum *result = ast_enum(pos, typespec, members); + Ast_Decl *result = ast_enum(pos, typespec, members); return result; } @@ -550,13 +544,13 @@ Needs peeking only because I didn't want to duplicate code for parsing statements and it makes code nicer. Statements can have named syntax i := */ -function Ast_Named * -parse_named(B32 is_global){ - Ast_Named *result = 0; +function Ast_Decl * +parse_decl(B32 is_global){ + Ast_Decl *result = 0; if(is_global) { token_match(SAME_SCOPE); if(pctx->indent != 0){ - parsing_error(token_get(), "Top level declarations shouldn't be indented"); + compiler_error(token_get(), "Top level declarations shouldn't be indented"); } } @@ -568,15 +562,12 @@ parse_named(B32 is_global){ Token *tname = token_get(); if(token_match(TK_Identifier, TK_DoubleColon)){ // @note parse struct binding - Token *struct_pos = token_get(); if(token_match_keyword(keyword_struct)){ - Ast_Struct *struct_val = parse_struct(struct_pos); - result = ast_const(tname, tname->intern_val, (Ast_Expr *)struct_val); + result = parse_struct(tname); } else if(token_match_keyword(keyword_enum)){ - Ast_Enum *enum_val = parse_enum(struct_pos); - result = ast_const(tname, tname->intern_val, (Ast_Expr *)enum_val); + result = parse_enum(tname); } // @note parse constant expression @@ -596,10 +587,11 @@ parse_named(B32 is_global){ result = ast_var(tname, 0, tname->intern_val, expr); } else if(is_global && tname->kind != TK_End){ - parsing_error(tname, "Unexpected token: [%s] when parsing a declaration", name(tname->kind)); + compiler_error(tname, "Unexpected token: [%s] when parsing a declaration", name(tname->kind)); } if(result){ + result->name = tname->intern_val; result->flags = set_flag(result->flags, flags); } diff --git a/typechecking.cpp b/typechecking.cpp index e320e12..91610c7 100644 --- a/typechecking.cpp +++ b/typechecking.cpp @@ -1,32 +1,6 @@ #define CASE(kind,type) case AST_##kind: { Ast_##type *node = (Ast_##type *)ast; #define BREAK() } break -function void -type_error(Token *token, Ast_Resolved_Type *expected, Ast_Resolved_Type *actual, const char *str, ...){ - Scratch scratch; - STRING_FMT(scratch, str, string); - - // @Note(Krzosa): Print nice error message - printf("\nType error :: %s :: ", string.str); - printf("Expected %s, got instead %s", docname(expected), docname(actual)); - if(token){ - printf(" :: %s:%d\n", token->file.str, (S32)token->line + 1); - - // @Note(Krzosa): Print error line - { - int i = 0; - while(token->line_begin[i]!='\n' && token->line_begin[i]!=0) i++; - printf("%.*s\n", i, token->line_begin); - - // @Note(Krzosa): Print error marker - int token_i = token->str - token->line_begin; - for(int i = 0; i < token_i-2; i++) printf(" "); - printf("^^^^^^\n"); - } - } - - __debugbreak(); -} //----------------------------------------------------------------------------- // Evaluating constant expressions @@ -38,7 +12,7 @@ check_value_bounds(Token *pos, Value *a){ Scratch scratch; if(!bigint_fits_in_bits(&a->big_int_val, a->type->size*8, is_signed_int(a->type))){ const char *string = bigint_to_error_string(scratch, &a->big_int_val, 10); - parsing_error(pos, "Value %s doesn't fit in type %s", string, docname(a->type)); + compiler_error(pos, "Value %s doesn't fit in type %s", string, docname(a->type)); } } @@ -60,7 +34,7 @@ convert_untyped_to_typed(Token *pos, Value a, Ast_Resolved_Type *new_type){ ; // nothing to do else if(is_string(a.type) && is_string(new_type)) ; // nothing to do - else parsing_error(pos, "Type mismatch when converting from %s to %s", docname(a.type), docname(new_type)); + else compiler_error(pos, "Type mismatch when converting from %s to %s", docname(a.type), docname(new_type)); a.type = new_type; check_value_bounds(pos, &a); @@ -77,7 +51,7 @@ make_sure_types_are_compatible(Token *pos, Value *a, Value *b){ } else if(is_typed(a->type) && is_typed(b->type)){ if(a->type != b->type){ - fail: parsing_error(pos, "Type mismatch in make_sure_types_are_compatible - left: %s right: %s", docname(a->type), docname(b->type)); + fail: compiler_error(pos, "Type mismatch in make_sure_types_are_compatible - left: %s right: %s", docname(a->type), docname(b->type)); } } @@ -100,7 +74,7 @@ make_sure_types_are_compatible(Token *pos, Value *a, Value *b){ function Value compare_values(Token *pos, Token_Kind op, Value a, Value b, bool is_const){ if(!(is_numeric(a.type) && is_numeric(b.type))) - parsing_error(pos, "Constant application of binary %s on values of type %s and %s is not allowed", name(op), docname(a.type), docname(b.type)); + compiler_error(pos, "Constant application of binary %s on values of type %s and %s is not allowed", name(op), docname(a.type), docname(b.type)); make_sure_types_are_compatible(pos, &a, &b); @@ -154,7 +128,7 @@ eval_binary(Token *pos, Token_Kind op, Value a, Value b, bool is_const){ return compare_values(pos, op, a, b, is_const); if(!(is_numeric(a.type) && is_numeric(b.type))) - parsing_error(pos, "Constant application of binary %s on values of type %s and %s is not allowed", name(op), docname(a.type), docname(b.type)); + compiler_error(pos, "Constant application of binary %s on values of type %s and %s is not allowed", name(op), docname(a.type), docname(b.type)); make_sure_types_are_compatible(pos, &a, &b); @@ -220,14 +194,14 @@ eval_unary(Token *pos, Token_Kind op, Operand *operand){ Value *a = &operand->value; Ast_Resolved_Type *type = a->type; if(!is_numeric(type)) - parsing_error(pos, "Unary [%s] cant be applied to value of type %s", name(op), docname(type)); + compiler_error(pos, "Unary [%s] cant be applied to value of type %s", name(op), docname(type)); if(op == TK_Not) a->type = untyped_bool; if(op == TK_Increment || op == TK_Decrement || op == TK_PostIncrement || op == TK_PostDecrement) if(!operand->is_lvalue) - parsing_error(pos, "Unary [%s] requires an assignable value(lvalue)", name(op)); + compiler_error(pos, "Unary [%s] requires an assignable value(lvalue)", name(op)); if(!operand->is_const) return; @@ -269,7 +243,7 @@ eval_unary(Token *pos, Token_Kind op, Operand *operand){ default:goto failure; } } break; - default: failure: parsing_error(pos, "Constant application of unary %s on values of type %s is not allowed", name(op), docname(a->type)); + default: failure: compiler_error(pos, "Constant application of unary %s on values of type %s is not allowed", name(op), docname(a->type)); } } @@ -319,10 +293,11 @@ make_sure_value_is_compatible_with_type(Token *pos, Operand *expr, Ast_Resolved_ } if(type && expr->type != type){ - parsing_error(pos, "Assigning but incompatible types, expression: %s expected var type: %s", docname(expr->type), docname(type)); + compiler_error(pos, "Assigning but incompatible types, expression: %s expected var type: %s", docname(expr->type), docname(type)); } - type_complete(expr->type); + // @todo + // type_complete(expr->type); check_value_bounds(pos, &expr->value); assert(expr->type); } @@ -337,11 +312,7 @@ _rewrite_into_const(Ast *node, U64 ast_size, Value value){ ast->value = value; } -function void -_rewrite_into_const(Ast *node, U64 ast_size, Sym *sym){ - _rewrite_into_const(node, ast_size, sym->value); -} - +#if 0 function Ast_Resolved_Type * resolve_typespec(Ast_Expr *ast, B32 ast_can_be_null){ if(ast_can_be_null && ast == 0) @@ -349,7 +320,7 @@ resolve_typespec(Ast_Expr *ast, B32 ast_can_be_null){ Operand resolved = resolve_expr(ast); if(resolved.type != type_type) - parsing_error(ast->pos, "Expected [Type] got instead %s", type_names[resolved.type->kind]); + compiler_error(ast->pos, "Expected [Type] got instead %s", type_names[resolved.type->kind]); return resolved.type_val; } @@ -360,12 +331,12 @@ require_const_int(Ast_Expr *expr, B32 ast_can_be_null){ if(expr == 0 && ast_can_be_null) return op; else if(expr == 0) - parsing_error(expr->pos, "This field cannot be null"); + compiler_error(expr->pos, "This field cannot be null"); if(!op.is_const) - parsing_error(expr->pos, "Expected a const value"); + compiler_error(expr->pos, "Expected a const value"); if(!is_int(op.type)) - parsing_error(expr->pos, "Expected a constant integer got instead %s", docname(op.type)); + compiler_error(expr->pos, "Expected a constant integer got instead %s", docname(op.type)); return op; } @@ -375,12 +346,12 @@ resolve_and_require_bool(const char *error, Ast_Expr *expr, B32 ast_can_be_null if(!expr){ if(ast_can_be_null) return {}; - else parsing_error(0, "Compiler error: Null expression"); + else compiler_error(0, "Compiler error: Null expression"); } Operand op = resolve_expr(expr); if(!is_bool(op.type)){ - type_error(expr->pos, type_bool, op.type, "%s", error); + compiler_error(expr->pos, "Expected type [Bool] got instead type %s :: %s", docname(op.type), error); } return op; @@ -395,9 +366,9 @@ resolve_stmt(Ast *ast, Ast_Resolved_Type *ret){ switch(ast->kind){ CASE(RETURN, Return){ // @todo: need to check if all paths return a value Operand op = resolve_expr(node->expr); - if(!op.type && ret != type_void) parsing_error(node->pos, "Function expects a void return value but the returned value is %s", docname(op.type)); + if(!op.type && ret != type_void) compiler_error(node->pos, "Function expects a void return value but the returned value is %s", docname(op.type)); op.value = convert_untyped_to_typed(node->pos, op.value, ret); - if(op.type && op.type != ret) parsing_error(node->pos, "Return statement has different type then returned value, expecting: %s got instead %s", docname(ret), docname(op.type)); + if(op.type && op.type != ret) compiler_error(node->pos, "Return statement has different type then returned value, expecting: %s got instead %s", docname(ret), docname(op.type)); BREAK(); } @@ -570,7 +541,7 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res CASE(ARRAY, Array){ // @todo: Arrays of inferred size [] Operand type = resolve_expr(node->base); - if(type.type != type_type) parsing_error(node->pos, "Prefix array operator is only allowed on types"); + if(type.type != type_type) compiler_error(node->pos, "Prefix array operator is only allowed on types"); Operand expr = require_const_int(node->expr, AST_CAN_BE_NULL); Ast_Resolved_Type *resolved = type_array(type.type_val, node->expr ? 1 : 0, bigint_as_unsigned(&expr.big_int_val)); @@ -583,10 +554,11 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res Operand left = resolve_expr(node->expr); Operand index = resolve_expr(node->index); if(!is_int(index.type)){ - type_error(node->pos, untyped_int, index.type,"Trying to index the array with invalid type, expected int"); + + compiler_error(node->pos, "Trying to index the array with invalid type, expected [Int] got instead %s", docname(index.type)); } if(!is_array(left.type) && !is_pointer(left.type)){ - parsing_error(node->pos, "Indexing variable that is not an [Array] or [Pointer], it's of type %s instead", docname(left.type)); + compiler_error(node->pos, "Indexing variable that is not an [Array] or [Pointer], it's of type %s instead", docname(left.type)); } sym_new_resolved(SYM_VAR, {}, left.value, node); @@ -605,26 +577,26 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res if(name.type == type_type){ type = name.type_val; if(expected_type && expected_type != type) - parsing_error(node->pos, "Variable type different from explicit compound type"); + compiler_error(node->pos, "Variable type different from explicit compound type"); if(type->kind == TYPE_LAMBDA) - parsing_error(node->pos, "Calling a lambda type"); + compiler_error(node->pos, "Calling a lambda type"); } type_complete(type); node->type = type; if(type->kind == TYPE_ARRAY){ if(node->exprs.len > type->arr.size && type->arr.size != ARRAY_SIZE_INFERRED) - parsing_error(node->pos, "compound statement has too many items for this type"); + compiler_error(node->pos, "compound statement has too many items for this type"); Ast_Resolved_Type *item_type = type->arr.base; For(node->exprs){ Ast_Call_Item *i = (Ast_Call_Item *)it; assert(i->kind == AST_CALL_ITEM); - if(i->name) parsing_error(i->pos, "Invalid indexing kind in a compound expression of type %s", type_names[type->kind]); + if(i->name) compiler_error(i->pos, "Invalid indexing kind in a compound expression of type %s", type_names[type->kind]); if(i->index){ Operand index_op = require_const_int(i->index, AST_CANT_BE_NULL); U64 index = bigint_as_unsigned(&index_op.big_int_val); - if(index > (type->arr.size - 1)) parsing_error(i->pos, "Invalid index in compound expression, larger then type can store"); + if(index > (type->arr.size - 1)) compiler_error(i->pos, "Invalid index in compound expression, larger then type can store"); } Operand expr = resolve_expr(i->item, item_type); expr.value = convert_untyped_to_typed(i->pos, expr.value, item_type); @@ -637,7 +609,7 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res S64 default_iter = 0; For_It(node->exprs, expr){ - if(expr->index) parsing_error(expr->index->pos, "Function call indexing is illegal"); + if(expr->index) compiler_error(expr->index->pos, "Function call indexing is illegal"); Ast_Atom *name = expr->name; S64 expr_index = node->exprs.get_index(&expr); @@ -647,7 +619,7 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res assert(name->kind == AST_IDENT); For_It(agg->members, member){ if(member->name.str == name->intern_val.str){ - if(member->kind == AST_CONST) parsing_error(expr->pos, "Initializing a value that is a constant"); + if(member->kind == AST_CONST) compiler_error(expr->pos, "Initializing a value that is a constant"); found = member; found_type = &type->agg.members[agg->members.get_index(&member)]; break; @@ -658,18 +630,18 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res S64 i = default_iter++; found = agg->members[i]; found_type = &type->agg.members[i]; - if(i >= agg->members.len) parsing_error(expr->pos, "Too many arguments in compound constructor"); + if(i >= agg->members.len) compiler_error(expr->pos, "Too many arguments in compound constructor"); } - else parsing_error(expr->pos, "Positional argument after named or indexed argument"); + else compiler_error(expr->pos, "Positional argument after named or indexed argument"); - if(!found) parsing_error(expr->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"); + if(!found) compiler_error(expr->pos, "Invalid argument in compound constructor"); + if(is_flag_set(found->flags, AST_ITEM_INCLUDED)) compiler_error(found->pos, "Item included multiple times in compound constructor"); found->flags = set_flag(found->flags, AST_ITEM_INCLUDED); Operand op = resolve_expr(expr->item, found_type->type); op.value = convert_untyped_to_typed(node->pos, op.value, found_type->type); - if(found_type->type != op.type) parsing_error(expr->pos, "Invalid type of compound constructor item, expected %s got instead %s", type_names[found_type->type->kind], type_names[op.type->kind]); + if(found_type->type != op.type) compiler_error(expr->pos, "Invalid type of compound constructor item, expected %s got instead %s", type_names[found_type->type->kind], type_names[op.type->kind]); } // @note: cleanup, required? @@ -691,7 +663,7 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res // there are three kinds of possible matches: indexed, named, default Ast_Call_Item *item = 0; For_It(node->exprs, expr){ - if(expr->index) parsing_error(expr->index->pos, "Function call indexing is illegal"); + if(expr->index) compiler_error(expr->index->pos, "Function call indexing is illegal"); Ast_Atom *name = expr->name; if(name){ @@ -704,7 +676,7 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res item = expr; } else if(node->exprs.get_index(&expr) > default_iter){ - parsing_error(expr->pos, "Positional argument after named argument"); + compiler_error(expr->pos, "Positional argument after named argument"); } if(item) @@ -722,13 +694,13 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res 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"); + else compiler_error(arg->pos, "Required value in lambda call was not passed"); } } if(lambda->has_var_args){ if(was_name_indexed) - parsing_error(lambda->pos, "Cant name index a lambda with var args"); + compiler_error(lambda->pos, "Cant name index a lambda with var args"); for(S64 i = lambda->args.len; i < node->exprs.len; i++){ Ast_Call_Item *item = node->exprs.data[i]; resolve_expr(item->item); @@ -740,14 +712,14 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res // @note: check if all arguments are included and cleanup For(node->exprs){ if(!is_flag_set(it->flags, AST_ITEM_INCLUDED)) - parsing_error(it->pos, "Invalid argument to function call"); + compiler_error(it->pos, "Invalid argument to function call"); else it->flags = unset_flag(it->flags, AST_ITEM_INCLUDED); } node->exprs = items.tight_copy(pctx->perm); type = type->func.ret; } - else parsing_error(node->pos, "Invalid function call type"); + else compiler_error(node->pos, "Invalid function call type"); return operand_rvalue(type); BREAK(); @@ -788,7 +760,7 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res expr.type = type; } else goto failure; } break; - default: failure: parsing_error(node->pos, "Failed to cast from %s to %s", docname(expr.type), docname(type));; + default: failure: compiler_error(node->pos, "Failed to cast from %s to %s", docname(expr.type), docname(type));; } if(original_type != type) assert(expr.type == type); @@ -807,7 +779,7 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res sym_type(type, node); return operand_type(type); } - else{ parsing_error(node->pos, "Dereferencing expression %s that is not a [Pointer] or [Type]", type_names[value.type->kind]); return {}; } + else{ compiler_error(node->pos, "Dereferencing expression %s that is not a [Pointer] or [Type]", type_names[value.type->kind]); return {}; } }break; case TK_Dereference:{ return operand_lvalue(type_pointer(value.type)); @@ -846,11 +818,11 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res else if(token_is_assign(node->op)){ assert(is_flag_set(node->flags, AST_STMT)); Operand left = resolve_expr(node->left); - if(!left.is_lvalue) parsing_error(node->pos, "Assigning to rvalue"); + if(!left.is_lvalue) compiler_error(node->pos, "Assigning to rvalue"); Operand right = resolve_expr(node->right); right.value = convert_untyped_to_typed(node->pos, right.value, left.type); - if(left.type != right.type) parsing_error(node->pos, "Can't assign value when left is %s and right is %s", docname(left.type), docname(right.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)); } //----------------------------------------------------------------------------- @@ -878,7 +850,7 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res } else{ type_complete(type); - if(!(is_struct(type) || is_enum(type))) parsing_error(node->pos, "Trying to access inside a value that is not a struct or enum"); + if(!(is_struct(type) || is_enum(type))) compiler_error(node->pos, "Trying to access inside a value that is not a struct or enum"); // This happens only on binary nodes which further chain with dots and require lookups // This part cant happen on enums @@ -893,7 +865,7 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res Ast *query = query_struct(agg, ident->intern_val); if(query){ Sym *sym = resolved_get(query); - if(required_to_be_const && sym->kind != SYM_CONST) parsing_error(ident->pos, "Required to be constant"); + if(required_to_be_const && sym->kind != SYM_CONST) compiler_error(ident->pos, "Required to be constant"); type = sym->type; // @copy_paste if(type == type_type){ @@ -902,10 +874,10 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res } if(is_pointer(type)) type = type->base; type_complete(type); - if(!(is_struct(type) || is_enum(type))) parsing_error(node->pos, "Trying to access inside a value that is not a struct or enum"); + if(!(is_struct(type) || is_enum(type))) compiler_error(node->pos, "Trying to access inside a value that is not a struct or enum"); sym_associate(ident, sym); - } else parsing_error(ident->pos, "No such member in struct"); + } else compiler_error(ident->pos, "No such member in struct"); } // Here we can resolve the last part, this doesnt need to be a struct @@ -932,9 +904,9 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res if(sym->kind == SYM_CONST) rewrite_into_const(node, Ast_Binary, sym); else sym_associate(ident, sym); - } else parsing_error(ident->pos, "No such member in struct"); + } else compiler_error(ident->pos, "No such member in struct"); } - else parsing_error(ident->pos, "Trying to [.] access a value that is not [Enum] or [Struct]"); + else compiler_error(ident->pos, "Trying to [.] access a value that is not [Enum] or [Struct]"); if(result.is_const == false && required_to_be_const){ invalid_codepath; @@ -972,41 +944,7 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res function Operand resolve_const(Ast_Expr *ast, Sym *sym){ - switch(ast->kind){ - CASE(LAMBDA, Lambda){ - return resolve_lambda(node, sym); - BREAK(); - } - CASE(ENUM, Enum){ - 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++); - } - - sym_const(it->name, op, it, INSERT_INTO_SCOPE); - } - scope_close(scope_index); - return operand_type(type); - BREAK(); - } - - CASE(STRUCT, Struct){ - Ast_Resolved_Type *type = type_struct(node); - return operand_type(type); - BREAK(); - } - - default: return resolve_expr(ast, 0, sym); - } } function Operand @@ -1024,7 +962,7 @@ resolve_binding(Ast *ast, Sym *sym){ CASE(CONST, Const){ Operand expr = resolve_const((Ast_Expr *)node->value, sym); - if(!expr.is_const) parsing_error(node->pos, "Value of constant variable is not a constant expression"); + if(!expr.is_const) compiler_error(node->pos, "Value of constant variable is not a constant expression"); assert(expr.type); return expr; BREAK(); @@ -1033,50 +971,126 @@ resolve_binding(Ast *ast, Sym *sym){ } } -function void -resolve_sym(Sym *sym){ - if(sym->state == SYM_RESOLVED){ - return; - } - else if(sym->state == SYM_RESOLVING){ - parsing_error(sym->ast->pos, "Cyclic dependency"); - return; - } - assert(sym->state == SYM_NOT_RESOLVED); - assert(sym->ast->kind == AST_VAR || sym->ast->kind == AST_CONST); +#endif - sym->state = SYM_RESOLVING; - { - Operand op = resolve_binding(sym->ast, sym); - sym->value = op.value; +#define Enter_Scope(x) Enter_Scope_Defer package_scope(x) +struct Enter_Scope_Defer{ + Ast_Scope *scope; + Ast_Package *package; + Enter_Scope_Defer(Ast_Scope *new_p){ + scope = pctx->current_scope; + pctx->current_scope = new_p; + if(new_p->kind == AST_PACKAGE){ + package = pctx->resolving_package; + pctx->resolving_package = (Ast_Package *)new_p; + } } - sym->state = SYM_RESOLVED; + ~Enter_Scope_Defer(){ + pctx->current_scope = scope; + if(package){ + pctx->resolving_package = package; + } + } +}; - pctx->resolving_package->ordered.add((Ast_Named *)sym->ast); +function Ast_Decl * +search_for_decl(Ast_Scope *scope, Intern_String name){ + For(scope->decls){ + if(it->name == name){ + return it; + } + } + return 0; } -function Sym * +function Ast_Decl * +search_for_decl_in_current_context(Intern_String name){ + Ast_Decl *result = search_for_decl(pctx->current_scope, name); + if(!result) + result = search_for_decl(pctx->resolving_package, name); + return result; +} + +function void +resolve_decl(Ast_Decl *ast){ + if(ast->state == DECL_RESOLVED){ + return; + } + else if(ast->state == DECL_RESOLVING){ + compiler_error(ast->pos, "Cyclic dependency of %s", ast->name.str); + return; + } + assert(ast->state == DECL_NOT_RESOLVED); + + ast->state = DECL_RESOLVING; + { + Operand result = {}; + switch(ast->kind){ + CASE(LAMBDA, Decl){ + // return resolve_lambda(node, sym); + 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++); + // } + + // sym_const(it->name, op, it, INSERT_INTO_SCOPE); + // } + // scope_close(scope_index); + // return operand_type(type); + 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); +} + +function Ast_Decl * resolve_name(Token *pos, Intern_String name){ - Sym *sym = sym_get(name); - if(!sym) parsing_error(pos, "Unidentified name [%s]", name.str); - resolve_sym(sym); - return sym; + Ast_Decl *decl = search_for_decl_in_current_context(name); + if(!decl) compiler_error(pos, "Unidentified name [%s]", name.str); + resolve_decl(decl); + return decl; } function void resolve_package(Ast_Package *package){ + Enter_Scope(package); For(package->decls){ resolve_name(it->pos, it->name); - if(ast_is_struct(it)){ - type_complete(const_get_struct(it)->type); + if(it->kind == AST_STRUCT){ + // type_complete(it->type); } } } -function Ast_Package * -parse_file(){ - Scratch scratch; +function void +parse_file(Ast_File *file){ + lex_restream(pctx, file->filecontent, file->filename); + Scratch scratch; // // @note: pop the first token with token_next() / token_expect() // which always should be an indentation token, @@ -1085,66 +1099,91 @@ parse_file(){ // the first line is properly updated // Token *token = token_get(); - Arraydecls = {scratch}; - while(!token_is(TK_End)){ - token_expect(SAME_SCOPE); - Ast_Named *decl = parse_named(true); + file->name = token->file; + file->decls = {scratch}; + + if(token_is(SAME_SCOPE) && token_is_keyword(keyword_package, 1)){ + token_next(); token_next(); + Token *package = token_expect(TK_Identifier); + file->name = package->intern_val; + } + + while(token_expect(SAME_SCOPE)){ + Ast_Decl *decl = parse_decl(true); if(!decl) break; - Sym *sym = sym_new(SYM_VAR, decl->name, decl); - if(decl->kind == AST_CONST) { - sym->kind = SYM_CONST; - Ast_Struct *s = const_try_getting_struct(decl); - if(s){ - s->type = type_incomplete(s); - sym->type_val = s->type; - sym->type = type_type; - sym->state = SYM_RESOLVED; - } + if(decl->kind == AST_STRUCT){ + decl->type = type_incomplete(decl); + decl->state = DECL_RESOLVED; } - else assert(decl->kind == AST_VAR); - sym_insert(sym); - decls.add(decl); + file->decls.add(decl); } - Ast_Package *result = ast_package(token, token->file, decls); + + file->decls = file->decls.tight_copy(pctx->perm); +} + +function Ast_File +ast_file(String filename, String filecontent){ + Ast_File result = {}; + result.filecontent = filecontent; + result.filename = filename; return result; } -function void -test_types(){ - Scratch scratch; - Parse_Ctx ctx = {}; - parse_init(&ctx, scratch, scratch); - pctx = &ctx; - - Ast_Resolved_Type *array_type1 = type_array(type_s64, 1, 32); - Ast_Resolved_Type *array_type2 = type_array(type_s64, 1, 32); - Ast_Resolved_Type *array_type3 = type_array(type_s64, 1, 48); - assert(array_type1 == array_type2); - assert(array_type2 != array_type3); - Ast_Resolved_Type *pointer_type1 = type_pointer(type_s64); - Ast_Resolved_Type *pointer_type2 = type_pointer(type_s64); - assert(pointer_type2 == pointer_type1); - Ast_Resolved_Type *pointer_type3 = type_pointer(pointer_type1); - Ast_Resolved_Type *pointer_type4 = type_pointer(pointer_type2); - assert(pointer_type3 != pointer_type1); - assert(pointer_type3 == pointer_type4); - - Array types = {scratch}; - types.add(type_array(type_s64, 1, 32)); - 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 types2 = {scratch}; - { - types2.add(type_array(type_s64, 1, 32)); - types2.add(type_s64); +function Ast_Package * +find_package(Intern_String name, Array *packages){ + For(*packages){ + if(it.name == name){ + return ⁢ + } } - types.add(type_s64); - 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); -} \ No newline at end of file + 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 59d59e4..769fb23 100644 --- a/typechecking.h +++ b/typechecking.h @@ -1,4 +1,12 @@ +struct Operand{ + INLINE_VALUE_FIELDS; + U8 is_const : 1; + U8 is_lvalue: 1; +}; + + +#if 0 //----------------------------------------------------------------------------- // Symbols //----------------------------------------------------------------------------- @@ -22,12 +30,6 @@ struct Sym{ INLINE_VALUE_FIELDS; }; -struct Operand{ - INLINE_VALUE_FIELDS; - bool is_const: 1; - bool is_lvalue: 1; -}; - 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); @@ -42,7 +44,7 @@ function void sym_insert(Sym *sym){ U64 hash = hash_string(sym->name.s); Sym *is_sym = (Sym *)map_get(&pctx->syms, hash); - if(is_sym) parsing_error(sym->ast->pos, "Symbol with name: [%s] defined multiple times", sym->name.s.str); + if(is_sym) compiler_error(sym->ast->pos, "Symbol with name: [%s] defined multiple times", sym->name.s.str); if(pctx->scope > 0) pctx->local_syms.add(sym); map_insert(&pctx->syms, hash, sym); } @@ -254,7 +256,7 @@ operand_rvalue(Ast_Resolved_Type *type){ result.is_lvalue = false; return result; } - +#endif //----------------------------------------------------------------------------- // Hash consed types //----------------------------------------------------------------------------- @@ -332,9 +334,11 @@ type_lambda(Ast *ast, Ast_Resolved_Type *ret, Array args){ return result; } + function Ast_Resolved_Type * -type_enum(Ast_Enum *ast){ - Ast_Resolved_Type *type = resolve_typespec(ast->typespec, AST_CAN_BE_NULL); +type_enum(Ast_Decl *ast){ + Ast_Resolved_Type *type = 0; + // Ast_Resolved_Type *type = resolve_typespec(ast->typespec, AST_CAN_BE_NULL); if(!type){ type = untyped_int; } @@ -362,16 +366,17 @@ type_incomplete(Ast *ast){ result->ast = ast; return result; } - +#if 0 function void -type_struct_complete(Ast_Resolved_Type *type, Ast_Struct *node){ +type_struct_complete(Ast_Resolved_Type *type, Ast_Decl *node){ + assert(node->kind == AST_STRUCT); // @todo: compute size, alignement, offset !!! // @note: resolve all the struct members first type->kind = TYPE_COMPLETING; Scratch scratch; Array members = {scratch}; - For(node->members){ - Operand op = resolve_binding(it); + 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}); @@ -407,7 +412,7 @@ type_complete(Ast_Resolved_Type *type){ return; } if(type->kind == TYPE_COMPLETING){ - parsing_error(type->ast->pos, "Cyclic type dependency"); + compiler_error(type->ast->pos, "Cyclic type dependency"); } else if(type->kind != TYPE_INCOMPLETE){ return; @@ -417,3 +422,5 @@ type_complete(Ast_Resolved_Type *type){ type_struct_complete(type, node); pctx->resolving_package->ordered.add((Ast_Named *)node->parent); } + +#endif \ No newline at end of file