--- /dev/null
+The current way I do symbol resolution is:
+ - Join all top level symbols at parse time into a single struct
+ - Add all top level symbols to a string table that maps from
+ their name to their AST node
+ - Then step through every function linearly and resolve each symbol using the table
+ * Function locals are added when they are declared and then removed at the end
+ of their scope as would be expected
+
+This method works, but it is not great and feels like a hack.
+ - References to other things are just pointers to the AST node
+ - This produces a heavy reliance on the AST instead of other, more efficient data structures
+
+
+
+
+PROPOSED NEW METHOD:
+ Every top level declaration will add a declinfo entry that will contain the following information:
+ - Identifier
+ - Pointer to AST node
--- /dev/null
+Some optimizations to make to the output WASM:
+ [ ] local.set followed by local.get turns into local.tee
+ [ ] Dead code elimination
+ - Function level: If a function is not explicitly called or exported, it may be removed
+ - Local level: If a local is not read, it may be removed
+ [ ] Add compile-time evaluation for simple operations
+ [ ] If statement compile-time condition evaluation
+ - If the condition of an if statement is compile time known, only generate the case that
+ is used
+ [ ] Inline-ing functions that have been explicitly marked
+
void* onyx_ast_node_new(bh_allocator alloc, i32 size, AstNodeKind kind);
OnyxParser onyx_parser_create(bh_allocator alloc, OnyxTokenizer *tokenizer, OnyxMessages* msgs);
void onyx_parser_free(OnyxParser* parser);
-AstNode* onyx_parse(OnyxParser *parser);
+bh_arr(AstNode *) onyx_parse(OnyxParser *parser);
#endif // #ifndef ONYXPARSER_H
bh_arr_free(opts->files);
}
-static AstNode* parse_source_file(CompilerState* compiler_state, bh_file_contents* file_contents) {
+static bh_arr(AstNode *) parse_source_file(CompilerState* compiler_state, bh_file_contents* file_contents) {
// NOTE: Maybe don't want to recreate the tokenizer and parser for every file
if (compiler_state->options->verbose_output)
bh_printf("[Lexing] %s\n", file_contents->filename);
bh_table_put(bh_file_contents, compiler_state->loaded_files, (char *) filename, fc);
fc = bh_table_get(bh_file_contents, compiler_state->loaded_files, (char *) filename);
- AstNode* root_node = parse_source_file(compiler_state, &fc);
+ bh_arr(AstNode *) top_nodes = parse_source_file(compiler_state, &fc);
- if (compiler_state->options->print_ast) {
- onyx_ast_print(root_node, 0);
- bh_printf("\n");
- }
-
- AstNode* walker = root_node;
- while (walker) {
- switch (walker->kind) {
+ bh_arr_each(AstNode *, node, top_nodes) {
+ switch ((*node)->kind) {
case AST_NODE_KIND_USE:
- bh_arr_push(compiler_state->program.uses, (AstNodeUse *) walker);
+ bh_arr_push(compiler_state->program.uses, (AstNodeUse *) (*node));
break;
case AST_NODE_KIND_GLOBAL:
- bh_arr_push(compiler_state->program.globals, (AstNodeGlobal *) walker);
+ bh_arr_push(compiler_state->program.globals, (AstNodeGlobal *) (*node));
break;
case AST_NODE_KIND_FOREIGN:
- bh_arr_push(compiler_state->program.foreigns, (AstNodeForeign *) walker);
+ bh_arr_push(compiler_state->program.foreigns, (AstNodeForeign *) (*node));
break;
case AST_NODE_KIND_FUNCTION:
- bh_arr_push(compiler_state->program.functions, (AstNodeFunction *) walker);
- break;
-
- case AST_NODE_KIND_PROGRAM:
- // Dummy initial node
+ bh_arr_push(compiler_state->program.functions, (AstNodeFunction *) (*node));
break;
default:
assert(("Invalid top level node", 0));
break;
}
-
- walker = walker->next;
}
bh_arr_each(AstNodeUse *, use_node, compiler_state->program.uses) {
static void parser_prev_token(OnyxParser* parser);
static b32 is_terminating_token(TokenType token_type);
static OnyxToken* expect(OnyxParser* parser, TokenType token_type);
-static AstNodeScope* enter_scope(OnyxParser* parser);
-static AstNodeScope* leave_scope(OnyxParser* parser);
-static void insert_identifier(OnyxParser* parser, AstNode* ident, b32 is_local);
-static void remove_identifier(OnyxParser* parser, AstNode* ident);
static AstNodeNumLit* parse_numeric_literal(OnyxParser* parser);
static AstNodeTyped* parse_factor(OnyxParser* parser);
static AstNodeTyped* parse_expression(OnyxParser* parser);
bh_table_free(parser->identifiers);
}
-AstNode* onyx_parse(OnyxParser *parser) {
- AstNode* program = make_node(AstNode, AST_NODE_KIND_PROGRAM);
+bh_arr(AstNode *) onyx_parse(OnyxParser *parser) {
+ bh_arr(AstNode *) top_level_nodes = NULL;
+ bh_arr_new(global_heap_allocator, top_level_nodes, 4);
- AstNode** prev_stmt = &program->next;
- AstNode* curr_stmt = NULL;
while (parser->curr_token->type != TOKEN_TYPE_END_STREAM) {
- curr_stmt = parse_top_level_statement(parser);
+ AstNode* curr_stmt = parse_top_level_statement(parser);
// Building a linked list of statements down the "next" chain
if (curr_stmt != NULL && curr_stmt != &error_node) {
- *prev_stmt = curr_stmt;
-
- while (curr_stmt->next != NULL) curr_stmt = curr_stmt->next;
- prev_stmt = &curr_stmt->next;
+ while (curr_stmt != NULL) {
+ bh_arr_push(top_level_nodes, curr_stmt);
+ curr_stmt = curr_stmt->next;
+ }
}
}
- return program;
+ return top_level_nodes;
}