Entity_State_Error,
Entity_State_Parse_Builtin,
+ Entity_State_Introduce_Symbols,
Entity_State_Parse,
Entity_State_Resolve_Symbols,
Entity_State_Check_Types,
Entity_Type_Load_Path,
Entity_Type_Load_File,
+ Entity_Type_Binding,
Entity_Type_Use_Package,
Entity_Type_String_Literal,
Entity_Type_File_Contents,
union {
AstInclude *include;
AstUsePackage *use_package;
+ AstBinding *binding;
AstFunction *function;
AstOverloadedFunction *overloaded_function;
AstGlobal *global;
if (context.options->verbose_output == 3) {
if (ent->expr && ent->expr->token)
printf("%s | %s | %s:%i:%i\n",
- entity_state_strings[ent->state],
- entity_type_strings[ent->type],
- ent->expr->token->pos.filename,
- ent->expr->token->pos.line,
- ent->expr->token->pos.column);
+ entity_state_strings[ent->state],
+ entity_type_strings[ent->type],
+ ent->expr->token->pos.filename,
+ ent->expr->token->pos.line,
+ ent->expr->token->pos.column);
+
+ else if (ent->expr)
+ printf("%s | %s\n",
+ entity_state_strings[ent->state],
+ entity_type_strings[ent->type]);
}
+
+ // CLEANUP: There should be a nicer way to track if the builtins have
+ // already been initialized.
+ static b32 builtins_initialized = 0;
switch (ent->state) {
case Entity_State_Parse_Builtin:
process_load_entity(ent);
ent->state = Entity_State_Finalized;
- if (onyx_has_errors()) return 0;
-
- initialize_builtins(context.ast_alloc);
+ case Entity_State_Introduce_Symbols:
+ // Currently, introducing symbols is handled in the symbol resolution
+ // function. Maybe there should be a different place where that happens?
+ symres_entity(ent);
break;
-
+
case Entity_State_Parse:
+ if (!builtins_initialized) {
+ builtins_initialized = 1;
+ initialize_builtins(context.ast_alloc);
+ }
+
process_load_entity(ent);
ent->state = Entity_State_Finalized;
break;
#if defined(_BH_LINUX)
static void output_dummy_progress_bar() {
EntityHeap* eh = &context.entities;
+ if (bh_arr_length(eh->entities) == 0) return;
printf("\e[2;1H");
for (i32 i = 0; i < Entity_State_Count - 1; i++) {
const char* entity_state_strings[Entity_State_Count] = {
"Error",
"Parse Builtin",
+ "Introduce Symbols",
"Parse",
- "Resolve_Symbols",
- "Check_Types",
- "Code_Gen",
+ "Resolve Symbols",
+ "Check Types",
+ "Code Gen",
"Finalized",
};
"Unknown",
"Add to Load Path",
"Load File",
+ "Binding (Declaration)",
"Use Package",
"String Literal",
"File Contents",
break;
}
+ case Ast_Kind_Binding: {
+ ent.state = Entity_State_Introduce_Symbols;
+ ent.type = Entity_Type_Binding;
+ ent.binding = (AstBinding *) node;
+ entity_heap_insert(entities, ent);
+ break;
+ }
+
case Ast_Kind_Function: {
if ((node->flags & Ast_Flag_Foreign) != 0) {
ent.type = Entity_Type_Foreign_Function_Header;
-// The job of the parser for Onyx is to do two things:
-// 1. Submit nodes to the entity heap for further processing.
-// Nodes such as procedure defintions, string literals, etc.
-//
-// 2. Insert static symbols into scopes.
-// Things defined at top level or inside of static scopes such
-// as bindings in procedures or in struct scopes.
+// The sole job of the parser for Onyx is to submit nodes to the
+// entity heap for further processing. These nodes include things
+// such as procedure definitions, string literals, struct definitions
+// and declarations to be introduced into scopes.
// Things that need to be cleaned up in the parser:
// - control block local variables should be more extensible and reuse more code
#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 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 };
AstBinding* binding = parse_top_level_binding(parser, symbol);
if (parser->hit_unexpected_token) return 2;
- Scope* insertion_scope = bh_arr_last(parser->scope_stack);
- symbol_introduce(insertion_scope, symbol, binding->node);
+ ENTITY_SUBMIT(binding);
return 2;
}
consume_token(parser);
AstBinding* binding = parse_top_level_binding(parser, binding_name);
- symbol_introduce(s_node->scope, binding->token, binding->node);
+ ENTITY_SUBMIT(binding);
consume_token_if_next(parser, ';');
target_scope = parser->package->private_scope;
if (((AstBinding *) curr_stmt)->node->flags & Ast_Flag_Private_File)
target_scope = parser->file_scope;
-
- symbol_introduce(target_scope,
- ((AstBinding *) curr_stmt)->token,
- ((AstBinding *) curr_stmt)->node);
+
+ ENTITY_SUBMIT_IN_SCOPE(curr_stmt, target_scope);
break;
}
EntityState next_state = Entity_State_Check_Types;
switch (ent->type) {
+ case Entity_Type_Binding: {
+ symbol_introduce(curr_scope, ent->binding->token, ent->binding->node);
+ next_state = Entity_State_Finalized;
+ break;
+ }
+
case Entity_Type_Foreign_Function_Header:
case Entity_Type_Function_Header: symres_function_header(ent->function); break;
case Entity_Type_Function: symres_function(ent->function); break;