break;
}
+ case '&':
case '^': {
AstAddressOf* aof_node = make_node(AstAddressOf, Ast_Kind_Address_Of);
- aof_node->token = expect_token(parser, '^');
+ aof_node->token = parser->curr->type == '^' ? expect_token(parser, '^') : expect_token(parser, '&'); // HACK
aof_node->expr = parse_factor(parser);
retval = (AstTyped *) aof_node;
for_node->no_close = 1;
}
- if (consume_token_if_next(parser, '^')) {
+ if (consume_token_if_next(parser, '^') || consume_token_if_next(parser, '&')) {
for_node->by_pointer = 1;
}
// fallthrough
}
- case '(': case '+': case '-': case '!': case '*': case '^':
+ case '(': case '+': case '-': case '!': case '*': case '^': case '&':
case Token_Type_Literal_Integer:
case Token_Type_Literal_Float:
case Token_Type_Literal_String:
if (parser->hit_unexpected_token) return root;
switch ((u16) parser->curr->type) {
+ case '&':
case '^': {
AstPointerType* new = make_node(AstPointerType, Ast_Kind_Pointer_Type);
new->flags |= Basic_Flag_Pointer;
- new->token = expect_token(parser, '^');
+ // new->token = expect_token(parser, '^');
+ new->token = parser->curr->type == '^' ? expect_token(parser, '^') : expect_token(parser, '&'); // HACK
*next_insertion = (AstType *) new;
next_insertion = &new->elem;
// These cases have to happen first because these are not necessarily "binary operators",
// they are just things that I want to be able to overload. []= is technically a ternary
// operator so all these things are horribly named anyway.
- if (next_tokens_are(parser, 3, '^', '[', ']')) {
+ if (next_tokens_are(parser, 3, '^', '[', ']')
+ || next_tokens_are(parser, 3, '&', '[', ']')) {
consume_tokens(parser, 3);
operator->operator = Binary_Op_Ptr_Subscript;
goto operator_determined;
switch (type->kind) {
case Type_Kind_Basic: return type->Basic.name;
- case Type_Kind_Pointer: return bh_aprintf(global_scratch_allocator, "^%s", type_get_unique_name(type->Pointer.elem));
+ case Type_Kind_Pointer: return bh_aprintf(global_scratch_allocator, "&%s", type_get_unique_name(type->Pointer.elem));
case Type_Kind_Array: return bh_aprintf(global_scratch_allocator, "[%d] %s", type->Array.count, type_get_unique_name(type->Array.elem));
case Type_Kind_Struct:
if (type->Struct.name)
switch (type->kind) {
case Type_Kind_Basic: return type->Basic.name;
- case Type_Kind_Pointer: return bh_aprintf(global_scratch_allocator, "^%s", type_get_name(type->Pointer.elem));
+ case Type_Kind_Pointer: return bh_aprintf(global_scratch_allocator, "&%s", type_get_name(type->Pointer.elem));
case Type_Kind_Array: return bh_aprintf(global_scratch_allocator, "[%d] %s", type->Array.count, type_get_name(type->Array.elem));
case Type_Kind_PolyStruct:
from_stack :: macro (size: u32) -> rawptr {
// This should do something about the alignment...
// Everything so far has assume that the stack is aligned to 16 bytes.
- defer __stack_top = ~~(cast(^u8) __stack_top + size);
+ defer __stack_top = ~~(cast(&u8) __stack_top + size);
return __stack_top;
}
array_from_stack :: macro ($T: type_expr, size: u32) -> [] T {
- defer __stack_top = ~~(cast(^u8) __stack_top + size * sizeof T);
- return (cast(^T) __stack_top)[0 .. size];
+ defer __stack_top = ~~(cast(&u8) __stack_top + size * sizeof T);
+ return (cast(&T) __stack_top)[0 .. size];
}
-on_heap :: macro (v: $V) -> ^V {
- out := cast(^V) raw_alloc(context.allocator, sizeof V);
+on_heap :: macro (v: $V) -> &V {
+ out := cast(&V) raw_alloc(context.allocator, sizeof V);
core.memory.set(out, 0, sizeof V);
*out = v;
return out;
init_temp_allocator :: () {
temp_state = arena.make(heap_allocator, TEMPORARY_ALLOCATOR_SIZE);
- temp_allocator = as_allocator(^temp_state);
+ temp_allocator = as_allocator(&temp_state);
}
clear_temp_allocator :: () {
- arena.clear(^temp_state);
+ arena.clear(&temp_state);
}
Arena :: struct {
backing_allocator : Allocator;
- first_arena : ^ArenaBlock;
- current_arena : ^ArenaBlock;
+ first_arena : &ArenaBlock;
+ current_arena : &ArenaBlock;
size : u32;
arena_size : u32;
}
-ArenaBlock :: struct { next : ^ArenaBlock; }
+ArenaBlock :: struct { next : &ArenaBlock; }
#local
arena_alloc_proc :: (data: rawptr, aa: AllocationAction, size: u32, align: u32, oldptr: rawptr) -> rawptr {
- alloc_arena := cast(^Arena) data;
+ alloc_arena := cast(&Arena) data;
if aa == .Alloc {
// An allocation of this size does not fit into a single arena,
// so make a new "special" arena that only stores this allocation.
if size > alloc_arena.arena_size - sizeof rawptr {
- ret_arena := cast(^ArenaBlock) raw_alloc(alloc_arena.backing_allocator, size + sizeof rawptr);
- new_arena := cast(^ArenaBlock) raw_alloc(alloc_arena.backing_allocator, alloc_arena.arena_size);
+ ret_arena := cast(&ArenaBlock) raw_alloc(alloc_arena.backing_allocator, size + sizeof rawptr);
+ new_arena := cast(&ArenaBlock) raw_alloc(alloc_arena.backing_allocator, alloc_arena.arena_size);
if ret_arena == null || new_arena == null do return null;
alloc_arena.current_arena = new_arena;
- return cast(rawptr) (cast(^u8) ret_arena + sizeof rawptr);
+ return cast(rawptr) (cast(&u8) ret_arena + sizeof rawptr);
}
if alloc_arena.size % align != 0 {
}
if alloc_arena.size + size >= alloc_arena.arena_size {
- new_arena := cast(^ArenaBlock) raw_alloc(alloc_arena.backing_allocator, alloc_arena.arena_size);
+ new_arena := cast(&ArenaBlock) raw_alloc(alloc_arena.backing_allocator, alloc_arena.arena_size);
if new_arena == null do return null;
alloc_arena.size = sizeof rawptr;
alloc_arena.current_arena = new_arena;
}
- retval := cast(rawptr) (cast(^u8) alloc_arena.current_arena + alloc_arena.size);
+ retval := cast(rawptr) (cast(&u8) alloc_arena.current_arena + alloc_arena.size);
alloc_arena.size += size;
return retval;
make :: (backing: Allocator, arena_size: u32) -> Arena {
assert(arena_size >= 4, "Arena size was expected to be at least 4 bytes.");
- initial_arena := cast(^ArenaBlock) raw_alloc(backing, arena_size);
+ initial_arena := cast(&ArenaBlock) raw_alloc(backing, arena_size);
initial_arena.next = null;
return Arena.{
}
#match core.alloc.as_allocator make_allocator
-make_allocator :: (rs: ^Arena) -> Allocator {
+make_allocator :: (rs: &Arena) -> Allocator {
return Allocator.{
func = arena_alloc_proc,
data = rs,
};
}
-free :: (arena: ^Arena) {
+free :: (arena: &Arena) {
walker := arena.first_arena;
trailer := walker;
while walker != null {
}
// Clears and frees every page, except for first page.
-clear :: (arena: ^Arena) {
+clear :: (arena: &Arena) {
walker := arena.first_arena.next;
while walker != null {
next := walker.next;
arena.size = sizeof rawptr;
}
-get_allocated_arenas :: (arena: ^Arena) -> u32 {
+get_allocated_arenas :: (arena: &Arena) -> u32 {
arenas := 0;
walker := arena.first_arena;
while walker != null {
return arenas;
}
-get_allocated_bytes :: (arena: ^Arena) -> u32 {
+get_allocated_bytes :: (arena: &Arena) -> u32 {
return get_allocated_arenas(arena) * (arena.arena_size - 1) + arena.size;
}
a := arena.make(heap_allocator, size);
old_allocator := #unquote dest;
- (#unquote dest) = arena.make_allocator(^a);
+ (#unquote dest) = arena.make_allocator(&a);
defer {
- arena.free(^a);
+ arena.free(&a);
(#unquote dest) = old_allocator;
}
},
make :: (a: Allocator) -> AtomicAllocator {
atomic: AtomicAllocator = .{ a = a };
- sync.mutex_init(^atomic.m);
+ sync.mutex_init(&atomic.m);
return atomic;
}
-make_allocator :: (atomic: ^AtomicAllocator) =>
+make_allocator :: (atomic: &AtomicAllocator) =>
Allocator.{ atomic, atomic_alloc };
#overload
#local
-atomic_alloc :: (atomic: ^AtomicAllocator, aa: AllocationAction, size: u32, align: u32, oldptr: rawptr) -> rawptr {
- sync.scoped_mutex(^atomic.m);
+atomic_alloc :: (atomic: &AtomicAllocator, aa: AllocationAction, size: u32, align: u32, oldptr: rawptr) -> rawptr {
+ sync.scoped_mutex(&atomic.m);
return atomic.a.func(atomic.a.data, aa, size, align, oldptr);
}
#local
fixed_allocator_proc :: (data: rawptr, aa: AllocationAction, size: u32, align: u32, oldptr: rawptr) -> rawptr {
- fa_data := cast(^FixedAllocatorData) data;
+ fa_data := cast(&FixedAllocatorData) data;
if aa != .Alloc do return null;
if size > fa_data.size do return null;
}
#match core.alloc.as_allocator make_allocator
-make_allocator :: (fa_data: ^FixedAllocatorData) -> Allocator {
+make_allocator :: (fa_data: &FixedAllocatorData) -> Allocator {
return Allocator.{
func = fixed_allocator_proc,
data = fa_data,
GCState :: struct {
backing_allocator: Allocator;
- first: ^GCLink;
+ first: &GCLink;
}
#local
GCLink :: struct {
- prev: ^GCLink;
- next: ^GCLink;
+ prev: &GCLink;
+ next: &GCLink;
magic_number: u32;
}
return hs;
}
-clear :: (hs: ^GCState) {
+clear :: (hs: &GCState) {
while l := hs.first; l != null {
n := l.next;
raw_free(hs.backing_allocator, l);
}
#match core.alloc.as_allocator make_allocator
-make_allocator :: (hs: ^GCState) -> Allocator {
+make_allocator :: (hs: &GCState) -> Allocator {
return Allocator.{
func = gc_alloc_proc,
data = hs
gcs := gc.make();
old_allocator := context.allocator;
- context.allocator = core.alloc.as_allocator(^gcs);
+ context.allocator = core.alloc.as_allocator(&gcs);
defer {
- gc.clear(^gcs);
+ gc.clear(&gcs);
context.allocator = old_allocator;
}
},
#local
GC_Link_Magic_Number :: 0x1337face
-#local gc_alloc_proc :: (data: ^GCState, aa: AllocationAction, size: u32, align: u32, oldptr: rawptr) -> rawptr {
+#local gc_alloc_proc :: (data: &GCState, aa: AllocationAction, size: u32, align: u32, oldptr: rawptr) -> rawptr {
- old: ^GCLink;
+ old: &GCLink;
if oldptr != null {
- old = (cast(^GCLink) oldptr) - 1;
+ old = (cast(&GCLink) oldptr) - 1;
//
// If this allocated space was not from an gc allocator,
}
}
- newptr: ^GCLink = data.backing_allocator.func(
+ newptr: &GCLink = data.backing_allocator.func(
data.backing_allocator.data, aa,
size + sizeof GCLink, align, old);
heap_state.remaining_space = (memory_size() << 16) - cast(u32) __heap_start;
use core.alloc { heap_allocator }
- heap_allocator.data = ^heap_state;
+ heap_allocator.data = &heap_state;
heap_allocator.func = heap_alloc_proc;
#if runtime.Multi_Threading_Enabled {
- sync.mutex_init(^heap_mutex);
+ sync.mutex_init(&heap_mutex);
}
}
// The global heap state
heap_state : struct {
- free_list : ^heap_freed_block;
+ free_list : &heap_freed_block;
next_alloc : rawptr;
remaining_space : u32;
}
heap_freed_block :: struct {
use base: heap_block;
- next : ^heap_freed_block;
- prev : ^heap_freed_block;
+ next : &heap_freed_block;
+ prev : &heap_freed_block;
}
heap_allocated_block :: struct {
heap_alloc :: (size_: u32, align: u32) -> rawptr {
if size_ == 0 do return null;
- #if runtime.Multi_Threading_Enabled do sync.scoped_mutex(^heap_mutex);
+ #if runtime.Multi_Threading_Enabled do sync.scoped_mutex(&heap_mutex);
size := size_ + sizeof heap_block;
size = math.max(size, sizeof heap_freed_block);
- memory.align(~~^size, ~~align);
+ memory.align(~~&size, ~~align);
- prev := ^heap_state.free_list;
+ prev := &heap_state.free_list;
hb := heap_state.free_list;
best_extra := 0xffffffff;
}
}
- prev = ^hb.next;
+ prev = &hb.next;
hb = hb.next;
}
}
if best.size - size >= Block_Split_Size {
- new_block := cast(^heap_freed_block) (cast(uintptr) best + size);
+ new_block := cast(&heap_freed_block) (cast(uintptr) best + size);
new_block.size = best.size - size;
new_block.next = best.next;
new_block.prev = best.prev;
}
if size < heap_state.remaining_space {
- ret := cast(^heap_allocated_block) heap_state.next_alloc;
+ ret := cast(&heap_allocated_block) heap_state.next_alloc;
ret.size = size;
ret.size |= Allocated_Flag;
ret.magic_number = Alloc_Block_Magic_Number;
}
heap_state.remaining_space += new_pages << 16;
- ret := cast(^heap_allocated_block) heap_state.next_alloc;
+ ret := cast(&heap_allocated_block) heap_state.next_alloc;
ret.size = size;
ret.size |= Allocated_Flag;
ret.magic_number = Alloc_Block_Magic_Number;
heap_free :: (ptr: rawptr) {
#if Enable_Debug do assert(ptr != null, "Trying to free a null pointer.");
- #if runtime.Multi_Threading_Enabled do sync.scoped_mutex(^heap_mutex);
+ #if runtime.Multi_Threading_Enabled do sync.scoped_mutex(&heap_mutex);
- hb_ptr := cast(^heap_freed_block) (cast(uintptr) ptr - sizeof heap_allocated_block);
+ hb_ptr := cast(&heap_freed_block) (cast(uintptr) ptr - sizeof heap_allocated_block);
#if Enable_Debug {
// assert(hb_ptr.size & Allocated_Flag == Allocated_Flag, "Corrupted heap on free. This could be due to a double free, or using memory past were you allocated it.");
}
if cast(uintptr) hb_ptr + hb_ptr.size < cast(uintptr) heap_state.next_alloc {
- next_block := cast(^heap_freed_block) (cast(uintptr) hb_ptr + hb_ptr.size);
+ next_block := cast(&heap_freed_block) (cast(uintptr) hb_ptr + hb_ptr.size);
if next_block.size & Allocated_Flag == 0 && next_block.magic_number == Free_Block_Magic_Number {
hb_ptr.size += next_block.size;
{
walker := heap_state.free_list;
while walker != null {
- after_block := cast(^heap_freed_block) (cast(uintptr) walker + walker.size);
+ after_block := cast(&heap_freed_block) (cast(uintptr) walker + walker.size);
if after_block == hb_ptr {
hb_ptr.next = null;
hb_ptr.prev = null;
heap_resize :: (ptr: rawptr, new_size_: u32, align: u32) -> rawptr {
if ptr == null do return heap_alloc(new_size_, align);
- #if runtime.Multi_Threading_Enabled do sync.scoped_mutex(^heap_mutex);
+ #if runtime.Multi_Threading_Enabled do sync.scoped_mutex(&heap_mutex);
new_size := new_size_ + sizeof heap_block;
new_size = math.max(new_size, sizeof heap_freed_block);
new_size = ~~memory.align(cast(u64) new_size, ~~align);
- hb_ptr := cast(^heap_allocated_block) (cast(uintptr) ptr - sizeof heap_allocated_block);
+ hb_ptr := cast(&heap_allocated_block) (cast(uintptr) ptr - sizeof heap_allocated_block);
#if Enable_Debug do assert(hb_ptr.size & Allocated_Flag == Allocated_Flag, "Corrupted heap on resize.");
hb_ptr.size &= ~Allocated_Flag;
hb_ptr.size |= Allocated_Flag;
new_ptr := heap_alloc(new_size_, align);
- #if runtime.Multi_Threading_Enabled do sync.mutex_lock(^heap_mutex);
+ #if runtime.Multi_Threading_Enabled do sync.mutex_lock(&heap_mutex);
memory_copy(new_ptr, ptr, old_size - sizeof heap_block);
heap_free(ptr);
#local
logging_allocator_proc :: (data: rawptr, aa: AllocationAction, size: u32, align: u32, oldptr: rawptr) -> rawptr {
- allocator := cast(^Allocator) data;
+ allocator := cast(&Allocator) data;
res := allocator.func(allocator.data, aa, size, align, oldptr);
use core { tprintf }
return res;
}
-logging_allocator :: (alloc: ^Allocator) -> Allocator {
+logging_allocator :: (alloc: &Allocator) -> Allocator {
return Allocator.{
func = logging_allocator_proc,
data = alloc,
PoolAllocator :: struct (Elem: type_expr) {
buffer : [] Elem;
- first_free : ^Elem;
+ first_free : &Elem;
alloc :: pool_alloc
free :: pool_free
}
#local
-pool_allocator_proc :: (pool: ^PoolAllocator($Elem), aa: AllocationAction, size: u32, align: u32, oldptr: rawptr) -> rawptr {
+pool_allocator_proc :: (pool: &PoolAllocator($Elem), aa: AllocationAction, size: u32, align: u32, oldptr: rawptr) -> rawptr {
switch aa {
case .Alloc {
assert(size == sizeof Elem, "Allocating wrong size from pool allocator.");
return null;
}
-pool_alloc :: (pool: ^PoolAllocator($Elem)) -> ^Elem {
+pool_alloc :: (pool: &PoolAllocator($Elem)) -> &Elem {
if pool.first_free == null do return null;
- defer pool.first_free = cast(^Elem) *(cast(^rawptr) pool.first_free);
+ defer pool.first_free = cast(&Elem) *(cast(&rawptr) pool.first_free);
return pool.first_free;
}
-pool_free :: (pool: ^PoolAllocator($Elem), elem: ^Elem) {
+pool_free :: (pool: &PoolAllocator($Elem), elem: &Elem) {
// @TODO
// Add a check that the elem pointer is actually in the buffer??
- *(cast(^rawptr) elem) = cast(rawptr) pool.first_free;
+ *(cast(&rawptr) elem) = cast(rawptr) pool.first_free;
pool.first_free = elem;
}
assert(sizeof Elem >= sizeof rawptr, "Cannot have a pool allocator of a type less than a rawptr in size.");
for i: 0 .. buffer.count - 1 {
- *(cast(^rawptr) ^buffer[i]) = cast(rawptr) ^buffer[i + 1];
+ *(cast(&rawptr) &buffer[i]) = cast(rawptr) &buffer[i + 1];
}
- *(cast(^rawptr) ^buffer[buffer.count - 1]) = null;
+ *(cast(&rawptr) &buffer[buffer.count - 1]) = null;
return .{
buffer = buffer,
- first_free = ^buffer[0],
+ first_free = &buffer[0],
};
}
#match core.alloc.as_allocator make_allocator
-make_allocator :: (pool: ^PoolAllocator($Elem)) -> Allocator {
+make_allocator :: (pool: &PoolAllocator($Elem)) -> Allocator {
return Allocator.{
func = #solidify pool_allocator_proc { Elem = Elem },
data = pool,
#local
ring_alloc_proc :: (data: rawptr, aa: AllocationAction, size: u32, align: u32, oldptr: rawptr) -> rawptr {
- ss := cast(^RingState) data;
+ ss := cast(&RingState) data;
if aa == .Alloc {
retval := null;
if ss.curr + size < ss.size {
- retval = cast(^u8) ss.base_ptr + ss.curr;
+ retval = cast(&u8) ss.base_ptr + ss.curr;
ss.curr += size;
}
elseif size <= ss.size {
}
#match core.alloc.as_allocator make_allocator
-make_allocator :: (rs: ^RingState) -> Allocator {
+make_allocator :: (rs: &RingState) -> Allocator {
return .{
func = ring_alloc_proc,
data = rs,
// A string is simply a slice of bytes, and a c-string is a pointer
// to byte, with a null-terminator ('\0') at the end.
str :: #type [] u8;
-cstr :: #type ^ u8;
+cstr :: #type & u8;
// Defines what happens when `log()` is called. Defaults to a
// logger that filters log messages by their severity.
- logger : Logger = .{ default_logger_proc, ^default_logger };
+ logger : Logger = .{ default_logger_proc, &default_logger };
// Defines what happens when an `assert()` check fails. Defaults
// to printing the error and running an unreachable instruction,
// Define helper methods for setting and retrieving the user_data
// stored on the context.
#inject OnyxContext {
- set_user_data :: macro (c: ^OnyxContext, data: ^$T) {
+ set_user_data :: macro (c: &OnyxContext, data: &$T) {
c.user_data = data;
c.user_data_type = T;
}
- get_user_data :: macro (c: ^OnyxContext, $T: type_expr) -> ^T {
+ get_user_data :: macro (c: &OnyxContext, $T: type_expr) -> &T {
if c.user_data_type != T do return null;
return ~~ c.user_data;
}
}
#if runtime.runtime != .Custom {
- #local default_logger_proc :: (logger: ^Default_Logger, level: Log_Level, msg: str, module: str) {
+ #local default_logger_proc :: (logger: &Default_Logger, level: Log_Level, msg: str, module: str) {
if level < logger.minimum_level do return;
if module {
new :: #match #local {}
#overload
- new :: ($T: type_expr, allocator := context.allocator) -> ^T {
+ new :: ($T: type_expr, allocator := context.allocator) -> &T {
use package core.intrinsics.onyx { __initialize }
memory :: package core.memory
- res := cast(^T) raw_alloc(allocator, sizeof T);
+ res := cast(&T) raw_alloc(allocator, sizeof T);
memory.set(res, 0, sizeof T);
__initialize(res);
memory.set(res, 0, size);
if info.kind == .Struct {
- s_info := cast(^type_info.Type_Info_Struct) info;
+ s_info := cast(&type_info.Type_Info_Struct) info;
for s_info.members {
if it.default != null {
member_size := type_info.size_of(it.type);
- memory.copy(cast(^u8) res + it.offset, it.default, member_size);
+ memory.copy(cast(&u8) res + it.offset, it.default, member_size);
}
}
}
#overload
make :: macro ($T: type_expr, allocator := context.allocator) => {
- return __make_overload(cast(^T) null, allocator=allocator);
+ return __make_overload(cast(&T) null, allocator=allocator);
}
#overload
make :: macro ($T: type_expr, n: u32, allocator := context.allocator) => {
- return __make_overload(cast(^T) null, n, allocator=allocator);
+ return __make_overload(cast(&T) null, n, allocator=allocator);
}
make_temp :: #match #local {}
//
// This is the fallback option for make. It simply allocates a zero-intialized
// element of type T.
- #order 1000 (_: ^$T, allocator := context.allocator) -> ^T {
+ #order 1000 (_: &$T, allocator := context.allocator) -> &T {
memory :: package core.memory
- res := cast(^T) raw_alloc(allocator, sizeof T);
+ res := cast(&T) raw_alloc(allocator, sizeof T);
memory.set(res, 0, sizeof T);
return res;
},
}
delete :: #match {
- #order 1000 macro (x: ^$T, allocator := context.allocator) {
+ #order 1000 macro (x: &$T, allocator := context.allocator) {
if x != null do raw_free(allocator, x);
}
}
// a similar construction to varargs in C/C++. Because it is incredibly unsafe
// and not programmer friendly, this way of doing it has been deprecated in
// favor of using '..any', which provides type information along with the data.
-vararg :: #type ^struct {
+vararg :: #type &struct {
data: rawptr;
count: i32;
}
// [..] T == Array(T)
// where
// Array :: struct (T: type_expr) {
-// data : ^T;
+// data : &T;
// count : u32;
// capacity : u32;
// allocator : Allocator;
#overload
make :: ($T: type_expr, capacity := 4, allocator := context.allocator) -> [..] T {
arr : [..] T;
- init(^arr, capacity, allocator);
+ init(&arr, capacity, allocator);
return arr;
}
#overload
make :: (base: [] $T, allocator := context.allocator) -> [..] T {
arr: [..] T;
- init(^arr, base.count, allocator);
- for^ base do arr << *it;
+ init(&arr, base.count, allocator);
+ for& base do arr << *it;
return arr;
}
#overload
-__make_overload :: macro (_: ^[..] $T, allocator := context.allocator) -> [..] T {
+__make_overload :: macro (_: &[..] $T, allocator := context.allocator) -> [..] T {
return core.array.make(T, allocator=allocator);
}
#overload
-__make_overload :: macro (_: ^[..] $T, capacity: u32, allocator := context.allocator) -> [..] T {
+__make_overload :: macro (_: &[..] $T, capacity: u32, allocator := context.allocator) -> [..] T {
return core.array.make(T, capacity, allocator);
}
-init :: (arr: ^[..] $T, capacity := 4, allocator := context.allocator) {
+init :: (arr: &[..] $T, capacity := 4, allocator := context.allocator) {
arr.count = 0;
arr.capacity = capacity;
arr.allocator = allocator;
arr.data = raw_alloc(allocator, sizeof T * arr.capacity);
}
-free :: (arr: ^[..] $T) {
+free :: (arr: &[..] $T) {
arr.count = 0;
arr.capacity = 0;
}
#overload
-builtin.delete :: macro (x: ^[..] $T) {
+builtin.delete :: macro (x: &[..] $T) {
core.array.free(x);
}
copy :: #match #locked {
- (arr: ^[..] $T, allocator := context.allocator) -> [..] T {
+ (arr: &[..] $T, allocator := context.allocator) -> [..] T {
new_arr : [..] T;
- init(^new_arr, arr.count, allocator);
+ init(&new_arr, arr.count, allocator);
new_arr.count = arr.count;
for i: 0 .. arr.count do new_arr.data[i] = arr.data[i];
}
}
-copy_range :: (arr: ^[..] $T, r: range, allocator := context.allocator) -> [..] T {
+copy_range :: (arr: &[..] $T, r: range, allocator := context.allocator) -> [..] T {
new_arr : [..] T;
- init(^new_arr, r.high - r.low, allocator);
+ init(&new_arr, r.high - r.low, allocator);
new_arr.count = r.high - r.low;
for i: r do new_arr.data[i] = arr.data[i];
return new_arr;
}
-clear :: (arr: ^[..] $T) {
+clear :: (arr: &[..] $T) {
arr.count = 0;
}
-ensure_capacity :: (arr: ^[..] $T, capacity: u32) -> bool {
+ensure_capacity :: (arr: &[..] $T, capacity: u32) -> bool {
if arr.capacity >= capacity do return true;
if arr.data == null do init(arr);
return true;
}
-alloc_one :: (arr: ^[..] $T) -> ^T {
+alloc_one :: (arr: &[..] $T) -> &T {
if !ensure_capacity(arr, arr.count + 1) do return null;
arr.count += 1;
- return ^arr.data[arr.count - 1];
+ return &arr.data[arr.count - 1];
}
-push :: (arr: ^[..] $T, x: T) -> bool {
+push :: (arr: &[..] $T, x: T) -> bool {
if !ensure_capacity(arr, arr.count + 1) do return false;
arr.data[arr.count] = x;
arr.count += 1;
}
// Semi-useful shortcut for adding something to an array.
-#operator << macro (arr: [..] $T, v: T) do core.array.push(^arr, v);
+#operator << macro (arr: [..] $T, v: T) do core.array.push(&arr, v);
-insert :: (arr: ^[..] $T, idx: u32, x: T) -> bool {
+insert :: (arr: &[..] $T, idx: u32, x: T) -> bool {
if !ensure_capacity(arr, arr.count + 1) do return false;
arr.count += 1;
return true;
}
-insert_empty :: (arr: ^[..] $T, idx: u32) -> bool {
+insert_empty :: (arr: &[..] $T, idx: u32) -> bool {
if !ensure_capacity(arr, arr.count + 1) do return false;
arr.count += 1;
return true;
}
-remove :: (arr: ^[..] $T, elem: T) {
+remove :: (arr: &[..] $T, elem: T) {
move := 0;
while i := 0; i < arr.count - move {
arr.count -= move;
}
-delete :: (arr: ^[..] $T, idx: u32) -> T {
+delete :: (arr: &[..] $T, idx: u32) -> T {
if idx >= arr.count do return .{};
to_return := arr.data[idx];
return to_return;
}
-fast_delete :: (arr: ^[..] $T, idx: u32) -> T {
+fast_delete :: (arr: &[..] $T, idx: u32) -> T {
if idx >= arr.count do return .{};
to_return := arr.data[idx];
return to_return;
}
-pop :: (arr: ^[..] $T) -> T {
+pop :: (arr: &[..] $T) -> T {
if arr.count == 0 do return .{};
arr.count -= 1;
concat :: #match #local {}
#overload
-concat :: (arr: ^[..] $T, other: [] T) {
+concat :: (arr: &[..] $T, other: [] T) {
if !ensure_capacity(arr, arr.count + other.count) do return;
core.memory.copy(arr.data + arr.count, other.data, other.count * sizeof T);
}
#overload
-concat :: (arr: ^[..] $T, other: Iterator(T)) {
+concat :: (arr: &[..] $T, other: Iterator(T)) {
for other {
push(arr, it);
}
}
-filter :: macro (arr: ^[..] $T, body: Code) {
+filter :: macro (arr: &[..] $T, body: Code) {
move := 0;
while i := 0; i < arr.count - move {
elem := arr[0];
for i: 1 .. arr.count {
- A := ^arr[i];
- B := ^elem;
+ A := &arr[i];
+ B := &elem;
if #unquote cmp {
idx = i;
elem = arr[i];
return arr.data[idx];
}
-get_ptr :: (arr: [] $T, idx: i32) -> ^T {
+get_ptr :: (arr: [] $T, idx: i32) -> &T {
if arr.count == 0 do return null;
while idx < 0 do idx += arr.count;
while idx >= arr.count do idx -= arr.count;
- return ^arr.data[idx];
+ return &arr.data[idx];
}
set :: (arr: [] $T, idx: i32, value: T) {
}
#overload
-sort :: (arr: [] $T, cmp: (^T, ^T) -> i32) -> [] T {
+sort :: (arr: [] $T, cmp: (&T, &T) -> i32) -> [] T {
for i: 1 .. arr.count {
j := i;
while j > 0 {
- if cmp(^arr.data[j - 1], ^arr.data[j]) > 0 {
+ if cmp(&arr.data[j - 1], &arr.data[j]) > 0 {
tmp := arr.data[j];
arr.data[j] = arr.data[j - 1];
arr.data[j - 1] = tmp;
quicksort :: #match #locked {
(arr: [] $T, cmp: ( T, T) -> i32) => { quicksort_impl(arr, cmp, 0, arr.count - 1); return arr; },
- (arr: [] $T, cmp: (^T, ^T) -> i32) => { quicksort_impl(arr, cmp, 0, arr.count - 1); return arr; },
+ (arr: [] $T, cmp: (&T, &T) -> i32) => { quicksort_impl(arr, cmp, 0, arr.count - 1); return arr; },
}
#local {
}
#overload
- quicksort_partition :: (arr: [] $T, cmp: (^T, ^T) -> i32, lo, hi: i32) -> i32 {
- pivot := ^arr[hi];
+ quicksort_partition :: (arr: [] $T, cmp: (&T, &T) -> i32, lo, hi: i32) -> i32 {
+ pivot := &arr[hi];
i := lo - 1;
for j: lo .. hi+1 {
- if cmp(^arr[j], pivot) <= 0 {
+ if cmp(&arr[j], pivot) <= 0 {
i += 1;
tmp := arr[i];
arr[i] = arr[j];
// This assumes that the elements are sorted in some fashion,
// such that equal elements would be next to each other.
-unique :: (arr: ^[] $T) {
+unique :: (arr: &[] $T) {
idx := 0;
while i := 0; i < arr.count - 1 {
defer i += 1;
#overload
some :: macro (arr: [] $T/type_is_struct, predicate_body: Code) -> bool {
- for ^ arr {
+ for & arr {
if #unquote predicate_body do return true;
}
return false;
to_list :: (arr: [] $T, allocator := context.allocator) -> List(T) {
new_list := list.make(T, allocator);
- for ^it: arr {
- list.push_end(^new_list, *it);
+ for &it: arr {
+ list.push_end(&new_list, *it);
}
return new_list;
#overload
find :: macro (arr: [] $T/type_is_struct, pred: Code) -> i32 {
for i: arr.count {
- it := ^arr[i];
+ it := &arr[i];
if #unquote pred do return i;
}
return -1;
}
-find_ptr :: (arr: [] $T, value: T) -> ^T {
- for ^it: arr {
+find_ptr :: (arr: [] $T, value: T) -> &T {
+ for &it: arr {
if value == *it do return it;
}
}
first :: #match #locked {
- macro (arr: [] $T, predicate: (T) -> bool) -> ^T {
+ macro (arr: [] $T, predicate: (T) -> bool) -> &T {
first :: first
return first(arr, #(predicate(it)));
},
- macro (arr: [] $T/type_is_struct, predicate_body: Code) -> ^T {
- for ^ arr {
+ macro (arr: [] $T/type_is_struct, predicate_body: Code) -> &T {
+ for & arr {
if #unquote predicate_body do return it;
}
return null;
},
- macro (arr: [] $T, predicate_body: Code) -> ^T {
+ macro (arr: [] $T, predicate_body: Code) -> &T {
// This is to preserve the semantics that "it" is
// not a pointer (same as contains), when T is not a
// structure.
- for ^it_ptr: arr {
+ for &it_ptr: arr {
it := *it_ptr;
if #unquote predicate_body do return it_ptr;
}
use core {iter}
return iter.generator(
- ^.{ arr=arr, width=width, pos=0 },
+ &.{ arr=arr, width=width, pos=0 },
ctx => {
if ctx.pos + ctx.width < ctx.arr.count {
defer ctx.pos += 1;
use core {iter}
return iter.generator(
- ^.{ arr=arr, width=width, pos=0 },
+ &.{ arr=arr, width=width, pos=0 },
ctx => {
if ctx.pos < ctx.arr.count {
defer ctx.pos += ctx.width;
AVL_Tree :: struct (T: type_expr) {
data: T;
- left, right: ^AVL_Tree(T);
+ left, right: &AVL_Tree(T);
height: i32;
}
-insert :: (ptree: ^^AVL_Tree($T), data: T) {
+insert :: (ptree: & &AVL_Tree($T), data: T) {
tree := *ptree;
if tree == null {
node := new(typeof *tree);
}
if data < tree.data {
- insert(^tree.left, data);
+ insert(&tree.left, data);
} else {
- insert(^tree.right, data);
+ insert(&tree.right, data);
}
tree.height = math.max(get_height(tree.left), get_height(tree.right)) + 1;
if child_bf < 0 {
rotate_left(ptree);
} else {
- rotate_right(^tree.right);
+ rotate_right(&tree.right);
rotate_left(ptree);
}
if child_bf < 0 {
rotate_right(ptree);
} else {
- rotate_left(^tree.left);
+ rotate_left(&tree.left);
rotate_right(ptree);
}
}
}
-delete :: (tree: ^AVL_Tree, data: tree.T) {
+delete :: (tree: &AVL_Tree, data: tree.T) {
}
-contains :: (tree: ^AVL_Tree, data: tree.T) -> bool {
+contains :: (tree: &AVL_Tree, data: tree.T) -> bool {
if tree == null do return false;
if tree.data == data do return true;
else do return contains(tree.right, data);
}
-print :: (tree: ^AVL_Tree) {
+print :: (tree: &AVL_Tree) {
use core {
std_print :: print,
printf
}
}
-#local get_height :: (tree: ^AVL_Tree) -> i32 {
+#local get_height :: (tree: &AVL_Tree) -> i32 {
if tree == null do return -1;
return tree.height;
}
-#local rotate_left :: (tree: ^^AVL_Tree) {
+#local rotate_left :: (tree: & &AVL_Tree) {
A := *tree;
B := A.right;
A.right = B.left;
B.height = math.max(get_height(B.left), get_height(B.right)) + 1;
}
-#local rotate_right :: (tree: ^^AVL_Tree) {
+#local rotate_right :: (tree: & &AVL_Tree) {
A := *tree;
B := A.left;
A.left = B.right;
Bucket :: struct (T: type_expr) {
count : i32;
- data : ^T; // Actually an array of elements_per_bucket things, but putting that
+ data : &T; // Actually an array of elements_per_bucket things, but putting that
// that into the type system makes these cumbersome to work with.
}
}
array_allocator := context.allocator, bucket_allocator := context.allocator) -> Bucket_Array(T) {
buckets : Bucket_Array(T);
- init(^buckets, elements);
+ init(&buckets, elements);
return buckets;
}
-init :: (use b: ^Bucket_Array($T), elements: i32,
+init :: (use b: &Bucket_Array($T), elements: i32,
array_allocator := context.allocator, bucket_allocator := context.allocator) {
allocator = bucket_allocator;
buckets = array.make(Bucket_Array.Bucket(T), allocator=array_allocator);
initial_bucket := alloc_bucket(b);
- array.push(^buckets, initial_bucket);
+ array.push(&buckets, initial_bucket);
}
// Frees all the buckets
-clear :: (use b: ^Bucket_Array($T)) {
- for ^bucket: ^buckets {
+clear :: (use b: &Bucket_Array($T)) {
+ for &bucket: &buckets {
raw_free(bucket_allocator, bucket.data);
bucket.count = 0;
}
- array.clear(^buckets);
+ array.clear(&buckets);
}
#operator [] macro (b: Bucket_Array($T), idx: i32) -> T {
get :: get
- return get(^b, idx);
+ return get(&b, idx);
}
-#operator ^[] macro (b: Bucket_Array($T), idx: i32) -> ^T {
+#operator &[] macro (b: Bucket_Array($T), idx: i32) -> &T {
get_ptr :: get_ptr
- return get_ptr(^b, idx);
+ return get_ptr(&b, idx);
}
-get :: (use b: ^Bucket_Array($T), idx: i32) -> T {
+get :: (use b: &Bucket_Array($T), idx: i32) -> T {
bucket_index := idx / elements_per_bucket;
elem_index := idx % elements_per_bucket;
return buckets[bucket_index].data[elem_index];
}
-get_ptr :: (use b: ^Bucket_Array($T), idx: i32) -> ^T {
+get_ptr :: (use b: &Bucket_Array($T), idx: i32) -> &T {
bucket_index := idx / elements_per_bucket;
elem_index := idx % elements_per_bucket;
- return ^buckets[bucket_index].data[elem_index];
+ return &buckets[bucket_index].data[elem_index];
}
-push :: (use b: ^Bucket_Array($T), elem: T) -> bool {
- last_bucket := ^buckets[buckets.count - 1];
+push :: (use b: &Bucket_Array($T), elem: T) -> bool {
+ last_bucket := &buckets[buckets.count - 1];
if last_bucket.count < elements_per_bucket {
last_bucket.data[last_bucket.count] = elem;
last_bucket.count += 1;
} else {
new_bucket := alloc_bucket(b);
- array.push(^buckets, new_bucket);
+ array.push(&buckets, new_bucket);
- last_bucket = ^buckets[buckets.count - 1];
+ last_bucket = &buckets[buckets.count - 1];
last_bucket.data[last_bucket.count] = elem;
last_bucket.count += 1;
}
}
-#operator << macro (b: Bucket_Array($T), elem: T) do core.bucket_array.push(^b, elem);
+#operator << macro (b: Bucket_Array($T), elem: T) do core.bucket_array.push(&b, elem);
-pop :: (use b: ^Bucket_Array($T)) {
- last_bucket := ^buckets[buckets.count - 1];
+pop :: (use b: &Bucket_Array($T)) {
+ last_bucket := &buckets[buckets.count - 1];
last_bucket.count -= 1;
}
// Give you a pointer to the bucket data via 'it'.
for_each :: macro (b: Bucket_Array($T), body: Code) {
- for ^bucket: b.buckets {
+ for &bucket: b.buckets {
for bucket_index: bucket.count {
- it := ^bucket.data[bucket_index];
+ it := &bucket.data[bucket_index];
#unquote body;
}
}
#match iter.as_iter as_iter
-as_iter :: (b: ^Bucket_Array($T)) -> Iterator(T) {
+as_iter :: (b: &Bucket_Array($T)) -> Iterator(T) {
Context :: struct (T: type_expr) {
- ba : ^Bucket_Array(T);
+ ba : &Bucket_Array(T);
bucket_idx : i32;
elem_idx : i32;
}
c.bucket_idx = 0;
c.elem_idx = 0;
- next :: (use c: ^Context($T)) -> (T, bool) {
+ next :: (use c: &Context($T)) -> (T, bool) {
use core.intrinsics.onyx
- bucket := ^ba.buckets[bucket_idx];
+ bucket := &ba.buckets[bucket_idx];
while elem_idx == bucket.count {
bucket_idx += 1;
if bucket_idx == ba.buckets.count do return .{}, false;
- bucket = ^ba.buckets[bucket_idx];
+ bucket = &ba.buckets[bucket_idx];
elem_idx = 0;
}
}
#package
-alloc_bucket :: (use b: ^Bucket_Array($T)) -> Bucket_Array.Bucket(T) {
+alloc_bucket :: (use b: &Bucket_Array($T)) -> Bucket_Array.Bucket(T) {
data := raw_alloc(allocator, sizeof T * elements_per_bucket);
return .{ 0, data };
}
make :: ($T: type_expr, cmp: (T, T) -> i32 = null_proc) -> Heap(T) {
h: Heap(T);
- init(^h, cmp);
+ init(&h, cmp);
return h;
}
-init :: (use heap: ^Heap, cmp: (heap.T, heap.T) -> i32 = null_proc) {
- array.init(^data);
+init :: (use heap: &Heap, cmp: (heap.T, heap.T) -> i32 = null_proc) {
+ array.init(&data);
compare = cmp;
}
-insert :: (use heap: ^Heap, v: heap.T) {
+insert :: (use heap: &Heap, v: heap.T) {
data << v;
shift_up(heap, data.count - 1);
}
-#operator << macro (heap: Heap($T), v: T) do core.heap.insert(^heap, v);
+#operator << macro (heap: Heap($T), v: T) do core.heap.insert(&heap, v);
-remove_top :: (use heap: ^Heap) -> heap.T {
+remove_top :: (use heap: &Heap) -> heap.T {
x := data[0];
- array.fast_delete(^data, 0);
+ array.fast_delete(&data, 0);
shift_down(heap, 0);
return x;
}
heap_lchild :: macro (index) => (index * 2) + 1
heap_rchild :: macro (index) => (index * 2) + 2
- shift_down :: (use heap: ^Heap, idx: i32) {
+ shift_down :: (use heap: &Heap, idx: i32) {
while true {
min_index := idx;
}
}
- shift_up :: (use heap: ^Heap, idx: i32) {
+ shift_up :: (use heap: &Heap, idx: i32) {
while idx > 0 {
parent := heap_parent(idx);
if compare(data[parent], data[idx]) <= 0 do break;
//
#overload #order 10000
-as_iter :: (x: ^$T/ImplicitIterator) => {
+as_iter :: (x: &$T/ImplicitIterator) => {
x->iter_open();
return generator_no_copy(x, T.iter_next, T.iter_close);
}
#overload
filter :: (it: Iterator($T), predicate: (T) -> bool) =>
generator(
- ^.{ iterator = it, predicate = predicate },
+ &.{ iterator = it, predicate = predicate },
fi => {
value, cont := next(fi.iterator);
#overload
filter :: (it: Iterator($T), ctx: $Ctx, predicate: (T, Ctx) -> bool) =>
generator(
- ^.{ iterator = it, predicate = predicate, ctx = ctx },
+ &.{ iterator = it, predicate = predicate, ctx = ctx },
fi => {
value, cont := next(fi.iterator);
#overload
map :: (it: Iterator($T), transform: (T) -> $R) =>
generator(
- ^.{ iterator = it, transform = transform },
+ &.{ iterator = it, transform = transform },
mi => {
value, cont := next(mi.iterator);
#overload
map :: (it: Iterator($T), ctx: $Ctx, transform: (T, Ctx) -> $R) =>
generator(
- ^.{ iterator = it, transform = transform, ctx = ctx },
+ &.{ iterator = it, transform = transform, ctx = ctx },
mi => {
value, cont := next(mi.iterator);
// Only yields the first `count` values, then closes.
take :: (it: Iterator($T), count: u32) -> Iterator(T) {
return generator(
- ^.{ iterator = it, remaining = count },
+ &.{ iterator = it, remaining = count },
ti => {
if ti.remaining > 0 {
// Yields values while the predicate returns true.
take_while :: (it: Iterator($T), predicate: (T) -> bool) -> Iterator(T) {
return generator(
- ^.{ iterator = it, predicate = predicate },
+ &.{ iterator = it, predicate = predicate },
ti => {
value, cont := next(ti.iterator);
// Discards the first `count` values and yields all remaining values,
skip :: (it: Iterator($T), count: u32) -> Iterator(T) {
return generator(
- ^.{ iterator = it, to_skip = count, skipped = false },
+ &.{ iterator = it, to_skip = count, skipped = false },
si => {
while !si.skipped && si.to_skip > 0 {
#overload
skip_while :: (it: Iterator($T), predicate: (T) -> bool) -> Iterator(T) {
return generator(
- ^.{ iterator = it, predicate = predicate, skipped = false },
+ &.{ iterator = it, predicate = predicate, skipped = false },
si => {
while !si.skipped {
#overload
skip_while :: (it: Iterator($T), ctx: $Ctx, predicate: (T, Ctx) -> bool) -> Iterator(T) {
return generator(
- ^.{ iterator = it, ctx = ctx, predicate = predicate, skipped = false },
+ &.{ iterator = it, ctx = ctx, predicate = predicate, skipped = false },
si => {
while !si.skipped {
// the value from each of the iterators.
zip :: (left_iterator: Iterator($T), right_iterator: Iterator($R)) -> Iterator(Pair(T, R)) {
return generator(
- ^.{ left_iter = left_iterator, right_iter = right_iterator },
+ &.{ left_iter = left_iterator, right_iter = right_iterator },
zi => {
v1, cont1 := next(zi.left_iter);
// one, then yielding all values from the next, and so on.
concat :: (iters: ..Iterator($T)) -> Iterator(T) {
return generator(
- ^.{
+ &.{
iters = memory.copy_slice(iters, context.temp_allocator),
idx = 0
},
},
c => {
- for^ c.iters {
+ for& c.iters {
close(*it);
}
});
//
// Yields the same value indefinitely. Useful with iter.zip.
const :: (value: $T) -> Iterator(T) {
- return generator(^.{ v = value }, c => (c.v, true));
+ return generator(&.{ v = value }, c => (c.v, true));
}
#overload
enumerate :: (it: Iterator($T), start_index: i32 = 0) -> Iterator(Enumeration_Value(T)) {
return generator(
- ^.{ iterator = it, current_index = start_index },
+ &.{ iterator = it, current_index = start_index },
ec => {
value, cont := next(ec.iterator);
#overload
from_array :: (arr: [] $T/type_is_struct) => generator(
- ^.{ data = arr.data, count = arr.count, current = 0 },
+ &.{ data = arr.data, count = arr.count, current = 0 },
ctx => {
if ctx.current < ctx.count {
defer ctx.current += 1;
- return ^ctx.data[ctx.current], true;
+ return &ctx.data[ctx.current], true;
}
return null, false;
#overload
from_array :: (arr: [] $T) => generator(
- ^.{ data = arr.data, count = arr.count, current = 0 },
+ &.{ data = arr.data, count = arr.count, current = 0 },
ctx => {
if ctx.current < ctx.count {
// Iterators created from pointers to dynamic arrays are
// special, because they support the #remove directive.
#local
-generic_dynamic_array_as_iter :: (x: ^[..] $T, $access: Code, $return_type: type_expr) => {
+generic_dynamic_array_as_iter :: (x: &[..] $T, $access: Code, $return_type: type_expr) => {
Context :: struct (T: type_expr) {
- arr: ^[..] T;
+ arr: &[..] T;
current: u32;
}
c.arr = x;
c.current = 0;
- next :: (use _: ^Context($T), $access: Code) => {
+ next :: (use _: &Context($T), $access: Code) => {
if current < arr.count {
defer current += 1;
return (#unquote access), true;
}
}
- remove :: (use _: ^Context($T)) {
+ remove :: (use _: &Context($T)) {
//
// This is current - 1 because current will have already
// been incremented by the time this element calls #remove.
#overload
-as_iter :: macro (x: ^[..] $T) => {
+as_iter :: macro (x: &[..] $T) => {
G :: generic_dynamic_array_as_iter
return G(x, #(arr.data[current]), Iterator(T));
}
#overload
-as_iter :: macro (x: ^[..] $T, by_pointer: bool) => {
+as_iter :: macro (x: &[..] $T, by_pointer: bool) => {
G :: generic_dynamic_array_as_iter
- return G(x, #(^arr.data[current]), Iterator(^T));
+ return G(x, #(&arr.data[current]), Iterator(&T));
}
#overload
as_iter :: (r: range) => generator(
- ^.{ r = r, v = r.low },
+ &.{ r = r, v = r.low },
ctx => {
if ctx.r.step > 0 {
if ctx.v >= ctx.r.high {
// using the allocator provided (context.allocator by default).
to_array :: (it: Iterator($T), allocator := context.allocator) -> [..] T {
arr := array.make(T, allocator=allocator);
- for v: it do array.push(^arr, v);
+ for v: it do array.push(&arr, v);
return arr;
}
y_val, _ := take_one(y_iter);
return generator(
- ^.{
+ &.{
x = x,
x_iter = as_iter(x),
comp :: #match #local {}
#overload
-comp :: macro (i: Iterator(^$V), value: Code) => {
+comp :: macro (i: Iterator(&$V), value: Code) => {
it: V;
a := make([..] typeof #unquote value);
generator :: #match #local {}
#overload
-generator :: (ctx: ^$Ctx, gen: (^Ctx) -> ($T, bool)) -> Iterator(T) {
+generator :: (ctx: &$Ctx, gen: (&Ctx) -> ($T, bool)) -> Iterator(T) {
v := raw_alloc(context.temp_allocator, sizeof Ctx);
core.memory.copy(v, ctx, sizeof Ctx);
}
#overload
-generator :: (ctx: ^$Ctx, gen: (^Ctx) -> ($T, bool), close: (^Ctx) -> void) -> Iterator(T) {
+generator :: (ctx: &$Ctx, gen: (&Ctx) -> ($T, bool), close: (&Ctx) -> void) -> Iterator(T) {
v := raw_alloc(context.temp_allocator, sizeof Ctx);
core.memory.copy(v, ctx, sizeof Ctx);
generator_no_copy :: #match #local {}
#overload
-generator_no_copy :: (ctx: ^$Ctx, gen: (^Ctx) -> ($T, bool)) =>
+generator_no_copy :: (ctx: &$Ctx, gen: (&Ctx) -> ($T, bool)) =>
Iterator(T).{ ctx, gen }
#overload
-generator_no_copy :: (ctx: ^$Ctx, gen: (^Ctx) -> ($T, bool), close: (^Ctx) -> void) =>
+generator_no_copy :: (ctx: &$Ctx, gen: (&Ctx) -> ($T, bool), close: (&Ctx) -> void) =>
Iterator(T).{ ctx, gen, close }
ended := false;
}
- next :: (use c: ^Context($T)) -> (T, bool) {
+ next :: (use c: &Context($T)) -> (T, bool) {
if ended do return .{}, false;
- sync.scoped_mutex(^mutex);
+ sync.scoped_mutex(&mutex);
if v, success := take_one(iterator); !success {
ended = true;
}
}
- close :: (use c: ^Context($T)) {
- sync.mutex_destroy(^c.mutex);
+ close :: (use c: &Context($T)) {
+ sync.mutex_destroy(&c.mutex);
delete(c);
}
// a lot of iterators in their theads and I don't want to cause
// the distributor's context be overwritten.
c := new(Context(it.Iter_Type));
- sync.mutex_init(^c.mutex);
+ sync.mutex_init(&c.mutex);
c.iterator = it;
return .{c, #solidify next {T=it.Iter_Type}, #solidify close {T=it.Iter_Type}};
// Allows you to easily write a parallelized for-loop over an iterator.
// For example,
//
- // iter.parallel_for(1 .. 100, 4, ^.{}) {
+ // iter.parallel_for(1 .. 100, 4, &.{}) {
// printf("Thread {} has {}!\n", context.thread_id, it);
// }
//
parallel_for :: #match #local {}
#overload
- parallel_for :: macro (iterable: $I/Iterable, thread_count: u32, thread_data: ^$Ctx, body: Code) {
+ parallel_for :: macro (iterable: $I/Iterable, thread_count: u32, thread_data: &$Ctx, body: Code) {
#this_package.parallel_for(
#this_package.as_iter(iterable),
thread_count,
}
#overload
- parallel_for :: macro (iter: Iterator($T), thread_count: u32, thread_data: ^$Ctx, body: Code) {
+ parallel_for :: macro (iter: Iterator($T), thread_count: u32, thread_data: &$Ctx, body: Code) {
use core {thread, alloc}
if thread_count != 0 {
dist := #this_package.distributor(iter);
- t_data := ^.{iter = ^dist, data = thread_data};
+ t_data := &.{iter = &dist, data = thread_data};
threads := alloc.array_from_stack(thread.Thread, thread_count - 1);
- for^ threads do thread.spawn(it, t_data, #solidify thread_function {body=body});
+ for& threads do thread.spawn(it, t_data, #solidify thread_function {body=body});
thread_function(t_data, body);
- for^ threads do thread.join(it);
+ for& threads do thread.join(it);
if dist.close != null_proc do dist.close(dist.data);
}
- thread_function :: (__data: ^$T, $body: Code) {
+ thread_function :: (__data: &$T, $body: Code) {
thread_data := __data.data;
for #no_close *__data.iter {
#unquote body;
package core.list
ListElem :: struct (T: type_expr) {
- next: ^ListElem(T) = null;
- prev: ^ListElem(T) = null;
+ next: &ListElem(T) = null;
+ prev: &ListElem(T) = null;
data: T;
}
List :: struct (Elem_Type: type_expr) {
allocator: Allocator;
- first: ^ListElem(Elem_Type) = null;
- last: ^ListElem(Elem_Type) = null;
+ first: &ListElem(Elem_Type) = null;
+ last: &ListElem(Elem_Type) = null;
}
#inject List {
return .{ allocator = allocator };
}
-free :: (list: ^List) {
+free :: (list: &List) {
elem := list.first;
while elem != null {
to_delete := elem;
}
}
-push_end :: (list: ^List, x: list.Elem_Type) {
+push_end :: (list: &List, x: list.Elem_Type) {
new_elem := allocate_elem(list);
new_elem.data = x;
if list.first == null do list.first = new_elem;
}
-push_begin :: (list: ^List, x: list.Elem_Type) {
+push_begin :: (list: &List, x: list.Elem_Type) {
new_elem := allocate_elem(list);
new_elem.data = x;
if list.last == null do list.last = new_elem;
}
-pop_end :: (list: ^List($T), default: T = .{}) -> T {
+pop_end :: (list: &List($T), default: T = .{}) -> T {
if list.last == null do return default;
end := list.last;
return end.data;
}
-pop_begin :: (list: ^List($T), default: T = .{}) -> T {
+pop_begin :: (list: &List($T), default: T = .{}) -> T {
if list.last == null do return default;
begin := list.first;
return begin.data;
}
-count :: (list: ^List) -> i32 {
+count :: (list: &List) -> i32 {
c := 0;
elem := list.first;
while elem != null {
return c;
}
-at :: (list: ^List, index: i32) -> ^T {
+at :: (list: &List, index: i32) -> &T {
elem := list.first;
while elem != null {
- if index == 0 do return ^elem.data;
+ if index == 0 do return &elem.data;
index -= 1;
elem = elem.next;
}
return null;
}
-contains :: (list: ^List, x: list.Elem_Type) -> bool {
+contains :: (list: &List, x: list.Elem_Type) -> bool {
elem := list.first;
while elem != null {
if elem.data == x do return true;
return false;
}
-fold :: (list: ^List($T), init: $R, f: (T, R) -> R) -> R {
+fold :: (list: &List($T), init: $R, f: (T, R) -> R) -> R {
val := init;
link := list.first;
}
map :: #match #local {}
-#match map (list: ^List($T), f: (T) -> $R) -> List(R) {
+#match map (list: &List($T), f: (T) -> $R) -> List(R) {
new_list := make(R, allocator=list.allocator);
elem := list.first;
while elem != null {
- push_end(^new_list, f(elem.data));
+ push_end(&new_list, f(elem.data));
elem = elem.next;
}
return new_list;
}
-#match map (list: ^List($T), f: (^T) -> void) {
+#match map (list: &List($T), f: (&T) -> void) {
elem := list.first;
while elem != null {
- f(^elem.data);
+ f(&elem.data);
elem = elem.next;
}
}
#match core.iter.as_iter as_iter
-as_iter :: (list: ^List) =>
- core.iter.generator(^.{current = list.first}, (ctx) => {
+as_iter :: (list: &List) =>
+ core.iter.generator(&.{current = list.first}, (ctx) => {
if ctx.current != null {
defer ctx.current = ctx.current.next;
return ctx.current.data, true;
return .{}, false;
});
-#local allocate_elem :: macro (list: ^List($T)) => new(ListElem(T), allocator=list.allocator);
+#local allocate_elem :: macro (list: &List($T)) => new(ListElem(T), allocator=list.allocator);
// m := make(Map(str, i32));
//
#overload
-__make_overload :: macro (x: ^Map($K, $V), allocator := context.allocator) =>
+__make_overload :: macro (x: &Map($K, $V), allocator := context.allocator) =>
#this_package.make(K, V);
//
// Creates and initializes a new map using the types provided.
make :: macro ($Key: type_expr, $Value: type_expr, default := Value.{}) -> Map(Key, Value) {
map : Map(Key, Value);
- #this_package.init(^map, default = default);
+ #this_package.init(&map, default = default);
return map;
}
//
// Initializes a map.
-init :: (use map: ^Map($K, $V), default := V.{}) {
+init :: (use map: &Map($K, $V), default := V.{}) {
__initialize(map);
allocator = context.allocator;
hashes = builtin.make([] u32, 8, allocator=allocator);
array.fill(hashes, -1);
- array.init(^entries, allocator=allocator);
+ array.init(&entries, allocator=allocator);
}
//
-// Allows for deletion of a Map using delete(^map).
+// Allows for deletion of a Map using delete(&map).
#match builtin.delete core.map.free
//
// Destroys a map and frees all memory.
-free :: (use map: ^Map) {
- if hashes.data != null do memory.free_slice(^hashes, allocator=allocator);
- if entries.data != null do array.free(^entries);
+free :: (use map: &Map) {
+ if hashes.data != null do memory.free_slice(&hashes, allocator=allocator);
+ if entries.data != null do array.free(&entries);
}
//
// Sets the value at the specified key, or creates a new entry
// if the key was not already present.
-put :: (use map: ^Map, key: map.Key_Type, value: map.Value_Type) {
+put :: (use map: &Map, key: map.Key_Type, value: map.Value_Type) {
lr := lookup(map, key);
if lr.entry_index >= 0 {
//
// Returns true if the map contains the key.
-has :: (use map: ^Map, key: map.Key_Type) -> bool {
+has :: (use map: &Map, key: map.Key_Type) -> bool {
lr := lookup(map, key);
return lr.entry_index >= 0;
}
// This is subject to change with the addition of Optional to the
// standard library.
//
-get :: (use map: ^Map, key: map.Key_Type) -> map.Value_Type {
+get :: (use map: &Map, key: map.Key_Type) -> map.Value_Type {
lr := lookup(map, key);
if lr.entry_index >= 0 do return entries[lr.entry_index].value;
//
// Returns a pointer to the value at the specified key, or null if
// the key is not present.
-get_ptr :: (use map: ^Map, key: map.Key_Type) -> ^map.Value_Type {
+get_ptr :: (use map: &Map, key: map.Key_Type) -> &map.Value_Type {
lr := lookup(map, key);
- if lr.entry_index >= 0 do return ^entries[lr.entry_index].value;
+ if lr.entry_index >= 0 do return &entries[lr.entry_index].value;
return null;
}
// Returns a pointer to the value at the specified key. If the key
// is not in the map, a new value is created and inserted, then the
// pointer to that value is returned.
-get_ptr_or_create :: (use map: ^Map, key: map.Key_Type) -> ^map.Value_Type {
+get_ptr_or_create :: (use map: &Map, key: map.Key_Type) -> &map.Value_Type {
lr := lookup(map, key);
if lr.entry_index < 0 {
put(map, key, .{});
lr = lookup(map, key);
}
- return ^entries[lr.entry_index].value;
+ return &entries[lr.entry_index].value;
}
//
// Returns an Optional of the value at the specified key. The Optional
// has a value if the key is present, otherwise the optional does not
// have a value.
-get_opt :: (use map: ^Map, key: map.Key_Type) -> ?map.Value_Type {
+get_opt :: (use map: &Map, key: map.Key_Type) -> ?map.Value_Type {
lr := lookup(map, key);
if lr.entry_index >= 0 do return Optional.make(entries[lr.entry_index].value);
//
// Removes an entry from the map.
-delete :: (use map: ^Map, key: map.Key_Type) {
+delete :: (use map: &Map, key: map.Key_Type) {
lr := lookup(map, key);
if lr.entry_index < 0 do return;
else do entries[lr.entry_prev].next = entries[lr.entry_index].next;
if lr.entry_index == entries.count - 1 {
- array.pop(^entries);
+ array.pop(&entries);
return;
}
- array.fast_delete(^entries, lr.entry_index);
+ array.fast_delete(&entries, lr.entry_index);
last := lookup(map, entries[lr.entry_index].key);
if last.entry_prev >= 0 do entries[last.entry_prev].next = lr.entry_index;
// or:
// m->update("test", #(*it += 10));
//
-update :: macro (map: ^Map, key: map.Key_Type, body: Code) {
+update :: macro (map: &Map, key: map.Key_Type, body: Code) {
lookup_ :: lookup
lr := lookup_(map, key);
if lr.entry_index >= 0 {
- it := ^map.entries[lr.entry_index].value;
+ it := &map.entries[lr.entry_index].value;
#unquote body;
}
}
//
// Removes all entries from the hash map. Does NOT
// modify memory, so be wary of dangling pointers!
-clear :: (use map: ^Map) {
+clear :: (use map: &Map) {
for i: 0 .. hashes.count do hashes.data[i] = -1;
entries.count = 0;
}
//
// Returns if the map does not contain any elements.
-empty :: (use map: ^Map) -> bool {
+empty :: (use map: &Map) -> bool {
return entries.count == 0;
}
//
// Helper procedure to nicely format a Map when printing.
// Rarely ever called directly, instead used by conv.format_any.
-format_map :: (output: ^conv.Format_Output, format: ^conv.Format, x: ^Map($K, $V)) {
+format_map :: (output: &conv.Format_Output, format: &conv.Format, x: &Map($K, $V)) {
if format.pretty_printing {
output->write("{\n");
- for^ x.entries {
+ for& x.entries {
conv.format(output, " {\"p} => {\"p}\n", it.key, it.value);
}
output->write("}");
} else {
output->write("{ ");
- for^ x.entries {
+ for& x.entries {
if !#first do output->write(", ");
conv.format(output, "{\"p} => {\"p}", it.key, it.value);
}
//
literal :: ($Key: type_expr, $Value: type_expr, values: [] MapLiteralValue(Key, Value)) => {
m := core.map.make(Key, Value);
- for ^ values {
+ for & values {
m->put(it.key, it.value);
}
//
// Produces an iterator that yields all values of the map,
// in an unspecified order, as Map is unordered.
-as_iter :: (m: ^Map) =>
+as_iter :: (m: &Map) =>
core.iter.generator(
- ^.{ m = m, i = 0 },
+ &.{ m = m, i = 0 },
ctx => {
if ctx.i >= ctx.m.entries.count {
}
defer ctx.i += 1;
- return ^ctx.m.entries.data[ctx.i], true;
+ return &ctx.m.entries.data[ctx.i], true;
});
//
// Helper operator overloads for accessing values, accessing
// values by pointer, and setting values.
-#operator [] macro (map: Map($K, $V), key: K) -> V { return #this_package.get(^map, key); }
-#operator ^[] macro (map: Map($K, $V), key: K) -> ^V { return #this_package.get_ptr(^map, key); }
-#operator []= macro (map: Map($K, $V), key: K, value: V) { #this_package.put(^map, key, value); }
+#operator [] macro (map: Map($K, $V), key: K) -> V { return #this_package.get(&map, key); }
+#operator &[] macro (map: Map($K, $V), key: K) -> &V { return #this_package.get_ptr(&map, key); }
+#operator []= macro (map: Map($K, $V), key: K, value: V) { #this_package.put(&map, key, value); }
//
// Private symbols
hash : u32 = 0;
}
- lookup :: (use map: ^Map, key: map.Key_Type) -> MapLookupResult {
+ lookup :: (use map: &Map, key: map.Key_Type) -> MapLookupResult {
if hashes.data == null do init(map);
lr := MapLookupResult.{};
return lr;
}
- full :: (use map: ^Map) => entries.count >= (hashes.count >> 2) * 3;
+ full :: (use map: &Map) => entries.count >= (hashes.count >> 2) * 3;
- grow :: (use map: ^Map) {
+ grow :: (use map: &Map) {
new_size := math.max(hashes.count << 1, 8);
rehash(map, new_size);
}
- rehash :: (use map: ^Map, new_size: i32) {
- memory.free_slice(^hashes, allocator);
+ rehash :: (use map: &Map, new_size: i32) {
+ memory.free_slice(&hashes, allocator);
hashes = builtin.make([] u32, new_size, allocator=allocator);
array.fill(hashes, -1);
- for ^entry: entries do entry.next = -1;
+ for &entry: entries do entry.next = -1;
index := 0;
- for ^entry: entries {
+ for &entry: entries {
defer index += 1;
hash_index := entry.hash % hashes.count;
}
#doc "Clears the value in the Optional, zeroing the memory of the value."
- reset :: (o: ^?$T) {
+ reset :: (o: &?$T) {
o.has_value = false;
- core.memory.set(^o.value, 0, sizeof T);
+ core.memory.set(&o.value, 0, sizeof T);
}
#doc "Sets the value in the Optional."
- set :: (o: ^?$T, value: T) {
+ set :: (o: &?$T, value: T) {
o.has_value = true;
o.value = value;
}
#inject Pair {
make :: macro (x: $X, y: $Y) => Pair(X, Y).{x, y};
- _format :: (output: ^conv.Format_Output, format: ^conv.Format, p: ^Pair($First_Type, $Second_Type)) {
+ _format :: (output: &conv.Format_Output, format: &conv.Format, p: &Pair($First_Type, $Second_Type)) {
conv.format(output, "({}, {})", p.first, p.second);
}
}
#unquote on_err;
}
- format :: (o: ^conv.Format_Output, format: ^conv.Format, res: ^Result($T, $E)) {
+ format :: (o: &conv.Format_Output, format: &conv.Format, res: &Result($T, $E)) {
if res.status == .Ok {
conv.format(o, "{}({\"})", res.status, res.__data.value);
} else {
make :: ($T: type_expr, default := T.{}, allocator := context.allocator) -> Set(T) {
set : Set(T);
- init(^set, default=default, allocator=allocator);
+ init(&set, default=default, allocator=allocator);
return set;
}
#overload
-builtin.__make_overload :: macro (x: ^Set, allocator: Allocator) => core.set.make(x.Elem_Type, allocator = allocator);
+builtin.__make_overload :: macro (x: &Set, allocator: Allocator) => core.set.make(x.Elem_Type, allocator = allocator);
-init :: (set: ^Set($T), default := T.{}, allocator := context.allocator) {
+init :: (set: &Set($T), default := T.{}, allocator := context.allocator) {
set.allocator = allocator;
set.default_value = default;
- memory.alloc_slice(^set.hashes, 8, allocator=allocator);
+ memory.alloc_slice(&set.hashes, 8, allocator=allocator);
array.fill(set.hashes, -1);
- array.init(^set.entries, 4, allocator=allocator);
+ array.init(&set.entries, 4, allocator=allocator);
}
-free :: (use set: ^Set) {
- memory.free_slice(^hashes, allocator=allocator);
- array.free(^entries);
+free :: (use set: &Set) {
+ memory.free_slice(&hashes, allocator=allocator);
+ array.free(&entries);
}
#overload
builtin.delete :: core.set.free
-insert :: (use set: ^Set, value: set.Elem_Type) {
+insert :: (use set: &Set, value: set.Elem_Type) {
if hashes.data == null do init(set);
lr := lookup(set, value);
if full(set) do grow(set);
}
-#operator << macro (set: Set($T), value: T) do core.set.insert(^set, value);
+#operator << macro (set: Set($T), value: T) do core.set.insert(&set, value);
-has :: (use set: ^Set, value: set.Elem_Type) -> bool {
+has :: (use set: &Set, value: set.Elem_Type) -> bool {
lr := lookup(set, value);
return lr.entry_index >= 0;
}
-get :: (use set: ^Set, value: set.Elem_Type) -> set.Elem_Type {
+get :: (use set: &Set, value: set.Elem_Type) -> set.Elem_Type {
lr := lookup(set, value);
return entries[lr.entry_index].value if lr.entry_index >= 0 else set.Elem_Type.{};
}
-get_ptr :: (use set: ^Set, value: set.Elem_Type) -> ^set.Elem_Type {
+get_ptr :: (use set: &Set, value: set.Elem_Type) -> &set.Elem_Type {
lr := lookup(set, value);
- return (^entries[lr.entry_index].value) if lr.entry_index >= 0 else null;
+ return (&entries[lr.entry_index].value) if lr.entry_index >= 0 else null;
}
-get_opt :: (use set: ^Set, value: set.Elem_Type) -> Optional(set.Elem_Type) {
+get_opt :: (use set: &Set, value: set.Elem_Type) -> Optional(set.Elem_Type) {
lr := lookup(set, value);
if lr.entry_index >= 0 do return Optional.make(entries[lr.entry_index].value);
return .{};
}
-remove :: (use set: ^Set, value: set.Elem_Type) {
+remove :: (use set: &Set, value: set.Elem_Type) {
lr := lookup(set, value);
if lr.entry_index < 0 do return;
else do entries[lr.entry_prev].next = entries[lr.entry_index].next;
if lr.entry_index == entries.count - 1 {
- array.pop(^entries);
+ array.pop(&entries);
return;
}
- array.fast_delete(^entries, lr.entry_index);
+ array.fast_delete(&entries, lr.entry_index);
last := lookup(set, entries[lr.entry_index].value);
if last.entry_prev >= 0 do entries[last.entry_prev].next = lr.entry_index;
else do hashes[last.hash_index] = lr.entry_index;
}
-clear :: (use set: ^Set) {
+clear :: (use set: &Set) {
array.fill(hashes, -1);
- array.clear(^entries);
+ array.clear(&entries);
}
-empty :: (use set: ^Set) -> bool {
+empty :: (use set: &Set) -> bool {
return entries.count == 0;
}
#overload core.iter.as_iter as_iter
-as_iter :: (s: ^Set) =>
+as_iter :: (s: &Set) =>
core.iter.generator(
- ^.{ s = s, i = 0 },
+ &.{ s = s, i = 0 },
(ctx) => {
if ctx.i >= ctx.s.entries.count {
- return (typeof ^ctx.s.entries.data.value).{}, false;
+ return (typeof &ctx.s.entries.data.value).{}, false;
}
defer ctx.i += 1;
- return ^ctx.s.entries.data[ctx.i].value, true;
+ return &ctx.s.entries.data[ctx.i].value, true;
});
//
hash : u32 = 0;
}
- lookup :: (use set: ^Set, value: set.Elem_Type) -> SetLookupResult {
+ lookup :: (use set: &Set, value: set.Elem_Type) -> SetLookupResult {
lr := SetLookupResult.{};
hash_value: u32 = hash.to_u32(value); // You cannot have a set of this type without defining a to_u32 hash.
return lr;
}
- full :: (use set: ^Set) => entries.count >= (hashes.count >> 2) * 3;
+ full :: (use set: &Set) => entries.count >= (hashes.count >> 2) * 3;
- grow :: (use set: ^Set) {
+ grow :: (use set: &Set) {
new_size := math.max(hashes.count << 1, 8);
rehash(set, new_size);
}
- rehash :: (use set: ^Set, new_size: i32) {
- memory.free_slice(^hashes, allocator);
+ rehash :: (use set: &Set, new_size: i32) {
+ memory.free_slice(&hashes, allocator);
hashes = builtin.make([] u32, new_size, allocator=allocator);
array.fill(hashes, -1);
- for ^entry: entries do entry.next = -1;
+ for &entry: entries do entry.next = -1;
index := 0;
- for ^entry: entries {
+ for &entry: entries {
defer index += 1;
hash_index := entry.hash % hashes.count;
str_to_i64 :: macro (s: str, base: u32 = 10) -> i64 {
str_to_i64 :: str_to_i64;
s_ := s;
- return str_to_i64(^s_, base);
+ return str_to_i64(&s_, base);
}
#overload
-str_to_i64 :: (s: ^str, base: u32 = 10) -> i64 {
+str_to_i64 :: (s: &str, base: u32 = 10) -> i64 {
use package core
string.strip_leading_whitespace(s);
str_to_f64 :: macro (s: str) -> f64 {
str_to_f64 :: str_to_f64;
s_ := s;
- return str_to_f64(^s_);
+ return str_to_f64(&s_);
}
#overload
-str_to_f64 :: (s: ^str) -> f64 {
+str_to_f64 :: (s: &str) -> f64 {
use package core
string.strip_leading_whitespace(s);
return value;
- parse_sign :: (s: ^str) -> f64 {
+ parse_sign :: (s: &str) -> f64 {
switch s.data[0] {
case #char "-" { string.advance(s, 1); return -1; }
case #char "+" { string.advance(s, 1); return 1; }
}
}
- parse_digits :: (s: ^str) -> (f64, digit_count: i32) {
+ parse_digits :: (s: &str) -> (f64, digit_count: i32) {
value: f64 = 0;
count := 0;
while s.count > 0 do switch s.data[0] {
n = -n;
}
- c := ^buf[buf.count - 1];
+ c := &buf[buf.count - 1];
len := 0;
BASE64_MAP := "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/";
// Converts an unsigned number into a string using the buffer provided.
// Behaves like i64_to_str.
u64_to_str :: (n: u64, base: u64, buf: [] u8, min_length := 0, prefix := false) -> str {
- c := ^buf[buf.count - 1];
+ c := &buf[buf.count - 1];
len := 0;
BASE64_MAP := "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/";
use core {map, string, array, math}
#package {
- custom_formatters: Map(type_expr, #type (^Format_Output, ^Format, rawptr) -> void);
+ custom_formatters: Map(type_expr, #type (&Format_Output, &Format, rawptr) -> void);
custom_parsers : Map(type_expr, #type (rawptr, str, Allocator) -> bool);
}
// It looks for all custom formatting and parsing definitions and
// registers them to be used in format_any and parse_any.
custom_formatters_initialized :: #init () {
- map.init(^custom_formatters, default=null_proc);
- map.init(^custom_parsers, default=null_proc);
+ map.init(&custom_formatters, default=null_proc);
+ map.init(&custom_parsers, default=null_proc);
#if Enable_Custom_Formatters {
use package runtime.info;
type := type_table[type_idx];
if type.kind != .Struct do continue;
- s_info := cast(^Type_Info_Struct) type;
+ s_info := cast(&Type_Info_Struct) type;
for s_info.tags {
if it.type == Custom_Format {
- custom_format := cast(^Custom_Format) it.data;
+ custom_format := cast(&Custom_Format) it.data;
custom_formatters[cast(type_expr) type_idx] = custom_format.format;
}
if it.type == Custom_Parse {
- custom_parse := cast(^Custom_Parse) it.data;
+ custom_parse := cast(&Custom_Parse) it.data;
custom_parsers[cast(type_expr) type_idx] = custom_parse.parse;
}
}
}
format_procedures := get_procedures_with_tag(Custom_Format_Proc);
- defer delete(^format_procedures);
+ defer delete(&format_procedures);
for p: format_procedures {
custom_format := p.tag;
- custom_formatters[custom_format.type] = *cast(^(^Format_Output, ^Format, rawptr) -> void, ^p.func);
+ custom_formatters[custom_format.type] = *cast(&(&Format_Output, &Format, rawptr) -> void, &p.func);
}
parse_procedures := get_procedures_with_tag(Custom_Parse_Proc);
- defer delete(^parse_procedures);
+ defer delete(&parse_procedures);
for p: parse_procedures {
custom_parse := p.tag;
- custom_parsers[custom_parse.type] = *cast(^(rawptr, str, Allocator) -> bool, ^p.func);
+ custom_parsers[custom_parse.type] = *cast(&(rawptr, str, Allocator) -> bool, &p.func);
}
}
}
//
// Registers a formatting function for a particular type. This type is
// inferred from the type of the third argument in the given function.
-register_custom_formatter :: (formatter: (^Format_Output, ^Format, ^$T) -> void) {
+register_custom_formatter :: (formatter: (&Format_Output, &Format, &$T) -> void) {
custom_formatters[T] = formatter;
}
//
// Registers a parsing function for a particular type. This type is
// inferred from the type of the first argument in the given function.
-register_custom_parser :: (parser: (^$T, str, Allocator) -> bool) {
+register_custom_parser :: (parser: (&$T, str, Allocator) -> bool) {
custom_parsers[T] = parser;
}
// TheStructure :: struct { ... }
//
Custom_Format :: struct {
- format: (^Format_Output, ^Format, rawptr) -> void;
+ format: (&Format_Output, &Format, rawptr) -> void;
}
// to format a type.
//
// @conv.Custom_Format_Proc.{ TheStructure }
-// format_structure :: (output: ^conv.Format_Output, format: ^conv.Format, data: ^TheStructure) { ... }
+// format_structure :: (output: &conv.Format_Output, format: &conv.Format, data: &TheStructure) { ... }
//
Custom_Format_Proc :: struct {
type: type_expr;
// to parse a type.
//
// @conv.Custom_Parse_Proc.{ TheStructure }
-// parse_structure :: (data: ^TheStructure, input: str, allocator: Allocator) -> bool { ... }
+// parse_structure :: (data: &TheStructure, input: str, allocator: Allocator) -> bool { ... }
//
Custom_Parse_Proc :: struct {
type: type_expr;
// When the internal buffer is filled, `flush` is called to empty the
// buffer to the final destination.
Format_Output :: struct {
- data: ^u8;
+ data: &u8;
count: u32;
capacity: u32;
flush: Format_Flush_Callback;
write :: #match {
- (use output: ^Format_Output, c: u8) {
+ (use output: &Format_Output, c: u8) {
if count >= capacity {
if flush.func == null_proc do return;
if !flush.func(flush.data, data[0 .. count]) do return;
count += 1;
},
- (use output: ^Format_Output, s: str) {
+ (use output: &Format_Output, s: str) {
for c: s {
if count >= capacity {
if flush.func == null_proc do return;
}
#local
-flush_to_dynstr :: (dynstr: ^[..] u8, to_write: str) => {
+flush_to_dynstr :: (dynstr: &[..] u8, to_write: str) => {
array.concat(dynstr, to_write);
return true;
}
}
#overload
-format :: (output: ^Format_Output, format: str, va: ..any) -> str {
+format :: (output: &Format_Output, format: str, va: ..any) -> str {
return format_va(output, format, ~~va);
}
#overload
-format :: (buffer: ^[..] u8, format: str, va: ..any) {
+format :: (buffer: &[..] u8, format: str, va: ..any) {
buffer.count = buffer.capacity;
out := format_va(*buffer, format, ~~va);
buffer.count = out.count;
out := make([..] u8);
output := Format_Output.{
~~buffer, 0, buffer.count,
- flush=.{ ^out, flush_to_dynstr }
+ flush=.{ &out, flush_to_dynstr }
};
- final := format_va(^output, format, ~~va);
- array.concat(^out, final);
+ final := format_va(&output, format, ~~va);
+ array.concat(&out, final);
return out;
}
#overload
format_va :: (buffer: [] u8, format: str, va: [] any, flush := Format_Flush_Callback.{}) -> str {
output := Format_Output.{ buffer.data, 0, buffer.count, flush };
- return format_va(^output, format, va);
+ return format_va(&output, format, va);
}
#overload
-format_va :: (buffer: ^[..] u8, format: str, va: [] any, flush := Format_Flush_Callback.{}) {
+format_va :: (buffer: &[..] u8, format: str, va: [] any, flush := Format_Flush_Callback.{}) {
buffer.count = buffer.capacity;
out := format_va(*buffer, format, va, flush);
buffer.count = out.count;
out := make([..] u8, allocator=allocator);
output := Format_Output.{
~~buffer, 0, buffer.count,
- flush=.{ ^out, flush_to_dynstr }
+ flush=.{ &out, flush_to_dynstr }
};
- final := format_va(^output, format, ~~va);
- array.concat(^out, final);
+ final := format_va(&output, format, ~~va);
+ array.concat(&out, final);
return out;
}
#overload
-format_va :: (output: ^Format_Output, format: str, va: [] any) -> str {
+format_va :: (output: &Format_Output, format: str, va: [] any) -> str {
vararg_index := 0;
while i := 0; i < format.count {
case #char "}" {
arg := va[vararg_index];
vararg_index += 1;
- format_any(output, ^formatting, arg);
+ format_any(output, &formatting, arg);
break break;
}
// This procedure converts any value into a string, using the type information system.
// If a custom formatter is specified for the type, that is used instead.
// This procedure is generally not used directly; instead, through format or format_va.
-format_any :: (output: ^Format_Output, formatting: ^Format, v: any) {
+format_any :: (output: &Format_Output, formatting: &Format, v: any) {
use package runtime.info
array :: package core.array;
formatting.dereference = false;
new_any: any;
- new_any.type = (cast(^Type_Info_Pointer) ti).to;
- new_any.data = *(cast(^rawptr) v.data);
+ new_any.type = (cast(&Type_Info_Pointer) ti).to;
+ new_any.data = *(cast(&rawptr) v.data);
format_any(output, formatting, new_any);
return;
}
switch v.type {
case bool {
- value := *(cast(^bool) v.data);
+ value := *(cast(&bool) v.data);
if value do output->write("true");
else do output->write("false");
}
case u8 {
- value := *(cast(^u8) v.data);
+ value := *(cast(&u8) v.data);
if value > 31 {
output->write(value);
int_case :: macro (T: type_expr) {
case T {
- value := *(cast(^T) v.data);
+ value := *(cast(&T) v.data);
ibuf : [128] u8;
istr := i64_to_str(~~value, formatting.base, ~~ibuf, min_length=formatting.minimum_width);
uint_case :: macro (T: type_expr) {
case T {
- value := *(cast(^T) v.data);
+ value := *(cast(&T) v.data);
ibuf : [128] u8;
istr := u64_to_str(~~value, formatting.base, ~~ibuf, min_length=formatting.minimum_width);
uint_case(u64);
case f32 {
- value := *(cast(^f32) v.data);
+ value := *(cast(&f32) v.data);
fbuf : [128] u8;
fstr := f64_to_str(~~value, ~~fbuf, formatting.digits_after_decimal);
}
case f64 {
- value := *(cast(^f64) v.data);
+ value := *(cast(&f64) v.data);
fbuf : [128] u8;
fstr := f64_to_str(~~value, ~~fbuf, formatting.digits_after_decimal);
if formatting.quote_strings do output->write("\"");
if formatting.single_quote_strings do output->write("'");
width := formatting.minimum_width;
- to_output := *cast(^str) v.data;
+ to_output := *cast(&str) v.data;
// @Todo // escape '"' when quote_strings is enabled.
output->write(to_output);
}
case rawptr {
- value := *(cast(^rawptr) v.data);
+ value := *(cast(&rawptr) v.data);
if value == null {
output->write("(null)");
}
case type_expr {
- value := *(cast(^type_expr) v.data);
+ value := *(cast(&type_expr) v.data);
io :: package core.io
// is through a io.Writer. That should maybe be changed in the future? Also, I think
// 256 bytes is enough for the name of a type but I'm not entirely sure...
stream := io.buffer_stream_make(~~buf, fixed=true);
- writer := io.writer_make(^stream, 0);
- write_type_name(^writer, value);
- io.writer_flush(^writer);
+ writer := io.writer_make(&stream, 0);
+ write_type_name(&writer, value);
+ io.writer_flush(&writer);
- output->write(io.buffer_stream_to_str(^stream));
+ output->write(io.buffer_stream_to_str(&stream));
}
case #default {
info := get_type_info(v.type);
if info.kind == .Struct {
- s := cast(^Type_Info_Struct) info;
+ s := cast(&Type_Info_Struct) info;
if s.constructed_from == Optional {
- opt := cast(^?bool) v.data;
+ opt := cast(&?bool) v.data;
if opt.has_value {
format := *formatting;
format.quote_strings = true;
output->write("Some(");
- format_any(output, ^format, .{ ~~(cast(^u8) v.data + s.members[1].offset), s.members[1].type });
+ format_any(output, &format, .{ ~~(cast(&u8) v.data + s.members[1].offset), s.members[1].type });
output->write(")");
} else {
format.indentation += 4;
}
- for ^member: s.members {
+ for &member: s.members {
if member != s.members.data do output->write(", ");
if formatting.pretty_printing {
output->write(member.name);
output->write(" = ");
- format_any(output, ^format, .{ ~~(cast(^u8) v.data + member.offset), member.type });
+ format_any(output, &format, .{ ~~(cast(&u8) v.data + member.offset), member.type });
}
}
if info.kind == .Function {
output->write("func[");
- value := *(cast(^i32) v.data);
+ value := *(cast(&i32) v.data);
ibuf : [128] u8;
istr := i64_to_str(~~value, 10, ~~ibuf);
}
if info.kind == .Pointer {
- value := *(cast(^rawptr) v.data);
+ value := *(cast(&rawptr) v.data);
ibuf : [128] u8;
istr := i64_to_str(~~value, 16, ~~ibuf, prefix=true);
output->write("[ ");
}
- a := cast(^Type_Info_Dynamic_Array) info;
- arr := cast(^array.Untyped_Array) v.data;
+ a := cast(&Type_Info_Dynamic_Array) info;
+ arr := cast(&array.Untyped_Array) v.data;
data := arr.data;
count := arr.count;
for _: format.indentation do output->write(#char " ");
}
- format_any(output, ^format, .{ ~~(cast(^u8) data + get_type_info(a.of).size * i), a.of });
+ format_any(output, &format, .{ ~~(cast(&u8) data + get_type_info(a.of).size * i), a.of });
}
if info.kind == .Array {
output->write("[ ");
- a := cast(^Type_Info_Array) info;
+ a := cast(&Type_Info_Array) info;
data := v.data;
for i: a.count {
if i != 0 do output->write(", ");
- format_any(output, formatting, .{ ~~(cast(^u8) data + get_type_info(a.of).size * i), a.of });
+ format_any(output, formatting, .{ ~~(cast(&u8) data + get_type_info(a.of).size * i), a.of });
}
output->write(" ]");
}
if info.kind == .Enum {
- e := cast(^Type_Info_Enum) info;
+ e := cast(&Type_Info_Enum) info;
value: u64;
switch e.backing_type {
- case i8, u8 do value = cast(u64) *(cast(^u8) v.data);
- case i16, u16 do value = cast(u64) *(cast(^u16) v.data);
- case i32, u32 do value = cast(u64) *(cast(^u32) v.data);
- case i64, u64 do value = cast(u64) *(cast(^u64) v.data);
+ case i8, u8 do value = cast(u64) *(cast(&u8) v.data);
+ case i16, u16 do value = cast(u64) *(cast(&u16) v.data);
+ case i32, u32 do value = cast(u64) *(cast(&u32) v.data);
+ case i64, u64 do value = cast(u64) *(cast(&u64) v.data);
case #default do assert(false, "Bad enum backing type");
}
if !formatting.interpret_numbers {
- format_any(output, formatting, .{^value, u64});
+ format_any(output, formatting, .{&value, u64});
break;
}
if !e.is_flags {
- for ^member: e.members {
+ for &member: e.members {
if value == member.value {
output->write(member.name);
break break;
} else {
first := true;
- for ^member: e.members {
+ for &member: e.members {
if value & member.value != 0 {
if !first do output->write(" | ");
output->write(member.name);
}
if info.kind == .Distinct {
- d := cast(^Type_Info_Distinct) info;
+ d := cast(&Type_Info_Distinct) info;
if formatting.interpret_numbers {
output->write(d.name);
parse_any :: #match {}
#overload
-parse_any :: macro (v: ^$T, to_parse: str, string_allocator := context.allocator) -> bool {
+parse_any :: macro (v: &$T, to_parse: str, string_allocator := context.allocator) -> bool {
return #this_package.parse_any(v, T, to_parse, string_allocator);
}
switch data_type {
case bool {
- dest := cast(^bool) target;
+ dest := cast(&bool) target;
*dest = false;
if to_parse[0] == #char "t" || to_parse[0] == #char "T" {
*dest = true;
integer_case :: macro (T: type_expr) {
case T {
- dest := cast(^T) target;
+ dest := cast(&T) target;
*dest = cast(T) str_to_i64(to_parse);
return true;
}
integer_case(u64);
case f32 {
- dest := cast(^f32) target;
+ dest := cast(&f32) target;
*dest = ~~ str_to_f64(to_parse);
return true;
}
case f64 {
- dest := cast(^f64) target;
+ dest := cast(&f64) target;
*dest = ~~ str_to_f64(to_parse);
return true;
}
if to_parse.count == 0 do return false;
if to_parse[0] != #char "\"" do return false;
line := to_parse;
- string.advance(^line);
+ string.advance(&line);
- dest := cast(^str) target;
- *dest = string.read_until(^line, #char "\"") |> string.alloc_copy(string_allocator); // @BUG // This does not handle escaped strings!
+ dest := cast(&str) target;
+ *dest = string.read_until(&line, #char "\"") |> string.alloc_copy(string_allocator); // @BUG // This does not handle escaped strings!
return true;
}
if info.kind == .Enum {
// TEMPORARY this needs to look at the backing type for the
// enum in order to know how large this integer should be.
- *cast(^u32) target = ~~ str_to_i64(to_parse);
+ *cast(&u32) target = ~~ str_to_i64(to_parse);
return true;
}
if info.kind == .Distinct {
- d_info := cast(^Type_Info_Distinct) info;
+ d_info := cast(&Type_Info_Distinct) info;
return parse_any(target, d_info.base_type, to_parse, string_allocator);
}
}
//
// Frees all data in a CSV.
- delete :: (csv: ^CSV) {
- delete(^csv.entries);
+ delete :: (csv: &CSV) {
+ delete(&csv.entries);
}
//
// headers, and cross checked with the CSV_Column tag information.
// Use this when the columns from your CSV have a different order
// from the order of fields in the structure.
- ingress_string :: (csv: ^CSV, contents: str, headers_present := true) -> bool {
+ ingress_string :: (csv: &CSV, contents: str, headers_present := true) -> bool {
reader, stream := io.reader_from_string(contents);
defer cfree(stream);
- return csv->ingress(^reader, headers_present);
+ return csv->ingress(&reader, headers_present);
}
//
// Ingests data from an Reader containing CSV data.
// Uses the type of the CSV to know what columns should be expectd.
- ingress :: (csv: ^CSV, reader: ^io.Reader, headers_present := true) -> bool {
+ ingress :: (csv: &CSV, reader: &io.Reader, headers_present := true) -> bool {
Header :: struct {
type: type_expr;
offset: i32;
}
any_headers := make([..] Header);
- defer delete(^any_headers);
+ defer delete(&any_headers);
- output_type_info: ^Type_Info_Struct = ~~ get_type_info(csv.Output_Type);
+ output_type_info: &Type_Info_Struct = ~~ get_type_info(csv.Output_Type);
if headers_present {
header_line := reader->read_line(allocator=context.temp_allocator)
}
} else {
- for ^member: output_type_info.members {
+ for &member: output_type_info.members {
any_headers << .{ member.type, member.offset };
}
}
for entry: string.split_iter(line, #char ",")
|> iter.enumerate()
{
- header := ^any_headers[entry.index];
+ header := &any_headers[entry.index];
if header.offset == -1 do continue;
- target := cast(^u8) ^out + header.offset;
+ target := cast(&u8) &out + header.offset;
if header.type == str {
- *cast(^str) target = string.alloc_copy(entry.value);
+ *cast(&str) target = string.alloc_copy(entry.value);
} else {
conv.parse_any(target, header.type, entry.value);
}
// Outputs data from a CSV into a Writer.
// When `include_headers` is true, the first line outputted will be
// the headers of the CSV, according to the CSV_Column tag information.
- egress :: (csv: ^CSV, writer: ^io.Writer, include_headers := true) {
- output_type_info: ^Type_Info_Struct = ~~ get_type_info(csv.Output_Type);
+ egress :: (csv: &CSV, writer: &io.Writer, include_headers := true) {
+ output_type_info: &Type_Info_Struct = ~~ get_type_info(csv.Output_Type);
if include_headers {
- for ^member: output_type_info.members {
+ for &member: output_type_info.members {
if !#first do io.write(writer, ",");
if tag := array.first(member.tags, #(it.type == CSV_Column)); tag {
io.write(writer, "\n");
}
- for ^it: csv.entries {
- for ^member: output_type_info.members {
+ for &it: csv.entries {
+ for &member: output_type_info.members {
if !#first do io.write(writer, ",");
- io.write_format_va(writer, "{}", .[ .{cast(^u8) it + member.offset, member.type} ]);
+ io.write_format_va(writer, "{}", .[ .{cast(&u8) it + member.offset, member.type} ]);
}
io.write(writer, "\n");
//
@core.test.test.{"CSV Test"}
-(t: ^core.test.T) {
+(t: &core.test.T) {
data := """first,second,third
1,test 1,1.2
2,test 2,2.4
// Parses an ini file into the variable given. Only structures
// work with this procedure, as the structure provides the section
// and value names.
-parse_ini_file :: macro (r: ^io.Reader, output_ptr: ^$T/type_is_struct) => {
+parse_ini_file :: macro (r: &io.Reader, output_ptr: &$T/type_is_struct) => {
parse_ini_file_inner :: parse_ini_file_inner
// No need to make the actual implementation polymorphic.
}
#local
-parse_ini_file_inner :: (r: ^io.Reader, output_ptr: any) -> (IniParseResult, IniParseError) {
+parse_ini_file_inner :: (r: &io.Reader, output_ptr: any) -> (IniParseResult, IniParseError) {
info :: runtime.info
line := 1;
if t := info.get_type_info(output_ptr.type); t.kind != .Pointer {
error("Expected pointer type for parameter.");
} else {
- output.data = *cast(^rawptr) output_ptr.data;
- output.type = (cast(^info.Type_Info_Pointer) t).to;
+ output.data = *cast(&rawptr) output_ptr.data;
+ output.type = (cast(&info.Type_Info_Pointer) t).to;
}
defer alloc.clear_temp_allocator();
error(msg = aprintf("'{}' is not a valid section name.", stripped_section_name));
}
- active_item_ptr = cast(^u8) output.data + member.offset;
+ active_item_ptr = cast(&u8) output.data + member.offset;
active_item_type = member.type;
parse_method := info.get_struct_method(active_item_type, "parse_ini");
if parse_method != null {
next_line();
- f := *cast(^(rawptr, ^io.Reader) -> bool) parse_method.data;
+ f := *cast(&(rawptr, &io.Reader) -> bool) parse_method.data;
if !f(active_item_ptr, r) {
error(msg = aprintf("Failed parsing."));
}
assert(r->read_byte() == #char "=", "expected =");
field := info.get_struct_member(active_item_type, string.strip_whitespace(field_name));
- target := cast(^u8) active_item_ptr + field.offset;
+ target := cast(&u8) active_item_ptr + field.offset;
value_string := r->read_until(#char "\n", allocator=context.temp_allocator);
parsed_successfully := conv.parse_any(target, field.type, value_string);
// If the type is a string, then the value can be the entire line
// of text. No need to force the quotes.
if field.type == str {
- *cast(^str) target = value_string
+ *cast(&str) target = value_string
|> string.strip_whitespace()
|> string.alloc_copy();
//
// Outputs a two-level structure into an ini file. The inverse of `parse_ini_file`.
-write_ini_file :: macro (w: ^io.Writer, output: $T/type_is_struct) => {
+write_ini_file :: macro (w: &io.Writer, output: $T/type_is_struct) => {
write_ini_file_inner :: write_ini_file_inner
// See note above in parse_ini_file.
}
#local
-write_ini_file_inner :: (w: ^io.Writer, output: any) -> bool {
+write_ini_file_inner :: (w: &io.Writer, output: any) -> bool {
info :: runtime.info
- output_info := cast(^info.Type_Info_Struct) info.get_type_info(output.type);
+ output_info := cast(&info.Type_Info_Struct) info.get_type_info(output.type);
if output_info.kind != .Struct do return false;
- for^ output_info.members {
+ for& output_info.members {
io.write_format(w, "[{}]\n", it.name);
defer io.write(w, "\n");
- member_info := cast(^info.Type_Info_Struct) info.get_type_info(it.type);
+ member_info := cast(&info.Type_Info_Struct) info.get_type_info(it.type);
if member_info.kind != .Struct do continue;
- member_data := cast(^u8) output.data + it.offset;
+ member_data := cast(&u8) output.data + it.offset;
if write_method := info.get_struct_method(it.type, "write_ini"); write_method != null {
- wm := *cast(^(rawptr, ^io.Writer) -> bool) write_method.data;
+ wm := *cast(&(rawptr, &io.Writer) -> bool) write_method.data;
if !wm(member_data, w) {
return false;
}
continue;
}
- for^ prop: member_info.members {
+ for& prop: member_info.members {
io.write_format_va(w, "{}={}\n", .[
- .{^prop.name, str},
+ .{&prop.name, str},
.{member_data + prop.offset, prop.type}
]);
}
// __atomic_wait is only valid for i32 and i64
#if runtime.Wait_Notify_Available {
- __atomic_wait :: (addr: ^$T, value: T, timeout: i64 = -1) -> i32 #intrinsic ---
+ __atomic_wait :: (addr: &$T, value: T, timeout: i64 = -1) -> i32 #intrinsic ---
__atomic_notify :: (addr: rawptr, maximum: i32 = 1) -> i32 #intrinsic ---
}
__atomic_fence :: () -> void #intrinsic ---
// These are only valid for the eight integer types (i8, u8, i16, u16, i32, u32, i64, u64)
-__atomic_load :: (addr: ^$T) -> T #intrinsic ---
-__atomic_store :: (addr: ^$T, value: T) -> void #intrinsic ---
-__atomic_add :: (addr: ^$T, value: T) -> T #intrinsic ---
-__atomic_sub :: (addr: ^$T, value: T) -> T #intrinsic ---
-__atomic_and :: (addr: ^$T, value: T) -> T #intrinsic ---
-__atomic_or :: (addr: ^$T, value: T) -> T #intrinsic ---
-__atomic_xor :: (addr: ^$T, value: T) -> T #intrinsic ---
-__atomic_xchg :: (addr: ^$T, value: T) -> T #intrinsic ---
-__atomic_cmpxchg :: (addr: ^$T, compare: T, value: T) -> T #intrinsic ---
+__atomic_load :: (addr: &$T) -> T #intrinsic ---
+__atomic_store :: (addr: &$T, value: T) -> void #intrinsic ---
+__atomic_add :: (addr: &$T, value: T) -> T #intrinsic ---
+__atomic_sub :: (addr: &$T, value: T) -> T #intrinsic ---
+__atomic_and :: (addr: &$T, value: T) -> T #intrinsic ---
+__atomic_or :: (addr: &$T, value: T) -> T #intrinsic ---
+__atomic_xor :: (addr: &$T, value: T) -> T #intrinsic ---
+__atomic_xchg :: (addr: &$T, value: T) -> T #intrinsic ---
+__atomic_cmpxchg :: (addr: &$T, compare: T, value: T) -> T #intrinsic ---
// Special intrinsic function that initializes a value.
// This is generally used on structure to execute their
// default initializer expressions.
-__initialize :: (val: ^$T) -> void #intrinsic ---
+__initialize :: (val: &$T) -> void #intrinsic ---
//
// Helpful macro to create an initialized value.
__initialize :: __initialize
val: T;
- __initialize(^val);
+ __initialize(&val);
return val;
}
// Int: u8, .., u64 i8, .., i64
// Float: f32 f64
// Simd: v128 i8x16 i16x8 i32x4 i64x2 f32x4 f64x2
-// Pointer: ^T rawptr
+// Pointer: &T rawptr
// Compound: array, slice, struct
// Array: [$N] $T
// Slice: [] $T
use core
BinaryWriter :: struct {
- stream: ^Stream;
+ stream: &Stream;
}
-binary_writer_make :: (s: ^Stream) -> BinaryWriter {
+binary_writer_make :: (s: &Stream) -> BinaryWriter {
assert(s.vtable != null, "Stream vtable was not setup correctly.");
return BinaryWriter.{ s };
}
-binary_write_byte :: (use bw: ^BinaryWriter, byte: u8) {
+binary_write_byte :: (use bw: &BinaryWriter, byte: u8) {
stream_write_byte(stream, byte);
}
-binary_write :: (use bw: ^BinaryWriter, $T: type_expr, v: ^T) {
+binary_write :: (use bw: &BinaryWriter, $T: type_expr, v: &T) {
stream_write(stream, .{ ~~ v, sizeof T });
}
-binary_write_slice :: (use bw: ^BinaryWriter, sl: [] $T, output_size := false) {
+binary_write_slice :: (use bw: &BinaryWriter, sl: [] $T, output_size := false) {
assert(false, "binary_write_slice is not working at the moment");
if output_size do binary_write(bw, i32, sl.count);
bytes := ([] u8).{
- data = cast(^u8) ^sl.data[0],
+ data = cast(&u8) &sl.data[0],
count = sizeof T * sl.count,
};
BinaryReader :: struct {
- stream: ^Stream;
+ stream: &Stream;
}
-binary_reader_make :: (s: ^Stream) -> BinaryReader {
+binary_reader_make :: (s: &Stream) -> BinaryReader {
assert(s.vtable != null, "Stream vtable was not setup correctly.");
return BinaryReader.{ s };
}
-binary_read_byte :: (use br: ^BinaryReader) -> u8 {
+binary_read_byte :: (use br: &BinaryReader) -> u8 {
_, byte := stream_read_byte(stream);
return byte;
}
-binary_read :: (use br: ^BinaryReader, $T: type_expr) -> T {
+binary_read :: (use br: &BinaryReader, $T: type_expr) -> T {
buf: [sizeof T] u8;
_, bytes_read := stream_read(stream, ~~ buf);
- return *(cast(^T) buf);
+ return *(cast(&T) buf);
}
-binary_read_slice :: (use br: ^BinaryReader,
+binary_read_slice :: (use br: &BinaryReader,
$T: type_expr,
size := 0, read_size := false,
allocator := context.allocator) -> [] T {
sl := memory.make_slice(u8, size * sizeof T, allocator = allocator);
_, bytes_read := stream_read(stream, sl);
- return .{ data = cast(^T) sl.data, count = size };
+ return .{ data = cast(&T) sl.data, count = size };
}
return BinaryReader.{ data = data, pos = initial_pos };
}
-seek :: (use br: ^BinaryReader, new_pos: u32) -> u32 {
+seek :: (use br: &BinaryReader, new_pos: u32) -> u32 {
old_pos := pos;
pos = new_pos;
return old_pos;
}
-tell :: (use br: ^BinaryReader) -> u32 do return pos;
+tell :: (use br: &BinaryReader) -> u32 do return pos;
-read_u8 :: (use br: ^BinaryReader) -> u8 {
+read_u8 :: (use br: &BinaryReader) -> u8 {
ret := data[pos];
pos += 1;
return ret;
}
-read_u16 :: (use br: ^BinaryReader) -> u16 do return ~~(read_u8(br) << ~~8 | read_u8(br));
+read_u16 :: (use br: &BinaryReader) -> u16 do return ~~(read_u8(br) << ~~8 | read_u8(br));
-read_u32 :: (use br: ^BinaryReader) -> u32 {
+read_u32 :: (use br: &BinaryReader) -> u32 {
// Encoding is big endian
ret: u32 = 0;
ret |= cast(u32) read_u8(br) << 24;
return ret;
}
-read_i16 :: (use br: ^BinaryReader) -> i16 {
+read_i16 :: (use br: &BinaryReader) -> i16 {
ret := read_u16(br);
if ret & ~~0x8000 != ~~0 do ret -= ~~(1 << 16);
return ret;
}
-read_i32 :: (use br: ^BinaryReader) -> i32 {
+read_i32 :: (use br: &BinaryReader) -> i32 {
return ~~read_u32(br);
}
-read_fword :: (use br: ^BinaryReader) -> i16 do return read_i16(br);
+read_fword :: (use br: &BinaryReader) -> i16 do return read_i16(br);
-read_2dot14 :: (use br: ^BinaryReader) -> f32 {
+read_2dot14 :: (use br: &BinaryReader) -> f32 {
val := cast(i32) read_i16(br);
return ~~val / cast(f32) (1 << 14);
}
-read_fixed :: (use br: ^BinaryReader) -> f32 {
+read_fixed :: (use br: &BinaryReader) -> f32 {
val := read_i32(br);
return ~~val / cast(f32) (1 << 16);
}
-read_string :: (use br: ^BinaryReader, len: i32) -> str {
+read_string :: (use br: &BinaryReader, len: i32) -> str {
ret := data.data[pos .. pos + len];
pos += len;
return ret;
}
-read_date :: (use br: ^BinaryReader) -> u64 {
+read_date :: (use br: &BinaryReader) -> u64 {
mac_time := (cast(u64) (read_u32(br))) << 32 |
(cast(u64) (read_u32(br)));
utf_time := mac_time - 2082844800;
use core {memory, math, array, iter}
Reader :: struct {
- stream: ^Stream;
+ stream: &Stream;
buffer: [] u8;
buffer_allocator: Allocator;
lines :: lines;
}
-reader_make :: (s: ^Stream, buffer_size := 4096, allocator := context.allocator) -> Reader {
+reader_make :: (s: &Stream, buffer_size := 4096, allocator := context.allocator) -> Reader {
assert(s.vtable != null, "Stream vtable was not setup correctly.");
reader: Reader;
reader.stream = s;
reader.error = .None;
- memory.alloc_slice(^reader.buffer, buffer_size, allocator);
+ memory.alloc_slice(&reader.buffer, buffer_size, allocator);
reader.buffer_allocator = allocator;
- reader_reset(^reader);
+ reader_reset(&reader);
return reader;
}
-reader_reset :: (use reader: ^Reader) {
+reader_reset :: (use reader: &Reader) {
start, end = 0, 0;
last_byte = #char "\0";
done = false;
}
#overload delete :: reader_free
-reader_free :: (use reader: ^Reader) {
- memory.free_slice(^buffer, buffer_allocator);
+reader_free :: (use reader: &Reader) {
+ memory.free_slice(&buffer, buffer_allocator);
}
// You need to free the StringStream from the context.allocator when you use this. For example,
// reader, stream := reader_from_string(s);
// defer cfree(stream);
-reader_from_string :: (s: str) -> (Reader, ^BufferStream) {
+reader_from_string :: (s: str) -> (Reader, &BufferStream) {
stream_ptr := new(BufferStream);
*stream_ptr = buffer_stream_make(s, fixed=true, write_enabled=false);
return reader_make(stream_ptr), stream_ptr;
}
-reader_get_buffered :: (use reader: ^Reader) -> i32 {
+reader_get_buffered :: (use reader: &Reader) -> i32 {
return end - start;
}
-reader_empty :: (use reader: ^Reader) -> bool {
+reader_empty :: (use reader: &Reader) -> bool {
return done && reader_get_buffered(reader) == 0;
}
-read_all :: (use reader: ^Reader, allocator := context.allocator) -> [] u8 {
+read_all :: (use reader: &Reader, allocator := context.allocator) -> [] u8 {
output := array.make(u8, 128, allocator=allocator);
while !reader_empty(reader) {
buffered := reader_get_buffered(reader);
if buffered > 0 {
- array.ensure_capacity(^output, output.count + buffered);
+ array.ensure_capacity(&output, output.count + buffered);
memory.copy(output.data + output.count, buffer.data, buffered);
output.count += buffered;
start = end;
return output;
}
-read_byte :: (use reader: ^Reader) -> u8 {
+read_byte :: (use reader: &Reader) -> u8 {
while start == end {
if reader_empty(reader) do return 0;
return byte;
}
-unread_byte :: (use reader: ^Reader) -> Error {
+unread_byte :: (use reader: &Reader) -> Error {
if last_byte < 0 || (start == 0 && end > 0) {
return .InvalidUnread;
}
// returns ReadPending, this function may only fill part / none
// of the buffer. If the function exits with a .None error, the
// buffer is filled completely.
-read_bytes :: (use reader: ^Reader, bytes: [] u8) -> (i32, Error) {
+read_bytes :: (use reader: &Reader, bytes: [] u8) -> (i32, Error) {
n := bytes.count;
if n == 0 {
if reader_get_buffered(reader) > 0 do return 0, .None;
return bytes.count, .None;
}
-read_string :: (use reader: ^Reader, bytes := 1, allocator := context.allocator) -> str {
+read_string :: (use reader: &Reader, bytes := 1, allocator := context.allocator) -> str {
buf := memory.make_slice(u8, bytes, allocator);
bytes_read, err := read_bytes(reader, buf);
return buf[0 .. bytes_read];
};
-read_i32 :: (use reader: ^Reader) -> i32 {
+read_i32 :: (use reader: &Reader) -> i32 {
n: i32 = 0;
skip_whitespace(reader);
return n;
}
-read_i64 :: (use reader: ^Reader) -> i64 {
+read_i64 :: (use reader: &Reader) -> i64 {
n: i64 = 0;
skip_whitespace(reader);
return n;
}
-read_u32 :: (use reader: ^Reader) -> u32 {
+read_u32 :: (use reader: &Reader) -> u32 {
n: u32 = 0;
skip_whitespace(reader);
return n;
}
-read_u64 :: (use reader: ^Reader) -> u64 {
+read_u64 :: (use reader: &Reader) -> u64 {
n: u64 = 0;
skip_whitespace(reader);
return n;
}
-read_line :: (use reader: ^Reader, consume_newline := true, allocator := context.allocator, inplace := false) -> str {
+read_line :: (use reader: &Reader, consume_newline := true, allocator := context.allocator, inplace := false) -> str {
//
// Reading in place is special. It does not make a special allocation for the data,
// instead just return a pointer to the internal data.
}
out: [..] u8;
- array.init(^out, allocator=allocator);
+ array.init(&out, allocator=allocator);
while done := false; !done {
count := start;
}
if count != start {
- array.ensure_capacity(^out, out.count + (count - start));
+ array.ensure_capacity(&out, out.count + (count - start));
memory.copy(out.data + out.count, buffer.data + start, count - start);
out.count += count - start;
start = count;
return out;
}
-read_word :: (use reader: ^Reader, numeric_allowed := false, allocator := context.allocator, inplace := false) -> str {
+read_word :: (use reader: &Reader, numeric_allowed := false, allocator := context.allocator, inplace := false) -> str {
skip_whitespace(reader);
while reader_read_next_chunk(reader) == .ReadPending {
skip_whitespace(reader);
}
out: [..] u8;
- array.init(^out, allocator=allocator);
+ array.init(&out, allocator=allocator);
while done := false; !done {
count := start;
}
if count != start {
- array.ensure_capacity(^out, out.count + (count - start));
+ array.ensure_capacity(&out, out.count + (count - start));
memory.copy(out.data + out.count, buffer.data + start, count - start);
out.count += count - start;
start = count;
return out;
}
-read_until :: (use reader: ^Reader, until: u8, skip: u32 = 0, allocator := context.allocator, consume_end := false, inplace := false) -> str {
+read_until :: (use reader: &Reader, until: u8, skip: u32 = 0, allocator := context.allocator, consume_end := false, inplace := false) -> str {
//
// Reading in place is special. It does not make a special allocation for the data,
// instead just return a pointer to the internal data.
}
out: [..] u8;
- array.init(^out, allocator=allocator);
+ array.init(&out, allocator=allocator);
while done := false; !done {
count := start;
}
if count != start {
- array.ensure_capacity(^out, out.count + (count - start));
+ array.ensure_capacity(&out, out.count + (count - start));
memory.copy(out.data + out.count, buffer.data + start, count - start);
out.count += count - start;
start = count;
return out;
}
-peek_byte :: (use reader: ^Reader, advance := 0) -> (u8, Error) {
+peek_byte :: (use reader: &Reader, advance := 0) -> (u8, Error) {
if reader_empty(reader) do return 0, .EOF;
if start == end {
return buffer[start + advance], .None;
}
-advance_line :: (use reader: ^Reader) {
+advance_line :: (use reader: &Reader) {
if reader_empty(reader) do return;
while true {
}
}
-skip_whitespace :: (use reader: ^Reader) {
+skip_whitespace :: (use reader: &Reader) {
if reader_empty(reader) do return;
while start < end {
}
}
-skip_bytes :: (use reader: ^Reader, bytes: u32) -> (skipped: i32, err: Error) {
+skip_bytes :: (use reader: &Reader, bytes: u32) -> (skipped: i32, err: Error) {
if bytes == 0 do return 0, .None;
if reader_empty(reader) do return 0, .EOF;
return 0, .None;
}
-lines :: (r: ^Reader, inplace := false, allocator := context.allocator) =>
- iter.generator(^.{
+lines :: (r: &Reader, inplace := false, allocator := context.allocator) =>
+ iter.generator(&.{
r = r,
inplace = inplace,
allocator = allocator,
});
-#local reader_consume_error :: (use reader: ^Reader) -> Error {
+#local reader_consume_error :: (use reader: &Reader) -> Error {
defer error = .None;
return error;
}
// does mean that the reading process should stop and be tried again later.
// - The stream returns anything other than None. This error is silently stored
// and be fetched using reader_consume_error later.
-#local reader_read_next_chunk :: (use reader: ^Reader) -> Error {
+#local reader_read_next_chunk :: (use reader: &Reader) -> Error {
if start > 0 {
// This assumes that memory.copy behaves like memmove, in that the
// buffer may overlap, but it should do the right thing.
// so you will likely never need to call it.
__stdio_init :: () {
stdio.print_stream = io.buffer_stream_make(2048, context.allocator);
- stdio.print_writer = io.writer_make(^stdio.print_stream, 0);
+ stdio.print_writer = io.writer_make(&stdio.print_stream, 0);
- stdio.stream = .{ vtable = ^stdio_vtable, flags = .Block_On_Read };
+ stdio.stream = .{ vtable = &stdio_vtable, flags = .Block_On_Read };
stdio.auto_flush = true;
}
//
// Internal procedure to flush data from the print_stream to standard
-// output. Can be used directly, or through io.stream_flush(^stdio.stream);
+// output. Can be used directly, or through io.stream_flush(&stdio.stream);
__flush_stdio :: () {
if stdio.print_stream.data.count == 0 do return;
- ^stdio.print_stream
+ &stdio.print_stream
|> io.buffer_stream_to_str()
|> runtime.platform.__output_string();
- ^stdio.print_stream |> io.stream_flush();
+ &stdio.print_stream |> io.stream_flush();
}
//
// that are sent directly to io.write.
print :: #match #locked {
(x: str) {
- io.write(^stdio.print_writer, x);
+ io.write(&stdio.print_writer, x);
if x[x.count - 1] == #char "\n" && stdio.auto_flush do __flush_stdio();
},
- (x) => { io.write(^stdio.print_writer, x); },
- (x, y) => { io.write(^stdio.print_writer, x, y); },
+ (x) => { io.write(&stdio.print_writer, x); },
+ (x, y) => { io.write(&stdio.print_writer, x, y); },
}
//
// Standard formatted print to standard output.
printf :: (format: str, va: ..any) {
flush :: (_, to_output) => {
- io.write(^stdio.print_writer, to_output);
+ io.write(&stdio.print_writer, to_output);
__flush_stdio();
return true;
}
__byte_dump :: (ptr: rawptr, byte_count: u32, bytes_per_line := 8) {
temp: [3] u8;
- u8_ptr := cast(^u8) ptr;
+ u8_ptr := cast(&u8) ptr;
for i: byte_count {
val := u8_ptr[i];
//
// The v-table for the stream in stdio.
#local stdio_vtable := io.Stream_Vtable.{
- read = (_: ^io.Stream, buffer: [] u8) -> (io.Error, u32) {
+ read = (_: &io.Stream, buffer: [] u8) -> (io.Error, u32) {
__flush_stdio();
bytes_read := runtime.platform.__read_from_input(buffer);
if bytes_read == 0 do return .ReadPending, 0;
return .None, bytes_read;
},
- read_byte = (_: ^io.Stream) -> (io.Error, u8) {
+ read_byte = (_: &io.Stream) -> (io.Error, u8) {
__flush_stdio();
buf: [1] u8;
bytes_read := runtime.platform.__read_from_input(buf);
return .None, buf[0];
},
- write = (_: ^io.Stream, buffer: [] u8) -> (io.Error, u32) {
- return io.stream_write(^stdio.print_stream, buffer);
+ write = (_: &io.Stream, buffer: [] u8) -> (io.Error, u32) {
+ return io.stream_write(&stdio.print_stream, buffer);
},
- write_byte = (_: ^io.Stream, byte: u8) -> io.Error {
- return io.stream_write_byte(^stdio.print_stream, byte);
+ write_byte = (_: &io.Stream, byte: u8) -> io.Error {
+ return io.stream_write_byte(&stdio.print_stream, byte);
},
- flush = (_: ^io.Stream) -> io.Error {
+ flush = (_: &io.Stream) -> io.Error {
__flush_stdio();
return .None;
}
use core
Stream :: struct {
- use vtable : ^Stream_Vtable;
+ use vtable : &Stream_Vtable;
flags: Stream_Flags;
}
}
Stream_Vtable :: struct {
- seek : (s: ^Stream, to: i32, whence: SeekFrom) -> Error = null_proc;
- tell : (s: ^Stream) -> (Error, u32) = null_proc;
+ seek : (s: &Stream, to: i32, whence: SeekFrom) -> Error = null_proc;
+ tell : (s: &Stream) -> (Error, u32) = null_proc;
- read : (s: ^Stream, buffer: [] u8) -> (Error, u32) = null_proc;
- read_at : (s: ^Stream, at: u32, buffer: [] u8) -> (Error, u32) = null_proc;
- read_byte : (s: ^Stream) -> (Error, u8) = null_proc;
+ read : (s: &Stream, buffer: [] u8) -> (Error, u32) = null_proc;
+ read_at : (s: &Stream, at: u32, buffer: [] u8) -> (Error, u32) = null_proc;
+ read_byte : (s: &Stream) -> (Error, u8) = null_proc;
- write : (s: ^Stream, buffer: [] u8) -> (Error, u32) = null_proc;
- write_at : (s: ^Stream, at: u32, buffer: [] u8) -> (Error, u32) = null_proc;
- write_byte : (s: ^Stream, byte: u8) -> Error = null_proc;
+ write : (s: &Stream, buffer: [] u8) -> (Error, u32) = null_proc;
+ write_at : (s: &Stream, at: u32, buffer: [] u8) -> (Error, u32) = null_proc;
+ write_byte : (s: &Stream, byte: u8) -> Error = null_proc;
- close : (s: ^Stream) -> Error = null_proc;
- flush : (s: ^Stream) -> Error = null_proc;
+ close : (s: &Stream) -> Error = null_proc;
+ flush : (s: &Stream) -> Error = null_proc;
- size : (s: ^Stream) -> i32 = null_proc;
+ size : (s: &Stream) -> i32 = null_proc;
}
SeekFrom :: enum {
End :: 0x02;
}
-stream_seek :: (use s: ^Stream, to: i32, whence: SeekFrom) -> Error {
+stream_seek :: (use s: &Stream, to: i32, whence: SeekFrom) -> Error {
if vtable == null do return .NoVtable;
if vtable.seek == null_proc do return .NotImplemented;
return vtable.seek(s, to, whence);
}
-stream_tell :: (use s: ^Stream) -> (Error, u32) {
+stream_tell :: (use s: &Stream) -> (Error, u32) {
if vtable == null do return .NoVtable, 0;
if vtable.tell == null_proc do return .NotImplemented, 0;
return vtable.tell(s);
}
-stream_read :: (use s: ^Stream, buffer: [] u8) -> (Error, u32) {
+stream_read :: (use s: &Stream, buffer: [] u8) -> (Error, u32) {
if vtable == null do return .NoVtable, 0;
if vtable.read == null_proc do return .NotImplemented, 0;
return vtable.read(s, buffer);
}
-stream_read_at :: (use s: ^Stream, at: u32, buffer: [] u8) -> (Error, u32) {
+stream_read_at :: (use s: &Stream, at: u32, buffer: [] u8) -> (Error, u32) {
if vtable == null do return .NoVtable, 0;
if vtable.read_at == null_proc do return .NotImplemented, 0;
return vtable.read_at(s, at, buffer);
}
-stream_read_byte :: (use s: ^Stream) -> (Error, u8) {
+stream_read_byte :: (use s: &Stream) -> (Error, u8) {
if vtable == null do return .NoVtable, cast(u8) 0;
if vtable.read_byte == null_proc do return .NotImplemented, 0;
return vtable.read_byte(s);
}
-stream_write :: (use s: ^Stream, buffer: [] u8) -> (Error, u32) {
+stream_write :: (use s: &Stream, buffer: [] u8) -> (Error, u32) {
if vtable == null do return .NoVtable, 0;
if vtable.write == null_proc do return .NotImplemented, 0;
return vtable.write(s, buffer);
}
-stream_write_at :: (use s: ^Stream, at: u32, buffer: [] u8) -> (Error, u32) {
+stream_write_at :: (use s: &Stream, at: u32, buffer: [] u8) -> (Error, u32) {
if vtable == null do return .NoVtable, 0;
if vtable.write_at == null_proc do return .NotImplemented, 0;
return vtable.write_at(s, at, buffer);
}
-stream_write_byte :: (use s: ^Stream, byte: u8) -> Error {
+stream_write_byte :: (use s: &Stream, byte: u8) -> Error {
if vtable == null do return .NoVtable;
if vtable.write_byte == null_proc do return .NotImplemented;
return vtable.write_byte(s, byte);
}
-stream_close :: (use s: ^Stream) -> Error {
+stream_close :: (use s: &Stream) -> Error {
if vtable == null do return .NoVtable;
if vtable.close == null_proc do return .NotImplemented;
return vtable.close(s);
}
-stream_flush :: (use s: ^Stream) -> Error {
+stream_flush :: (use s: &Stream) -> Error {
if vtable == null do return .NoVtable;
if vtable.flush == null_proc do return .NotImplemented;
return vtable.flush(s);
}
-stream_size :: (use s: ^Stream) -> i32 {
+stream_size :: (use s: &Stream) -> i32 {
if vtable == null do return 0;
if vtable.size == null_proc do return 0;
(initial_data: [] u8, allocator := context.allocator, fixed := false, write_enabled := true) -> BufferStream {
if !write_enabled {
return .{
- .{ vtable = ^buffer_stream_vtable },
+ .{ vtable = &buffer_stream_vtable },
data = .{
data = initial_data.data,
count = initial_data.count
data = array.make(initial_data, allocator);
}
- return .{ .{ vtable = ^buffer_stream_vtable }, data, fixed=fixed };
+ return .{ .{ vtable = &buffer_stream_vtable }, data, fixed=fixed };
},
(initial_size := 1024, allocator := context.allocator) -> BufferStream {
return .{
- .{ vtable = ^buffer_stream_vtable },
+ .{ vtable = &buffer_stream_vtable },
make([..] u8, initial_size, allocator = allocator)
};
}
}
#match builtin.delete buffer_stream_free
-buffer_stream_free :: (use bs: ^BufferStream) {
+buffer_stream_free :: (use bs: &BufferStream) {
if write_enabled && !fixed {
- delete(^data);
+ delete(&data);
}
}
#match core.string.as_str buffer_stream_to_str
-buffer_stream_to_str :: (use bs: ^BufferStream) -> str {
+buffer_stream_to_str :: (use bs: &BufferStream) -> str {
if !write_enabled do return null_str;
return data[0 .. curr_pos];
#package
buffer_stream_vtable := Stream_Vtable.{
- seek = (use ss: ^BufferStream, to: i32, whence: SeekFrom) -> Error {
+ seek = (use ss: &BufferStream, to: i32, whence: SeekFrom) -> Error {
if to >= data.count do return .OutOfBounds;
switch whence {
return .None;
},
- tell = (use ss: ^BufferStream) -> (Error, u32) {
+ tell = (use ss: &BufferStream) -> (Error, u32) {
return .None, curr_pos;
},
- read = (use ss: ^BufferStream, buffer: [] u8) -> (Error, u32) {
+ read = (use ss: &BufferStream, buffer: [] u8) -> (Error, u32) {
if curr_pos >= data.count do return .EOF, 0;
bytes_to_read := math.min(buffer.count, data.count - curr_pos);
- memory.copy(buffer.data, ^data.data[curr_pos], bytes_to_read);
+ memory.copy(buffer.data, &data.data[curr_pos], bytes_to_read);
curr_pos += bytes_to_read;
return .None, bytes_to_read;
},
- read_at = (use ss: ^BufferStream, at: u32, buffer: [] u8) -> (Error, u32) {
+ read_at = (use ss: &BufferStream, at: u32, buffer: [] u8) -> (Error, u32) {
if at >= data.count do return .EOF, 0;
bytes_to_read := math.min(buffer.count, data.count - at);
- memory.copy(buffer.data, ^data.data[at], bytes_to_read);
+ memory.copy(buffer.data, &data.data[at], bytes_to_read);
return .None, bytes_to_read;
},
- read_byte = (use ss: ^BufferStream) -> (Error, u8) {
+ read_byte = (use ss: &BufferStream) -> (Error, u8) {
if curr_pos >= data.count do return .EOF, 0;
defer curr_pos += 1;
return .None, data[curr_pos];
},
- write = (use dss: ^BufferStream, buffer: [] u8) -> (Error, u32) {
+ write = (use dss: &BufferStream, buffer: [] u8) -> (Error, u32) {
if !write_enabled do return .NotImplemented, 0;
if curr_pos + buffer.count >= data.capacity {
if fixed do return .EOF, 0;
- if !array.ensure_capacity(^data, curr_pos + buffer.count) do return .EOF, 0;
+ if !array.ensure_capacity(&data, curr_pos + buffer.count) do return .EOF, 0;
}
- memory.copy(^data.data[curr_pos], buffer.data, buffer.count);
+ memory.copy(&data.data[curr_pos], buffer.data, buffer.count);
curr_pos += buffer.count;
data.count = math.max(data.count, curr_pos);
return .None, buffer.count;
},
- write_at = (use dss: ^BufferStream, at: u32, buffer: [] u8) -> (Error, u32) {
+ write_at = (use dss: &BufferStream, at: u32, buffer: [] u8) -> (Error, u32) {
if !write_enabled do return .NotImplemented, 0;
if at + buffer.count >= data.capacity {
if fixed do return .EOF, 0;
- if !array.ensure_capacity(^data, at + buffer.count) do return .EOF, 0;
+ if !array.ensure_capacity(&data, at + buffer.count) do return .EOF, 0;
}
- memory.copy(^data.data[at], buffer.data, buffer.count);
+ memory.copy(&data.data[at], buffer.data, buffer.count);
data.count = math.max(data.count, at + buffer.count);
return .None, buffer.count;
},
- write_byte = (use dss: ^BufferStream, byte: u8) -> Error {
+ write_byte = (use dss: &BufferStream, byte: u8) -> Error {
if !write_enabled do return .NotImplemented;
if curr_pos + 1 >= data.capacity {
if fixed do return .EOF;
- if !array.ensure_capacity(^data, data.count + 1) do return .EOF;
+ if !array.ensure_capacity(&data, data.count + 1) do return .EOF;
}
data[curr_pos] = byte;
return .None;
},
- size = (use dss: ^BufferStream) -> i32 {
+ size = (use dss: &BufferStream) -> i32 {
return data.count;
},
- flush = (use dss: ^BufferStream) -> Error {
+ flush = (use dss: &BufferStream) -> Error {
if !write_enabled || fixed do return .NotImplemented;
curr_pos = 0;
- array.clear(^data);
+ array.clear(&data);
return .None;
},
- close = (use dss: ^BufferStream) -> Error {
+ close = (use dss: &BufferStream) -> Error {
if write_enabled && !fixed {
- delete(^data);
+ delete(&data);
}
return .None;
// of writer_make, all buffering will be disabled.
Writer :: struct {
- stream : ^Stream;
+ stream : &Stream;
buffer: [] u8;
buffer_filled: u32;
}
-writer_make :: (s: ^Stream, buffer_size := 4096) -> Writer {
+writer_make :: (s: &Stream, buffer_size := 4096) -> Writer {
assert(s.vtable != null, "Stream vtable was not setup correctly.");
w := Writer.{s};
//
// Future-proofing the API
-writer_free :: (w: ^Writer) {
+writer_free :: (w: &Writer) {
writer_flush(w);
- delete(^w.buffer);
+ delete(&w.buffer);
}
-writer_flush :: (w: ^Writer) {
+writer_flush :: (w: &Writer) {
if w.buffer_filled == 0 do return;
stream_write(w.stream, w.buffer[0 .. w.buffer_filled]);
w.buffer_filled = 0;
}
-writer_remaining_capacity :: (w: ^Writer) -> u32 {
+writer_remaining_capacity :: (w: &Writer) -> u32 {
return w.buffer.count - w.buffer_filled;
}
-string_builder :: (allocator := context.allocator) -> (Writer, ^BufferStream) {
+string_builder :: (allocator := context.allocator) -> (Writer, &BufferStream) {
new_stream := new(BufferStream, allocator=allocator);
*new_stream = buffer_stream_make();
return writer_make(new_stream, 0), new_stream;
}
-write_byte :: (use writer: ^Writer, byte: u8) {
+write_byte :: (use writer: &Writer, byte: u8) {
if buffer.count == 0 {
stream_write_byte(stream, byte);
} else {
}
}
-write_str :: (use writer: ^Writer, s: str) {
+write_str :: (use writer: &Writer, s: str) {
if buffer.count == 0 {
stream_write(stream, s);
} elseif writer_remaining_capacity(writer) > s.count {
- memory.copy(^buffer[buffer_filled], s.data, s.count);
+ memory.copy(&buffer[buffer_filled], s.data, s.count);
buffer_filled += s.count;
} else {
}
}
-write_cstr :: (use writer: ^Writer, cs: cstr) {
+write_cstr :: (use writer: &Writer, cs: cstr) {
s := string.from_cstr(cs);
write_str(writer, s);
}
-write_i32 :: (use writer: ^Writer, n: i32, base: u32 = 10) {
+write_i32 :: (use writer: &Writer, n: i32, base: u32 = 10) {
buf : [256] u8;
s := conv.i64_to_str(cast(i64) n, cast(u64) base, ~~buf);
write_str(writer, s);
}
-write_i64 :: (use writer: ^Writer, n: i64, base: u64 = 10) {
+write_i64 :: (use writer: &Writer, n: i64, base: u64 = 10) {
buf : [256] u8;
s := conv.i64_to_str(n, base, ~~buf);
write_str(writer, s);
}
-write_f32 :: (use writer: ^Writer, f: f32) {
+write_f32 :: (use writer: &Writer, f: f32) {
buf : [256] u8;
s := conv.f64_to_str(cast(f64) f, ~~buf);
write_str(writer, s);
}
-write_f64 :: (use writer: ^Writer, f: f64) {
+write_f64 :: (use writer: &Writer, f: f64) {
buf : [256] u8;
s := conv.f64_to_str(f, ~~buf);
write_str(writer, s);
}
-write_bool :: (use writer: ^Writer, b: bool) {
+write_bool :: (use writer: &Writer, b: bool) {
if b do write_str(writer, "true");
else do write_str(writer, "false");
}
-write_ptr :: (use writer: ^Writer, p: ^void) {
+write_ptr :: (use writer: &Writer, p: &void) {
write_i64(writer, cast(i64) p, 16);
}
-write_range :: (use writer: ^Writer, r: range, sep := " ") {
+write_range :: (use writer: &Writer, r: range, sep := " ") {
for i: r {
write_i32(writer, i);
if i + r.step < r.high do write_str(writer, sep);
}
}
-write_format :: (use writer: ^Writer, format: str, va: ..any) {
+write_format :: (use writer: &Writer, format: str, va: ..any) {
write_format_va(writer, format, ~~ va);
}
-write_format_va :: (use writer: ^Writer, format: str, va: [] any) {
+write_format_va :: (use writer: &Writer, format: str, va: [] any) {
flush :: (writer, to_output) => {
write_str(writer, to_output);
return true;
write_str(writer, conv.format_va(buffer, format, va, .{writer, flush}));
}
-write_escaped_str :: (use writer: ^Writer, s: str) {
+write_escaped_str :: (use writer: &Writer, s: str) {
write_byte(writer, #char "\"");
while i := 0; i < s.count {
write_format,
// Catch all for any type. Has a high order so you can easily override it.
- #order 1000 macro (w: ^Writer, a: $T) {
+ #order 1000 macro (w: &Writer, a: $T) {
write_format :: write_format
write_format(w, "{}", a);
}
// are needed. Logarithms are implemented using a polynomial that is accurate in the range of
// [1, 2], and then utilizes this identity for values outside of that range,
//
-// ln(x) = ln(2^n * v) = n * ln(2) + ln(v), v is in [1, 2]
+// ln(x) = ln(2&n * v) = n * ln(2) + ln(v), v is in [1, 2]
//
// FIX: This definition is very wrong. It casts E to be whatever the type of the argument is,
#overload
is_nan :: (x: f32) -> bool {
v := x;
- i := *cast(^u32) ^v;
+ i := *cast(&u32) &v;
return (i & 0x7f800000) == 0x7f800000
&& (i & 0x007fffff) != 0;
}
#overload
is_nan :: (x: f64) -> bool {
v := x;
- i := *cast(^u64) ^v;
+ i := *cast(&u64) &v;
return (i & 0x7ff0000000000000) == 0x7ff0000000000000
&& (i & 0x000fffffffffffff) != 0;
}
#overload
is_inf :: (x: f32) -> bool {
v := x;
- i := *cast(^u32) ^v;
+ i := *cast(&u32) &v;
return (i & 0x7f800000) == 0x7f800000
&& (i & 0x007fffff) == 0;
}
#overload
is_inf :: (x: f64) -> bool {
v := x;
- i := *cast(^u64) ^v;
+ i := *cast(&u64) &v;
return (i & 0x7ff0000000000000) == 0x7ff0000000000000
&& (i & 0x000fffffffffffff) == 0;
}
use core {test}
@test.test.{"GCD works"}
-(t: ^test.T) {
+(t: &test.T) {
t->assert(gcd(35, 18) == 1, "gcd(35, 18) == 1");
t->assert(gcd(35, 15) == 5, "gcd(35, 15) == 5");
t->assert(gcd(35, 21) == 7, "gcd(35, 21) == 7");
//
// Initializes a slice by allocating memory for it out of the allocator.
-alloc_slice :: (sl: ^[] $T, count: i32, allocator := context.allocator) {
+alloc_slice :: (sl: &[] $T, count: i32, allocator := context.allocator) {
sl.data = raw_alloc(allocator, sizeof T * count);
sl.count = count;
}
//
// Releases the memory for the slice, as well as setting the fields of the
// slice to be 0 so it cannot be used again.
-free_slice :: (sl: ^[] $T, allocator := context.allocator) {
+free_slice :: (sl: &[] $T, allocator := context.allocator) {
if sl.data == null do return;
raw_free(allocator, sl.data);
align :: #match #local {}
#overload
-align :: (size: ^u64, align: u64) {
+align :: (size: &u64, align: u64) {
if *size % align != 0 {
*size += align - (*size % align);
}
//
// Allows for make([] i32).
#overload
-builtin.__make_overload :: macro (_: ^[] $T, count: u32, allocator := context.allocator) -> [] T {
+builtin.__make_overload :: macro (_: &[] $T, count: u32, allocator := context.allocator) -> [] T {
ret := #this_package.make_slice(T, count, allocator);
#this_package.set(ret.data, 0, sizeof T * count);
return ret;
}
//
-// Allows for delete(^sl);
+// Allows for delete(&sl);
#overload
-builtin.delete :: macro (x: ^[] $T) {
+builtin.delete :: macro (x: &[] $T) {
#this_package.free_slice(x);
}
// much of the rest of the standard library uses `as_...` for
// conversion.
as_any :: to_any
-to_any :: macro (x: ^$T) => any.{x, T};
+to_any :: macro (x: &$T) => any.{x, T};
-any_as :: (a: any, $T: type_expr) -> ^T {
+any_as :: (a: any, $T: type_expr) -> &T {
if a.type != T do return null;
- return cast(^T) a.data;
+ return cast(&T) a.data;
}
//
any_dereference :: (v: any) -> any {
t := get_type_info(v.type);
if t.kind == .Pointer {
- p := cast(^Type_Info_Pointer) t;
- return any.{*cast(^rawptr) v.data, p.to};
+ p := cast(&Type_Info_Pointer) t;
+ return any.{*cast(&rawptr) v.data, p.to};
}
return v;
}
return any.{
- cast(^u8) base_ptr + get_type_info(elem_type).size * index,
+ cast(&u8) base_ptr + get_type_info(elem_type).size * index,
elem_type
};
}
if t.kind == .Struct {
member := get_struct_member(v.type, member_name);
if member != null {
- return any.{cast(^u8) v.data + member.offset, member.type};
+ return any.{cast(&u8) v.data + member.offset, member.type};
}
}
member := get_struct_member(v.type, part_name);
if member {
if next_name {
- return any_nested_selector(any.{cast(^u8) v.data + member.offset, member.type}, next_name);
+ return any_nested_selector(any.{cast(&u8) v.data + member.offset, member.type}, next_name);
}
return any.{
- cast(^u8, v.data) + member.offset, member.type
+ cast(&u8, v.data) + member.offset, member.type
};
}
vals = any_dereference(vals);
}
- val_info := cast(^Type_Info_Struct) get_type_info(vals.type);
+ val_info := cast(&Type_Info_Struct) get_type_info(vals.type);
if val_info.kind != .Struct {
return .{}, false;
}
out: Map(str, any);
- for ^ val_info.members {
+ for & val_info.members {
out->put(it.name, any_selector(vals, it.name));
}
}
return iter.generator(
- ^.{
+ &.{
base_ptr = base_ptr,
elem_type = elem_type,
elem_size = get_type_info(elem_type).size,
(ctx: $T) -> (any, bool) {
if ctx.index < ctx.count {
defer ctx.index += 1;
- return any.{ cast(^u8) ctx.base_ptr + ctx.elem_size * ctx.index, ctx.elem_type }, true;
+ return any.{ cast(&u8) ctx.base_ptr + ctx.elem_size * ctx.index, ctx.elem_type }, true;
}
return .{}, false;
switch info.kind {
case .Array {
- a := cast(^Type_Info_Array) info;
+ a := cast(&Type_Info_Array) info;
return arr.data, a.of, a.count;
}
case .Slice, .Dynamic_Array, .Variadic_Argument {
- a := cast(^array.Untyped_Array) arr.data;
- return a.data, (cast(^Type_Info_Dynamic_Array) info).of, a.count;
+ a := cast(&array.Untyped_Array) arr.data;
+ return a.data, (cast(&Type_Info_Dynamic_Array) info).of, a.count;
}
case #default {
//
// main :: (args) => {
// o: Options;
-// arg_parse.arg_parse(args, ^o);
+// arg_parse.arg_parse(args, &o);
// }
//
// Options that are strings and integers expect an argument after
use runtime.info;
- ptr_type := cast(^Type_Info_Pointer) get_type_info(output.type);
+ ptr_type := cast(&Type_Info_Pointer) get_type_info(output.type);
if ptr_type.kind != .Pointer do return false;
- arg_type := cast(^Type_Info_Struct) get_type_info(ptr_type.to);
+ arg_type := cast(&Type_Info_Struct) get_type_info(ptr_type.to);
if arg_type.kind != .Struct do return false;
- data_base := *cast(^rawptr) output.data;
+ data_base := *cast(&rawptr) output.data;
for #no_close arg: arg_iter {
- for ^member: arg_type.members {
- for ^tag: member.tags {
+ for &member: arg_type.members {
+ for &tag: member.tags {
if tag.type != str do continue;
- to_match := *cast(^str) tag.data;
+ to_match := *cast(&str) tag.data;
if arg != to_match do continue;
switch member.type {
case bool {
- *(cast(^bool) (cast(^u8) data_base + member.offset)) = !*(cast(^bool) (cast(^u8) data_base + member.offset));
+ *(cast(&bool) (cast(&u8) data_base + member.offset)) = !*(cast(&bool) (cast(&u8) data_base + member.offset));
}
case i32 {
if !success do return false;
value := conv.str_to_i64(value_str);
- *(cast(^i32) (cast(^u8) data_base + member.offset)) = ~~value;
+ *(cast(&i32) (cast(&u8) data_base + member.offset)) = ~~value;
}
case str {
value, success := iter.take_one(arg_iter, no_close=true);
if !success do return false;
- *(cast(^str) (cast(^u8) data_base + member.offset)) = value;
+ *(cast(&str) (cast(&u8) data_base + member.offset)) = value;
}
case #default {
port: u16;
addr: u32;
- addr_as_str :: (use this: ^Socket_Address, allocator := context.allocator) -> str {
+ addr_as_str :: (use this: &Socket_Address, allocator := context.allocator) -> str {
str_addr := ipv4_to_str(this.addr);
return string.alloc_copy(str_addr, allocator=allocator);
}
}
-make_ipv4_address :: (out: ^Socket_Address, addr: u32, port: u16) {
+make_ipv4_address :: (out: &Socket_Address, addr: u32, port: u16) {
out.family = ~~ SocketDomain.Inet;
out.port = port;
out.addr = addr;
}
-make_unix_address :: (out: ^Socket_Address, path: str) {
+make_unix_address :: (out: &Socket_Address, path: str) {
out.family = ~~ SocketDomain.Unix;
out.port = 0;
// at the address where the addr field is in the Socket_Address.
// We also have to append a null-terminator, as that is what will
// be expected from any C function.
- out_path := cast(^u8) ^out.addr;
+ out_path := cast(&u8) &out.addr;
offset := 0;
while offset < math.min(path.count, UNIX_SOCKET_PATH_LEN - 1) {
defer offset += 1;
s.type = type;
s.family = domain;
- err := __net_create_socket(^s.handle, domain, type);
+ err := __net_create_socket(&s.handle, domain, type);
if err == .None {
- s.vtable = ^__net_socket_vtable;
+ s.vtable = &__net_socket_vtable;
s.flags |= .Block_On_Read;
}
return s, err;
}
-socket_close :: (s: ^Socket) {
+socket_close :: (s: &Socket) {
__net_close_socket(s.handle);
s.vtable = null;
}
-socket_setting :: (s: ^Socket, setting: SocketSetting, value: u32) {
+socket_setting :: (s: &Socket, setting: SocketSetting, value: u32) {
__net_setting(s.handle, setting, value);
if setting == .NonBlocking {
}
}
-socket_is_alive :: (s: ^Socket) -> bool {
+socket_is_alive :: (s: &Socket) -> bool {
return s.vtable != null;
}
-socket_connect :: (s: ^Socket, host: str, port: u16 = 0) -> SocketError {
+socket_connect :: (s: &Socket, host: str, port: u16 = 0) -> SocketError {
switch s.family {
case .Inet do return __net_connect_ipv4(s.handle, host, port);
case .Unix do return __net_connect_unix(s.handle, host);
}
}
-socket_bind :: (s: ^Socket, bind_address: ^Socket_Address) -> bool {
+socket_bind :: (s: &Socket, bind_address: &Socket_Address) -> bool {
return __net_bind(s.handle, bind_address);
}
-socket_listen :: (s: ^Socket, backlog := 32) {
+socket_listen :: (s: &Socket, backlog := 32) {
__net_listen(s.handle, backlog);
}
-socket_shutdown :: (s: ^Socket, how: SocketShutdown) {
+socket_shutdown :: (s: &Socket, how: SocketShutdown) {
__net_shutdown(s.handle, cast(u32) how);
}
-socket_accept :: (s: ^Socket) -> (Socket, Socket_Address) {
+socket_accept :: (s: &Socket) -> (Socket, Socket_Address) {
new_socket: Socket;
new_addr: Socket_Address;
- new_socket.handle = __net_accept(s.handle, ^new_addr);
+ new_socket.handle = __net_accept(s.handle, &new_addr);
if cast(i32) new_socket.handle >= 0 {
- new_socket.vtable = ^__net_socket_vtable;
+ new_socket.vtable = &__net_socket_vtable;
}
return new_socket, new_addr;
// TODO: Cleanup this function. The stat_buff should be something that is at least
// as big as the sockets array, and the timeout should be the last parameter because
// it is not required.
-socket_poll_all :: (sockets: [] ^Socket, timeout := -1, stat_buff: [] Socket_Poll_Status = .[]) {
+socket_poll_all :: (sockets: [] &Socket, timeout := -1, stat_buff: [] Socket_Poll_Status = .[]) {
if sockets.count > stat_buff.count do return;
handles := alloc.array_from_stack(Socket.Handle, sockets.count);
__net_poll_recv(handles, timeout, stat_buff.data);
}
-socket_send :: (s: ^Socket, data: [] u8) -> i32 {
+socket_send :: (s: &Socket, data: [] u8) -> i32 {
sent := __net_send(s.handle, data);
if sent < 0 { s.vtable = null; }
return sent;
}
-socket_sendto :: (s: ^Socket, data: [] u8, addr: ^Socket_Address) -> i32 {
+socket_sendto :: (s: &Socket, data: [] u8, addr: &Socket_Address) -> i32 {
sent := __net_sendto(s.handle, data, addr);
return sent;
}
-socket_sendall :: (s: ^Socket, data: [] u8) {
+socket_sendall :: (s: &Socket, data: [] u8) {
to_send := data;
while to_send.count > 0 {
}
}
-socket_recv :: (s: ^Socket, maxlen := 1024, allocator := context.allocator) -> [] u8 {
+socket_recv :: (s: &Socket, maxlen := 1024, allocator := context.allocator) -> [] u8 {
buffer := alloc.from_stack(maxlen);
would_block: bool;
- received := __net_recv(s.handle, .{ buffer, maxlen }, ^would_block);
+ received := __net_recv(s.handle, .{ buffer, maxlen }, &would_block);
if received < 0 {
if !would_block do s.vtable = null;
return .[];
return result;
}
-socket_recv_into :: (s: ^Socket, buffer: [] u8) -> i32 {
+socket_recv_into :: (s: &Socket, buffer: [] u8) -> i32 {
would_block: bool;
- received := __net_recv(s.handle, buffer, ^would_block);
+ received := __net_recv(s.handle, buffer, &would_block);
if received < 0 && !would_block do s.vtable = null;
if would_block do return 0;
return received;
}
-socket_recvfrom :: (s: ^Socket, buffer: [] u8) -> (Socket_Address, i32) {
+socket_recvfrom :: (s: &Socket, buffer: [] u8) -> (Socket_Address, i32) {
would_block: bool;
sa: Socket_Address;
- received := __net_recvfrom(s.handle, buffer, ^sa, ^would_block);
+ received := __net_recvfrom(s.handle, buffer, &sa, &would_block);
if received < 0 && !would_block do s.vtable = null;
if would_block do return sa, 0;
#match network_to_host (x: u32) => __net_net_to_host_l(x);
#local __net_socket_vtable := io.Stream_Vtable.{
- read = (use s: ^Socket, buffer: [] u8) -> (io.Error, u32) {
+ read = (use s: &Socket, buffer: [] u8) -> (io.Error, u32) {
if cast(i32) handle == 0 do return .BadFile, 0;
would_block := false;
- bytes_read := __net_recv(handle, buffer, ^would_block);
+ bytes_read := __net_recv(handle, buffer, &would_block);
if bytes_read < 0 && !would_block do s.vtable = null;
if would_block do return .ReadLater, bytes_read;
return .None, bytes_read;
},
- write_byte = (use s: ^Socket, byte: u8) -> io.Error {
+ write_byte = (use s: &Socket, byte: u8) -> io.Error {
if cast(i32) handle == 0 do return .BadFile;
bytes_written := __net_send(handle, .[ byte ]);
return .None;
},
- write = (use s: ^Socket, buffer: [] u8) -> (io.Error, u32) {
+ write = (use s: &Socket, buffer: [] u8) -> (io.Error, u32) {
if cast(i32) handle == 0 do return .BadFile, 0;
bytes_written := __net_send(handle, buffer);
return .None, bytes_written;
},
- close = (use p: ^Socket) -> io.Error {
+ close = (use p: &Socket) -> io.Error {
__net_close_socket(handle);
return .None;
}
// I need to see how WASI does sockets to see if this
// makes sense as an abstraction.
#foreign "onyx_runtime" {
- #package __net_create_socket :: (out_handle: ^Socket.Handle, domain: SocketDomain, type: SocketType) -> SocketError ---
+ #package __net_create_socket :: (out_handle: &Socket.Handle, domain: SocketDomain, type: SocketType) -> SocketError ---
#package __net_close_socket :: (handle: Socket.Handle) -> void ---
#package __net_setting :: (handle: Socket.Handle, setting: SocketSetting, value: i32) -> void ---
- #package __net_bind :: (handle: Socket.Handle, bind_address: ^Socket_Address) -> bool ---
+ #package __net_bind :: (handle: Socket.Handle, bind_address: &Socket_Address) -> bool ---
#package __net_listen :: (handle: Socket.Handle, backlog: i32) -> void ---
- #package __net_accept :: (handle: Socket.Handle, out_address: ^Socket_Address) -> Socket.Handle ---
+ #package __net_accept :: (handle: Socket.Handle, out_address: &Socket_Address) -> Socket.Handle ---
#package __net_connect_unix :: (handle: Socket.Handle, path: str) -> SocketError ---
#package __net_connect_ipv4 :: (handle: Socket.Handle, host: str, port: u16) -> SocketError ---
#package __net_shutdown :: (handle: Socket.Handle, how: u32) -> void ---
#package __net_send :: (handle: Socket.Handle, data: [] u8) -> i32 ---
- #package __net_sendto :: (handle: Socket.Handle, data: [] u8, addr: ^Socket_Address) -> i32 ---
- #package __net_recv :: (handle: Socket.Handle, data: [] u8, async_would_block: ^bool) -> i32 ---
- #package __net_recvfrom :: (handle: Socket.Handle, data: [] u8, out_recv_addr: ^Socket_Address, async_would_block: ^bool) -> i32 ---
- #package __net_poll_recv :: (handle: [] Socket.Handle, timeout: i32, out_statuses: ^Socket_Poll_Status) -> void ---
+ #package __net_sendto :: (handle: Socket.Handle, data: [] u8, addr: &Socket_Address) -> i32 ---
+ #package __net_recv :: (handle: Socket.Handle, data: [] u8, async_would_block: &bool) -> i32 ---
+ #package __net_recvfrom :: (handle: Socket.Handle, data: [] u8, out_recv_addr: &Socket_Address, async_would_block: &bool) -> i32 ---
+ #package __net_poll_recv :: (handle: [] Socket.Handle, timeout: i32, out_statuses: &Socket_Poll_Status) -> void ---
#package __net_host_to_net_s :: (s: u16) -> u16 ---
#package __net_host_to_net_l :: (s: u32) -> u32 ---
res: u32;
for 4 {
- octet := string.read_until(^ip_, #char ".");
- string.advance(^ip_, 1);
+ octet := string.read_until(&ip_, #char ".");
+ string.advance(&ip_, 1);
res = res << 8;
res |= ~~(conv.str_to_i64(octet) & cast(i64) 0xFF);
}
Connection :: struct {
- address : ^Socket_Address;
+ address : &Socket_Address;
// This is only set when the event is coming from the server.
- client : ^TCP_Server.Client;
+ client : &TCP_Server.Client;
}
Disconnection :: struct {
- address: ^Socket_Address;
+ address: &Socket_Address;
// This is only set when the event is coming from the server.
- client : ^TCP_Server.Client;
+ client : &TCP_Server.Client;
}
Data :: struct {
- address: ^Socket_Address;
+ address: &Socket_Address;
// This is only set when the event is coming from the server.
- client : ^TCP_Server.Client;
+ client : &TCP_Server.Client;
contents: [] u8;
}
Ready :: struct {
- address: ^Socket_Address;
+ address: &Socket_Address;
// This is only set when the event is coming from the server.
- client : ^TCP_Server.Client;
+ client : &TCP_Server.Client;
}
}
// Iterator implementation for TCP_Connection
#inject TCP_Connection {
- iter_open :: (use conn: ^TCP_Connection) {
+ iter_open :: (use conn: &TCP_Connection) {
conn.event_cursor = 0;
}
- iter_next :: (use conn: ^TCP_Connection) -> (TCP_Event, bool) {
+ iter_next :: (use conn: &TCP_Connection) -> (TCP_Event, bool) {
if event_cursor == events.count do return .{}, false;
defer event_cursor += 1;
return events[event_cursor], true;
}
- iter_close :: (use conn: ^TCP_Connection) {
+ iter_close :: (use conn: &TCP_Connection) {
for events {
switch it.kind {
case .Data {
- raw_free(event_allocator, (cast(^TCP_Event.Data) it.data).contents.data);
+ raw_free(event_allocator, (cast(&TCP_Event.Data) it.data).contents.data);
}
}
raw_free(event_allocator, it.data);
}
- array.clear(^events);
+ array.clear(&events);
}
}
use connection: TCP_Connection;
client_allocator: Allocator;
- clients: [] ^Client;
+ clients: [] &Client;
// max clients is stored as clients.count.
client_count: u32;
}
#inject TCP_Server.Client {
- read_complete :: (use this: ^TCP_Server.Client) {
+ read_complete :: (use this: &TCP_Server.Client) {
recv_ready_event_present = false;
}
}
-tcp_server_make :: (max_clients := 32, allocator := context.allocator) -> ^TCP_Server {
+tcp_server_make :: (max_clients := 32, allocator := context.allocator) -> &TCP_Server {
socket, err := socket_create(.Inet, .Stream); // IPv6?
if err != .None do return null;
server.client_count = 0;
server.client_allocator = allocator;
- server.clients = make([] ^TCP_Server.Client, max_clients, allocator=allocator);
+ server.clients = make([] &TCP_Server.Client, max_clients, allocator=allocator);
array.fill(server.clients, null);
- sync.mutex_init(^server.event_mutex);
+ sync.mutex_init(&server.event_mutex);
return server;
}
-#local tcp_server_listener :: (use server: ^TCP_Server) {
+#local tcp_server_listener :: (use server: &TCP_Server) {
while server.alive {
if server.client_count == server.clients.count {
os.sleep(1);
client.socket = client_socket;
client.address = client_addr;
- for^ clients do if *it == null { *it = client; break; }
+ for& clients do if *it == null { *it = client; break; }
server.client_count += 1;
conn_event := new(TCP_Event.Connection, allocator=server.event_allocator);
- conn_event.address = ^client.address;
+ conn_event.address = &client.address;
conn_event.client = client;
- sync.critical_section(^server.event_mutex) {
+ sync.critical_section(&server.event_mutex) {
server.events << .{ .Connection, conn_event }; // @Threading
}
}
}
-tcp_server_listen :: (use server: ^TCP_Server, port: u16) -> bool {
+tcp_server_listen :: (use server: &TCP_Server, port: u16) -> bool {
sa: Socket_Address;
- make_ipv4_address(^sa, 0x00000000, port);
- if !(socket->bind(^sa)) do return false;
+ make_ipv4_address(&sa, 0x00000000, port);
+ if !(socket->bind(&sa)) do return false;
socket->listen();
- thread.spawn(^listener_thread, server, tcp_server_listener);
+ thread.spawn(&listener_thread, server, tcp_server_listener);
return true;
}
-tcp_server_stop :: (use server: ^TCP_Server) {
+tcp_server_stop :: (use server: &TCP_Server) {
server.alive = false;
for clients {
}
server.socket->close();
- thread.kill(^listener_thread);
+ thread.kill(&listener_thread);
}
-tcp_server_pulse :: (use server: ^TCP_Server) -> bool {
- for^ clients {
+tcp_server_pulse :: (use server: &TCP_Server) -> bool {
+ for& clients {
client := *it;
if !client do continue;
data_event := new(TCP_Event.Data, allocator=server.event_allocator);
data_event.client = it;
- data_event.address = ^it.address;
+ data_event.address = &it.address;
data_event.contents = memory.copy_slice(msg_buffer[0 .. bytes_read], allocator=server.event_allocator);
- sync.critical_section(^server.event_mutex) {
+ sync.critical_section(&server.event_mutex) {
server.events << .{ .Data, data_event }; // @Threading // See comment above.
}
it.recv_ready_event_present = true;
ready_event := new(TCP_Event.Ready, allocator=server.event_allocator);
ready_event.client = it;
- ready_event.address = ^it.address;
- sync.critical_section(^server.event_mutex) {
+ ready_event.address = &it.address;
+ sync.critical_section(&server.event_mutex) {
server.events << .{ .Ready, ready_event }; // @Threading // See comment above.
}
}
if it.state == .Dying {
disconnect_event := new(TCP_Event.Disconnection, allocator=server.event_allocator);
disconnect_event.client = it;
- disconnect_event.address = ^it.address;
- sync.critical_section(^server.event_mutex) {
+ disconnect_event.address = &it.address;
+ sync.critical_section(&server.event_mutex) {
server.events << .{ .Disconnection, disconnect_event }; // @Threading // See comment above.
}
}
return server.alive;
}
-tcp_server_send :: (use server: ^TCP_Server, client: ^TCP_Server.Client, data: [] u8) {
+tcp_server_send :: (use server: &TCP_Server, client: &TCP_Server.Client, data: [] u8) {
client.socket->send(data);
}
-tcp_server_broadcast :: (use server: ^TCP_Server, data: [] u8, except: ^TCP_Server.Client = null) {
+tcp_server_broadcast :: (use server: &TCP_Server, data: [] u8, except: &TCP_Server.Client = null) {
for clients {
if it == null do continue;
if it.state != .Alive do continue;
}
}
-tcp_server_handle_events :: macro (server: ^TCP_Server, handler: Code) {
+tcp_server_handle_events :: macro (server: &TCP_Server, handler: Code) {
while server->pulse() {
- for iter.as_iter(^server.connection) {
+ for iter.as_iter(&server.connection) {
switch it.kind do #unquote handler;
}
}
}
-tcp_server_kill_client :: (use server: ^TCP_Server, client: ^TCP_Server.Client) {
+tcp_server_kill_client :: (use server: &TCP_Server, client: &TCP_Server.Client) {
client.state = .Being_Killed;
client.socket->shutdown(.ReadWrite);
client.socket->close();
#local
-wait_to_get_client_messages :: (use server: ^TCP_Server) -> [] ^TCP_Server.Client {
- active_clients := alloc.array_from_stack(^TCP_Server.Client, client_count);
+wait_to_get_client_messages :: (use server: &TCP_Server) -> [] &TCP_Server.Client {
+ active_clients := alloc.array_from_stack(&TCP_Server.Client, client_count);
active_clients.count = 0;
for clients {
}
status_buffer := alloc.array_from_stack(core.net.Socket_Poll_Status, client_count);
- socket_poll_all(cast([] ^Socket) active_clients, pulse_time_ms, status_buffer);
+ socket_poll_all(cast([] &Socket) active_clients, pulse_time_ms, status_buffer);
- recv_clients: [..] ^TCP_Server.Client;
+ recv_clients: [..] &TCP_Server.Client;
for it: client_count {
if status_buffer[it] == .Readable {
recv_clients << active_clients[it];
wrote := false;
for file: os.with_file(output_file, .Write) {
writer := io.writer_make(file);
- defer io.writer_free(^writer);
+ defer io.writer_free(&writer);
fb := runtime.info.get_foreign_block(foreign_block);
- write_file_introduction(^writer, preamble, fb.module_name);
+ write_file_introduction(&writer, preamble, fb.module_name);
for fb.funcs {
for impl: custom_implementations {
if impl.name == it.name {
- io.write(^writer, impl.impl);
- io.write(^writer, "\n");
+ io.write(&writer, impl.impl);
+ io.write(&writer, "\n");
continue continue;
}
}
- write_function_body(^writer, it, cast_map, name_map);
+ write_function_body(&writer, it, cast_map, name_map);
}
- write_library_block(^writer, fb.funcs);
+ write_library_block(&writer, fb.funcs);
wrote = true;
}
}
proc := os.process_spawn(Linux_Compiler, args);
- defer os.process_destroy(^proc);
+ defer os.process_destroy(&proc);
- proc_reader := io.reader_make(^proc);
- output := io.read_all(^proc_reader);
- defer memory.free_slice(^output);
+ proc_reader := io.reader_make(&proc);
+ output := io.read_all(&proc_reader);
+ defer memory.free_slice(&output);
- exit := os.process_wait(^proc);
+ exit := os.process_wait(&proc);
if exit != .Success {
eprintf("Failed to compile {}\n", path);
eprintf("{}\n", output);
#local {
- write_file_introduction :: (writer: ^io.Writer, preamble: [] str, name: str) {
+ write_file_introduction :: (writer: &io.Writer, preamble: [] str, name: str) {
io.write_format(writer, "//\n");
io.write_format(writer, "// THIS FILE WAS AUTOMATICALLY GENERATED.\n");
io.write_format(writer, "//\n");
use runtime.info;
method_type := ff.type;
- method_info := cast (^Type_Info_Function) get_type_info(method_type);
+ method_info := cast (&Type_Info_Function) get_type_info(method_type);
assert(method_info.kind == .Function, "Expected function type.");
io.write_format(writer, "ONYX_DEF({}, (", ff.name);
param_num := 0;
for method_info.parameter_types {
if get_type_info(it).kind == .Slice {
- io.write_format(^callw, "ONYX_PTR(P({}, i32)), P({}, i32)", param_num, param_num + 1);
+ io.write_format(&callw, "ONYX_PTR(P({}, i32)), P({}, i32)", param_num, param_num + 1);
param_num += 1;
} elseif is_pointer(it) {
- io.write_format(^callw, "ONYX_PTR(P({}, i32))", param_num);
+ io.write_format(&callw, "ONYX_PTR(P({}, i32))", param_num);
} else {
matched := false;
- for^ m: cast_map {
+ for& m: cast_map {
if m.type == it {
- io.write_format(^callw, "({}) P({}, {})", m.name, param_num, type_to_wasm_type(it));
+ io.write_format(&callw, "({}) P({}, {})", m.name, param_num, type_to_wasm_type(it));
matched = true;
break;
}
}
- if !matched do io.write_format(^callw, "P({}, {})", param_num, type_to_wasm_type(it));
+ if !matched do io.write_format(&callw, "P({}, {})", param_num, type_to_wasm_type(it));
}
- io.write_format(^callw, ", ");
+ io.write_format(&callw, ", ");
param_num += 1;
}
case .Function do assert(false, "Passing functions between wasm and c is not yet supported.");
case .Array do return "i32";
case .Slice do assert(false, "ASDFASDF");
- case .Enum do return type_to_wasm_type((cast(^Type_Info_Enum) param_info).backing_type);
- case .Distinct do return type_to_wasm_type((cast(^Type_Info_Distinct) param_info).base_type);
+ case .Enum do return type_to_wasm_type((cast(&Type_Info_Enum) param_info).backing_type);
+ case .Distinct do return type_to_wasm_type((cast(&Type_Info_Distinct) param_info).base_type);
case .Struct {
- s_info := cast(^Type_Info_Struct) param_info;
+ s_info := cast(&Type_Info_Struct) param_info;
if s_info.constructed_from == cptr && for_return {
return "cptr";
case .Function do assert(false, "Passing functions between wasm and c is not yet supported.");
case .Array do return "WASM_I32";
case .Slice do return "WASM_I32,WASM_I32";
- case .Enum do return type_encoding((cast(^Type_Info_Enum) param_info).backing_type);
- case .Distinct do return type_encoding((cast(^Type_Info_Distinct) param_info).base_type);
+ case .Enum do return type_encoding((cast(&Type_Info_Enum) param_info).backing_type);
+ case .Distinct do return type_encoding((cast(&Type_Info_Distinct) param_info).base_type);
case .Struct {
- s_info := cast(^Type_Info_Struct) param_info;
+ s_info := cast(&Type_Info_Struct) param_info;
if s_info.members.count == 1 {
return type_encoding(s_info.members[0].type);
}
#inject cptr {
//
// Creates a new C-pointer from an Onyx pointer.
- make :: macro (ptr: ^$T) -> cptr(T) {
+ make :: macro (ptr: &$T) -> cptr(T) {
__cptr_make :: __cptr_make
return .{ __cptr_make(ptr) };
}
(this: cptr($T)) -> T {
buf: [sizeof T] u8;
__cptr_read(this.data, ~~buf, sizeof T);
- return *cast(^T) buf;
+ return *cast(&T) buf;
}
}
//
// This procedure attempts to convert a C-pointer back into an
// Onyx pointer, if the pointer lives with the Onyx memory space.
- to_rawptr :: (this: cptr($T)) -> ^T {
+ to_rawptr :: (this: cptr($T)) -> &T {
// I'm treating NULL as more of a concept, than as an actual value here,
// because if something returns a NULL pointer, it should logically map
// to the same idea as 'null' in Onyx.
return elem->read();
}
- format :: (output: ^conv.Format_Output, format: ^conv.Format, p: ^cptr($T)) {
+ format :: (output: &conv.Format_Output, format: &conv.Format, p: &cptr($T)) {
conv.format(output, "cptr({})[0x{b16}]", T, p.data);
}
}
name_length : u32;
name_data : [256] u8;
- name :: (use dir: ^DirectoryEntry) => str.{ ~~name_data, name_length };
+ name :: (use dir: &DirectoryEntry) => str.{ ~~name_data, name_length };
}
dir_open :: (path: str) -> (Directory, bool) {
dir: Directory;
- success := fs.__dir_open(path, ^dir);
+ success := fs.__dir_open(path, &dir);
return dir, success;
}
fs.__dir_close(dir);
}
-dir_read :: (dir: Directory, out_entry: ^DirectoryEntry) -> bool {
+dir_read :: (dir: Directory, out_entry: &DirectoryEntry) -> bool {
return fs.__dir_read(dir, out_entry);
}
opened := false;
}
- next :: (use c: ^Context) -> (DirectoryEntry, bool) {
+ next :: (use c: &Context) -> (DirectoryEntry, bool) {
if !opened do return .{}, false;
entry: DirectoryEntry;
- if !dir_read(dir, ^entry) {
+ if !dir_read(dir, &entry) {
return .{}, false;
}
return entry, true;
}
- close :: (use c: ^Context) {
+ close :: (use c: &Context) {
dir_close(dir);
cfree(c);
}
remove_file :: fs.__file_remove
rename_file :: fs.__file_rename
-get_contents_from_file :: (file: ^File) -> str {
+get_contents_from_file :: (file: &File) -> str {
size := cast(u32) io.stream_size(file);
- data := cast(^u8) raw_alloc(context.allocator, size);
+ data := cast(&u8) raw_alloc(context.allocator, size);
_, prev_loc := io.stream_tell(file);
io.stream_seek(file, 0, .Start);
if error != .None do return .{ .Err, .{error=error} };
file.data = file_data;
- file.vtable = ^fs.__file_stream_vtable;
+ file.vtable = &fs.__file_stream_vtable;
return .{ .Ok, .{value=file} };
}
-close :: (file: ^File) {
+close :: (file: &File) {
fs.__file_close(file.data);
file.stream.vtable = null;
}
(path: str) -> str {
file := open(path, .Read)->or_return(null_str);
- defer close(^file);
+ defer close(&file);
- return get_contents(^file);
+ return get_contents(&file);
}
}
-with_file :: (path: str, mode := OpenMode.Read) -> Iterator(^File) {
+with_file :: (path: str, mode := OpenMode.Read) -> Iterator(&File) {
Context :: struct {
valid_file_stream := false;
c.valid_file_stream = true;
}
- next :: (use c: ^Context) -> (^File, bool) {
+ next :: (use c: &Context) -> (&File, bool) {
if !valid_file_stream do return null, false;
defer valid_file_stream = false;
- return ^file_stream, true;
+ return &file_stream, true;
}
- close_context :: (use c: ^Context) {
- close(^file_stream);
+ close_context :: (use c: &Context) {
+ close(&file_stream);
cfree(c);
}
is_file :: (path: str) -> bool {
s: FileStat;
- if !file_stat(path, ^s) do return false;
+ if !file_stat(path, &s) do return false;
return s.type == .RegularFile;
}
is_directory :: (path: str) -> bool {
s: FileStat;
- if !file_stat(path, ^s) do return false;
+ if !file_stat(path, &s) do return false;
return s.type == .Directory;
}
//
File_Logger :: struct {
- file: ^File;
+ file: &File;
filename: str;
allocator: Allocator;
old_logger: Logger;
}
-file_logger_open :: (filename: str, allocator := context.allocator) -> Result(^File_Logger, str) {
+file_logger_open :: (filename: str, allocator := context.allocator) -> Result(&File_Logger, str) {
file_logger := new(File_Logger, allocator);
file_logger.allocator = allocator;
file_logger.filename = filename;
return .{ .Ok, .{ value=file_logger } };
}
-file_logger_use :: (logger: ^File_Logger) {
+file_logger_use :: (logger: &File_Logger) {
logger.old_logger = context.logger;
context.logger = .{ file_logger_proc, logger };
}
-file_logger_close :: (logger: ^File_Logger) {
+file_logger_close :: (logger: &File_Logger) {
if logger.old_logger.data {
context.logger = logger.old_logger;
}
}
#local
-file_logger_proc :: (logger: ^File_Logger, level: Log_Level, msg: str, module: str) {
+file_logger_proc :: (logger: &File_Logger, level: Log_Level, msg: str, module: str) {
writer := io.writer_make(logger.file, 0);
if module {
- io.write_format(^writer, "[{}][{}] {}\n", level, module, msg);
+ io.write_format(&writer, "[{}][{}] {}\n", level, module, msg);
} else {
- io.write_format(^writer, "[{}] {}\n", level, msg);
+ io.write_format(&writer, "[{}] {}\n", level, msg);
}
}
handle := __process_spawn(path, args, non_blocking_io, starting_directory);
return .{
- .{ ^process_stream_vtable },
+ .{ &process_stream_vtable },
handle,
};
}
-process_kill :: (use p: ^Process) -> bool {
+process_kill :: (use p: &Process) -> bool {
return __process_kill(process_handle);
}
-process_wait :: (use p: ^Process) => {
+process_wait :: (use p: &Process) => {
return __process_wait(process_handle);
}
-process_destroy :: (use p: ^Process) => {
+process_destroy :: (use p: &Process) => {
__process_destroy(process_handle);
}
}
#local process_stream_vtable := io.Stream_Vtable.{
- read = (use p: ^Process, buffer: [] u8) -> (io.Error, u32) {
+ read = (use p: &Process, buffer: [] u8) -> (io.Error, u32) {
// Read from the process stdout
if cast(i64) process_handle == 0 do return .BadFile, 0;
return .None, bytes_read;
},
- write = (use p: ^Process, buffer: [] u8) -> (io.Error, u32) {
+ write = (use p: &Process, buffer: [] u8) -> (io.Error, u32) {
// Write to the process stdin
if cast(i64) process_handle == 0 do return .BadFile, 0;
return .None, bytes_written;
},
- close = (use p: ^Process) -> io.Error {
+ close = (use p: &Process) -> io.Error {
process_kill(p);
return .None;
}
//
// Sets the seed of the random number generator
set_seed :: #match {
- (self: ^Random, s: u32) { self.seed = ~~s; },
- (self: ^Random, s: u64) { self.seed = s; },
+ (self: &Random, s: u32) { self.seed = ~~s; },
+ (self: &Random, s: u64) { self.seed = s; },
}
//
// Generates a random 32-bit integer.
- int :: (self: ^Random) -> u32 {
+ int :: (self: &Random) -> u32 {
s := self.seed * RANDOM_MULTIPLIER + RANDOM_INCREMENT;
defer self.seed = s;
return cast(u32) ((s >> 16) & ~~0xffffffff);
//
// Generates a random 32-bit integer between `lo` and `hi`.
- between :: (self: ^Random, lo: i32, hi: i32) -> i32 {
+ between :: (self: &Random, lo: i32, hi: i32) -> i32 {
return self->int() % (hi + 1 - lo) + lo;
}
//
// Generates a random floating point number between `lo` and `hi`.
- float :: (self: ^Random, lo := 0.0f, hi := 1.0f) -> f32 {
+ float :: (self: &Random, lo := 0.0f, hi := 1.0f) -> f32 {
return (cast(f32) (self->int() % (1 << 20)) / cast(f32) (1 << 20)) * (hi - lo) + lo;
}
//
// Returns a random element from a slice.
- choice :: (self: ^Random, a: [] $T) -> T {
+ choice :: (self: &Random, a: [] $T) -> T {
return a[self->between(0, a.count - 1)];
}
//
// Returns a random string of length `bytes_long`. If `alpha_numeric` is
// true, then the string will only consist of alpha-numeric characters.
- string :: (self: ^Random, bytes_long: u32, alpha_numeric := false, allocator := context.allocator) -> str {
+ string :: (self: &Random, bytes_long: u32, alpha_numeric := false, allocator := context.allocator) -> str {
memory :: package core.memory
s := memory.make_slice(u8, bytes_long, allocator=allocator);
- for^ s {
+ for& s {
if alpha_numeric {
#persist alpha_numeral := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
*it = self->choice(alpha_numeral);
alloc.init_temp_allocator();
- __initialize(^context);
+ __initialize(&context);
context.allocator = alloc.heap_allocator;
context.temp_allocator = alloc.temp_allocator;
context.assert_handler = __assert_handler;
foreign_block :: #distinct u32
-foreign_blocks: [] ^Foreign_Block;
+foreign_blocks: [] &Foreign_Block;
Foreign_Block :: struct {
module_name: str;
}
}
-get_foreign_block :: (f: foreign_block) -> ^Foreign_Block {
+get_foreign_block :: (f: foreign_block) -> &Foreign_Block {
if ~~f < cast(i32) 0 || ~~f >= cast(i32) foreign_blocks.count do return null;
return foreign_blocks[cast(i32) f];
use core {io}
-write_type_name :: (writer: ^io.Writer, t: type_expr) {
+write_type_name :: (writer: &io.Writer, t: type_expr) {
info := get_type_info(t);
if info == null do return;
switch info.kind {
case .Basic {
- basic := cast(^Type_Info_Basic) info;
+ basic := cast(&Type_Info_Basic) info;
switch basic.basic_kind {
case .Void do io.write_str(writer, "void");
}
case .Pointer {
- pointer := cast(^Type_Info_Pointer) info;
- io.write_str(writer, "^");
+ pointer := cast(&Type_Info_Pointer) info;
+ io.write_str(writer, "&");
write_type_name(writer, pointer.to);
}
case .Array {
- arr := cast(^Type_Info_Array) info;
+ arr := cast(&Type_Info_Array) info;
io.write_format(writer, "[{}] ", arr.count);
write_type_name(writer, arr.of);
}
case .Slice {
- slice := cast(^Type_Info_Slice) info;
+ slice := cast(&Type_Info_Slice) info;
io.write_str(writer, "[] ");
write_type_name(writer, slice.of);
}
case .Dynamic_Array {
- dyn := cast(^Type_Info_Dynamic_Array) info;
+ dyn := cast(&Type_Info_Dynamic_Array) info;
io.write_str(writer, "[..] ");
write_type_name(writer, dyn.of);
}
case .Variadic_Argument {
- va := cast(^Type_Info_Variadic_Argument) info;
+ va := cast(&Type_Info_Variadic_Argument) info;
io.write_str(writer, "..");
write_type_name(writer, va.of);
}
case .Enum {
- e := cast(^Type_Info_Enum) info;
+ e := cast(&Type_Info_Enum) info;
io.write_str(writer, e.name);
}
case .Struct {
- s := cast(^Type_Info_Struct) info;
+ s := cast(&Type_Info_Struct) info;
if s.name.count > 0 do io.write_str(writer, s.name);
else do io.write_str(writer, "<anonymous struct>");
}
case .Polymorphic_Struct {
- s := cast(^Type_Info_Polymorphic_Struct) info;
+ s := cast(&Type_Info_Polymorphic_Struct) info;
if s.name.count > 0 do io.write_str(writer, s.name);
else do io.write_str(writer, "<anonymous polymorphic struct>");
}
case .Compound {
- comp := cast(^Type_Info_Compound) info;
+ comp := cast(&Type_Info_Compound) info;
io.write_str(writer, "(");
i := 0;
}
case .Function {
- f := cast(^Type_Info_Function) info;
+ f := cast(&Type_Info_Function) info;
io.write_str(writer, "(");
i := 0;
}
case .Distinct {
- d := cast(^Type_Info_Distinct) info;
+ d := cast(&Type_Info_Distinct) info;
io.write_str(writer, d.name);
}
}
switch info.kind {
case .Basic {
- basic := cast(^Type_Info_Basic) info;
+ basic := cast(&Type_Info_Basic) info;
switch basic.basic_kind {
case .Void do return 0;
case .Pointer do return sizeof rawptr;
case .Array {
- arr := cast(^Type_Info_Array) info;
+ arr := cast(&Type_Info_Array) info;
return size_of(arr.of) * arr.count;
}
case .Dynamic_Array do return sizeof [..] void;
case .Variadic_Argument do return sizeof str;
case .Enum {
- e := cast(^Type_Info_Enum) info;
+ e := cast(&Type_Info_Enum) info;
return e.size;
}
case .Struct {
- s := cast(^Type_Info_Struct) info;
+ s := cast(&Type_Info_Struct) info;
return s.size;
}
case .Function do return 4;
case .Distinct {
- d := cast(^Type_Info_Distinct) info;
+ d := cast(&Type_Info_Distinct) info;
return size_of(d.base_type);
}
}
if info == null do return 0;
if info.kind != .Struct do return 0;
- struct_info := cast(^Type_Info_Struct) info;
- for ^m: struct_info.members {
+ struct_info := cast(&Type_Info_Struct) info;
+ for &m: struct_info.members {
if m.name == member_name do return m.offset;
}
return 0;
}
-get_struct_member :: (S: type_expr, member_name: str) -> ^Type_Info_Struct.Member {
- info := cast(^Type_Info_Struct) get_type_info(S);
+get_struct_member :: (S: type_expr, member_name: str) -> &Type_Info_Struct.Member {
+ info := cast(&Type_Info_Struct) get_type_info(S);
if info == null do return null;
if info.kind != .Struct do return null;
- for^ info.members {
+ for& info.members {
if it.name == member_name do return it;
}
ti := get_type_info(S);
if ti.kind != .Struct do return .[];
- for ^ (cast(^Type_Info_Struct) ti).members {
+ for & (cast(&Type_Info_Struct) ti).members {
if it.name == member_name {
return it.tags;
}
struct_info := get_type_info(struct_type);
if struct_info.kind != .Struct do return false;
- return (cast(^Type_Info_Struct) struct_info).constructed_from == base_type;
+ return (cast(&Type_Info_Struct) struct_info).constructed_from == base_type;
}
struct_inherits :: (struct_type: type_expr, base_type: type_expr) -> bool {
- struct_info := cast(^Type_Info_Struct) get_type_info(struct_type);
+ struct_info := cast(&Type_Info_Struct) get_type_info(struct_type);
if struct_info.kind != .Struct do return false;
- first_member := ^struct_info.members[0];
+ first_member := &struct_info.members[0];
return first_member.used && first_member.type == base_type;
}
info := get_type_info(Backing_Type);
if info.kind != .Enum do return null_str;
- etype := cast(^Type_Info_Enum) info;
- for ^member: etype.members {
+ etype := cast(&Type_Info_Enum) info;
+ for &member: etype.members {
if member.value == ~~value do return member.name;
}
info := get_type_info(E);
if info.kind != .Enum do return ~~0;
- etype := cast(^Type_Info_Enum) info;
- for ^member: etype.members {
+ etype := cast(&Type_Info_Enum) info;
+ for &member: etype.members {
if member.name == name do return ~~member.value;
}
}
enum_values :: (E: type_expr) -> [] Type_Info_Enum.Member {
- info := cast(^Type_Info_Enum) get_type_info(E);
+ info := cast(&Type_Info_Enum) get_type_info(E);
if info.kind != .Enum do return .[];
return info.members;
defer index += 1;
if it.kind != .Struct do continue;
- if (cast(^Type_Info_Struct) it).name == name do return cast(type_expr) index;
+ if (cast(&Type_Info_Struct) it).name == name do return cast(type_expr) index;
}
return void;
}
-get_struct_method :: (type: type_expr, method_name: str) -> ^any {
- info := cast(^Type_Info_Struct) get_type_info(type);
+get_struct_method :: (type: type_expr, method_name: str) -> &any {
+ info := cast(&Type_Info_Struct) get_type_info(type);
if info.kind != .Struct do return null;
method := core.array.first(info.methods, #(it.name == method_name));
- if method != null do return ^method.func;
+ if method != null do return &method.func;
return null;
}
-populate_struct_vtable :: (table: ^$Table_Type, struct_type: type_expr, safe := true) {
- v_info := cast(^Type_Info_Struct) get_type_info(Table_Type);
+populate_struct_vtable :: (table: &$Table_Type, struct_type: type_expr, safe := true) {
+ v_info := cast(&Type_Info_Struct) get_type_info(Table_Type);
if v_info.kind != .Struct do return;
- for^ member: v_info.members {
+ for& member: v_info.members {
if get_type_info(member.type).kind != .Function do continue;
struct_method := get_struct_method(struct_type, member.name);
if struct_method == null do continue;
if safe && struct_method.type != member.type do continue;
- dest := cast(^()->void) (cast(^u8) table + member.offset);
- *dest = *cast(^()->void) struct_method.data;
+ dest := cast(&()->void) (cast(&u8) table + member.offset);
+ *dest = *cast(&()->void) struct_method.data;
}
}
use core {array}
-tagged_procedures: [] ^Tagged_Procedure
+tagged_procedures: [] &Tagged_Procedure
Tagged_Procedure :: struct {
// This should be cast to the correct function type.
- // i.e. *cast(^(i32, i32) -> i32) ^tagged_procedures[0].func;
+ // i.e. *cast(&(i32, i32) -> i32) &tagged_procedures[0].func;
func: () -> void;
type: type_expr;
tags: [] any;
if get_type_info(T).kind != .Function do return .[];
for tagged_procedures {
- if (*cast(^T) ^it.func) == func do return it.tags;
+ if (*cast(&T) &it.func) == func do return it.tags;
}
return .[];
#local GPWT_Result :: struct (T: type_expr) {
func: () -> void;
type: type_expr;
- tag : ^T;
+ tag : &T;
pack: package_id;
}
for proc: tagged_procedures {
if tag := array.first(proc.tags, #(it.type == tag_type)); tag != null {
- array.push(^results, .{
+ array.push(&results, .{
func = proc.func,
type = proc.type,
- tag = cast(^tag_type) tag.data,
+ tag = cast(&tag_type) tag.data,
pack = proc.pack,
});
}
package runtime.info
-type_table : [] ^Type_Info;
+type_table : [] &Type_Info;
Type_Info :: struct {
// This must match the order of the elements in onyxtypes.h
name: str;
}
-get_type_info :: (t: type_expr) -> ^Type_Info {
+get_type_info :: (t: type_expr) -> &Type_Info {
// Grossness to get around the fact that type_exprs are not technically comparable, because in most
// cases you should not compare them as the number assigned to them is arbitrary.
if ~~t < cast(i32) 0 || ~~t >= cast(i32) type_table.count do return null;
#local {
#foreign "onyx_runtime" {
- __file_open_impl :: (path: str, mode: os.OpenMode, out_handle: ^FileData) -> os.FileError ---
+ __file_open_impl :: (path: str, mode: os.OpenMode, out_handle: &FileData) -> os.FileError ---
__file_close :: (fd: FileData) -> os.FileError ---
- __file_stat :: (path: str, stat: ^os.FileStat) -> bool ---
+ __file_stat :: (path: str, stat: &os.FileStat) -> bool ---
__file_exists :: (path: str) -> bool ---
__file_remove :: (path: str) -> bool ---
__file_rename :: (old_path: str, new_path: str) -> bool ---
__file_seek :: (handle: FileData, to: i32, whence: io.SeekFrom) -> i32 ---
__file_tell :: (handle: FileData) -> u32 ---
- __file_read :: (handle: FileData, output_buffer: [] u8, bytes_read: ^u64) -> io.Error ---
- __file_write :: (handle: FileData, input_buffer: [] u8, bytes_wrote: ^u64) -> io.Error ---
+ __file_read :: (handle: FileData, output_buffer: [] u8, bytes_read: &u64) -> io.Error ---
+ __file_write :: (handle: FileData, input_buffer: [] u8, bytes_wrote: &u64) -> io.Error ---
__file_flush :: (handle: FileData) -> io.Error ---
__file_size :: (handle: FileData) -> u32 ---
- __dir_open :: (path: str, dir: ^DirectoryData) -> bool ---
+ __dir_open :: (path: str, dir: &DirectoryData) -> bool ---
__dir_close :: (dir: DirectoryData) -> void ---
- __dir_read :: (dir: DirectoryData, out_entry: ^os.DirectoryEntry) -> bool ---
+ __dir_read :: (dir: DirectoryData, out_entry: &os.DirectoryEntry) -> bool ---
__dir_create :: (path: str) -> bool ---
__dir_remove :: (path: str) -> bool ---
__file_open :: (path: str, mode := os.OpenMode.Read) -> (FileData, os.FileError) {
handle: FileData;
- error := __file_open_impl(path, mode, ^handle);
+ error := __file_open_impl(path, mode, &handle);
return handle, error;
}
__dir_remove :: __dir_remove
__file_stream_vtable := io.Stream_Vtable.{
- seek = (use fs: ^os.File, to: i32, whence: io.SeekFrom) -> io.Error {
+ seek = (use fs: &os.File, to: i32, whence: io.SeekFrom) -> io.Error {
now := __file_seek(data, to, whence);
return (.None) if now >= 0 else .BadFile;
},
- tell = (use fs: ^os.File) -> (io.Error, u32) {
+ tell = (use fs: &os.File) -> (io.Error, u32) {
return .None, __file_tell(data);
},
- read = (use fs: ^os.File, buffer: [] u8) -> (io.Error, u32) {
+ read = (use fs: &os.File, buffer: [] u8) -> (io.Error, u32) {
bytes_read: u64;
- error := __file_read(data, buffer, ^bytes_read);
+ error := __file_read(data, buffer, &bytes_read);
return error, ~~bytes_read;
},
- read_at = (use fs: ^os.File, at: u32, buffer: [] u8) -> (io.Error, u32) {
+ read_at = (use fs: &os.File, at: u32, buffer: [] u8) -> (io.Error, u32) {
__file_seek(data, at, .Start);
bytes_read: u64;
- error := __file_read(data, buffer, ^bytes_read);
+ error := __file_read(data, buffer, &bytes_read);
return error, ~~bytes_read;
},
- read_byte = (use fs: ^os.File) -> (io.Error, u8) {
+ read_byte = (use fs: &os.File) -> (io.Error, u8) {
byte: u8;
- error := __file_read(data, ~~ cast([1] u8) ^byte, null);
+ error := __file_read(data, ~~ cast([1] u8) &byte, null);
return error, byte;
},
- write = (use fs: ^os.File, buffer: [] u8) -> (io.Error, u32) {
+ write = (use fs: &os.File, buffer: [] u8) -> (io.Error, u32) {
bytes_wrote: u64;
- error := __file_write(data, buffer, ^bytes_wrote);
+ error := __file_write(data, buffer, &bytes_wrote);
return error, ~~bytes_wrote;
},
- write_at = (use fs: ^os.File, at: u32, buffer: [] u8) -> (io.Error, u32) {
+ write_at = (use fs: &os.File, at: u32, buffer: [] u8) -> (io.Error, u32) {
__file_seek(data, at, .Start);
bytes_wrote: u64;
- error := __file_write(data, buffer, ^bytes_wrote);
+ error := __file_write(data, buffer, &bytes_wrote);
return error, ~~bytes_wrote;
},
- write_byte = (use fs: ^os.File, byte: u8) -> io.Error {
+ write_byte = (use fs: &os.File, byte: u8) -> io.Error {
b := byte;
bytes_wrote: u64;
- error := __file_write(data, .{ ^b, 1 }, ^bytes_wrote);
+ error := __file_write(data, .{ &b, 1 }, &bytes_wrote);
return error;
},
- close = (use fs: ^os.File) -> io.Error {
+ close = (use fs: &os.File) -> io.Error {
__file_close(data);
return .None;
},
- flush = (use fs: ^os.File) -> io.Error {
+ flush = (use fs: &os.File) -> io.Error {
return __file_flush(data);
},
- size = (use fs: ^os.File) -> i32 {
+ size = (use fs: &os.File) -> i32 {
return __file_size(data);
},
};
}
__output_string :: (s: str) -> u32 {
- err, wrote := io.stream_write(^__stdout, s);
+ err, wrote := io.stream_write(&__stdout, s);
return wrote;
}
__output_error :: (s: str) -> u32 {
- err, wrote := io.stream_write(^__stderr, s);
+ err, wrote := io.stream_write(&__stderr, s);
return wrote;
}
__read_from_input :: (buffer: [] u8) -> i32 {
- err, read := io.stream_read(^__stdin, buffer);
+ err, read := io.stream_read(&__stdin, buffer);
if err == .ReadPending do return 0;
if err != .None do return -1;
return read;
#foreign "onyx_runtime" {
// Arguments
- __args_get :: (argv: ^^u8, arg_buf: ^u8) -> void ---
- __args_sizes_get :: (argc: ^i32, arg_buf_size: ^i32) -> void ---
+ __args_get :: (argv: & &u8, arg_buf: &u8) -> void ---
+ __args_sizes_get :: (argc: &i32, arg_buf_size: &i32) -> void ---
// OS
__exit :: (status: i32) -> void ---
// Time and sleep
__time :: () -> u64 ---
- __time_localtime :: (time: u64, tm: ^core.time.Timestamp) -> void ---
- __time_gmtime :: (time: u64, tm: ^core.time.Timestamp) -> void ---
- __time_mktime :: (tm: ^time.Timestamp) -> i64 ---
- __time_strftime :: (buf: [] u8, format: cstr, tm: ^time.Timestamp) -> u32 ---
+ __time_localtime :: (time: u64, tm: &core.time.Timestamp) -> void ---
+ __time_gmtime :: (time: u64, tm: &core.time.Timestamp) -> void ---
+ __time_mktime :: (tm: &time.Timestamp) -> i64 ---
+ __time_strftime :: (buf: [] u8, format: cstr, tm: &time.Timestamp) -> u32 ---
// Processes
__process_spawn :: (path: str, args: [] str, non_blocking_io: bool, starting_directory: str) -> ProcessData ---
__process_destroy :: (handle: ProcessData) -> void ---
// Misc
- __file_get_standard :: (fd: i32, out: ^FileData) -> bool ---
+ __file_get_standard :: (fd: i32, out: &FileData) -> bool ---
}
__start :: () {
fd: FileData;
- __file_get_standard(1, ^fd);
+ __file_get_standard(1, &fd);
__stdout = .{
- .{ ^__file_stream_vtable },
+ .{ &__file_stream_vtable },
fd
};
- __file_get_standard(2, ^fd);
+ __file_get_standard(2, &fd);
__stderr = .{
- .{ ^__file_stream_vtable },
+ .{ &__file_stream_vtable },
fd
};
- __file_get_standard(0, ^fd);
+ __file_get_standard(0, &fd);
__stdin = .{
- .{ ^__file_stream_vtable, .Block_On_Read },
+ .{ &__file_stream_vtable, .Block_On_Read },
fd
};
} else {
args : [] cstr;
argv_buf_size : i32;
- __args_sizes_get(^args.count, ^argv_buf_size);
+ __args_sizes_get(&args.count, &argv_buf_size);
args = memory.make_slice(cstr, args.count);
argv_buf := cast(cstr) calloc(argv_buf_size);
time :: () -> u64 {
output_time: Timestamp;
- clock_time_get(.Realtime, 500000, ^output_time);
+ clock_time_get(.Realtime, 500000, &output_time);
return ~~(output_time / 1000000);
}
time_ns :: () -> u64 {
output_time: Timestamp;
- clock_time_get(.Realtime, 1, ^output_time);
+ clock_time_get(.Realtime, 1, &output_time);
return ~~output_time;
}
event: Event;
number_of_events: u32;
- error_code := poll_oneoff(^subscription, ^event, 1, ^number_of_events);
+ error_code := poll_oneoff(&subscription, &event, 1, &number_of_events);
}
}
get_env :: (allocator := context.allocator) -> Environment {
env_count, env_buf_size : Size;
- environ_sizes_get(^env_count, ^env_buf_size);
+ environ_sizes_get(&env_count, &env_buf_size);
env_var := memory.make_slice(cstr, env_count, allocator=allocator);
env_buf := memory.make_slice(u8, env_buf_size, allocator=allocator);
while i := cast(i32) (env_var.count - 1); i >= 0 {
defer i -= 1;
- env_var[i] = cast(cstr) (cast(^u32) env_var.data)[i];
+ env_var[i] = cast(cstr) (cast(&u32) env_var.data)[i];
}
env_map := map.make(str, str, "");
for env: env_var {
s := string.from_cstr(env);
- var := string.read_until(^s, #char "=");
- map.put(^env_map, var, string.advance(s, 1));
+ var := string.read_until(&s, #char "=");
+ map.put(&env_map, var, string.advance(s, 1));
}
raw_free(allocator, env_var.data);
};
}
-free_env :: (use env: ^Environment) {
- map.free(^vars);
+free_env :: (use env: &Environment) {
+ map.free(&vars);
raw_free(buffer_allocator, buffer.data);
}
vec := IOVec.{ buf = cast(u32) s.data, len = s.count };
tmp : Size;
- fd_write(STDOUT_FILENO, ^vec, 1, ^tmp);
+ fd_write(STDOUT_FILENO, &vec, 1, &tmp);
fd_datasync(STDOUT_FILENO);
return tmp;
}
vec := IOVec.{ buf = cast(i32) buffer.data, len = buffer.count };
read: Size;
- error := fd_read(STDIN_FILENO, ^vec, 1, ^read);
+ error := fd_read(STDIN_FILENO, &vec, 1, &read);
if error != .Success do return -1;
return read;
event: Event;
number_of_events: u32;
- error_code := poll_oneoff(^subscription, ^event, 1, ^number_of_events);
+ error_code := poll_oneoff(&subscription, &event, 1, &number_of_events);
}
} else {
args : [] cstr;
argv_buf_size : Size;
- args_sizes_get(^args.count, ^argv_buf_size);
+ args_sizes_get(&args.count, &argv_buf_size);
args = memory.make_slice(cstr, args.count);
argv_buf := cast(cstr) calloc(argv_buf_size);
while i := cast(i32) (args.count - 1); i >= 0 {
defer i -= 1;
- args[i] = cast(cstr) (cast(^u32) args.data)[i];
+ args[i] = cast(cstr) (cast(&u32) args.data)[i];
}
(package main).main(args);
FileDescriptor :: #type i32;
IOVec :: struct {
- buf : u32; // actually a ^u8, but WASM is 32-bit at the moment;
+ buf : u32; // actually a &u8, but WASM is 32-bit at the moment;
len : u32;
}
// FUNCTIONS
-args_get :: (argv: ^^u8, argv_buf: ^u8) -> Errno #foreign "wasi_snapshot_preview1" "args_get"---
-args_sizes_get :: (argc: ^Size, argv_buf_size: ^Size) -> Errno #foreign "wasi_snapshot_preview1" "args_sizes_get" ---
+args_get :: (argv: & &u8, argv_buf: &u8) -> Errno #foreign "wasi_snapshot_preview1" "args_get"---
+args_sizes_get :: (argc: &Size, argv_buf_size: &Size) -> Errno #foreign "wasi_snapshot_preview1" "args_sizes_get" ---
-environ_get :: (environ: ^^u8, environ_buf: ^u8) -> Errno #foreign "wasi_snapshot_preview1" "environ_get" ---
-environ_sizes_get :: (environc: ^Size, environ_buf_size: ^Size) -> Errno #foreign "wasi_snapshot_preview1" "environ_sizes_get" ---
+environ_get :: (environ: & &u8, environ_buf: &u8) -> Errno #foreign "wasi_snapshot_preview1" "environ_get" ---
+environ_sizes_get :: (environc: &Size, environ_buf_size: &Size) -> Errno #foreign "wasi_snapshot_preview1" "environ_sizes_get" ---
-clock_res_get :: (id: ClockID, resolution: ^Timestamp) -> Errno #foreign "wasi_snapshot_preview1" "clock_res_get" ---
-clock_time_get :: (id: ClockID, precision: Timestamp, time: ^Timestamp) -> Errno #foreign "wasi_snapshot_preview1" "clock_time_get" ---
+clock_res_get :: (id: ClockID, resolution: &Timestamp) -> Errno #foreign "wasi_snapshot_preview1" "clock_res_get" ---
+clock_time_get :: (id: ClockID, precision: Timestamp, time: &Timestamp) -> Errno #foreign "wasi_snapshot_preview1" "clock_time_get" ---
fd_advise :: (fd: FileDescriptor, offset: Filesize, len: Filesize, advice: Advice) -> Errno #foreign "wasi_snapshot_preview1" "fd_advise" ---
fd_allocate :: (fd: FileDescriptor, offset: Filesize, len: Filesize) -> Errno #foreign "wasi_snapshot_preview1" "fd_allocate" ---
fd_close :: (fd: FileDescriptor) -> Errno #foreign "wasi_snapshot_preview1" "fd_close" ---
fd_datasync :: (fd: FileDescriptor) -> Errno #foreign "wasi_snapshot_preview1" "fd_datasync" ---
-fd_fdstat_get :: (fd: FileDescriptor, stat: ^FDStat) -> Errno #foreign "wasi_snapshot_preview1" "fd_fdstat_get" ---
+fd_fdstat_get :: (fd: FileDescriptor, stat: &FDStat) -> Errno #foreign "wasi_snapshot_preview1" "fd_fdstat_get" ---
fd_fdstat_set_flags :: (fd: FileDescriptor, flags: FDFlags) -> Errno #foreign "wasi_snapshot_preview1" "fd_fdstat_set_flags" ---
fd_fdstat_set_rights :: (fd: FileDescriptor, rights_base: Rights, rights_inheriting: Rights) -> Errno #foreign "wasi_snapshot_preview1" "fd_fdstat_set_rights" ---
-fd_filestat_get :: (fd: FileDescriptor, buf: ^FileStat) -> Errno #foreign "wasi_snapshot_preview1" "fd_filestat_get" ---
+fd_filestat_get :: (fd: FileDescriptor, buf: &FileStat) -> Errno #foreign "wasi_snapshot_preview1" "fd_filestat_get" ---
fd_filestat_set_size :: (fd: FileDescriptor, size: Filesize) -> Errno #foreign "wasi_snapshot_preview1" "fd_filestat_set_size" ---
fd_filestat_set_times :: (fd: FileDescriptor, atim: Timestamp, mtim: Timestamp, fst_flags: FSTFlags) -> Errno #foreign "wasi_snapshot_preview1" "fd_filestat_set_times" ---
-fd_pread :: (fd: FileDescriptor, iovs: ^IOVec, iovs_len: Size, offset: Filesize, nread: ^Size) -> Errno #foreign "wasi_snapshot_preview1" "fd_pread" ---
-fd_prestat_get :: (fd: FileDescriptor, buf: ^PrestatTagged) -> Errno #foreign "wasi_snapshot_preview1" "fd_prestat_get" ---
+fd_pread :: (fd: FileDescriptor, iovs: &IOVec, iovs_len: Size, offset: Filesize, nread: &Size) -> Errno #foreign "wasi_snapshot_preview1" "fd_pread" ---
+fd_prestat_get :: (fd: FileDescriptor, buf: &PrestatTagged) -> Errno #foreign "wasi_snapshot_preview1" "fd_prestat_get" ---
fd_prestat_dir_name :: (fd: FileDescriptor, path: str) -> Errno #foreign "wasi_snapshot_preview1" "fd_prestat_dir_name" ---
-fd_pwrite :: (fd: FileDescriptor, iovs: ^IOVec, iovs_len: Size, offset: Filesize, nwritten: ^Size) -> Errno #foreign "wasi_snapshot_preview1" "fd_pwrite" ---
-fd_read :: (fd: FileDescriptor, iovs: ^IOVec, iovs_len: Size, nread: ^Size) -> Errno #foreign "wasi_snapshot_preview1" "fd_read" ---
-fd_readdir :: (fd: FileDescriptor, buf: ^u8, buf_len: Size, cookie: DirCookie, bufused: ^Size) -> Errno #foreign "wasi_snapshot_preview1" "fd_readdir" ---
+fd_pwrite :: (fd: FileDescriptor, iovs: &IOVec, iovs_len: Size, offset: Filesize, nwritten: &Size) -> Errno #foreign "wasi_snapshot_preview1" "fd_pwrite" ---
+fd_read :: (fd: FileDescriptor, iovs: &IOVec, iovs_len: Size, nread: &Size) -> Errno #foreign "wasi_snapshot_preview1" "fd_read" ---
+fd_readdir :: (fd: FileDescriptor, buf: &u8, buf_len: Size, cookie: DirCookie, bufused: &Size) -> Errno #foreign "wasi_snapshot_preview1" "fd_readdir" ---
fd_renumber :: (fd: FileDescriptor, to: FileDescriptor) -> Errno #foreign "wasi_snapshot_preview1" "fd_renumber" ---
-fd_seek :: (fd: FileDescriptor, offset: FileDelta, whence: Whence, newoffset: ^Filesize) -> Errno #foreign "wasi_snapshot_preview1" "fd_seek" ---
+fd_seek :: (fd: FileDescriptor, offset: FileDelta, whence: Whence, newoffset: &Filesize) -> Errno #foreign "wasi_snapshot_preview1" "fd_seek" ---
fd_sync :: (fd: FileDescriptor) -> Errno #foreign "wasi_snapshot_preview1" "fd_sync" ---
-fd_tell :: (fd: FileDescriptor, offset: ^Filesize) -> Errno #foreign "wasi_snapshot_preview1" "fd_tell" ---
-fd_write :: (fd: FileDescriptor, iovs: ^IOVec, iovs_len: Size, nwritten: ^Size) -> Errno #foreign "wasi_snapshot_preview1" "fd_write" ---
+fd_tell :: (fd: FileDescriptor, offset: &Filesize) -> Errno #foreign "wasi_snapshot_preview1" "fd_tell" ---
+fd_write :: (fd: FileDescriptor, iovs: &IOVec, iovs_len: Size, nwritten: &Size) -> Errno #foreign "wasi_snapshot_preview1" "fd_write" ---
path_create_directory :: (fd: FileDescriptor, path: str) -> Errno #foreign "wasi_snapshot_preview1" "path_create_directory" ---
-path_filestat_get :: (fd: FileDescriptor, flags: LookupFlags, path: str, buf: ^FileStat) -> Errno #foreign "wasi_snapshot_preview1" "path_filestat_get" ---
+path_filestat_get :: (fd: FileDescriptor, flags: LookupFlags, path: str, buf: &FileStat) -> Errno #foreign "wasi_snapshot_preview1" "path_filestat_get" ---
path_filestat_set_times :: (fd: FileDescriptor, flags: LookupFlags, path: str, atim: Timestamp, mtim: Timestamp, fst_flags: FSTFlags) -> Errno #foreign "wasi_snapshot_preview1" "path_filestat_set_times" ---
path_link :: (fd: FileDescriptor, old_flags: LookupFlags, old_path: str, new_fd: FileDescriptor, new_path: str) -> Errno #foreign "wasi_snapshot_preview1" "path_link" ---
, fs_rights_base: Rights
, fs_rights_inherting: Rights
, fdflags: FDFlags
- , opened_fd: ^FileDescriptor
+ , opened_fd: &FileDescriptor
) -> Errno
#foreign "wasi_snapshot_preview1" "path_open" ---
-path_readlink :: (fd: FileDescriptor, path: str, buf: ^u8, buf_len: Size, bufused: ^Size) -> Errno #foreign "wasi_snapshot_preview1" "path_readlink" ---
+path_readlink :: (fd: FileDescriptor, path: str, buf: &u8, buf_len: Size, bufused: &Size) -> Errno #foreign "wasi_snapshot_preview1" "path_readlink" ---
path_remove_directory :: (fd: FileDescriptor, path: str) -> Errno #foreign "wasi_snapshot_preview1" "path_remove_directory" ---
path_rename :: (fd: FileDescriptor, old_path: str, new_fd: FileDescriptor, new_path: str) -> Errno #foreign "wasi_snapshot_preview1" "path_rename" ---
-path_symlink :: (old_path: ^u8, old_path_len: Size, fd: FileDescriptor, new_path: str) -> Errno #foreign "wasi_snapshot_preview1" "path_symlink" ---
+path_symlink :: (old_path: &u8, old_path_len: Size, fd: FileDescriptor, new_path: str) -> Errno #foreign "wasi_snapshot_preview1" "path_symlink" ---
path_unlink_file :: (fd: FileDescriptor, path: str) -> Errno #foreign "wasi_snapshot_preview1" "path_unlink_file" ---
-poll_oneoff :: (in: ^Subscription, out: ^Event, nsubscriptions: Size, nevents: ^Size) -> Errno #foreign "wasi_snapshot_preview1" "poll_oneoff" ---
+poll_oneoff :: (in: &Subscription, out: &Event, nsubscriptions: Size, nevents: &Size) -> Errno #foreign "wasi_snapshot_preview1" "poll_oneoff" ---
proc_exit :: (rval: ExitCode) -> void #foreign "wasi_snapshot_preview1" "proc_exit" ---
proc_raise :: (sig: Signal) -> Errno #foreign "wasi_snapshot_preview1" "proc_raise" ---
sched_yield :: () -> Errno #foreign "wasi_snapshot_preview1" "sched_yield" ---
-random_get :: (buf: ^u8, buf_len: Size) -> Errno #foreign "wasi_snapshot_preview1" "random_get" ---
+random_get :: (buf: &u8, buf_len: Size) -> Errno #foreign "wasi_snapshot_preview1" "random_get" ---
-sock_recv :: (fd: FileDescriptor, ri_data: ^IOVec, ri_data_len: Size, ri_flags: RIFlags, ro_datalen: ^Size, ro_flags: ^ROFlags) -> Errno #foreign "wasi_snapshot_preview1" "sock_recv" ---
-sock_send :: (fd: FileDescriptor, si_data: ^IOVec, ri_data_len: Size, si_flags: SIFlags, so_datalen: ^Size) -> Errno #foreign "wasi_snapshot_preview1" "sock_send" ---
+sock_recv :: (fd: FileDescriptor, ri_data: &IOVec, ri_data_len: Size, ri_flags: RIFlags, ro_datalen: &Size, ro_flags: &ROFlags) -> Errno #foreign "wasi_snapshot_preview1" "sock_recv" ---
+sock_send :: (fd: FileDescriptor, si_data: &IOVec, ri_data_len: Size, si_flags: SIFlags, so_datalen: &Size) -> Errno #foreign "wasi_snapshot_preview1" "sock_send" ---
sock_shutdown :: (fd: FileDescriptor, how: SDFlags) -> Errno #foreign "wasi_snapshot_preview1" "sock_shutdown" ---
rights,
rights,
fd_flags,
- ^file.fd);
+ &file.fd);
err == .Success {
return file, .None;
}
return .None;
}
-__file_stat :: (path: str, out: ^os.FileStat) -> bool {
+__file_stat :: (path: str, out: &os.FileStat) -> bool {
fs: wasi.FileStat;
exists := false;
for .[3, 4] { // Trying both preopened directories
- err := wasi.path_filestat_get(it, .SymLinkFollow, path, ^fs);
+ err := wasi.path_filestat_get(it, .SymLinkFollow, path, &fs);
if err == .Success {
exists = true;
out.size = ~~ fs.size;
exists := false;
for .[3, 4] { // Trying both preopened directories
- err := wasi.path_filestat_get(it, .SymLinkFollow, path, ^fs);
+ err := wasi.path_filestat_get(it, .SymLinkFollow, path, &fs);
if err == .Success do exists = true;
}
}
__file_stream_vtable := io.Stream_Vtable.{
- seek = (use fs: ^os.File, to: i32, whence: io.SeekFrom) -> io.Error {
+ seek = (use fs: &os.File, to: i32, whence: io.SeekFrom) -> io.Error {
// Currently, the new offset is just ignored.
newoffset : wasi.Filesize;
- error := wasi.fd_seek(data.fd, ~~ to, ~~ whence, ^newoffset);
+ error := wasi.fd_seek(data.fd, ~~ to, ~~ whence, &newoffset);
if error != .Success do return .BadFile;
return .None;
},
- tell = (use fs: ^os.File) -> (io.Error, u32) {
+ tell = (use fs: &os.File) -> (io.Error, u32) {
location : wasi.Filesize;
- error := wasi.fd_tell(data.fd, ^location);
+ error := wasi.fd_tell(data.fd, &location);
if error != .Success do return .BadFile, 0;
return .None, ~~location;
},
- read = (use fs: ^os.File, buffer: [] u8) -> (io.Error, u32) {
+ read = (use fs: &os.File, buffer: [] u8) -> (io.Error, u32) {
bytes_read : wasi.Size;
vec := IOVec.{ buf = cast(u32) buffer.data, len = buffer.count };
- error := wasi.fd_read(data.fd, ^vec, 1, ^bytes_read);
+ error := wasi.fd_read(data.fd, &vec, 1, &bytes_read);
if error != .Success do return .BadFile, 0;
return .None, bytes_read;
},
- read_at = (use fs: ^os.File, at: u32, buffer: [] u8) -> (io.Error, u32) {
+ read_at = (use fs: &os.File, at: u32, buffer: [] u8) -> (io.Error, u32) {
bytes_read : wasi.Size;
vec := IOVec.{ buf = cast(u32) buffer.data, len = buffer.count };
- error := wasi.fd_pread(data.fd, ^vec, 1, ~~at, ^bytes_read);
+ error := wasi.fd_pread(data.fd, &vec, 1, ~~at, &bytes_read);
// FIX: Maybe report io.Error.OutOfBounds if the 'at' was out of bounds?
if error != .Success do return .BadFile, 0;
return .None, bytes_read;
},
- read_byte = (use fs: ^os.File) -> (io.Error, u8) {
+ read_byte = (use fs: &os.File) -> (io.Error, u8) {
bytes_read : wasi.Size;
byte : u8;
- vec := IOVec.{ buf = cast(u32) ^byte, len = 1};
- error := wasi.fd_read(data.fd, ^vec, 1, ^bytes_read);
+ vec := IOVec.{ buf = cast(u32) &byte, len = 1};
+ error := wasi.fd_read(data.fd, &vec, 1, &bytes_read);
if error != .Success do return .BadFile, 0;
return .None, byte;
},
- write = (use fs: ^os.File, buffer: [] u8) -> (io.Error, u32) {
+ write = (use fs: &os.File, buffer: [] u8) -> (io.Error, u32) {
bytes_written : wasi.Size;
vec := IOVec.{ buf = cast(u32) buffer.data, len = buffer.count };
- error := wasi.fd_write(data.fd, ^vec, 1, ^bytes_written);
+ error := wasi.fd_write(data.fd, &vec, 1, &bytes_written);
if error != .Success do return .BadFile, 0;
return .None, bytes_written;
},
- write_at = (use fs: ^os.File, at: u32, buffer: [] u8) -> (io.Error, u32) {
+ write_at = (use fs: &os.File, at: u32, buffer: [] u8) -> (io.Error, u32) {
bytes_written : wasi.Size;
vec := IOVec.{ buf = cast(u32) buffer.data, len = buffer.count };
- error := wasi.fd_pwrite(data.fd, ^vec, 1, ~~at, ^bytes_written);
+ error := wasi.fd_pwrite(data.fd, &vec, 1, ~~at, &bytes_written);
// FIX: Maybe report io.Error.OutOfBounds if the 'at' was out of bounds?
if error != .Success do return .BadFile, 0;
return .None, bytes_written;
},
- write_byte = (use fs: ^os.File, byte: u8) -> io.Error {
+ write_byte = (use fs: &os.File, byte: u8) -> io.Error {
bytes_written : wasi.Size;
byte_to_write := byte;
- vec := IOVec.{ buf = cast(u32) ^byte_to_write, len = 1 };
- error := wasi.fd_write(data.fd, ^vec, 1, ^bytes_written);
+ vec := IOVec.{ buf = cast(u32) &byte_to_write, len = 1 };
+ error := wasi.fd_write(data.fd, &vec, 1, &bytes_written);
if error != .Success do return .BadFile;
return .None;
},
- close = (use fs: ^os.File) -> io.Error {
+ close = (use fs: &os.File) -> io.Error {
__file_close(data);
return .None;
},
- flush = (use fs: ^os.File) -> io.Error {
+ flush = (use fs: &os.File) -> io.Error {
wasi.fd_datasync(data.fd);
return .None;
},
- size = (use fs: ^os.File) -> i32 {
+ size = (use fs: &os.File) -> i32 {
file_stat: FileStat;
- if wasi.fd_filestat_get(data.fd, ^file_stat) != .Success do return 0;
+ if wasi.fd_filestat_get(data.fd, &file_stat) != .Success do return 0;
return ~~ file_stat.size;
},
last_cookie: wasi.DirCookie;
}
-DirectoryData :: ^WasiDirectory;
+DirectoryData :: &WasiDirectory;
-__dir_open :: (path: str, dir: ^DirectoryData) -> bool {
+__dir_open :: (path: str, dir: &DirectoryData) -> bool {
dir_fd: FileDescriptor;
- err := wasi.path_open(4, .SymLinkFollow, path, .Directory, ~~0xffffffff, ~~0xffffffff, .Sync, ^dir_fd);
+ err := wasi.path_open(4, .SymLinkFollow, path, .Directory, ~~0xffffffff, ~~0xffffffff, .Sync, &dir_fd);
if err != .Success {
return false;
}
cfree(dir);
}
-__dir_read :: (dir: DirectoryData, out_entry: ^os.DirectoryEntry) -> bool {
+__dir_read :: (dir: DirectoryData, out_entry: &os.DirectoryEntry) -> bool {
buffer: [512] u8;
bufused: u32;
- err := wasi.fd_readdir(dir.dir_fd, ~~buffer, 512, dir.last_cookie, ^bufused);
+ err := wasi.fd_readdir(dir.dir_fd, ~~buffer, 512, dir.last_cookie, &bufused);
if err != .Success || bufused == 0 do return false;
- dirent := cast(^wasi.DirEnt) buffer;
+ dirent := cast(&wasi.DirEnt) buffer;
switch dirent.d_type {
case .Unknown do out_entry.type = .Unknown;
case .BlockDevice do out_entry.type = .Block;
out_entry.identifier = ~~dirent.d_ino;
out_entry.name_length = dirent.d_namlen;
- memory.set(~~^out_entry.name_data, 0, 256);
- memory.copy(~~^out_entry.name_data, ~~(dirent + 1), math.min(dirent.d_namlen, sizeof typeof out_entry.name_data));
+ memory.set(~~&out_entry.name_data, 0, 256);
+ memory.copy(~~&out_entry.name_data, ~~(dirent + 1), math.min(dirent.d_namlen, sizeof typeof out_entry.name_data));
dir.last_cookie = dirent.d_next;
return true;
use core {math}
String_Buffer :: struct {
- data : ^u8;
+ data : &u8;
count : u32;
capacity : u32;
}
return buffer;
}
-buffer_insert :: (use buffer: ^String_Buffer, position: i32, ch: u8) -> bool {
+buffer_insert :: (use buffer: &String_Buffer, position: i32, ch: u8) -> bool {
if position >= capacity do return false;
if count >= capacity do return false;
return true;
}
-buffer_append :: (use buffer: ^String_Buffer, end: str) -> bool {
+buffer_append :: (use buffer: &String_Buffer, end: str) -> bool {
if count + end.count > capacity do return false;
for i: end.count {
return true;
}
-buffer_delete :: (use buffer: ^String_Buffer, position: i32) -> bool {
+buffer_delete :: (use buffer: &String_Buffer, position: i32) -> bool {
if position > capacity do return false;
if position > count do return false;
if count == 0 do return false;
return true;
}
-buffer_clear :: (use buffer: ^String_Buffer) {
+buffer_clear :: (use buffer: &String_Buffer) {
count = 0;
}
-buffer_to_str :: (use buffer: ^String_Buffer) -> str do return .{data, count};
\ No newline at end of file
+buffer_to_str :: (use buffer: &String_Buffer) -> str do return .{data, count};
\ No newline at end of file
len1 := length(s1);
len2 := length(s2);
- data := cast(^u8) raw_alloc(allocator, len1 + len2);
+ data := cast(&u8) raw_alloc(allocator, len1 + len2);
memory.copy(data, s1.data, len1);
memory.copy(data + len1, s2.data, len2);
total_length := 0;
for s: strings do total_length += s.count;
- data := cast(^u8) raw_alloc(allocator, total_length);
+ data := cast(&u8) raw_alloc(allocator, total_length);
offset := 0;
for s: strings {
memory.copy(data + offset, s.data, s.count);
}
#overload
-concat :: (into: ^[..] u8, strings: ..str) -> str {
+concat :: (into: &[..] u8, strings: ..str) -> str {
for s: strings {
array.ensure_capacity(into, into.count + s.count);
memory.copy(into.data + into.count, s.data, s.count);
i := 0;
for strs {
if !#first {
- core.memory.copy(^out.data[i], sep.data, sep.count);
+ core.memory.copy(&out.data[i], sep.data, sep.count);
i += sep.count;
}
- core.memory.copy(^out.data[i], it.data, it.count);
+ core.memory.copy(&out.data[i], it.data, it.count);
i += it.count;
}
strip_whitespace :: #match #local {}
#overload
-strip_whitespace :: (s: ^str) {
+strip_whitespace :: (s: &str) {
strip_leading_whitespace(s);
strip_trailing_whitespace(s);
}
strip_leading_whitespace :: #match #local {}
#overload
-strip_leading_whitespace :: (s: ^str) {
+strip_leading_whitespace :: (s: &str) {
while s.count > 0 do switch s.data[0] {
case #char " ", #char "\t", #char "\n", #char "\r" {
s.data += 1;
#overload
strip_leading_whitespace :: (s: str) -> str {
out := s;
- strip_leading_whitespace(^out);
+ strip_leading_whitespace(&out);
return out;
}
strip_trailing_whitespace :: #match #local {}
#overload
-strip_trailing_whitespace :: (s: ^str) {
+strip_trailing_whitespace :: (s: &str) {
while s.count >= 1 do switch s.data[s.count - 1] {
case #char " ", #char "\t", #char "\n", #char "\r" {
s.count -= 1;
#overload
strip_trailing_whitespace :: (s: str) -> str {
out := s;
- strip_trailing_whitespace(^out);
+ strip_trailing_whitespace(&out);
return out;
}
to_uppercase :: (s: str) -> str {
- for^ ch: s {
+ for& ch: s {
if *ch >= #char "a" && *ch <= #char "z" {
*ch -= 32;
}
}
to_lowercase :: (s: str) -> str {
- for^ ch: s {
+ for& ch: s {
if *ch >= #char "A" && *ch <= #char "Z" {
*ch += 32;
}
trim_start :: #match #local {}
#overload
-trim_start :: (s: ^str, char: u8) {
+trim_start :: (s: &str, char: u8) {
while s.data[0] == char {
s.data += 1;
s.count -= 1;
#overload
trim_start :: (s: str, char: u8) -> str {
out := s;
- trim_start(^out, char);
+ trim_start(&out, char);
return out;
}
trim_end :: #match #local {}
#overload
-trim_end :: (s: ^str, char: u8) {
+trim_end :: (s: &str, char: u8) {
while s.data[s.count - 1] == char {
s.count -= 1;
}
#overload
trim_end :: (s: str, char: u8) -> str {
out := s;
- trim_end(^out, char);
+ trim_end(&out, char);
return out;
}
advance :: #match #local {}
#overload
-advance :: (s: ^str, chars := 1) {
+advance :: (s: &str, chars := 1) {
chars = math.min(chars, s.count);
s.data += chars;
}
replace :: (s: str, to_replace: u8, replace_with: u8) {
- for ^c: s {
+ for &c: s {
if *c == to_replace do *c = replace_with;
}
}
read_until :: #match #local {}
#overload
-read_until :: (s: ^str, upto: u8, skip := 0) -> str {
+read_until :: (s: &str, upto: u8, skip := 0) -> str {
if s.count == 0 do return "";
out : str;
}
#overload
-read_until :: (s: ^str, upto: str, skip := 0) -> str {
+read_until :: (s: &str, upto: str, skip := 0) -> str {
if s.count == 0 do return "";
out := str.{ data = s.data };
return out;
}
-read_alphanum :: (s: ^str) -> str {
+read_alphanum :: (s: &str) -> str {
if s.count == 0 do return "";
out : str;
return out;
}
-read_until_any :: (s: ^str, skip: u32, uptos: ..u8) -> str {
+read_until_any :: (s: &str, skip: u32, uptos: ..u8) -> str {
if s.count == 0 do return "";
out : str;
return out;
}
-advance_line :: (s: ^str) {
+advance_line :: (s: &str) {
if s.count == 0 do return;
adv := 0;
delim_count := 0;
for i: 0 .. s.count do if s[i] == delim do delim_count += 1;
- strarr := cast(^str) raw_alloc(allocator, sizeof str * (delim_count + 1));
+ strarr := cast(&str) raw_alloc(allocator, sizeof str * (delim_count + 1));
curr_str := 0;
begin := 0;
#overload
split_iter :: (s: str, delim: u8) -> Iterator(str) {
return iter.generator(
- ^.{ s = s, delim = delim },
+ &.{ s = s, delim = delim },
- (ctx: ^$T) -> (str, bool) {
+ (ctx: &$T) -> (str, bool) {
if string.empty(ctx.s) {
return "", false;
}
#overload
split_iter :: (s: str, delim: str) -> Iterator(str) {
return iter.generator(
- ^.{ s = s, delim = delim },
+ &.{ s = s, delim = delim },
- (ctx: ^$T) -> (str, bool) {
+ (ctx: &$T) -> (str, bool) {
if string.empty(ctx.s) {
return "", false;
}
//
// Copies a string into the pool, returning the copied string.
-pool_add :: (sp: ^StringPool, s: str) -> str {
+pool_add :: (sp: &StringPool, s: str) -> str {
if s.count > sp.arena.arena_size do return "";
- allocator := alloc.as_allocator(^sp.arena);
+ allocator := alloc.as_allocator(&sp.arena);
new_str := make(str, s.count, allocator);
memory.copy(new_str.data, s.data, s.count);
//
// Clears all entries in the pool.
-pool_flush :: (sp: ^StringPool) {
- arena.clear(^sp.arena);
+pool_flush :: (sp: &StringPool) {
+ arena.clear(&sp.arena);
}
//
// Completely frees all memory in the pool.
-pool_free :: (sp: ^StringPool) {
- arena.free(^sp.arena);
+pool_free :: (sp: &StringPool) {
+ arena.free(&sp.arena);
}
#overload
//
// Initializes a new generational barrier with `thread_count` threads.
-barrier_init :: (b: ^Barrier, thread_count: i32) {
- mutex_init(^b.mutex);
- condition_init(^b.cond);
+barrier_init :: (b: &Barrier, thread_count: i32) {
+ mutex_init(&b.mutex);
+ condition_init(&b.cond);
b.index = 0;
b.generation = 0;
//
// Destroys a generational barrier.
-barrier_destroy :: (b: ^Barrier) {
- mutex_destroy(^b.mutex);
- condition_destroy(^b.cond);
+barrier_destroy :: (b: &Barrier) {
+ mutex_destroy(&b.mutex);
+ condition_destroy(&b.cond);
}
//
// Signals that a thread has reached the barrier.
// The last thread to reach the barrier will wake up all other threads.
-barrier_wait :: (b: ^Barrier) {
- mutex_lock(^b.mutex);
- defer mutex_unlock(^b.mutex);
+barrier_wait :: (b: &Barrier) {
+ mutex_lock(&b.mutex);
+ defer mutex_unlock(&b.mutex);
local_gen := b.generation;
b.index += 1;
if b.index < b.thread_count {
while local_gen == b.generation && b.index < b.thread_count {
- condition_wait(^b.cond, ^b.mutex);
+ condition_wait(&b.cond, &b.mutex);
}
return;
}
b.index = 0;
b.generation += 1;
- condition_broadcast(^b.cond);
+ condition_broadcast(&b.cond);
return;
}
Condition_Variable :: struct {
Node :: struct {
semaphore : Semaphore;
- next : ^Node;
+ next : &Node;
}
mutex: Mutex;
- queue: ^Node;
+ queue: &Node;
}
//
// Initializes a new condition variable.
-condition_init :: (c: ^Condition_Variable) {
- mutex_init(^c.mutex);
+condition_init :: (c: &Condition_Variable) {
+ mutex_init(&c.mutex);
c.queue = null;
}
//
// Destroys a condition variable.
-condition_destroy :: (c: ^Condition_Variable) {
+condition_destroy :: (c: &Condition_Variable) {
if c.queue != null do condition_broadcast(c);
- mutex_destroy(^c.mutex);
+ mutex_destroy(&c.mutex);
}
//
// Enters the thread in the wait-queue of the condition variable.
// If `m` is not null, the mutex will first be released before
// entering the queue, and then relocked before returning.
-condition_wait :: (c: ^Condition_Variable, m: ^Mutex) {
+condition_wait :: (c: &Condition_Variable, m: &Mutex) {
node: Condition_Variable.Node;
- mutex_lock(^c.mutex);
+ mutex_lock(&c.mutex);
node.next = c.queue;
- c.queue = ^node;
- semaphore_init(^node.semaphore, 0);
- mutex_unlock(^c.mutex);
+ c.queue = &node;
+ semaphore_init(&node.semaphore, 0);
+ mutex_unlock(&c.mutex);
if m != null do mutex_unlock(m);
- semaphore_wait(^node.semaphore);
+ semaphore_wait(&node.semaphore);
if m != null do mutex_lock(m);
}
//
// Wakes up one thread from the wait-queue.
-condition_signal :: (c: ^Condition_Variable) {
- scoped_mutex(^c.mutex);
+condition_signal :: (c: &Condition_Variable) {
+ scoped_mutex(&c.mutex);
if c.queue != null {
- semaphore_post(^c.queue.semaphore);
+ semaphore_post(&c.queue.semaphore);
c.queue = c.queue.next;
}
}
//
// Wakes up all threads from the wait-queue.
-condition_broadcast :: (c: ^Condition_Variable) {
- scoped_mutex(^c.mutex);
+condition_broadcast :: (c: &Condition_Variable) {
+ scoped_mutex(&c.mutex);
while c.queue != null {
- semaphore_post(^c.queue.semaphore);
+ semaphore_post(&c.queue.semaphore);
c.queue = c.queue.next;
}
}
//
// Initializes a new mutex.
-mutex_init :: (m: ^Mutex) {
+mutex_init :: (m: &Mutex) {
m.lock = 0;
m.owner = -1;
}
//
// Destroys a mutex.
-mutex_destroy :: (m: ^Mutex) {
+mutex_destroy :: (m: &Mutex) {
m.lock = -1;
m.owner = -1;
}
// this function enters a spin loop until the mutex is unlocked.
// In a JavaScript based implementation, the __atomic_wait intrinsic
// is used to avoid having to spin loop.
-mutex_lock :: (m: ^Mutex) {
- while __atomic_cmpxchg(^m.lock, 0, 1) == 1 {
+mutex_lock :: (m: &Mutex) {
+ while __atomic_cmpxchg(&m.lock, 0, 1) == 1 {
if m.owner == context.thread_id do return;
#if runtime.Wait_Notify_Available {
// makes waiting for a mutex expensive because the only option
// is to do a spin-lock. Ugh.
if context.thread_id != 0 {
- __atomic_wait(^m.lock, 1);
+ __atomic_wait(&m.lock, 1);
}
} else {
while (m.lock == 1) ---
// Unlocks a mutex, if the calling thread currently holds the mutex.
// In a JavaScript based implementation, the __atomic_notify intrinsic
// is used to wake up one waiting thread.
-mutex_unlock :: (m: ^Mutex) {
+mutex_unlock :: (m: &Mutex) {
if m.owner != context.thread_id do return;
m.owner = -1;
- __atomic_store(^m.lock, 0);
+ __atomic_store(&m.lock, 0);
#if runtime.Wait_Notify_Available {
- __atomic_notify(^m.lock, maximum = 1);
+ __atomic_notify(&m.lock, maximum = 1);
}
}
// Helpful macro for making a particular block be protected by a macro.
//
// m: sync.Mutx;
-// sync.mutex_init(^m);
+// sync.mutex_init(&m);
//
// {
-// sync.scoped_mutex(^m);
+// sync.scoped_mutex(&m);
// // Everything here is done by one thread at a time.
// }
//
-scoped_mutex :: macro (m: ^Mutex) {
+scoped_mutex :: macro (m: &Mutex) {
ml :: mutex_lock
mu :: mutex_unlock
// calling scoped_mutex in the block of code given.
//
// m: sync.Mutx;
-// sync.mutex_init(^m);
+// sync.mutex_init(&m);
//
-// sync.critical_section(^m) {
+// sync.critical_section(&m) {
// // Everything here is done by one thread at a time.
// }
//
-critical_section :: macro (m: ^Mutex, body: Code) -> i32 {
+critical_section :: macro (m: &Mutex, body: Code) -> i32 {
scoped_mutex :: scoped_mutex;
scoped_mutex(m);
//
// Run a function with no arguments once.
#overload
-Once.exec :: (o: ^Once, f: () -> $R) {
- scoped_mutex(^o.mutex);
+Once.exec :: (o: &Once, f: () -> $R) {
+ scoped_mutex(&o.mutex);
if o.done do return;
o.done = true;
//
// Run a function with one argument once.
#overload
-Once.exec :: (o: ^Once, ctx: $Ctx, f: (Ctx) -> $R) {
- scoped_mutex(^o.mutex);
+Once.exec :: (o: &Once, ctx: $Ctx, f: (Ctx) -> $R) {
+ scoped_mutex(&o.mutex);
if o.done do return;
o.done = true;
//
// Initializes a semaphore with the specified value.
-semaphore_init :: (s: ^Semaphore, value: i32) {
+semaphore_init :: (s: &Semaphore, value: i32) {
s.counter = value;
- mutex_init(^s.mutex);
+ mutex_init(&s.mutex);
}
//
// Destroys a semaphore.
-semaphore_destroy :: (s: ^Semaphore) {
- mutex_destroy(^s.mutex);
+semaphore_destroy :: (s: &Semaphore) {
+ mutex_destroy(&s.mutex);
}
//
// Increment the counter in a semaphore by `count`.
-semaphore_post :: (s: ^Semaphore, count := 1) {
+semaphore_post :: (s: &Semaphore, count := 1) {
if count == 0 do return;
- scoped_mutex(^s.mutex);
+ scoped_mutex(&s.mutex);
s.counter += count;
// @Bug
// This is susceptible to starvation. Semaphores should have a queue
// or something like that.
#if runtime.Wait_Notify_Available {
- __atomic_notify(^s.counter, maximum = count);
+ __atomic_notify(&s.counter, maximum = count);
}
}
//
// Waits until the thread is able to decrement one from the semaphore.
-semaphore_wait :: (s: ^Semaphore) {
+semaphore_wait :: (s: &Semaphore) {
while true {
- mutex_lock(^s.mutex);
+ mutex_lock(&s.mutex);
if s.counter > 0 {
s.counter -= 1;
- mutex_unlock(^s.mutex);
+ mutex_unlock(&s.mutex);
return;
} else {
- mutex_unlock(^s.mutex);
+ mutex_unlock(&s.mutex);
#if runtime.Wait_Notify_Available {
- __atomic_wait(^s.counter, 0);
+ __atomic_wait(&s.counter, 0);
}
}
}
You can either use just the type name:
@core.test.test
- (t: ^core.test.T) {
+ (t: &core.test.T) {
}
Or you can specify a name using the full struct literal:
@core.test.test.{"Important test name"}
- (t: ^core.test.T) {
+ (t: &core.test.T) {
}
"""
test :: struct {
#doc "Testing context"
T :: struct {
- current_test_case: ^Test_Case;
+ current_test_case: &Test_Case;
}
#inject
-T.assert :: (t: ^T, cond: bool, name := "", site := #callsite) {
+T.assert :: (t: &T, cond: bool, name := "", site := #callsite) {
t.current_test_case.assertions << .{
name, cond, site
};
ctx: T;
cases := gather_test_cases(packages);
- defer delete(^cases);
+ defer delete(&cases);
- failed_cases := make([..] ^Test_Case);
+ failed_cases := make([..] &Test_Case);
if log do printf("Running {} test cases...\n", cases.count);
- for ^ cases {
+ for & cases {
ctx.current_test_case = it;
// Assume the test case passed until it didn't.
it.passed = true;
- it.runner(^ctx);
+ it.runner(&ctx);
if !it.passed {
failed_cases << it;
for failed_cases {
printf("[{}]\n", it.name if !string.empty(it.name) else "Unnamed test");
- for ^ it.assertions {
+ for & it.assertions {
if it.passed do continue;
printf(" {} at {}:{}\n",
//
#local
-runner_proc :: #type (^T) -> void;
+runner_proc :: #type (&T) -> void;
#local
Test_Case :: struct {
name: str;
- runner: (^T) -> void;
+ runner: (&T) -> void;
passed := false;
assertions: [..] Assertion = make([..] Assertion);
result := make([..] Test_Case);
procs1 := runtime.info.get_procedures_with_tag(test);
- defer delete(^procs1);
+ defer delete(&procs1);
for procs1 {
if packages.count == 0 || array.contains(packages, it.pack) {
- result << .{it.tag.name, *cast(^runner_proc) ^it.func};
+ result << .{it.tag.name, *cast(&runner_proc) &it.func};
}
}
procs2 := runtime.info.get_procedures_with_tag(type_expr);
- defer delete(^procs2);
+ defer delete(&procs2);
for procs2 {
if packages.count != 0 && !array.contains(packages, it.pack) do continue;
if *it.tag == test {
- tag := cast(^test) it.tag;
- result << .{"", *cast(^runner_proc) ^it.func};
+ tag := cast(&test) it.tag;
+ result << .{"", *cast(&runner_proc) &it.func};
}
}
#package {
thread_mutex : sync.Mutex;
next_thread_id := 1;
- thread_map : Map(Thread_ID, ^Thread);
+ thread_map : Map(Thread_ID, &Thread);
}
//
// storage and stack for the new thread, and pass those on.
// Currently the stack size is not controllable, but that could
// be remedied.
-spawn :: (t: ^Thread, data: ^$T, func: (^T) -> void) {
- sync.scoped_mutex(^thread_mutex);
+spawn :: (t: &Thread, data: &$T, func: (&T) -> void) {
+ sync.scoped_mutex(&thread_mutex);
t.id = next_thread_id;
t.alive = true;
// Waits for a thread to finish before returning.
// If the thread was not alive in the first place,
// immediately return.
-join :: (t: ^Thread) {
+join :: (t: &Thread) {
while t.alive {
#if runtime.Wait_Notify_Available {
- __atomic_wait(^t.id, t.id);
+ __atomic_wait(&t.id, t.id);
} else {
// To not completely kill the CPU.
runtime.platform.__sleep(1);
//
// Forcefully kill a thread using runtime.__kill_thread.
// Does nothing if the thread was not alive.
-kill :: (t: ^Thread) -> i32 {
+kill :: (t: &Thread) -> i32 {
if !t.alive do return -1;
ret := runtime.platform.__kill_thread(t.id);
// Special procedure that is called when a thread exits,
// or by kill() above.
__exited :: (id: i32) {
- sync.scoped_mutex(^thread_mutex);
+ sync.scoped_mutex(&thread_mutex);
thread := thread_map->get(id);
if thread != null {
thread.alive = false;
#if runtime.Wait_Notify_Available {
- __atomic_notify(^thread.id);
+ __atomic_notify(&thread.id);
}
thread_map->delete(id);
}
@conv.Custom_Format_Proc.{ Date }
-(output: ^conv.Format_Output, format: ^conv.Format, date: ^Date) {
+(output: &conv.Format_Output, format: &conv.Format, date: &Date) {
conv.format(output, "{}-{w2}-{w2}", date.year, date.month + 1, date.day);
}
@conv.Custom_Parse_Proc.{ Date }
-(d: ^Date, text: str, _: Allocator) -> bool {
+(d: &Date, text: str, _: Allocator) -> bool {
year, t := string.bisect(text, #char "-");
month, t' := string.bisect(t, #char "-");
day, t' := string.bisect(t, #char "-");
}
@conv.Custom_Format_Proc.{ Timestamp }
-(output: ^conv.Format_Output, format: ^conv.Format, time: ^Timestamp) {
+(output: &conv.Format_Output, format: &conv.Format, time: &Timestamp) {
time_buf: [64] u8;
to_output := strftime(time_buf, "%Y-%m-%d %H:%M:%S", time);
}
@conv.Custom_Parse_Proc.{ Timestamp }
-(time: ^Timestamp, data: str, _: Allocator) -> bool {
+(time: &Timestamp, data: str, _: Allocator) -> bool {
return strptime(data, "%Y-%m-%d %H:%M:%S", time);
}
#overload
localtime :: (seconds: u64) -> Timestamp {
t: Timestamp;
- __time_localtime(seconds, ^t);
+ __time_localtime(seconds, &t);
return t;
}
#overload
gmtime :: (seconds: u64) -> Timestamp {
t: Timestamp;
- __time_gmtime(seconds, ^t);
+ __time_gmtime(seconds, &t);
return t;
}
-strftime :: (buf: [] u8, format: [] u8, tm: ^Timestamp) -> str {
+strftime :: (buf: [] u8, format: [] u8, tm: &Timestamp) -> str {
f := cast(cstr) core.alloc.from_stack(format.length + 1);
core.memory.copy(f, format.data, format.length);
f[format.length] = 0;
return buf[0..len];
}
-strptime :: (buf_: [] u8, format_: [] u8, tm: ^Timestamp) -> bool {
+strptime :: (buf_: [] u8, format_: [] u8, tm: &Timestamp) -> bool {
use core
#persist weekdays := str.[ "sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday" ];
c := format[0];
switch c {
case #char "%" {
- string.advance(^format);
+ string.advance(&format);
switch format[0] {
case #char "a", #char "A" {
for i: weekdays.count {
w := weekdays[i];
if string.equal_insensitive(w, buf[0 .. w.length]) {
- string.advance(^buf, w.length);
+ string.advance(&buf, w.length);
tm.wday = i;
break break;
} elseif string.equal_insensitive(w[0 .. 3], buf[0 .. 3]) {
- string.advance(^buf, 3);
+ string.advance(&buf, 3);
tm.wday = i;
break break;
}
for i: monthnames.count {
m := monthnames[i];
if string.equal_insensitive(m, buf[0 .. m.length]) {
- string.advance(^buf, m.length);
+ string.advance(&buf, m.length);
tm.mon = i;
break break;
} elseif string.equal_insensitive(m[0 .. 3], buf[0 .. 3]) {
- string.advance(^buf, 3);
+ string.advance(&buf, 3);
tm.mon = i;
break break;
}
}
case #char "d", #char "e" {
- working = parse_number_and_advance(^buf, ^tm.mday, 1, 31, 0);
+ working = parse_number_and_advance(&buf, &tm.mday, 1, 31, 0);
}
case #char "D" {
- working = parse_number_and_advance(^buf, ^tm.mon, 1, 12, -1);
+ working = parse_number_and_advance(&buf, &tm.mon, 1, 12, -1);
if !working do break;
if buf[0] == #char "/" {
- string.advance(^buf);
- working = parse_number_and_advance(^buf, ^tm.mday, 1, 31, 0);
+ string.advance(&buf);
+ working = parse_number_and_advance(&buf, &tm.mday, 1, 31, 0);
if !working do break;
if buf[0] == #char "/" {
- string.advance(^buf);
- working = parse_number_and_advance(^buf, ^tm.year, 0, 99, 0);
+ string.advance(&buf);
+ working = parse_number_and_advance(&buf, &tm.year, 0, 99, 0);
if working && tm.year < 69 {
tm.year += 100;
}
}
}
- case #char "H" do working = parse_number_and_advance(^buf, ^tm.hour, 0, 23, 0);
- case #char "I" do working = parse_number_and_advance(^buf, ^tm.hour, 1, 12, 0);
- case #char "j" do working = parse_number_and_advance(^buf, ^tm.yday, 1, 366, -1);
- case #char "m" do working = parse_number_and_advance(^buf, ^tm.mon, 1, 12, -1);
- case #char "M" do working = parse_number_and_advance(^buf, ^tm.min, 0, 59, 0);
- case #char "n", #char "t" do string.strip_leading_whitespace(^buf);
+ case #char "H" do working = parse_number_and_advance(&buf, &tm.hour, 0, 23, 0);
+ case #char "I" do working = parse_number_and_advance(&buf, &tm.hour, 1, 12, 0);
+ case #char "j" do working = parse_number_and_advance(&buf, &tm.yday, 1, 366, -1);
+ case #char "m" do working = parse_number_and_advance(&buf, &tm.mon, 1, 12, -1);
+ case #char "M" do working = parse_number_and_advance(&buf, &tm.min, 0, 59, 0);
+ case #char "n", #char "t" do string.strip_leading_whitespace(&buf);
case #char "p" {
if string.equal_insensitive(buf[0 .. 2], "am") {
if tm.hour == 12 do tm.hour = 0;
- string.advance(^buf, 2);
+ string.advance(&buf, 2);
} elseif string.equal_insensitive(buf[0 .. 2], "pm") {
if tm.hour < 12 do tm.hour += 12;
- string.advance(^buf, 2);
+ string.advance(&buf, 2);
} else {
working = false;
}
case #char "r" {
- working = parse_number_and_advance(^buf, ^tm.hour, 1, 12, 0);
+ working = parse_number_and_advance(&buf, &tm.hour, 1, 12, 0);
if !working do break;
if buf[0] == #char ":" {
- string.advance(^buf);
+ string.advance(&buf);
- working = parse_number_and_advance(^buf, ^tm.min, 0, 59, 0);
+ working = parse_number_and_advance(&buf, &tm.min, 0, 59, 0);
if !working do break;
if buf[0] == #char ":" {
- string.advance(^buf);
+ string.advance(&buf);
- working = parse_number_and_advance(^buf, ^tm.sec, 0, 59, 0);
+ working = parse_number_and_advance(&buf, &tm.sec, 0, 59, 0);
if !working do break;
- string.strip_leading_whitespace(^buf);
+ string.strip_leading_whitespace(&buf);
if string.equal_insensitive(buf[0 .. 2], "am") {
if tm.hour == 12 do tm.hour = 0;
- string.advance(^buf, 2);
+ string.advance(&buf, 2);
} elseif string.equal_insensitive(buf[0 .. 2], "pm") {
if tm.hour < 12 do tm.hour += 12;
- string.advance(^buf, 2);
+ string.advance(&buf, 2);
} else {
working = false;
}
case #char "R" {
- working = parse_number_and_advance(^buf, ^tm.hour, 1, 12, 0);
+ working = parse_number_and_advance(&buf, &tm.hour, 1, 12, 0);
if !working do break;
if buf[0] == #char ":" {
- string.advance(^buf);
+ string.advance(&buf);
- working = parse_number_and_advance(^buf, ^tm.min, 0, 59, 0);
+ working = parse_number_and_advance(&buf, &tm.min, 0, 59, 0);
}
}
- case #char "S" do working = parse_number_and_advance(^buf, ^tm.sec, 0, 59, 0);
+ case #char "S" do working = parse_number_and_advance(&buf, &tm.sec, 0, 59, 0);
case #char "T" {
- working = parse_number_and_advance(^buf, ^tm.hour, 1, 12, 0);
+ working = parse_number_and_advance(&buf, &tm.hour, 1, 12, 0);
if !working do break;
if buf[0] == #char ":" {
- string.advance(^buf);
+ string.advance(&buf);
- working = parse_number_and_advance(^buf, ^tm.min, 0, 59, 0);
+ working = parse_number_and_advance(&buf, &tm.min, 0, 59, 0);
if !working do break;
if buf[0] == #char ":" {
- string.advance(^buf);
+ string.advance(&buf);
- working = parse_number_and_advance(^buf, ^tm.sec, 0, 59, 0);
+ working = parse_number_and_advance(&buf, &tm.sec, 0, 59, 0);
}
}
}
- case #char "w" do working = parse_number_and_advance(^buf, ^tm.wday, 0, 6, 0);
- case #char "Y" do working = parse_number_and_advance(^buf, ^tm.year, 1900, 65535, -1900);
+ case #char "w" do working = parse_number_and_advance(&buf, &tm.wday, 0, 6, 0);
+ case #char "Y" do working = parse_number_and_advance(&buf, &tm.year, 1900, 65535, -1900);
case #char "y" {
- working = parse_number_and_advance(^buf, ^tm.year, 0, 99, 0);
+ working = parse_number_and_advance(&buf, &tm.year, 0, 99, 0);
if working && tm.year < 69 {
tm.year += 100;
}
if buf[0] != #char "%" {
working = false;
}
- string.advance(^buf);
+ string.advance(&buf);
}
case #default {
}
case #char " ", #char "\t", #char "\r", #char "\n", #char "\f", #char "\v" {
- string.strip_leading_whitespace(^buf);
+ string.strip_leading_whitespace(&buf);
}
case #default {
working = false;
} else {
- string.advance(^buf);
+ string.advance(&buf);
}
}
}
- string.advance(^format);
+ string.advance(&format);
}
return working;
//
// Helper function used above
- parse_number_and_advance :: (buf: ^[] u8, result: ^i32, low, high, offset: i32) -> bool {
+ parse_number_and_advance :: (buf: &[] u8, result: &i32, low, high, offset: i32) -> bool {
use core {string}
n := 0;
expected_file : str;
}
-find_onyx_files :: (root: str, cases: ^[..] Test_Case) {
+find_onyx_files :: (root: str, cases: &[..] Test_Case) {
for os.list_directory(root) {
path_buffer: [512] u8;
if string.ends_with(it->name(), ".onyx") {
}
main :: (args) => {
- arg_parse.arg_parse(args, ^settings);
- printf("Using {p*}\n", ^settings);
+ arg_parse.arg_parse(args, &settings);
+ printf("Using {p*}\n", &settings);
Execution_Context :: struct {
// The executable to use when compiling
at_least_one_test_failed := false;
compile_only := false; // @Bug // why is this necessary? why is settings.compile_only false when in the thread code?
- failed_tests: ^[..] str;
+ failed_tests: &[..] str;
failed_tests_mutex: sync.Mutex;
}
exec_context := Execution_Context.{};
exec_context.compile_only = settings.compile_only;
failed_tests := make([..] str);
- exec_context.failed_tests = ^failed_tests;
- sync.mutex_init(^exec_context.failed_tests_mutex);
+ exec_context.failed_tests = &failed_tests;
+ sync.mutex_init(&exec_context.failed_tests_mutex);
switch runtime.compiler_os {
case .Linux {
}
cases := array.make(Test_Case, capacity=256);
- find_onyx_files(settings.test_folder, ^cases);
+ find_onyx_files(settings.test_folder, &cases);
- iter.parallel_for(cases, settings.threads, ^exec_context) {
+ iter.parallel_for(cases, settings.threads, &exec_context) {
// Weird macros mean I have to forward external names
use core
print_color :: print_color;
}
proc := os.process_spawn(thread_data.onyx_cmd, args);
- defer os.process_destroy(^proc);
+ defer os.process_destroy(&proc);
- proc_reader := io.reader_make(^proc);
- output := io.read_all(^proc_reader);
- defer delete(^output);
+ proc_reader := io.reader_make(&proc);
+ output := io.read_all(&proc_reader);
+ defer delete(&output);
- if exit := os.process_wait(^proc); exit != .Success {
+ if exit := os.process_wait(&proc); exit != .Success {
// Error running the test case
print_color(.Red, "[{}] Error '{}' in test case {}.\n{}", context.thread_id, exit, it.source_file, output);
thread_data.at_least_one_test_failed = true;
- sync.critical_section(^thread_data.failed_tests_mutex) {
+ sync.critical_section(&thread_data.failed_tests_mutex) {
array.push(thread_data.failed_tests, it.source_file);
}
for expected_file: os.with_file(it.expected_file) {
expected_reader := io.reader_make(expected_file);
- expected_output := io.read_all(^expected_reader);
+ expected_output := io.read_all(&expected_reader);
if output != expected_output {
print_color(.Red, "[{}] Output did not match for {}.\n", context.thread_id, it.source_file);
printf("Got:\n{}\n", output);
thread_data.at_least_one_test_failed = true;
- sync.critical_section(^thread_data.failed_tests_mutex) {
+ sync.critical_section(&thread_data.failed_tests_mutex) {
array.push(thread_data.failed_tests, it.source_file);
}
}