critical bugfixes and sublime/vim compiliation support
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Sat, 29 Aug 2020 20:01:55 +0000 (15:01 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Sat, 29 Aug 2020 20:01:55 +0000 (15:01 -0500)
15 files changed:
Makefile
core/builtin.onyx
core/stdio.onyx
include/bh.h
misc/onyx.sublime-build [new file with mode: 0644]
misc/onyx_compiler.vim [new file with mode: 0644]
onyx
progs/poly_test.onyx
progs/wasi_test.onyx
src/onyx.c
src/onyxclone.c
src/onyxmsgs.c
src/onyxparser.c
src/onyxutils.c
src/onyxwasm.c

index 177c8395c7cbb5f6629180f4644f4c60a2a190bf..21ec20250db27a7141109707c3d04a316458166d 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -37,8 +37,10 @@ install: $(TARGET) core/*
        cp -r core/ /usr/share/onyx
 
 install_syntax: misc/onyx.vim misc/onyx.sublime-syntax
+       cp ./misc/onyx_compiler.vim /usr/share/vim/vim82/compiler/onyx.vim
        cp ./misc/onyx.vim /usr/share/vim/vim82/syntax/onyx.vim
        cp ./misc/onyx.sublime-syntax /home/brendan/.config/sublime-text-3/Packages/User/onyx.sublime-syntax
+       cp ./misc/onyx.sublime-build /home/brendan/.config/sublime-text-3/Packages/User/Onyx.sublime-build
 
 clean:
        rm -f $(OBJ_FILES) 2>&1 >/dev/null
index 022be1df5948818a89ccba895633bbe8b23f8d46..694a074489c05e8073d4643274f692f301869858 100644 (file)
@@ -7,6 +7,9 @@ Buffer :: #type []void;
 
 null :: cast(rawptr) 0;
 
+// ---------------------------------
+//           Allocation
+// ---------------------------------
 DEFAULT_ALLOCATION_ALIGNMENT :: 16
 
 AllocAction :: enum {
@@ -38,6 +41,11 @@ calloc  :: proc (size: u32) -> rawptr do return alloc(context.allocator, size);
 cresize :: proc (ptr: rawptr, size: u32) -> rawptr do return resize(context.allocator, ptr, size);
 cfree   :: proc (ptr: rawptr) do free(context.allocator, ptr);
 
+
+
+// ---------------------------------
+//           Dynamic Arrays
+// ---------------------------------
 array_init :: proc (arr: ^[..] $T, initial_cap := 4) {
     arr.count = 0;
     arr.capacity = initial_cap;
@@ -78,7 +86,7 @@ array_add_at :: proc (arr: ^[..] $T, x: T, idx: u32) {
 }
 
 array_remove :: proc (arr: ^[..] $T, elem: T) {
-    move  := 0;
+    move := 0;
 
     for i: 0, arr.count - move {
         if arr.data[i + move] == elem do move += 1;
@@ -117,8 +125,12 @@ array_average :: proc (arr: ^[..] $T) -> T {
     return sum / cast(T) arr.count;
 }
 
+array_to_slice :: proc (arr: ^[..] $T) -> [] T {
+    return arr.data[0 : arr.count];
+}
+
 
 context : struct {
        allocator      : Allocator;
        temp_allocator : Allocator;
-}
\ No newline at end of file
+}
index 5eab4dfea99722a3a52ab3ad60a72174cf6aa0ca..9402b756199192c8b9194ca2d679b1cabe6c727d 100644 (file)
@@ -10,15 +10,15 @@ print_string  :: proc (s: string) {
 }
 
 print_cstring :: proc (s: cstring) do string_builder_append(^cout_state.sb, s);
-print_u64     :: proc (n: u64, base := 10l) do string_builder_append(^cout_state.sb, n, base);
-print_u32     :: proc (n: u32, base := 10)  do string_builder_append(^cout_state.sb, cast(u64) n, cast(u64) base);
+print_i64     :: proc (n: i64, base := 10l) do string_builder_append(^cout_state.sb, n, base);
+print_i32     :: proc (n: i32, base := 10)  do string_builder_append(^cout_state.sb, cast(i64) n, cast(u64) base);
 print_bool    :: proc (b: bool) do string_builder_append(^cout_state.sb, b);
 
 print :: proc #overloaded {
        print_string,
        print_cstring,
-       print_u64,
-       print_u32,
+       print_i64,
+       print_i32,
        print_bool,
 }
 
index 0a44d9af1d23ab937f057282d0a3afee86c22d6d..e5f0be8655a4cf852d73b87fe07c65a1ef8775a5 100644 (file)
@@ -1,6 +1,9 @@
 #ifndef BH_H
 #define BH_H
 
+// NOTE: For lseek64
+#define _LARGEFILE64_SOURCE
+
 #include <sys/stat.h>
 #include <unistd.h>
 #include <fcntl.h>
@@ -1255,9 +1258,9 @@ bh_file_error bh_file_open_mode(bh_file* file, bh_file_mode mode, const char* fi
     i32 os_mode = 0;
 
     switch (mode & BH_FILE_MODE_MODES) {
-    case BH_FILE_MODE_READ:                         os_mode = O_RDONLY; break;
-    case BH_FILE_MODE_WRITE:                        os_mode = O_WRONLY | O_CREAT | O_TRUNC; break;
-    case BH_FILE_MODE_APPEND:                       os_mode = O_RDONLY | O_APPEND | O_CREAT; break;
+    case BH_FILE_MODE_READ:                       os_mode = O_RDONLY; break;
+    case BH_FILE_MODE_WRITE:                      os_mode = O_WRONLY | O_CREAT | O_TRUNC; break;
+    case BH_FILE_MODE_APPEND:                     os_mode = O_RDONLY | O_APPEND | O_CREAT; break;
     case BH_FILE_MODE_READ   | BH_FILE_MODE_RW:   os_mode = O_RDWR; break;
     case BH_FILE_MODE_WRITE  | BH_FILE_MODE_RW:   os_mode = O_RDWR | O_CREAT | O_TRUNC; break;
     case BH_FILE_MODE_APPEND | BH_FILE_MODE_RW:   os_mode = O_RDWR | O_APPEND | O_CREAT; break;
@@ -1293,8 +1296,8 @@ b32 bh_file_read_at(bh_file* file, i64 offset, void* buffer, isize buff_size, is
 b32 bh_file_write_at(bh_file* file, i64 offset, void const* buffer, isize buff_size, isize* bytes_wrote) {
     isize res;
     i64 current_offset = 0;
-    bh__file_seek_wrapper(file->fd, offset, BH_FILE_WHENCE_CURRENT, &current_offset);
-    if (current_offset == offset) {
+    bh__file_seek_wrapper(file->fd, 0, BH_FILE_WHENCE_CURRENT, &current_offset);
+    if (current_offset == offset || file->fd == 1 || file->fd == 2) {
         // Standard in and out do like pwrite()
         res = write(file->fd, buffer, buff_size);
     } else {
@@ -1307,7 +1310,7 @@ b32 bh_file_write_at(bh_file* file, i64 offset, void const* buffer, isize buff_s
 }
 
 static b32 bh__file_seek_wrapper(i32 fd, i64 offset, bh_file_whence whence, i64* new_offset) {
-    i64 res = lseek(fd, offset, whence);
+    i64 res = lseek64(fd, offset, whence);
     if (res < 0) return 0;
     if (new_offset) *new_offset = res;
     return 1;
diff --git a/misc/onyx.sublime-build b/misc/onyx.sublime-build
new file mode 100644 (file)
index 0000000..fcf81ea
--- /dev/null
@@ -0,0 +1,7 @@
+{
+       "target": "exec",
+       "shell_cmd": "/usr/bin/onyx -o \"${folder}/${file_base_name}.wasm\" \"$file\"",
+       "working_dir": "${folder}",
+       "selector": "source.onyx",
+       "file_regex": "^\\(([^:]+):([0-9]+),([0-9]+)\\) (.*)",
+}
\ No newline at end of file
diff --git a/misc/onyx_compiler.vim b/misc/onyx_compiler.vim
new file mode 100644 (file)
index 0000000..dd24239
--- /dev/null
@@ -0,0 +1,19 @@
+" Vim compiler file
+" Compiler:             Onyx
+" Previous Maintainer:  Brendan Hansen <brendan.f.hansen@gmail.com>
+" Latest Revision:      2020-08-29
+
+if exists("current_compiler")
+  finish
+endif
+let current_compiler = "onyx"
+
+let s:cpo_save = &cpo
+set cpo&vim
+
+CompilerSet errorformat=%E\(%f\:%l\\,%c\)\ \%m,%C%.%#
+
+set makeprg=onyx\ %
+
+let &cpo = s:cpo_save
+unlet s:cpo_save
diff --git a/onyx b/onyx
index c9f25d80b16920f3d678788c514c1988f927cad7..ceacaca6cc918d42e89930c37ec176f37c11c934 100755 (executable)
Binary files a/onyx and b/onyx differ
index 430f4636ee824587d444bed8e8652f54f2b99494..45ccbbf4654774a52fdc260082563fe97c434b49 100644 (file)
@@ -11,11 +11,7 @@ package main
 #include_file "file"
 
 use package builtin
-
-// NOTE: Didn't realize this would work so easily
-use package core { string_builder_append as sba }
 use package core
-
 use package memory
 use package wasi
 use package intrinsics
@@ -30,10 +26,15 @@ print_arr_details :: proc (arr: ^[..] $T) {
     print(arr.capacity);
     print("\n\tData ptr: ");
     print(cast(u32) arr.data, 16);
+    print("\n\tSize of elements: ");
+    print(sizeof T);
+    print("\n\tAlignment of elements: ");
+    print(alignof T);
     print("\n\n");
 }
 
-print_arr :: proc (arr: ^[..] $T) {
+// This works on both slices and arrays
+print_arr :: proc (arr: $T) {
     for i: 0, arr.count {
         print(arr.data[i]);
         print(" ");
@@ -42,26 +43,61 @@ print_arr :: proc (arr: ^[..] $T) {
     print("\n");
 }
 
-print_vec_arr :: proc (arr: ^[..] Vec3) {
+print_vec_arr :: proc (arr: [..] Vec3) {
     for i: 0, arr.count {
         print("Vec3(");
-        print(arr.data[i].x);
+        print(arr[i].x);
         print(", ");
-        print(arr.data[i].y);
+        print(arr[i].y);
         print(", ");
-        print(arr.data[i].z);
+        print(arr[i].z);
         print(")\n");
     }
 
     print("\n");
 }
 
+// This demonstrates that we have something similar to static 'duck' typing.
+get_count :: proc (x: $T) -> u32 do return x.count;
+
+
+
+SOA :: struct {
+    a  : [..] i32;
+    b  : [..] i64;
+}
+
 main :: proc (args: [] cstring) {
+    s : SOA;
+    array_init(^s.a, 10);
+    array_init(^s.b, 10);
+    defer array_free(^s.a);
+    defer array_free(^s.b);
+
+    print_arr_details(^s.a);
+    print_arr_details(^s.b);
+
+    for i: 0, 100 {
+        array_add(^s.a, 5 * i);
+        array_add(^s.b, 3l * cast(i64) i);
+    }
+
+    print_arr(^s.a);
+    print_arr(array_to_slice(^s.a));
+
+    print("After adding...\n");
+    print_arr_details(^s.a);
+    print_arr_details(^s.b);
+}
+
+main2 :: proc (args: [] cstring) {
     print(cast(u32) __heap_start, 16);
 
+    iarr_backing : [32] i32;
     iarr : [..] i32;
-    array_init(^iarr, 24);
-    defer array_free(^iarr);
+    iarr.data = cast(^i32) iarr_backing;
+    iarr.count = 0;
+    iarr.capacity = 32;
 
     print_arr_details(^iarr);
 
@@ -116,15 +152,28 @@ main :: proc (args: [] cstring) {
     defer array_free(^varr);
 
     for i: 0, 20 {
-        array_add(^varr, Vec3.{ i, i * i, i * i * i });
+        array_add(^varr, Vec3.{
+            x = i,
+            y = i * i,
+            z = i * i * i,
+        });
     }
 
+    array_add(^varr, Vec3.{ 4, 2, 3 });
+
     print_arr_details(^varr);
-    print_vec_arr(^varr);
+    print_vec_arr(varr);
+
+    print(get_count(iarr));
+    print("\n");
+    print(get_count(barr));
+    print("\n");
+    print(get_count(varr));
+    print("\n");
 }
 
 Vec3 :: struct {
     x: i32;
     y: i32;
     z: i32;
-}
\ No newline at end of file
+}
index 62fbc25dec5e85da51d21a84d099f688886f7c19..45a4cb3132a3071f3509f3a683002a204fb6a5d6 100644 (file)
@@ -81,10 +81,10 @@ readdir :: proc (fd: FileDescriptor) {
         print("\n");
 
         print("\td_namlen: ");
-        print_u64(cast(u64) dirent.d_namlen, 16l);
+        print_i64(cast(u64) dirent.d_namlen, 16l);
         print("\n");
         print("\td_type: ");
-        print_u64(cast(u64) dirent.d_type, 16l);
+        print_i64(cast(u64) dirent.d_type, 16l);
         print("\n");
 
         bufused -= sizeof DirEnt + dirent.d_namlen;
@@ -186,7 +186,7 @@ main :: proc (args: []cstring) {
     sum := 0l;
     for i: 0, 20000 do if is_prime(i) do sum += cast(u64) i;
     print("Sum of primes less than 20000 is: ");
-    print_u64(sum);
+    print_i64(sum);
     print("\n");
 
     matches := string_split("This is a test string to test splitting. It surprisingly works very well.", #char " ");
@@ -215,7 +215,7 @@ main :: proc (args: []cstring) {
 
             case #default {
                 print("Unexpected token: ");
-                print_u64(cast(u64) tokens[i][0], 16l);
+                print_i64(cast(u64) tokens[i][0], 16l);
                 print("\n");
 
                 // This breaks out of the for loop
@@ -275,9 +275,9 @@ main :: proc (args: []cstring) {
     foobar(10, 1230);
 
     sl := make_i32_arr();
-    print_u64(cast(u64) sl.count);
+    print_i64(cast(u64) sl.count);
 
-    print_u64(cast(u64) fib(20));
+    print_i64(cast(u64) fib(20));
     print("\n");
 
     print(add(20l, 5l));
@@ -313,11 +313,11 @@ main :: proc (args: []cstring) {
 }
 
 foobar :: proc (a: i32, b := 1, c := 5l) {
-    print_u64(cast(u64) a);
+    print_i64(cast(u64) a);
     print("\n");
-    print_u64(cast(u64) b, 16l);
+    print_i64(cast(u64) b, 16l);
     print("\n");
-    print_u64(c);
+    print_i64(c);
     print("\n");
 }
 
index 4a86739724bd39705464b8bb410c61717182f962..32880828f61844a11475540f83b0bdff9a7cf4e3 100644 (file)
@@ -387,7 +387,7 @@ static i32 onyx_compile(CompilerState* compiler_state) {
     if (compiler_state->options->action == ONYX_COMPILE_ACTION_DOCUMENT) {
         OnyxDocumentation docs = onyx_docs_generate(&compiler_state->prog_info);
         onyx_docs_write(&docs);
-        
+
         return ONYX_COMPILER_PROGRESS_SUCCESS;
     }
 
@@ -462,7 +462,7 @@ int main(int argc, char *argv[]) {
             break;
 
         case ONYX_COMPILER_PROGRESS_SUCCESS:
-            if (compile_opts.verbose_output) bh_printf("Successfully compiled to '%s'\n", compile_opts.target_file);
+            bh_printf("Successfully compiled to '%s'\n", compile_opts.target_file);
             break;
     }
 
index 459d4630adf8388dfdcef3261e50d573cec48cf6..bbf5852646eace7d9483995ca8d2dd36e7a29f92 100644 (file)
@@ -201,6 +201,7 @@ AstNode* ast_clone(bh_allocator a, void* n) {
                case Ast_Kind_Block:
                        ((AstBlock *) nn)->body = ast_clone_list(a, ((AstBlock *) node)->body);
                        ((AstBlock *) nn)->locals = NULL;
+                       bh_arr_new(global_heap_allocator, ((AstBlock *) nn)->locals, 4);
                        break;
 
                case Ast_Kind_Defer:
@@ -288,6 +289,9 @@ AstNode* ast_clone(bh_allocator a, void* n) {
                        df->return_type = (AstType *) ast_clone(a, sf->return_type);
                        df->body = (AstBlock *) ast_clone(a, sf->body);
 
+                       df->locals = NULL;
+                   bh_arr_new(global_heap_allocator, df->locals, 4);
+
                        df->params = NULL;
                        bh_arr_new(global_heap_allocator, df->params, bh_arr_length(sf->params));
 
index 539a8730339a6d61ae9835e0500211c565ae5b9c..b436e9a92e23adb373f6fbe6719eb830913c1ce7 100644 (file)
@@ -59,6 +59,7 @@ void onyx_message_add(MsgType type, OnyxFilePos pos, ...) {
     va_end(arg_list);
 
     Message** walker = &msgs.first;
+    while (*walker && strcmp((*walker)->pos.filename, pos.filename) < 0) walker = &(*walker)->next;
     while (*walker && (*walker)->pos.line < pos.line) walker = &(*walker)->next;
     while (*walker && (*walker)->pos.line == pos.line && (*walker)->pos.column < pos.column) walker = &(*walker)->next;
 
index 8db27f256f890b99cd67c7dbb5940f6fe18dc072..177b4ad686bb7b4f1eec7ec20394b8a63a7b7e79 100644 (file)
@@ -1129,12 +1129,12 @@ static AstBlock* parse_block(OnyxParser* parser) {
 
     // NOTE: --- is for an empty block
     if (parser->curr->type == Token_Type_Empty_Block) {
-        expect_token(parser, Token_Type_Empty_Block);
+        block->token = expect_token(parser, Token_Type_Empty_Block);
         return block;
     }
 
     if (parser->curr->type == Token_Type_Keyword_Do) {
-        consume_token(parser);
+        block->token = expect_token(parser, Token_Type_Keyword_Do);
         block->body = parse_statement(parser);
         return block;
     }
@@ -1144,7 +1144,7 @@ static AstBlock* parse_block(OnyxParser* parser) {
         find_token(parser, '}');
         return block;
     }
-    expect_token(parser, '{');
+    block->token = expect_token(parser, '{');
 
     AstNode** next = &block->body;
     AstNode* stmt = NULL;
index 73cb70e4fe02d6d2f8ab291af4d93f5b1d3e9b6a..00c7bae42c564882379336369db5454571745a1e 100644 (file)
@@ -431,10 +431,19 @@ AstFunction* polymorphic_proc_lookup(AstPolyProc* pp, AstCall* call) {
     bh_table_put(AstFunction *, pp->concrete_funcs, key_buf, func);
 
     symres_function(func);
-    if (onyx_message_has_errors()) return NULL;
-    if (check_function_header(func)) return NULL;
-    if (check_function(func)) return NULL;
-    if (onyx_message_has_errors()) return NULL;
+    if (onyx_message_has_errors()) goto has_error;
+    if (check_function_header(func)) goto has_error;
+    if (check_function(func)) goto has_error;
+    if (onyx_message_has_errors()) goto has_error;
+    goto no_errors;
+
+has_error:
+    onyx_message_add(Msg_Type_Literal,
+            call->token->pos,
+            "error in polymorphic procedure generated from this call site.");
+    return NULL;
+
+no_errors:
 
     bh_arr_push(semstate.other_entities, ((Entity) {
         .type = Entity_Type_Function_Header,
index 13661c7a25049e1b1b8ad11baf88274d8c408ee1..f79e6ca11a34f5dc7ca04a687ce420e6132a7fb9 100644 (file)
@@ -1175,7 +1175,7 @@ COMPILE_FUNC(array_access_location, AstArrayAccess* aa, u64* offset_return) {
     } else if (aa->addr->kind == Ast_Kind_Field_Access
         && aa->addr->type->kind == Type_Kind_Array) {
         compile_field_access_location(mod, &code, (AstFieldAccess *) aa->addr, &offset);
-    } else if (aa->addr->kind == Ast_Kind_Local
+    } else if ((aa->addr->kind == Ast_Kind_Local || aa->addr->kind == Ast_Kind_Param)
         && aa->addr->type->kind == Type_Kind_Array) {
         compile_local_location(mod, &code, (AstLocal *) aa->addr, &offset);
     } else if (aa->addr->kind == Ast_Kind_Memres
@@ -1207,7 +1207,7 @@ COMPILE_FUNC(field_access_location, AstFieldAccess* field, u64* offset_return) {
         u64 o2 = 0;
         compile_array_access_location(mod, &code, (AstArrayAccess *) source_expr, &o2);
         offset += o2;
-    } else if (source_expr->kind == Ast_Kind_Local
+    } else if ((source_expr->kind == Ast_Kind_Local || source_expr->kind == Ast_Kind_Param)
         && source_expr->type->kind != Type_Kind_Pointer) {
         u64 o2 = 0;
         compile_local_location(mod, &code, (AstLocal *) source_expr, &o2);
@@ -1603,7 +1603,7 @@ COMPILE_FUNC(expression, AstTyped* expr) {
                 WID(WI_I32_CONST, sl->elem_size);
                 WI(WI_I32_MUL);
             }
-            compile_location(mod, &code, sl->addr);
+            compile_expression(mod, &code, sl->addr);
             WI(WI_I32_ADD);
             compile_expression(mod, &code, sl->hi);
             WIL(WI_LOCAL_GET, tmp_local);