From: Brendan Hansen Date: Sat, 6 Feb 2021 17:55:11 +0000 (-0600) Subject: added the basic of static if statements; complex cases are broken X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=8a774cda7ec9cbce25e3e6867b098957f7f6dd4f;p=onyx.git added the basic of static if statements; complex cases are broken --- diff --git a/bin/onyx b/bin/onyx index 103abee5..231b7cdc 100755 Binary files a/bin/onyx and b/bin/onyx differ diff --git a/include/onyxastnodes.h b/include/onyxastnodes.h index f8217c5b..0f440843 100644 --- a/include/onyxastnodes.h +++ b/include/onyxastnodes.h @@ -897,6 +897,7 @@ typedef enum EntityType { Entity_Type_Load_File, Entity_Type_Binding, Entity_Type_Use_Package, + Entity_Type_Static_If, Entity_Type_String_Literal, Entity_Type_File_Contents, Entity_Type_Enum, @@ -930,6 +931,7 @@ typedef struct Entity { AstInclude *include; AstUsePackage *use_package; AstBinding *binding; + AstStaticIf *static_if; AstFunction *function; AstOverloadedFunction *overloaded_function; AstGlobal *global; @@ -957,7 +959,9 @@ void entity_heap_insert(EntityHeap* entities, Entity e); Entity* entity_heap_top(EntityHeap* entities); void entity_heap_change_top(EntityHeap* entities, Entity* new_top); void entity_heap_remove_top(EntityHeap* entities); -void add_entities_for_node(AstNode* node, Scope* scope, Package* package); + +// If target_arr is null, the entities will be placed directly in the heap. +void add_entities_for_node(bh_arr(Entity *)* target_arr, AstNode* node, Scope* scope, Package* package); void entity_bring_to_state(Entity* ent, EntityState state); void symres_entity(Entity* ent); diff --git a/include/onyxparser.h b/include/onyxparser.h index c41622c9..1f5112ef 100644 --- a/include/onyxparser.h +++ b/include/onyxparser.h @@ -26,6 +26,7 @@ typedef struct OnyxParser { PolymorphicContext polymorph_context; bh_arr(Scope *) scope_stack; + bh_arr(AstStaticIf *) static_if_stack; b32 hit_unexpected_token : 1; } OnyxParser; diff --git a/onyx.exe b/onyx.exe index acff63a6..23f07482 100644 Binary files a/onyx.exe and b/onyx.exe differ diff --git a/src/onyx.c b/src/onyx.c index 55bbecab..3c7a01bb 100644 --- a/src/onyx.c +++ b/src/onyx.c @@ -124,9 +124,12 @@ typedef enum CompilerProgress { ONYX_COMPILER_PROGRESS_SUCCESS } CompilerProgress; +static OnyxToken implicit_load_token = { '#', 1, 0, { 0, 0, 0, 0, 0 } }; static AstInclude* create_load(bh_allocator alloc, char* filename) { + AstInclude* include_node = onyx_ast_node_new(alloc, sizeof(AstInclude), Ast_Kind_Load_File); include_node->name = filename; + include_node->token = &implicit_load_token; return include_node; } @@ -162,12 +165,12 @@ static void context_init(CompileOptions* opts) { .include = create_load(context.ast_alloc, "core/builtin"), })); - add_entities_for_node((AstNode *) &builtin_stack_top, context.global_scope, NULL); + add_entities_for_node(NULL, (AstNode *) &builtin_stack_top, context.global_scope, NULL); // NOTE: Add all files passed by command line to the queue bh_arr_each(const char *, filename, opts->files) { AstInclude* load_node = create_load(context.ast_alloc, (char *) *filename); - add_entities_for_node((AstNode *) load_node, context.global_scope, NULL); + add_entities_for_node(NULL, (AstNode *) load_node, context.global_scope, NULL); } } @@ -226,7 +229,7 @@ static void parse_source_file(bh_file_contents* file_contents) { onyx_parser_free(&parser); } -static void process_source_file(char* filename) { +static void process_source_file(char* filename, OnyxFilePos error_pos) { bh_arr_each(bh_file_contents, fc, context.loaded_files) { // CLEANUP: Add duplicate resolutions, such as // ./foo and ./test/../foo @@ -237,7 +240,7 @@ static void process_source_file(char* filename) { bh_file file; bh_file_error err = bh_file_open(&file, filename); if (err != BH_FILE_ERROR_NONE) { - onyx_report_error((OnyxFilePos) { 0 }, "Failed to open file %s\n", filename); + onyx_report_error(error_pos, "Failed to open file %s", filename); return; } @@ -260,7 +263,7 @@ static void process_load_entity(Entity* ent) { char* filename = lookup_included_file(include->name); char* formatted_name = bh_strdup(global_heap_allocator, filename); - process_source_file(formatted_name); + process_source_file(formatted_name, include->token->pos); } else if (include->kind == Ast_Kind_Load_Path) { bh_arr_push(context.options->included_folders, include->name); @@ -310,8 +313,12 @@ static b32 process_entity(Entity* ent) { ent->state = Entity_State_Finalized; break; + case Entity_State_Comptime_Resolve_Symbols: case Entity_State_Resolve_Symbols: symres_entity(ent); break; + + case Entity_State_Comptime_Check_Types: case Entity_State_Check_Types: check_entity(ent); break; + case Entity_State_Code_Gen: emit_entity(ent); break; default: diff --git a/src/onyxastnodes.c b/src/onyxastnodes.c index 89f7cba4..d7a700c1 100644 --- a/src/onyxastnodes.c +++ b/src/onyxastnodes.c @@ -124,6 +124,7 @@ const char* entity_type_strings[Entity_Type_Count] = { "Load File", "Binding (Declaration)", "Use Package", + "Static If", "String Literal", "File Contents", "Enum", diff --git a/src/onyxchecker.c b/src/onyxchecker.c index 51de8a54..0de1b0d9 100644 --- a/src/onyxchecker.c +++ b/src/onyxchecker.c @@ -8,12 +8,15 @@ #define CHECK(kind, ...) do { \ CheckStatus cs = check_ ## kind (__VA_ARGS__); \ - if (cs != Check_Success) return cs; \ + if (cs > Check_Errors_Start) return cs; \ } while (0) typedef enum CheckStatus { - Check_Success, - Check_Error, + Check_Success, // The node was successfully checked with out errors + Check_Complete, // The node is done processing + + Check_Errors_Start, + Check_Error, // There was an error when checking the node } CheckStatus; CheckStatus check_block(AstBlock* block); @@ -1794,6 +1797,27 @@ CheckStatus check_type(AstType* type) { return Check_Success; } +CheckStatus check_static_if(AstStaticIf* static_if) { + CHECK(expression, &static_if->cond); + + if (static_if->cond->flags & Ast_Flag_Comptime) { + AstNumLit* condition_value = (AstNumLit *) static_if->cond; + assert(condition_value->kind == Ast_Kind_NumLit); // This should be right, right? + + if (condition_value->value.i) { + bh_arr_each(Entity *, ent, static_if->true_entities) { + entity_heap_insert_existing(&context.entities, *ent); + } + } + + } else { + onyx_report_error(static_if->token->pos, "Expected this condition to be compile time known."); + return Check_Error; + } + + return Check_Complete; +} + CheckStatus check_node(AstNode* node) { switch (node->kind) { case Ast_Kind_Function: return check_function((AstFunction *) node); @@ -1838,7 +1862,7 @@ void check_entity(Entity* ent) { if (ent->type_alias->kind == Ast_Kind_Struct_Type) cs = check_struct((AstStructType *) ent->type_alias); else - check_type(ent->type_alias); + cs = check_type(ent->type_alias); break; case Entity_Type_Memory_Reservation_Type: @@ -1849,12 +1873,15 @@ void check_entity(Entity* ent) { cs = check_memres(ent->mem_res); break; + case Entity_Type_Static_If: + cs = check_static_if(ent->static_if); + break; + default: break; } - if (cs == Check_Success) { - ent->state = Entity_State_Code_Gen; - } + if (cs == Check_Success) ent->state = Entity_State_Code_Gen; + if (cs == Check_Complete) ent->state = Entity_State_Finalized; // else if (cs == Check_Yield) { // ent->attempts++; // } diff --git a/src/onyxentities.c b/src/onyxentities.c index 2164fbfd..40945214 100644 --- a/src/onyxentities.c +++ b/src/onyxentities.c @@ -101,7 +101,18 @@ void entity_heap_remove_top(EntityHeap* entities) { } // NOTE(Brendan Hansen): Uses the entity heap in the context structure -void add_entities_for_node(AstNode* node, Scope* scope, Package* package) { +void add_entities_for_node(bh_arr(Entity *) *target_arr, AstNode* node, Scope* scope, Package* package) { +#define ENTITY_INSERT(_ent) { \ + Entity* entity = entity_heap_register(entities, _ent); \ + if (target_arr) { \ + bh_arr(Entity *) __tmp_arr = *target_arr; \ + bh_arr_push(__tmp_arr, entity); \ + *target_arr = __tmp_arr; \ + } else { \ + entity_heap_insert_existing(entities, entity); \ + } \ + } + EntityHeap* entities = &context.entities; Entity ent; @@ -114,7 +125,7 @@ void add_entities_for_node(AstNode* node, Scope* scope, Package* package) { ent.state = Entity_State_Parse; ent.type = Entity_Type_Load_File; ent.include = (AstInclude *) node; - entity_heap_insert(entities, ent); + ENTITY_INSERT(ent); break; } @@ -122,7 +133,7 @@ void add_entities_for_node(AstNode* node, Scope* scope, Package* package) { ent.state = Entity_State_Parse; ent.type = Entity_Type_Load_Path; ent.include = (AstInclude *) node; - entity_heap_insert(entities, ent); + ENTITY_INSERT(ent); break; } @@ -130,7 +141,7 @@ void add_entities_for_node(AstNode* node, Scope* scope, Package* package) { ent.state = Entity_State_Introduce_Symbols; ent.type = Entity_Type_Binding; ent.binding = (AstBinding *) node; - entity_heap_insert(entities, ent); + ENTITY_INSERT(ent); break; } @@ -138,16 +149,16 @@ void add_entities_for_node(AstNode* node, Scope* scope, Package* package) { if ((node->flags & Ast_Flag_Foreign) != 0) { ent.type = Entity_Type_Foreign_Function_Header; ent.function = (AstFunction *) node; - entity_heap_insert(entities, ent); + ENTITY_INSERT(ent); } else { ent.type = Entity_Type_Function_Header; ent.function = (AstFunction *) node; - entity_heap_insert(entities, ent); + ENTITY_INSERT(ent); ent.type = Entity_Type_Function; ent.function = (AstFunction *) node; - entity_heap_insert(entities, ent); + ENTITY_INSERT(ent); } break; } @@ -155,7 +166,7 @@ void add_entities_for_node(AstNode* node, Scope* scope, Package* package) { case Ast_Kind_Overloaded_Function: { ent.type = Entity_Type_Overloaded_Function; ent.overloaded_function = (AstOverloadedFunction *) node; - entity_heap_insert(entities, ent); + ENTITY_INSERT(ent); break; } @@ -163,16 +174,16 @@ void add_entities_for_node(AstNode* node, Scope* scope, Package* package) { if ((node->flags & Ast_Flag_Foreign) != 0) { ent.type = Entity_Type_Foreign_Global_Header; ent.global = (AstGlobal *) node; - entity_heap_insert(entities, ent); + ENTITY_INSERT(ent); } else { ent.type = Entity_Type_Global_Header; ent.global = (AstGlobal *) node; - entity_heap_insert(entities, ent); + ENTITY_INSERT(ent); ent.type = Entity_Type_Global; ent.global = (AstGlobal *) node; - entity_heap_insert(entities, ent); + ENTITY_INSERT(ent); } break; } @@ -180,21 +191,21 @@ void add_entities_for_node(AstNode* node, Scope* scope, Package* package) { case Ast_Kind_StrLit: { ent.type = Entity_Type_String_Literal; ent.strlit = (AstStrLit *) node; - entity_heap_insert(entities, ent); + ENTITY_INSERT(ent); break; } case Ast_Kind_File_Contents: { ent.type = Entity_Type_File_Contents; ent.file_contents = (AstFileContents *) node; - entity_heap_insert(entities, ent); + ENTITY_INSERT(ent); break; } case Ast_Kind_Struct_Type: { ent.type = Entity_Type_Struct_Member_Default; ent.type_alias = (AstType *) node; - entity_heap_insert(entities, ent); + ENTITY_INSERT(ent); // fallthrough } @@ -202,53 +213,62 @@ void add_entities_for_node(AstNode* node, Scope* scope, Package* package) { case Ast_Kind_Type_Alias: { ent.type = Entity_Type_Type_Alias; ent.type_alias = (AstType *) node; - entity_heap_insert(entities, ent); + ENTITY_INSERT(ent); break; } case Ast_Kind_Enum_Type: { ent.type = Entity_Type_Enum; ent.enum_type = (AstEnumType *) node; - entity_heap_insert(entities, ent); + ENTITY_INSERT(ent); break; } case Ast_Kind_Use_Package: { + ent.state = Entity_State_Comptime_Resolve_Symbols; ent.type = Entity_Type_Use_Package; ent.use_package = (AstUsePackage *) node; - entity_heap_insert(entities, ent); + ENTITY_INSERT(ent); break; } case Ast_Kind_Use: { ent.type = Entity_Type_Use; ent.use = (AstUse *) node; - entity_heap_insert(entities, ent); + ENTITY_INSERT(ent); break; } case Ast_Kind_Memres: { ent.type = Entity_Type_Memory_Reservation_Type; ent.mem_res = (AstMemRes *) node; - entity_heap_insert(entities, ent); + ENTITY_INSERT(ent); ent.type = Entity_Type_Memory_Reservation; ent.mem_res = (AstMemRes *) node; - entity_heap_insert(entities, ent); + ENTITY_INSERT(ent); break; } case Ast_Kind_Polymorphic_Proc: { ent.type = Entity_Type_Polymorphic_Proc; ent.poly_proc = (AstPolyProc *) node; - entity_heap_insert(entities, ent); + ENTITY_INSERT(ent); + break; + } + + case Ast_Kind_Static_If: { + ent.state = Entity_State_Comptime_Resolve_Symbols; + ent.type = Entity_Type_Static_If; + ent.static_if = (AstStaticIf *) node; + ENTITY_INSERT(ent); break; } default: { ent.type = Entity_Type_Expression; ent.expr = (AstTyped *) node; - entity_heap_insert(entities, ent); + ENTITY_INSERT(ent); break; } } diff --git a/src/onyxparser.c b/src/onyxparser.c index 14c2c387..bb140cb2 100644 --- a/src/onyxparser.c +++ b/src/onyxparser.c @@ -13,18 +13,33 @@ #include "onyxparser.h" #include "onyxutils.h" -// NOTE: The one weird define you need to know before read the code below #define make_node(nclass, kind) onyx_ast_node_new(parser->allocator, sizeof(nclass), kind) #define peek_token(ahead) (parser->curr + ahead) -#define ENTITY_SUBMIT(node) (add_entities_for_node((AstNode *) (node), bh_arr_last(parser->scope_stack), parser->package)) -#define ENTITY_SUBMIT_IN_SCOPE(node, scope) (add_entities_for_node((AstNode *) (node), scope, parser->package)) static AstNode error_node = { Ast_Kind_Error, 0, NULL, NULL }; +#define ENTITY_SUBMIT(node) (submit_entity_in_scope(parser, (AstNode *) (node), bh_arr_last(parser->scope_stack), parser->package)) +#define ENTITY_SUBMIT_IN_SCOPE(node, scope) (submit_entity_in_scope(parser, (AstNode *) (node), scope, parser->package)) + +void submit_entity_in_scope(OnyxParser* parser, AstNode* node, Scope* scope, Package* package) { + if (bh_arr_length(parser->static_if_stack) == 0) { + add_entities_for_node(NULL, node, scope, package); + + } else { + AstStaticIf* static_if = bh_arr_last(parser->static_if_stack); + + // nocheckin This should also be able to place them in the false entities + add_entities_for_node(&static_if->true_entities, node, scope, package); + } +} + +// Parsing Utilities static void consume_token(OnyxParser* parser); static void unconsume_token(OnyxParser* parser); static OnyxToken* expect_token(OnyxParser* parser, TokenType token_type); static b32 consume_token_if_next(OnyxParser* parser, TokenType token_type); +static b32 next_tokens_are(OnyxParser* parser, i32 n, ...); +static OnyxToken* find_matching_paren(OnyxToken* paren); static AstNumLit* parse_int_literal(OnyxParser* parser); static AstNumLit* parse_float_literal(OnyxParser* parser); @@ -54,7 +69,7 @@ static AstTyped* parse_global_declaration(OnyxParser* parser); static AstEnumType* parse_enum_declaration(OnyxParser* parser); static AstTyped* parse_top_level_expression(OnyxParser* parser); static AstBinding* parse_top_level_binding(OnyxParser* parser, OnyxToken* symbol); -static AstNode* parse_top_level_statement(OnyxParser* parser); +static void parse_top_level_statement(OnyxParser* parser); static AstPackage* parse_package_name(OnyxParser* parser); static void consume_token(OnyxParser* parser) { @@ -201,7 +216,7 @@ static AstNumLit* parse_float_literal(OnyxParser* parser) { } static b32 parse_possible_directive(OnyxParser* parser, const char* dir) { - if (parser->curr->type != '#') return 0; + if (peek_token(0)->type != '#' || peek_token(1)->type != Token_Type_Symbol) return 0; expect_token(parser, '#'); OnyxToken* sym = expect_token(parser, Token_Type_Symbol); @@ -2093,6 +2108,29 @@ static AstEnumType* parse_enum_declaration(OnyxParser* parser) { return enum_node; } +static AstStaticIf* parse_static_if_stmt(OnyxParser* parser) { + AstStaticIf* static_if_node = make_node(AstStaticIf, Ast_Kind_Static_If); + static_if_node->token = expect_token(parser, '#'); + expect_token(parser, Token_Type_Keyword_If); + + static_if_node->cond = parse_expression(parser, 0); + + // TODO: Add else statements to static ifs + bh_arr_new(global_heap_allocator, static_if_node->true_entities, 4); + bh_arr_push(parser->static_if_stack, static_if_node); + + expect_token(parser, '{'); + while (!consume_token_if_next(parser, '}')) { + if (parser->hit_unexpected_token) return static_if_node; + + parse_top_level_statement(parser); + } + + bh_arr_pop(parser->static_if_stack); + + return static_if_node; +} + static AstTyped* parse_top_level_expression(OnyxParser* parser) { if (parser->curr->type == Token_Type_Keyword_Proc) { OnyxToken* proc_token = expect_token(parser, Token_Type_Keyword_Proc); @@ -2176,38 +2214,33 @@ static AstBinding* parse_top_level_binding(OnyxParser* parser, OnyxToken* symbol return binding; } -static AstNode* parse_top_level_statement(OnyxParser* parser) { +static void parse_top_level_statement(OnyxParser* parser) { AstFlags private_kind = 0; - if (parse_possible_directive(parser, "private")) { - private_kind = Ast_Flag_Private_Package; - } + if (parse_possible_directive(parser, "private")) private_kind = Ast_Flag_Private_Package; + else if (parse_possible_directive(parser, "private_file")) private_kind = Ast_Flag_Private_File; - else if (parse_possible_directive(parser, "private_file")) { - private_kind = Ast_Flag_Private_File; - } + AstBinding* binding = NULL; - // CLEANUP switch ((u16) parser->curr->type) { case Token_Type_Keyword_Use: { AstNode* use_node = parse_use_stmt(parser); ENTITY_SUBMIT(use_node); - return NULL; + return; } case Token_Type_Keyword_Proc: parse_top_level_expression(parser); - return NULL; + return; case Token_Type_Symbol: { OnyxToken* symbol = expect_token(parser, Token_Type_Symbol); expect_token(parser, ':'); if (parser->curr->type == ':') { - AstBinding* binding = parse_top_level_binding(parser, symbol); - + binding = parse_top_level_binding(parser, symbol); if (binding != NULL) binding->node->flags |= private_kind; - return (AstNode *) binding; + goto submit_binding_to_entities; } AstMemRes* memres = make_node(AstMemRes, Ast_Kind_Memres); @@ -2223,52 +2256,56 @@ static AstNode* parse_top_level_statement(OnyxParser* parser) { ENTITY_SUBMIT(memres); - AstBinding* binding = make_node(AstBinding, Ast_Kind_Binding); + binding = make_node(AstBinding, Ast_Kind_Binding); binding->token = symbol; binding->node = (AstNode *) memres; - return (AstNode *) binding; + goto submit_binding_to_entities; } case '#': { - while (parser->curr->type == '#') { - OnyxToken* dir_token = parser->curr; - - if (parse_possible_directive(parser, "load")) { - AstInclude* include = make_node(AstInclude, Ast_Kind_Load_File); - include->token = dir_token; - - OnyxToken* str_token = expect_token(parser, Token_Type_Literal_String); - if (str_token != NULL) { - token_toggle_end(str_token); - include->name = bh_strdup(parser->allocator, str_token->text); - token_toggle_end(str_token); - } - - ENTITY_SUBMIT(include); - return NULL; + if (next_tokens_are(parser, 2, '#', Token_Type_Keyword_If)) { + AstStaticIf* static_if = parse_static_if_stmt(parser); + ENTITY_SUBMIT(static_if); + return; + } + + OnyxToken* dir_token = parser->curr; + + if (parse_possible_directive(parser, "load")) { + AstInclude* include = make_node(AstInclude, Ast_Kind_Load_File); + include->token = dir_token; + + OnyxToken* str_token = expect_token(parser, Token_Type_Literal_String); + if (str_token != NULL) { + token_toggle_end(str_token); + include->name = bh_strdup(parser->allocator, str_token->text); + token_toggle_end(str_token); } - else if (parse_possible_directive(parser, "load_path")) { - AstInclude* include = make_node(AstInclude, Ast_Kind_Load_Path); - include->token = dir_token; - - OnyxToken* str_token = expect_token(parser, Token_Type_Literal_String); - if (str_token != NULL) { - token_toggle_end(str_token); - include->name = bh_strdup(parser->allocator, str_token->text); - token_toggle_end(str_token); - } - - ENTITY_SUBMIT(include); - return NULL; + + ENTITY_SUBMIT(include); + return; + } + else if (parse_possible_directive(parser, "load_path")) { + AstInclude* include = make_node(AstInclude, Ast_Kind_Load_Path); + include->token = dir_token; + + OnyxToken* str_token = expect_token(parser, Token_Type_Literal_String); + if (str_token != NULL) { + token_toggle_end(str_token); + include->name = bh_strdup(parser->allocator, str_token->text); + token_toggle_end(str_token); } - else { - OnyxToken* directive_token = expect_token(parser, '#'); - OnyxToken* symbol_token = expect_token(parser, Token_Type_Symbol); + + ENTITY_SUBMIT(include); + return; + } + else { + OnyxToken* directive_token = expect_token(parser, '#'); + OnyxToken* symbol_token = expect_token(parser, Token_Type_Symbol); - onyx_report_error(directive_token->pos, "unknown directive '#%b'.", symbol_token->text, symbol_token->length); - return NULL; - } + onyx_report_error(directive_token->pos, "unknown directive '#%b'.", symbol_token->text, symbol_token->length); + return; } } @@ -2276,7 +2313,21 @@ static AstNode* parse_top_level_statement(OnyxParser* parser) { } expect_token(parser, ';'); - return NULL; + return; + +submit_binding_to_entities: + { + if (!binding) return; + + Scope* target_scope = parser->package->scope; + + if (binding->node->flags & Ast_Flag_Private_Package) + target_scope = parser->package->private_scope; + if (binding->node->flags & Ast_Flag_Private_File) + target_scope = parser->file_scope; + + ENTITY_SUBMIT_IN_SCOPE(binding, target_scope); + } } static AstPackage* parse_package_name(OnyxParser* parser) { @@ -2350,6 +2401,7 @@ OnyxParser onyx_parser_create(bh_allocator alloc, OnyxTokenizer *tokenizer) { parser.prev = NULL; parser.hit_unexpected_token = 0; parser.scope_stack = NULL; + parser.static_if_stack = NULL; parser.polymorph_context = (PolymorphicContext) { .root_node = NULL, @@ -2357,6 +2409,7 @@ OnyxParser onyx_parser_create(bh_allocator alloc, OnyxTokenizer *tokenizer) { }; bh_arr_new(global_heap_allocator, parser.scope_stack, 4); + bh_arr_new(global_heap_allocator, parser.static_if_stack, 4); return parser; } @@ -2378,33 +2431,9 @@ void onyx_parse(OnyxParser *parser) { ENTITY_SUBMIT(implicit_use_builtin); while (parser->curr->type != Token_Type_End_Stream) { - if (parser->hit_unexpected_token) return; - - AstNode* curr_stmt = parse_top_level_statement(parser); - - if (curr_stmt != NULL && curr_stmt != &error_node) { - while (curr_stmt != NULL) { - if (parser->hit_unexpected_token) return; - - switch (curr_stmt->kind) { - case Ast_Kind_Binding: { - Scope* target_scope = parser->package->scope; - - if (((AstBinding *) curr_stmt)->node->flags & Ast_Flag_Private_Package) - target_scope = parser->package->private_scope; - if (((AstBinding *) curr_stmt)->node->flags & Ast_Flag_Private_File) - target_scope = parser->file_scope; - - ENTITY_SUBMIT_IN_SCOPE(curr_stmt, target_scope); - break; - } - - default: assert(("Invalid top level node", 0)); - } - - curr_stmt = curr_stmt->next; - } - } + if (parser->hit_unexpected_token) break; + if (onyx_has_errors()) break; + parse_top_level_statement(parser); } bh_arr_pop(parser->scope_stack); diff --git a/src/onyxsymres.c b/src/onyxsymres.c index 4d54afb4..3c914c13 100644 --- a/src/onyxsymres.c +++ b/src/onyxsymres.c @@ -9,6 +9,7 @@ static Scope* curr_scope = NULL; static Package* curr_package = NULL; static AstFunction* curr_function = NULL; bh_arr(AstBlock *) block_stack = NULL; +static b32 report_unresolved_symbols = 1; AstType* symres_type(AstType* type); static void symres_local(AstLocal** local, b32 add_to_block_locals); @@ -37,6 +38,7 @@ static void symres_enum(AstEnumType* enum_node); static void symres_memres_type(AstMemRes** memres); static void symres_memres(AstMemRes** memres); static void symres_struct_defaults(AstType* st); +static void symres_static_if(AstStaticIf* static_if); static void scope_enter(Scope* new_scope) { curr_scope = new_scope; @@ -46,6 +48,20 @@ static void scope_leave() { curr_scope = curr_scope->parent; } +static void symres_symbol(AstNode** symbol_node) { + OnyxToken* token = (*symbol_node)->token; + AstNode* res = symbol_resolve(curr_scope, token); + + if (!res) { // :SymresStall + onyx_report_error(token->pos, + "Unable to resolve symbol '%b'", + token->text, + token->length); + } else { + *symbol_node = res; + } +} + AstType* symres_type(AstType* type) { if (type == NULL) return NULL; @@ -55,7 +71,8 @@ AstType* symres_type(AstType* type) { } if (type->kind == Ast_Kind_Symbol) { - return (AstType *) symbol_resolve(curr_scope, ((AstNode *) type)->token); + symres_symbol((AstNode **) &type); + return type; } if (type->kind == Ast_Kind_Field_Access) { @@ -387,9 +404,7 @@ static void symres_expression(AstTyped** expr) { } switch ((*expr)->kind) { - case Ast_Kind_Symbol: - *expr = (AstTyped *) symbol_resolve(curr_scope, ((AstNode *) *expr)->token); - break; + case Ast_Kind_Symbol: symres_symbol((AstNode **) expr); break; case Ast_Kind_Binary_Op: symres_expression(&((AstBinaryOp *)(*expr))->left); @@ -825,8 +840,8 @@ static void symres_use_package(AstUsePackage* package) { bh_arr_each(AstAlias *, alias, package->only) { AstNode* thing = symbol_resolve(p->scope, (*alias)->token); - if (thing == NULL) { - onyx_report_error((*alias)->token->pos, "not found in package"); + if (thing == NULL) { // :SymresStall + onyx_report_error((*alias)->token->pos, "This symbol was not found in this package."); return; } @@ -844,9 +859,7 @@ static void symres_use_package(AstUsePackage* package) { } static void symres_enum(AstEnumType* enum_node) { - if (enum_node->backing->kind == Ast_Kind_Symbol) { - enum_node->backing = (AstType *) symbol_resolve(curr_scope, enum_node->backing->token); - } + if (enum_node->backing->kind == Ast_Kind_Symbol) symres_symbol((AstNode **) &enum_node->backing); if (enum_node->backing == NULL) return; enum_node->backing_type = type_build_from_ast(context.ast_alloc, enum_node->backing); @@ -942,6 +955,10 @@ static void symres_polyproc(AstPolyProc* pp) { } } +static void symres_static_if(AstStaticIf* static_if) { + symres_expression(&static_if->cond); +} + void symres_entity(Entity* ent) { if (block_stack == NULL) bh_arr_new(global_heap_allocator, block_stack, 16); @@ -962,6 +979,12 @@ void symres_entity(Entity* ent) { next_state = Entity_State_Finalized; break; } + + case Entity_Type_Static_If: { + symres_static_if(ent->static_if); + next_state = Entity_State_Comptime_Check_Types; + break; + } case Entity_Type_Foreign_Function_Header: case Entity_Type_Function_Header: symres_function_header(ent->function); break; diff --git a/src/onyxutils.c b/src/onyxutils.c index b1d99c21..c13a654e 100644 --- a/src/onyxutils.c +++ b/src/onyxutils.c @@ -129,14 +129,8 @@ AstNode* symbol_raw_resolve(Scope* start_scope, char* sym) { AstNode* symbol_resolve(Scope* start_scope, OnyxToken* tkn) { token_toggle_end(tkn); AstNode* res = symbol_raw_resolve(start_scope, tkn->text); - - if (res == NULL) { - onyx_report_error(tkn->pos, "Unable to resolve symbol '%s'.", tkn->text); - token_toggle_end(tkn); - return &empty_node; - } - token_toggle_end(tkn); + return res; }