Code clean up and added "start" section output
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 16 Jun 2020 04:12:17 +0000 (23:12 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 16 Jun 2020 04:12:17 +0000 (23:12 -0500)
.gitignore
docs/plan
onyx
progs/minimal.onyx
src/onyx.c
src/onyxutils.c
src/onyxwasm.c

index 8ca5336ca22e411d67de8e46a8ca5439f8eefc8c..e11e2b6947f5ec12e2154ce3f8e7eca4c0041016 100644 (file)
@@ -4,3 +4,4 @@ tags
 test.c
 test
 *.wasm
+*.html
index d78b4992e601f3b3dd9da95167beb47403df5398..d91c21b57d68b6e3ea651dac0fa279ac4b9c7a66 100644 (file)
--- a/docs/plan
+++ b/docs/plan
@@ -31,28 +31,81 @@ HOW:
        at once would be overwhelming and unsatisfying. The current progress of each stage:
 
        Stage 1 (MVP):
-               [ ] Can declare procedures
-               [ ] Procedures have params and returns of the following types:
+               [X] Can declare procedures
+               [X] Procedures have params and returns of the following types:
                        - i32, u32
                        - i64, u64
                        - f32, f64
-               [ ] Procedures have locals of the same set of types
-               [ ] Locals are declared in the following way
-                       local : (const) (type) (= initial value);
+               [X] Procedures have locals of the same set of types
+               [X] Locals are declared in the following way
+                       local : (type) ((= or :) initial value);
 
-                       if const is specified, the value is unmodifiable
+                       if : is used, the value is unmodifiable
                        if type is specified, that is assumed to be the correct type
                        if type is not specified, the type of initial value is used as the type
 
-               [ ] Five basic math operations are legal:
+               [X] Five basic math operations are legal:
                        + - * / %
-               [ ] Math operations are sign aware and only operate on operands of the same type
-               [ ] All casts are explicit using this syntax:
+               [X] Math operations are sign aware and only operate on operands of the same type
+               [X] All casts are explicit using this syntax:
                        X as T
 
                        casts X to type T
 
+               [ ] Numeric literals are parsed and minimum type detected
+               [ ] Comparison operators
+               [ ] Proper boolean type
                [ ] Conditional branching works as expected
                [ ] Curly braces are required for all bodies of blocks
                [ ] Simple while loop is functioning as expected
                [ ] break and continue semantics
+               [ ] Function calling works for the builtin types
+               [ ] Function return values are type checked
+
+       Stage 2:
+               [ ] Order of symbol declaration is irrelevant
+                       Either:
+                       make a graph of symbol dependencies and produce a schedule on the graph
+                       that would allow for all symbols to be resolved
+
+                       OR
+
+                       Do as many passes on the parse tree as needed to resolve all symbols.
+                       This could be slow but it would be easier than creating a graph
+                       scheduling algorithm.
+
+               [ ] Devise and implement a simple set of implicit type casting rules.
+                       - Numeric literals always type cast to whatever type is needed (very flexible).
+
+               [ ] Start work on evaluating compile time known values.
+                       - An expression marked COMPTIME will be reduced to its value in the parse tree.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/onyx b/onyx
index 532e9c8dca6cd6f33c97a34c8a62fb2c9bacbc7a..74ff9b5d862da4e596e74b3de33f281ac0dcdca4 100755 (executable)
Binary files a/onyx and b/onyx differ
index ba83edb0ce98601f2caf7f198bcf6b2d4703f797..17df6c750e699d08084955503074e59e1cdc735a 100644 (file)
@@ -19,4 +19,6 @@ export diff_square :: proc (a i32, b i32) -> i32 {
        return (c * d) as i32;
 }
 
-export dummy :: proc () { }
+export main :: proc () {
+       
+}
index 2c5e9d2b9c11201bcd054ca7f00ec5b25e69693f..c55a7b311db64b72005a8bf2b6c54ce8cb416342 100644 (file)
@@ -19,23 +19,16 @@ int main(int argc, char *argv[]) {
 
        bh_allocator alloc = bh_heap_allocator();
 
+       // NOTE: 1st: Read file contents
        bh_file_contents fc = bh_file_read_contents(alloc, &source_file);
        bh_file_close(&source_file);
 
+       // NOTE: 2nd: Tokenize the contents
        OnyxTokenizer tokenizer = onyx_tokenizer_create(alloc, &fc);
        onyx_lex_tokens(&tokenizer);
        bh_arr(OnyxToken) token_arr = tokenizer.tokens;
 
-#if 0
-       bh_printf("There are %d tokens (Allocated space for %d tokens)\n", bh_arr_length(token_arr), bh_arr_capacity(token_arr));
-
-       bh_arr_each(OnyxToken, it, token_arr) {
-               onyx_token_null_toggle(*it);
-               bh_printf("%s (%s:%l:%l)\n", onyx_get_token_type_name(it->type), it->pos.filename, it->pos.line, it->pos.column);
-               onyx_token_null_toggle(*it);
-       }
-#endif
-
+       // NOTE: Create the buffer for where compiler messages will be written
        bh_arena msg_arena;
        bh_arena_init(&msg_arena, alloc, 4096);
        bh_allocator msg_alloc = bh_arena_allocator(&msg_arena);
@@ -43,10 +36,13 @@ int main(int argc, char *argv[]) {
        OnyxMessages msgs;
        onyx_message_create(msg_alloc, &msgs);
 
+       // NOTE: Create the arena where AST nodes will exist
+       // Prevents nodes from being scattered across memory due to fragmentation
        bh_arena ast_arena;
        bh_arena_init(&ast_arena, alloc, 16 * 1024 * 1024); // 16MB
        bh_allocator ast_alloc = bh_arena_allocator(&ast_arena);
 
+       // NOTE: 3rd: parse the tokens to an AST
        OnyxParser parser = onyx_parser_create(ast_alloc, &tokenizer, &msgs);
        OnyxAstNode* program = onyx_parse(&parser);
 
@@ -56,13 +52,42 @@ int main(int argc, char *argv[]) {
                onyx_message_print(&msgs);
                goto main_exit;
        } else {
-               onyx_ast_print(program, 0);
+               // onyx_ast_print(program, 0);
                bh_printf("\nNo errors.\n");
        }
 
+       // NOTE: 4th: Generate a WASM module from the parse tree and
+       // write it to a file.
        OnyxWasmModule wasm_mod = onyx_wasm_generate_module(alloc, program);
 
-#if 1
+       bh_file out_file;
+       bh_file_create(&out_file, "out.wasm");
+       onyx_wasm_module_write_to_file(&wasm_mod, out_file);
+       bh_file_close(&out_file);
+
+       onyx_wasm_module_free(&wasm_mod);
+main_exit: // NOTE: Cleanup, since C doesn't have defer
+       bh_arena_free(&msg_arena);
+       bh_arena_free(&ast_arena);
+       onyx_parser_free(&parser);
+       onyx_tokenizer_free(&tokenizer);
+       bh_file_contents_free(&fc);
+
+       return 0;
+}
+
+// NOTE: Old bits of code that may be useful again at some point.
+#if 0
+       bh_printf("There are %d tokens (Allocated space for %d tokens)\n", bh_arr_length(token_arr), bh_arr_capacity(token_arr));
+
+       bh_arr_each(OnyxToken, it, token_arr) {
+               onyx_token_null_toggle(*it);
+               bh_printf("%s (%s:%l:%l)\n", onyx_get_token_type_name(it->type), it->pos.filename, it->pos.line, it->pos.column);
+               onyx_token_null_toggle(*it);
+       }
+#endif
+
+#if 0
        // NOTE: Ensure type table made correctly
 
        bh_printf("Type map:\n");
@@ -83,7 +108,7 @@ int main(int argc, char *argv[]) {
        }
 #endif
 
-#if 1
+#if 0
        // NOTE: Ensure the export table was built correctly
 
        bh_printf("Function types:\n");
@@ -96,19 +121,3 @@ int main(int argc, char *argv[]) {
                bh_printf("%s: %d %d\n", key, value.kind, value.idx);
        bh_hash_each_end;
 #endif
-
-       bh_file out_file;
-       bh_file_create(&out_file, "out.wasm");
-       onyx_wasm_module_write_to_file(&wasm_mod, out_file);
-       bh_file_close(&out_file);
-
-       onyx_wasm_module_free(&wasm_mod);
-main_exit: // NOTE: Cleanup, since C doesn't have defer
-       bh_arena_free(&msg_arena);
-       bh_arena_free(&ast_arena);
-       onyx_parser_free(&parser);
-       onyx_tokenizer_free(&tokenizer);
-       bh_file_contents_free(&fc);
-
-       return 0;
-}
index aff6aba5f38e09d0d4a3a37cdd59aae23ecd44be..ba50b4eec8fc2bea2fd50dfc9320b005926b1810 100644 (file)
@@ -89,8 +89,8 @@ void onyx_ast_print(OnyxAstNode* node, i32 indent) {
        }
 
        case ONYX_AST_NODE_KIND_RETURN: {
-               if (node->next) {
-                       onyx_ast_print(node->next, indent + 1);
+               if (node->left) {
+                       onyx_ast_print(node->left, indent + 1);
                }
 
                break;
index 35aabd435d2a7534e6ca41bd4f69835adff1cdf4..4b9f2007f94a571780bff5121ddcefef9b247c05 100644 (file)
@@ -510,24 +510,9 @@ static void process_function_definition(OnyxWasmModule* mod, OnyxAstNodeFuncDef*
                count++;
        }
 
-
-       bh_printf("\nLocals for function: %b\n", fd->token->token, fd->token->length);
-       bh_printf("\tI32 count: %d\n", wasm_func.locals.i32_count);
-       bh_printf("\tI64 count: %d\n", wasm_func.locals.i64_count);
-       bh_printf("\tF32 count: %d\n", wasm_func.locals.f32_count);
-       bh_printf("\tF64 count: %d\n", wasm_func.locals.f64_count);
-       bh_hash_each_start(i32, mod->local_map);
-               bh_printf("\t%s -> %d\n", key, value);
-       bh_hash_each_end;
-
        // Generate code
        process_function_body(mod, &wasm_func, fd);
 
-       bh_printf("Code for function:\n");
-       bh_arr_each(WasmInstruction, instr, wasm_func.code) {
-               bh_printf("\t%s\t%xd\n", wi_string(instr->type), instr->data.i1);
-       }
-
        bh_arr_push(mod->funcs, wasm_func);
 
        // NOTE: Clear the local map on exit of generating this function
@@ -719,6 +704,34 @@ static i32 output_exportsection(OnyxWasmModule* module, bh_buffer* buff) {
        return buff->length - prev_len;
 }
 
+static i32 output_startsection(OnyxWasmModule* module, bh_buffer* buff) {
+       i32 prev_len = buff->length;
+
+       i32 start_idx = -1;
+       bh_hash_each_start(WasmExport, module->exports) {
+               if (value.kind == WASM_EXPORT_FUNCTION) {
+                       if (strncmp("main", key, 5) == 0) {
+                               start_idx = value.idx;
+                               break;
+                       }
+               }
+       } bh_hash_each_end;
+
+       if (start_idx != -1) {
+               bh_buffer_write_byte(buff, WASM_SECTION_ID_START);
+
+               i32 start_leb_len, section_leb_len;
+               u8* start_leb = uint_to_uleb128((u64) start_idx, &start_leb_len);
+               u8* section_leb = uint_to_uleb128((u64) start_leb_len, &section_leb_len);
+               bh_buffer_append(buff, section_leb, section_leb_len);
+
+               start_leb = uint_to_uleb128((u64) start_idx, &start_leb_len);
+               bh_buffer_append(buff, start_leb, start_leb_len);
+       }
+
+       return buff->length - prev_len;
+}
+
 static i32 output_locals(WasmFunc* func, bh_buffer* buff) {
        i32 prev_len = buff->length;
 
@@ -840,8 +853,8 @@ void onyx_wasm_module_write_to_file(OnyxWasmModule* module, bh_file file) {
        output_typesection(module, &master_buffer);
        output_funcsection(module, &master_buffer);
        output_exportsection(module, &master_buffer);
+       output_startsection(module, &master_buffer);
        output_codesection(module, &master_buffer);
 
-
        bh_file_write(&file, master_buffer.data, master_buffer.length);
 }