"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": [],
package memory
+#include_file "memory"
#include_file "intrinsics"
use package intrinsics { memory_size, memory_grow }
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);
}
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;
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);
--- /dev/null
+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
[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
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;
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,
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; };
--- /dev/null
+#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
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;
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;
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]);
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
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;
}
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) {
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;
}
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);
// 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) {
}
}
+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);
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;
//
// 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) {
}
// 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;
}
}
}
scope_enter(block->scope);
if (block->body)
- symres_statement_chain(block->body, &block->body);
+ symres_statement_chain(&block->body);
scope_leave();
}