readded UFC syntax using the ' operator
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 11 Aug 2020 17:49:17 +0000 (12:49 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 11 Aug 2020 17:49:17 +0000 (12:49 -0500)
.vimspector.json
core/alloc.onyx
core/memory.onyx [new file with mode: 0644]
docs/plan
include/onyxastnodes.h
onyx
progs/heap_resize_test.onyx [new file with mode: 0644]
progs/stack_based.onyx
src/onyxchecker.c
src/onyxparser.c
src/onyxsymres.c

index 3423b8e3a1d43a607d79280eafda28685761fa56..f6625bc264beb33f3eb80a1e1b2df5540e266d01 100644 (file)
@@ -6,7 +6,7 @@
                 "type": "cppdbg",
                 "request": "launch",
                 "program": "${workspaceFolder}/onyx",
-                "args": ["-verbose", "-I", "progs/", "progs/stack_based.onyx"],
+                "args": ["-verbose", "progs/stack_based.onyx"],
                 "stopAtEntry": true,
                 "cwd": "${workspaceFolder}",
                 "environment": [],
index 40b7a4758e504f9fa3305be74e10534e0df74d4f..fda4cdb458b7bec413e786e7ed23bc199a765381 100644 (file)
@@ -1,5 +1,6 @@
 package memory
 
+#include_file "memory"
 #include_file "intrinsics"
 
 use package intrinsics { memory_size, memory_grow }
@@ -24,6 +25,10 @@ alloc :: proc (use a: ^Allocator, size: u32) -> rawptr {
     return func(data, AllocAction.Alloc, size, 16, null);
 }
 
+resize :: proc (use a: ^Allocator, ptr: rawptr, size: u32) -> rawptr {
+    return func(data, AllocAction.Resize, size, 16, ptr);
+}
+
 free :: proc (use a: ^Allocator, ptr: rawptr) {
     func(data, AllocAction.Free, 0, 0, ptr);
 }
@@ -120,9 +125,31 @@ heap_free :: proc (ptr: rawptr) {
     heap_state.free_list = hb_ptr;
 }
 
+#private
+heap_resize :: proc (ptr: rawptr, new_size: u32, align: u32) -> rawptr {
+    hb_ptr := cast(^heap_block) (cast(u32) ptr - sizeof heap_block);
+
+    // If there is already enough space in the current allocated block,
+    // just return the block that already exists and has the memory in it.
+    if hb_ptr.size >= new_size do return ptr;
+
+    // If we are at the end of the allocation space, just extend it
+    if hb_ptr.size + cast(u32) ptr >= cast(u32) heap_state.next_alloc {
+        hb_ptr.size = new_size;
+        heap_state.next_alloc = cast(rawptr) (cast(u32) ptr + hb_ptr.size);
+        return ptr;
+    }
+
+    new_ptr := heap_alloc(new_size, align);
+    memory_copy(new_ptr, ptr, hb_ptr.size);
+    heap_free(ptr);
+    return new_ptr;
+}
+
 #private
 heap_alloc_proc :: proc (data: rawptr, aa: AllocAction, size: u32, align: u32, oldptr: rawptr) -> rawptr {
     if aa == AllocAction.Alloc do return heap_alloc(size, align);
+    if aa == AllocAction.Resize do return heap_resize(oldptr, size, align);
     if aa == AllocAction.Free {
         heap_free(oldptr);
         return null;
@@ -131,5 +158,6 @@ heap_alloc_proc :: proc (data: rawptr, aa: AllocAction, size: u32, align: u32, o
     return null;
 }
 
-malloc :: proc (size: u32) -> rawptr do return alloc(^heap_allocator, size);
-mfree  :: proc (ptr: rawptr) do free(^heap_allocator, ptr);
+malloc  :: proc (size: u32) -> rawptr do return alloc(^heap_allocator, size);
+mfree   :: proc (ptr: rawptr) do free(^heap_allocator, ptr);
+mresize :: proc (ptr: rawptr, size: u32) -> rawptr do return resize(^heap_allocator, ptr, size);
diff --git a/core/memory.onyx b/core/memory.onyx
new file mode 100644 (file)
index 0000000..85f0db4
--- /dev/null
@@ -0,0 +1,19 @@
+package memory
+
+memory_copy :: proc (dst_: rawptr, src_: rawptr, len: u32) {
+       if len % 8 == 0 {
+               dst := cast(^u64) dst_;
+               src := cast(^u64) src_;
+               for i: 0, len >> 3 do dst[i] = src[i];
+               
+       } elseif len % 4 == 0 {
+               dst := cast(^u32) dst_;
+               src := cast(^u32) src_;
+               for i: 0, len >> 2 do dst[i] = src[i];
+
+       } else {
+               dst := cast(^u8) dst_;
+               src := cast(^u8) src_;
+               for i: 0, len do dst[i] = src[i];
+       }
+}
\ No newline at end of file
index 9035a49fdff76c0dcf075603022a125a834a5c88..d0424cfebf3a7783a7f8311685987b62ab7dfcd3 100644 (file)
--- a/docs/plan
+++ b/docs/plan
@@ -161,6 +161,12 @@ HOW:
 
         [X] Include other directories to search for files
 
+        [ ] Arrays need to be much better
+            - Currently, they are basically just a pointer.
+            - The length should be stored with the pointer
+            - Dynamic resizing?
+            - They are just very hard to use at the moment
+
         [ ] 'use' enums and packages at an arbitrary scope
 
         [ ] Array literals
index 4168bc07182fbcf9cdd55d327e50ed570e954876..735df3b9718baf9459209d46419f0e8c66971ed9 100644 (file)
@@ -20,6 +20,7 @@ typedef struct AstAddressOf AstAddressOf;
 typedef struct AstDereference AstDereference;
 typedef struct AstArrayAccess AstArrayAccess;
 typedef struct AstFieldAccess AstFieldAccess;
+typedef struct AstUfc AstUfc;
 typedef struct AstSizeOf AstSizeOf;
 typedef struct AstAlignOf AstAlignOf;
 typedef struct AstFileContents AstFileContents;
@@ -112,6 +113,7 @@ typedef enum AstKind {
     Ast_Kind_Dereference,
     Ast_Kind_Array_Access,
     Ast_Kind_Field_Access,
+    Ast_Kind_Ufc,
     Ast_Kind_Size_Of,
     Ast_Kind_Align_Of,
     Ast_Kind_File_Contents,
@@ -276,6 +278,7 @@ struct AstAddressOf     { AstTyped_base; AstTyped *expr; };
 struct AstDereference   { AstTyped_base; AstTyped *expr; };
 struct AstArrayAccess   { AstTyped_base; AstTyped *addr; AstTyped *expr; u64 elem_size; };
 struct AstFieldAccess   { AstTyped_base; AstTyped *expr; u64 offset; };
+struct AstUfc           { AstTyped_base; AstTyped *object; AstTyped *call; };
 struct AstSizeOf        { AstTyped_base; AstType *so_type; u64 size; };
 struct AstAlignOf       { AstTyped_base; AstType *ao_type; u64 alignment; };
 struct AstFileContents  { AstTyped_base; OnyxToken *filename; };
diff --git a/onyx b/onyx
index 59c6e8c9f3bea8cdbd2bc64b74687ee0a5412fe5..e19764a58caba808b6120ad51ad5e614a1c75682 100755 (executable)
Binary files a/onyx and b/onyx differ
diff --git a/progs/heap_resize_test.onyx b/progs/heap_resize_test.onyx
new file mode 100644 (file)
index 0000000..75e3783
--- /dev/null
@@ -0,0 +1,45 @@
+#include_folder "./core"
+
+#include_file "printing"
+#include_file "alloc"
+
+use package memory
+use package printing
+
+proc #export "start" {
+    heap_init();
+
+    print("Creating initial memories");
+    arr1 := cast(^u32) malloc(sizeof [10] u32);
+    print_hex(cast(u64) arr1);
+
+    arr2 := cast(^u32) malloc(sizeof [40] u32);
+    print_hex(cast(u64) arr2);
+
+    print("Freeing arr1");
+    mfree(arr1);
+
+    print("Resizing arr2 (shouldn't change location)");
+    arr2 = cast(^u32) mresize(arr2, sizeof [60] u32);
+    print_hex(cast(u64) arr2);
+
+    print("Allocating arr3 (should be bigger than arr2)");
+    arr3 := cast(^u32) malloc(sizeof [30] u32);
+    print_hex(cast(u64) arr3);
+
+    print("Allocating arr1 (should be in the same place as before)");
+    arr1 = cast(^u32) malloc(sizeof [5] u32);
+    print_hex(cast(u64) arr1);
+    for i: 0, 5 do arr1[i] = i;
+
+    print("Resizing arr1 (should be in the same place as before)");
+    arr1 = cast(^u32) mresize(arr1, sizeof[10] u32);
+    print_hex(cast(u64) arr1);
+
+    print("Resizing arr1 (should have moved to after arr3)");
+    arr1 = cast(^u32) mresize(arr1, sizeof[100] u32);
+    print_hex(cast(u64) arr1);
+
+    print("Testing if the data was copied.");
+    for i: 0, 5 do print(arr1[i]);
+}
\ No newline at end of file
index e9d52522e8b06ed506e2813461e04df58c453257..f07194e32cfbd2dc80dfcb5ac40d0a9ef5f4e769 100644 (file)
@@ -8,6 +8,18 @@ package main
 use package printing
 use package memory
 
+sort :: proc (arr: [N]i32, cmp: proc (i32, i32) -> i32) {
+    for i: 0, N {
+        smallest_idx := i;
+
+        for j: i, N do if cmp(arr[j], arr[smallest_idx]) < 0 do smallest_idx = j;
+
+        tmp :: arr[i];
+        arr[i] = arr[smallest_idx];
+        arr[smallest_idx] = tmp;
+    }
+}
+
 ret_val :: proc (x: i32, y: i32) -> i32 {
     big_arr : [128] i32;
     big_arr[0] = 1234;
@@ -73,7 +85,7 @@ start :: proc #export {
     arr[1][3] = 40;
     arr[1][4] = 50;
     arr[1][9] = 123;
-    print(sumN(arr[1]));
+    print(arr[1] 'sumN());
     print(summing(cast(^i32) arr[1]));
 
     v1: Vec3;
@@ -91,9 +103,10 @@ start :: proc #export {
     print(v3.x);
     print(v3.y);
     print(v3.z);
-    print(mag_squared(v3));
 
-    print(ret_val(10, 4));
+    print(v3'mag_squared());
+
+    print(10'ret_val(4));
     
     for i: 0, N do print(arr[1][i]);
 
@@ -108,4 +121,13 @@ start :: proc #export {
     fancy : [5 + 3 * 4] i32;
     fancy[2] = 123;
     print(fancy[2]);
+
+
+    something : [N] i32;
+    for i: 0, N do something[i] = N - i;
+    for i: 0, N do print(something[i]);
+
+    something'sort(proc (a: i32, b: i32) -> i32 { return a - b; });
+
+    for i: 0, N do print(something[i]);
 }
\ No newline at end of file
index 7a468ef918d87c175058de39d62719761c425c70..881b0cfae971256676f042d0458cfe5ed74b6409 100644 (file)
@@ -787,7 +787,7 @@ CHECK(expression, AstTyped** pexpr) {
     AstTyped* expr = *pexpr;
     if (expr->kind > Ast_Kind_Type_Start && expr->kind < Ast_Kind_Type_End) {
         onyx_message_add(Msg_Type_Literal,
-                (OnyxFilePos) { 0 },
+                expr->token->pos,
                 "type used as part of an expression");
         return 1;
     }
index ff1e915ad7d61e689fe3356c7ffa111b37d84106..c58469b7418bb9265cfd82656e75ea91074c911d 100644 (file)
@@ -357,7 +357,7 @@ static AstTyped* parse_factor(OnyxParser* parser) {
             return NULL;
     }
 
-    while (parser->curr->type == '[' || parser->curr->type == '.' || parser->curr->type == '(') {
+    while (1) {
         if (parser->hit_unexpected_token) return retval;
 
         switch ((u16) parser->curr->type) {
@@ -414,9 +414,23 @@ static AstTyped* parse_factor(OnyxParser* parser) {
                 retval = (AstTyped *) call_node;
                 break;
             }
+
+            case '\'': {
+                AstUfc* ufc_node = make_node(AstUfc, Ast_Kind_Ufc);
+                ufc_node->token = expect_token(parser, '\'');
+                ufc_node->object = retval;
+                ufc_node->call = parse_factor(parser);
+
+                retval = (AstTyped *) ufc_node;
+                break;
+            }
+
+            default: goto factor_parsed;
         }
     }
 
+factor_parsed:
+
     return retval;
 }
 
index f5c3e4bd6f7b2ba927b4ac5adefaab87cabf8fa6..c6432ad09c7b9a6670dfba2d623b97e84f15f685 100644 (file)
@@ -61,8 +61,8 @@ static void symres_return(AstReturn* ret);
 static void symres_if(AstIf* ifnode);
 static void symres_while(AstWhile* whilenode);
 static void symres_for(AstFor* fornode);
-static void symres_statement_chain(AstNode* walker, AstNode** trailer);
-static b32  symres_statement(AstNode* stmt);
+static void symres_statement_chain(AstNode** walker);
+static b32  symres_statement(AstNode** stmt);
 static void symres_block(AstBlock* block);
 static void symres_function(AstFunction* func);
 static void symres_global(AstGlobal* global);
@@ -183,7 +183,7 @@ static void symres_call(AstCall* call) {
     //     call->arg_count++;
     // }
 
-    symres_statement_chain((AstNode *) call->arguments, (AstNode **) &call->arguments);
+    symres_statement_chain((AstNode **) &call->arguments);
 }
 
 static void symres_size_of(AstSizeOf* so) {
@@ -222,6 +222,35 @@ static void symres_field_access(AstFieldAccess** fa) {
     }
 }
 
+static void symres_ufc(AstUfc** ufc) {
+    if ((*ufc)->call->kind != Ast_Kind_Call) {
+        onyx_message_add(Msg_Type_Literal,
+                (*ufc)->token->pos,
+                "universal function call expected call on right side");
+        return;
+    }
+
+    symres_expression(&(*ufc)->object);
+    if ((*ufc)->object == NULL) return;
+
+    AstCall* call_node = (AstCall *) (*ufc)->call;
+
+    AstArgument* implicit_arg = onyx_ast_node_new(semstate.node_allocator,
+            sizeof(AstArgument),
+            Ast_Kind_Argument);
+    implicit_arg->value = (*ufc)->object;
+    implicit_arg->next = (AstNode *) call_node->arguments;
+    
+    call_node->arguments = implicit_arg;
+    call_node->arg_count++;
+    call_node->next = (*ufc)->next;
+
+    symres_expression((AstTyped **) &call_node);
+
+    // NOTE: Not a UFC node
+    *ufc = (AstUfc *) call_node;
+}
+
 static void symres_unaryop(AstUnaryOp** unaryop) {
     if ((*unaryop)->operation == Unary_Op_Cast) {
         (*unaryop)->type_node = symres_type((*unaryop)->type_node);
@@ -252,6 +281,7 @@ static void symres_expression(AstTyped** expr) {
         case Ast_Kind_Address_Of:   symres_expression(&((AstAddressOf *)(*expr))->expr); break;
         case Ast_Kind_Dereference:  symres_expression(&((AstDereference *)(*expr))->expr); break;
         case Ast_Kind_Field_Access: symres_field_access((AstFieldAccess **) expr); break;
+        case Ast_Kind_Ufc:          symres_ufc((AstUfc **) expr); break;
         case Ast_Kind_Size_Of:      symres_size_of((AstSizeOf *)*expr); break;
         case Ast_Kind_Align_Of:     symres_align_of((AstAlignOf *)*expr); break;
 
@@ -284,8 +314,8 @@ static void symres_if(AstIf* ifnode) {
     //
     // The declaration will cause a problem but semantically the above
     // doesn't make sense.
-    if (ifnode->true_stmt != NULL)  symres_statement((AstNode *ifnode->true_stmt);
-    if (ifnode->false_stmt != NULL) symres_statement((AstNode *ifnode->false_stmt);
+    if (ifnode->true_stmt != NULL)  symres_statement((AstNode **) &ifnode->true_stmt);
+    if (ifnode->false_stmt != NULL) symres_statement((AstNode **) &ifnode->false_stmt);
 }
 
 static void symres_while(AstWhile* whilenode) {
@@ -310,36 +340,33 @@ static void symres_for(AstFor* fornode) {
 }
 
 // NOTE: Returns 1 if the statment should be removed
-static b32 symres_statement(AstNode* stmt) {
-    switch (stmt->kind) {
-        case Ast_Kind_Local:      symres_local((AstLocal **) &stmt);                return 1;
-        case Ast_Kind_Return:     symres_return((AstReturn *) stmt);                return 0;
-        case Ast_Kind_If:         symres_if((AstIf *) stmt);                        return 0;
-        case Ast_Kind_While:      symres_while((AstWhile *) stmt);                  return 0;
-        case Ast_Kind_For:        symres_for((AstFor *) stmt);                      return 0;
-        case Ast_Kind_Call:       symres_call((AstCall *) stmt);                    return 0;
-        case Ast_Kind_Argument:   symres_expression((AstTyped **) &((AstArgument *)stmt)->value); return 0;
-        case Ast_Kind_Block:      symres_block((AstBlock *) stmt);                  return 0;
-        case Ast_Kind_Defer:      symres_statement(((AstDefer *) stmt)->stmt);      return 0;
+static b32 symres_statement(AstNode** stmt) {
+    switch ((*stmt)->kind) {
+        case Ast_Kind_Local:      symres_local((AstLocal **) stmt);                  return 1;
+        case Ast_Kind_Return:     symres_return((AstReturn *) *stmt);                return 0;
+        case Ast_Kind_If:         symres_if((AstIf *) *stmt);                        return 0;
+        case Ast_Kind_While:      symres_while((AstWhile *) *stmt);                  return 0;
+        case Ast_Kind_For:        symres_for((AstFor *) *stmt);                      return 0;
+        case Ast_Kind_Call:       symres_call((AstCall *) *stmt);                    return 0;
+        case Ast_Kind_Argument:   symres_expression((AstTyped **) &((AstArgument *) *stmt)->value); return 0;
+        case Ast_Kind_Block:      symres_block((AstBlock *) *stmt);                  return 0;
+        case Ast_Kind_Defer:      symres_statement(&((AstDefer *) *stmt)->stmt);     return 0;
 
         case Ast_Kind_Break:      return 0;
         case Ast_Kind_Continue:   return 0;
 
-        default:                  symres_expression((AstTyped **) &stmt);           return 0;
+        default:                  symres_expression((AstTyped **) stmt);           return 0;
     }
 }
 
-static void symres_statement_chain(AstNode* walker, AstNode** trailer) {
-    while (walker) {
+static void symres_statement_chain(AstNode** walker) {
+    while (*walker) {
         if (symres_statement(walker)) {
-            *trailer = walker->next;
-
-            AstNode* tmp = walker->next;
-            walker->next = NULL;
-            walker = tmp;
+            AstNode* tmp = (*walker)->next;
+            (*walker)->next = NULL;
+            (*walker) = tmp;
         } else {
-            trailer = &walker->next;
-            walker = walker->next;
+            walker = &(*walker)->next;
         }
     }
 }
@@ -351,7 +378,7 @@ static void symres_block(AstBlock* block) {
     scope_enter(block->scope);
 
     if (block->body)
-        symres_statement_chain(block->body, &block->body);
+        symres_statement_chain(&block->body);
 
     scope_leave();
 }