standard library cleanup part 1; added time library
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 26 Aug 2022 02:49:28 +0000 (21:49 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 26 Aug 2022 02:49:28 +0000 (21:49 -0500)
18 files changed:
core/alloc/auto_heap.onyx
core/container/array.onyx
core/container/iter.onyx
core/math.onyx
core/memory.onyx
core/std.onyx
core/stdio.onyx
core/string.onyx
core/time/time.onyx [new file with mode: 0644]
include/astnodes.h
include/lex.h
src/astnodes.c
src/lex.c
src/onyx_runtime.c
src/parser.c
src/symres.c
tests/bugs/defer_block_in_macro.onyx
tests/overload_precedence.onyx

index bd8cbe0b12caf03344a13a87fe219583ad6babc6..03334251f812cf51d7a8d095908884ab760a20ab 100644 (file)
@@ -33,11 +33,16 @@ auto_heap_make :: (backing := context.allocator) -> AutoHeapState {
     return hs;
 }
 
-auto_heap_free :: (hs: ^AutoHeapState) {
+auto_heap_clear :: (hs: ^AutoHeapState) {
     for^ hs.set.entries {
         raw_free(hs.backing_allocator, it.value);
     }
 
+    hs.set->clear();
+}
+
+auto_heap_free :: (hs: ^AutoHeapState) {
+    auto_heap_clear(hs);
     hs.set->free();
 }
 
index e400b9d8973e48ea37fdc31ee265f25fce8be39f..ca36054c251570e6725593ddf70e6a19ae6b0db7 100644 (file)
@@ -12,26 +12,30 @@ package core.array
 // ---------------------------------
 //           Dynamic Arrays
 // ---------------------------------
-make :: #match #locked {
-    ($T: type_expr, capacity := 4, allocator := context.allocator) -> [..] T {
-        arr : [..] T;
-        init(^arr, capacity, allocator);
-        return arr;
-    },
-    
-    (base: [] $T, allocator := context.allocator) -> [..] T {
-        arr: [..] T;
-        init(^arr, base.count, allocator);
-        for^ base do arr << *it;
-        return arr;
-    }
+make :: #match #local {}
+
+#overload
+make :: ($T: type_expr, capacity := 4, allocator := context.allocator) -> [..] T {
+    arr : [..] T;
+    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;
+    return arr;
 }
 
-#match __make_overload macro (_: ^[..] $T, allocator := context.allocator) -> [..] T {
+#overload
+__make_overload :: macro (_: ^[..] $T, allocator := context.allocator) -> [..] T {
     return (package core.array).make(T, allocator=allocator);
 }
 
-#match __make_overload macro (_: ^[..] $T, capacity: u32, allocator := context.allocator) -> [..] T {
+#overload
+__make_overload :: macro (_: ^[..] $T, capacity: u32, allocator := context.allocator) -> [..] T {
     return (package core.array).make(T, capacity, allocator);
 }
 
@@ -50,8 +54,9 @@ free :: (arr: ^[..] $T) {
     arr.data = null;
 }
 
-#match (package builtin).delete macro (x: ^[..] $T) {
-    (package core.array).free(x);
+#overload
+builtin.delete :: macro (x: ^[..] $T) {
+    core.array.free(x);
 }
 
 copy :: #match #locked {
@@ -330,37 +335,39 @@ reverse :: (arr: [] $T) {
 // Simple insertion sort
 //    cmp should return >0 if left > right
 //
-sort :: #match #locked {
-    (arr: [] $T, cmp: (T, T) -> i32) {
-        for i: 1 .. arr.count {
-            x := arr.data[i];
-            j := i - 1;
-
-            @ShortCircuitLogicalOps // This is written this way because '&&' does not short circuit right now.
-            while j >= 0 {
-                if cmp(arr.data[j], x) > 0 {
-                    arr.data[j + 1] = arr.data[j];
-                    j -= 1;
-                } else {
-                    break;
-                }
-            }
+sort :: #match #local {}
 
-            arr.data[j + 1] = x;
+#overload
+sort :: (arr: [] $T, cmp: (T, T) -> i32) {
+    for i: 1 .. arr.count {
+        x := arr.data[i];
+        j := i - 1;
+
+        @ShortCircuitLogicalOps // This is written this way because '&&' does not short circuit right now.
+        while j >= 0 {
+            if cmp(arr.data[j], x) > 0 {
+                arr.data[j + 1] = arr.data[j];
+                j -= 1;
+            } else {
+                break;
+            }
         }
-    },
 
-    (arr: [] $T, cmp: (^T, ^T) -> i32) {
-        for i: 1 .. arr.count {
-            j := i;
-
-            while j > 0 {
-                if cmp(^arr.data[j - 1], ^arr.data[j]) > 0 {
-                    arr.data[j], arr.data[j - 1] = arr.data[j - 1], arr.data[j];
-                    j -= 1;
-                } else {
-                    break;
-                }
+        arr.data[j + 1] = x;
+    }
+}
+
+#overload
+sort :: (arr: [] $T, cmp: (^T, ^T) -> i32) {
+    for i: 1 .. arr.count {
+        j := i;
+
+        while j > 0 {
+            if cmp(^arr.data[j - 1], ^arr.data[j]) > 0 {
+                arr.data[j], arr.data[j - 1] = arr.data[j - 1], arr.data[j];
+                j -= 1;
+            } else {
+                break;
             }
         }
     }
@@ -381,34 +388,36 @@ quicksort :: #match #locked {
         quicksort_impl(arr, cmp, pivot + 1, hi);
     }
 
-    quicksort_partition :: #match #locked {
-        (arr: [] $T, cmp: (T, T) -> i32, lo, hi: i32) -> i32 {
-            pivot := arr[hi];
-            i := lo - 1;
+    quicksort_partition :: #match #local {}
+
+    #overload
+    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 {
-                    i += 1;
-                    arr[i], arr[j] = arr[j], arr[i];
-                }
+        for j: lo .. hi+1 {
+            if cmp(arr[j], pivot) <= 0 {
+                i += 1;
+                arr[i], arr[j] = arr[j], arr[i];
             }
+        }
 
-            return i;
-        },
+        return i;
+    }
 
-        (arr: [] $T, cmp: (^T, ^T) -> i32, lo, hi: i32) -> i32 {
-            pivot := ^arr[hi];
-            i := lo - 1;
+    #overload
+    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 {
-                    i += 1;
-                    arr[i], arr[j] = arr[j], arr[i];
-                }
+        for j: lo .. hi+1 {
+            if cmp(^arr[j], pivot) <= 0 {
+                i += 1;
+                arr[i], arr[j] = arr[j], arr[i];
             }
-
-            return i;
         }
+
+        return i;
     }
 }
 
index 3dc54efa5b6212af8af92a017821bc8d63a664f3..829db3b6baed1eecfcd6768ef8edfe1c01d04ad2 100644 (file)
@@ -37,8 +37,9 @@ close :: (it: Iterator($T)) {
     it.close(it.data);
 }
 
-filter :: #match {}
-#match filter (it: Iterator($T), predicate: (T) -> bool, allocator := iter_allocator) -> Iterator(T) {
+filter :: #match #local {}
+#overload
+filter :: (it: Iterator($T), predicate: (T) -> bool, allocator := iter_allocator) -> Iterator(T) {
     FilterIterator :: struct (T: type_expr) {
         iterator:  Iterator(T);
         predicate: (T) -> bool;
@@ -76,7 +77,8 @@ filter :: #match {}
     };
 }
 
-#match filter (it: Iterator($T), ctx: $Ctx, predicate: (T, Ctx) -> bool, allocator := iter_allocator) -> Iterator(T) {
+#overload
+filter :: (it: Iterator($T), ctx: $Ctx, predicate: (T, Ctx) -> bool, allocator := iter_allocator) -> Iterator(T) {
     FilterIterator :: struct (T: type_expr, Ctx: type_expr) {
         iterator:  Iterator(T);
         predicate: (T, Ctx) -> bool;
@@ -116,8 +118,10 @@ filter :: #match {}
     };
 }
 
-map :: #match {}
-#match map (it: Iterator($T), transform: (T) -> $R, allocator := iter_allocator) -> Iterator(R) {
+map :: #match #local {}
+
+#overload
+map :: (it: Iterator($T), transform: (T) -> $R, allocator := iter_allocator) -> Iterator(R) {
     MapIterator :: struct (T: type_expr, R: type_expr) {
         iterator:  Iterator(T);
         transform: (T) -> R;
@@ -148,7 +152,8 @@ map :: #match {}
     };
 }
 
-#match map (it: Iterator($T), ctx: $Ctx, transform: (T, Ctx) -> $R, allocator := iter_allocator) -> Iterator(R) {
+#overload
+map :: (it: Iterator($T), ctx: $Ctx, transform: (T, Ctx) -> $R, allocator := iter_allocator) -> Iterator(R) {
     MapIterator :: struct (T: type_expr, R: type_expr, Ctx: type_expr) {
         iterator:  Iterator(T);
         transform: (T, Ctx) -> R;
@@ -405,14 +410,17 @@ const :: (value: $T) -> Iterator(T) {
     value: T;
 }
 
-enumerate :: #match {}
-#match enumerate macro (it: $T, start_index: i32 = 0) -> #auto where Iterable(T) {
+enumerate :: #match #local {}
+
+#overload
+enumerate :: macro (it: $T, start_index: i32 = 0) -> #auto where Iterable(T) {
     as_iterator :: as_iterator
     enumerate :: enumerate
     return enumerate(as_iterator(it), start_index);
 }
 
-#match enumerate (it: Iterator($T), start_index: i32 = 0) -> Iterator(Enumeration_Value(T)) {
+#overload
+enumerate :: (it: Iterator($T), start_index: i32 = 0) -> Iterator(Enumeration_Value(T)) {
     Enumeration_Context :: struct (T: type_expr) {
         iterator:      Iterator(T);
         current_index: i32;
@@ -443,7 +451,8 @@ enumerate :: #match {}
     };
 }
 
-#match as_iterator from_array
+#overload
+as_iterator :: from_array
 from_array :: (arr: [] $T) -> Iterator(^T) {
     Context :: struct (T: type_expr) {
         data: ^T;
@@ -472,7 +481,8 @@ from_array :: (arr: [] $T) -> Iterator(^T) {
     };
 }
 
-#match as_iterator (x: ^[..] $T) -> Iterator(T) {
+#overload
+as_iterator :: (x: ^[..] $T) -> Iterator(T) {
     Context :: struct (T: type_expr) {
         arr: ^[..] T;
         current: u32;
@@ -508,7 +518,8 @@ from_array :: (arr: [] $T) -> Iterator(^T) {
     };
 }
 
-#match as_iterator (x: ^[..] $T, by_pointer: bool) -> Iterator(^T) {
+#overload
+as_iterator :: (x: ^[..] $T, by_pointer: bool) -> Iterator(^T) {
     Context :: struct (T: type_expr) {
         arr: ^[..] T;
         current: u32;
@@ -544,7 +555,8 @@ from_array :: (arr: [] $T) -> Iterator(^T) {
     };
 }
 
-#match as_iterator (r: range) -> Iterator(i32) {
+#overload
+as_iterator :: (r: range) -> Iterator(i32) {
     Context :: struct {
         r: range;
         v: i32;
@@ -579,14 +591,17 @@ from_array :: (arr: [] $T) -> Iterator(^T) {
     };
 }
 
-fold :: #match {}
+fold :: #match #local {}
+
 @Cleanup // some way to shorten this would be nice
-#match fold macro (it: $T, init: $R, combine: $S) -> #auto where Iterable(T) {
+#overload
+fold :: macro (it: $T, init: $R, combine: $S) -> #auto where Iterable(T) {
     fold :: fold
     return fold(as_iterator(it), init, combine);
 }
 
-#match fold (it: Iterator($T), initial_value: $R, combine: (T, R) -> R) -> R {
+#overload
+fold :: (it: Iterator($T), initial_value: $R, combine: (T, R) -> R) -> R {
     for value: it {
         initial_value = combine(value, initial_value);
     }
@@ -594,38 +609,47 @@ fold :: #match {}
     return initial_value;
 }
 
-count :: #match {}
-#match count macro (it: $T, cond: $F) -> #auto where Iterable(T) {
+count :: #match #local {}
+
+#overload
+count :: macro (it: $T, cond: $F) -> #auto where Iterable(T) {
     count :: count
     return count(as_iterator(it), cond);
 }
 
-#match count (it: Iterator($T), cond: (T) -> bool) -> i32 {
+#overload
+count :: (it: Iterator($T), cond: (T) -> bool) -> i32 {
     c := 0;
     for value: it do if cond(value) do c += 1;
     return c;
 }
 
-some :: #match {}
-#match some macro (it: $T, cond: $F) -> #auto where Iterable(T) {
+some :: #match #local {}
+
+#overload
+some :: macro (it: $T, cond: $F) -> #auto where Iterable(T) {
     some :: some
     as_iterator :: as_iterator
     return some(as_iterator(it), cond);
 }
 
-#match some (it: Iterator($T), cond: (T) -> bool) -> bool {
+#overload
+some :: (it: Iterator($T), cond: (T) -> bool) -> bool {
     for value: it do if cond(value) do return true;
     return false;
 }
 
-every :: #match {}
-#match every macro (it: $T, cond: $F) -> #auto where Iterable(T) {
+every :: #match #local {}
+
+#overload
+every :: macro (it: $T, cond: $F) -> #auto where Iterable(T) {
     every :: every
     as_iterator :: as_iterator
     return every(as_iterator(it), cond);
 }
 
-#match every (it: Iterator($T), cond: (T) -> bool) -> bool {
+#overload
+every :: (it: Iterator($T), cond: (T) -> bool) -> bool {
     for value: it do if !cond(value) do return false;
     return true;
 }
@@ -640,17 +664,20 @@ to_array :: (it: Iterator($T), allocator := context.allocator) -> [..] T {
 }
 
 
-#local runtime :: package runtime
 #if runtime.Multi_Threading_Enabled {
-    #local sync   :: package core.sync
-    distributor :: #match {}
-    #match distributor macro (it: $T) -> #auto where Iterable(T) {
+    #local sync :: core.sync
+
+    distributor :: #match #local {}
+
+    #overload
+    distributor :: macro (it: $T) -> #auto where Iterable(T) {
         distributor :: distributor;
         as_iterator :: as_iterator;
         return distributor(as_iterator(it));
     }
 
-    #match distributor (it: Iterator) -> Iterator(it.Iter_Type) {
+    #overload
+    distributor :: (it: Iterator) -> Iterator(it.Iter_Type) {
         Context :: struct (T: type_expr) {
             mutex: sync.Mutex;
             iterator: Iterator(T);
@@ -686,15 +713,18 @@ to_array :: (it: Iterator($T), allocator := context.allocator) -> [..] T {
         return .{c, #solidify next {T=it.Iter_Type}, #solidify close {T=it.Iter_Type}};
     }
 
-    parallel_for :: #match {}
-    #match parallel_for macro (iterable: $I, thread_count: u32, thread_data: ^$Ctx, body: Code) where Iterable(I) {
+    parallel_for :: #match #local {}
+
+    #overload
+    parallel_for :: macro (iterable: $I, thread_count: u32, thread_data: ^$Ctx, body: Code) where Iterable(I) {
         parallel_for :: parallel_for;
         as_iterator  :: as_iterator;
 
         parallel_for(as_iterator(iterable), thread_count, thread_data, body);
     }
 
-    #match parallel_for macro (iter: Iterator($T), thread_count: u32, thread_data: ^$Ctx, body: Code) {
+    #overload
+    parallel_for :: macro (iter: Iterator($T), thread_count: u32, thread_data: ^$Ctx, body: Code) {
         thread :: package core.thread;
         alloc  :: package core.alloc;
         distributor :: distributor;
index 592f86bbb621cc34f00398f1ef065c64562afdd2..a0e46fd7a3bda5e4ce6b61c9146455586f31e99a 100644 (file)
@@ -246,12 +246,12 @@ log :: (a: $T, base: $R) -> T {
 // they would be however, the fact that these overloads are intrinsic means they cannot
 // be reference from the element section and therefore cannot be passed around or used
 // as values.
-max :: #match { wasm.max_f32, wasm.max_f64, max_poly }
+max :: #match #local { wasm.max_f32, wasm.max_f64, max_poly }
 max_poly :: (a: $T, b: T) -> T {
     return a if a >= b else b;
 }
 
-min :: #match { wasm.min_f32, wasm.min_f64, min_poly }
+min :: #match #local { wasm.min_f32, wasm.min_f64, min_poly }
 min_poly :: (a: $T, b: T) -> T {
     return a if a <= b else b;
 }
@@ -262,12 +262,12 @@ clamp :: (v: $T, lo: T, hi: T) -> T {
     return v;
 }
 
-sqrt :: #match { wasm.sqrt_f32, wasm.sqrt_f64, sqrt_poly }
+sqrt :: #match #local { wasm.sqrt_f32, wasm.sqrt_f64, sqrt_poly }
 sqrt_poly :: (x: $T) -> T {
     return ~~ wasm.sqrt_f64(~~ x);
 }
 
-abs :: #match { wasm.abs_f32, wasm.abs_f64, abs_poly }
+abs :: #match #local { wasm.abs_f32, wasm.abs_f64, abs_poly }
 abs_poly :: (x: $T) -> T {
     return x if x >= 0 else -x;
 }
@@ -278,7 +278,7 @@ sign :: (x: $T) -> T {
     return 0;
 }
 
-copysign :: #match { wasm.copysign_f32, wasm.copysign_f64, copysign_poly }
+copysign :: #match #local { wasm.copysign_f32, wasm.copysign_f64, copysign_poly }
 copysign_poly :: (x: $T, y: T) -> T {
     return abs(x) * sign(y);
 }
@@ -290,10 +290,10 @@ copysign_poly :: (x: $T, y: T) -> T {
 // Floating point rounding
 //
 
-ceil    :: #match { wasm.ceil_f32,    wasm.ceil_f64    }
-floor   :: #match { wasm.floor_f32,   wasm.floor_f64   }
-trunc   :: #match { wasm.trunc_f32,   wasm.trunc_f64   }
-nearest :: #match { wasm.nearest_f32, wasm.nearest_f64 }
+ceil    :: #match #local { wasm.ceil_f32,    wasm.ceil_f64    }
+floor   :: #match #local { wasm.floor_f32,   wasm.floor_f64   }
+trunc   :: #match #local { wasm.trunc_f32,   wasm.trunc_f64   }
+nearest :: #match #local { wasm.nearest_f32, wasm.nearest_f64 }
 
 
 
@@ -301,11 +301,11 @@ nearest :: #match { wasm.nearest_f32, wasm.nearest_f64 }
 // Integer operations
 //
 
-clz          :: #match { wasm.clz_i32,    wasm.clz_i64    }
-ctz          :: #match { wasm.ctz_i32,    wasm.ctz_i64    }
-popcnt       :: #match { wasm.popcnt_i32, wasm.popcnt_i64 }
-rotate_left  :: #match { wasm.rotl_i32,   wasm.rotl_i64   }
-rotate_right :: #match { wasm.rotr_i32,   wasm.rotr_i64   }
+clz          :: #match #local { wasm.clz_i32,    wasm.clz_i64    }
+ctz          :: #match #local { wasm.ctz_i32,    wasm.ctz_i64    }
+popcnt       :: #match #local { wasm.popcnt_i32, wasm.popcnt_i64 }
+rotate_left  :: #match #local { wasm.rotl_i32,   wasm.rotl_i64   }
+rotate_right :: #match #local { wasm.rotr_i32,   wasm.rotr_i64   }
 
 
 
index 5ea845b199b14242a7743cb9fc7765ccd8927150..3c04d26a3ffca2c8a2dac7fa4b6703e1d7595f9d 100644 (file)
@@ -1,21 +1,22 @@
 package core.memory
 
-use package core.intrinsics.wasm { memory_copy, memory_fill }
-
-copy :: (dest: rawptr, src: rawptr, count: i32) do memory_copy(dest, src, count);
-set  :: (dest: rawptr, byte: u8, count: i32)    do memory_fill(dest, byte, count);
+align :: #match {
+    (size: ^u64, align: u64) {
+        if *size % align != 0 {
+            *size += align - (*size % align);
+        }
+    },
 
-// Old and slow copy and set
-copy_ :: (dst_: rawptr, src_: rawptr, len: u32) {
-    dst := cast(^u8) dst_;
-    src := cast(^u8) src_;
-    for i: 0 .. len do dst[i] = src[i];
+    (size: u64, align: u64) -> u64 {
+        if size % align != 0 {
+            size += align - (size % align);
+        }
+        return size;
+    }        
 }
 
-set_ :: (start: rawptr, value: u8, length: u32) {
-    s := cast(^u8) start;
-    for i: 0 .. length do s[i] = value;
-}
+copy :: core.intrinsics.wasm.memory_copy
+set  :: core.intrinsics.wasm.memory_fill
 
 alloc_slice :: (sl: ^[] $T, count: i32, allocator := context.allocator) {
     sl.data  = raw_alloc(allocator, sizeof T * count);
@@ -29,10 +30,6 @@ make_slice :: ($T: type_expr, count: i32, allocator := context.allocator) -> []
     };
 }
 
-#match __make_overload macro (_: ^[] $T, count: u32, allocator := context.allocator) -> [] T {
-    return (package core.memory).make_slice(T, count, allocator);
-}
-
 free_slice :: (sl: ^[] $T, allocator := context.allocator) {
     if sl.data == null do return;
 
@@ -41,10 +38,6 @@ free_slice :: (sl: ^[] $T, allocator := context.allocator) {
     sl.count = 0;
 }
 
-#match (package builtin).delete macro (x: ^[] $T) {
-    (package core.memory).free_slice(x);
-}
-
 copy_slice :: (sl: [] $T, allocator := context.allocator) -> [] T {
     data := raw_alloc(allocator, sl.count * sizeof T);
     copy(data, sl.data, sl.count * sizeof T);
@@ -62,17 +55,13 @@ resize_slice :: (sl: [] $T, new_size: i32, allocator := context.allocator) -> []
     return new_slice;
 }
 
-align :: #match {
-    (size: ^u64, align: u64) {
-        if *size % align != 0 {
-            *size += align - (*size % align);
-        }
-    },
 
-    (size: u64, align: u64) -> u64 {
-        if size % align != 0 {
-            size += align - (size % align);
-        }
-        return size;
-    }        
+#overload
+builtin.__make_overload :: macro (_: ^[] $T, count: u32, allocator := context.allocator) -> [] T {
+    return (package core.memory).make_slice(T, count, allocator);
+}
+
+#overload
+builtin.delete :: macro (x: ^[] $T) {
+    core.memory.free_slice(x);
 }
index 99a0187551ae620d3bcdbfe6d10221ee0392b6fc..dbab9d7e705ba3dbe54e0fd4db7a55bf3199a03e 100644 (file)
@@ -46,7 +46,9 @@ package core
 
 #if runtime.runtime == .Onyx   {
     #load "./runtime/onyx_run"
+
     #load "./os/process"
+    #load "./time/time"
 
     #load "./net/net"
     #load "./net/tcp"
index 20e2113f37ac0c2bd518c3251727c043ed9ff6da..4fa33c86693de876db2c48fe07f4c7ac43c7b8e4 100644 (file)
@@ -7,11 +7,12 @@ package core
 // in anyway.
 
 
-#local runtime :: package runtime
 #if runtime.runtime == .Custom {
     #error "'stdio' can only be included in the 'wasi' or 'js' runtime."
 }
 
+stdin: io.Stream;
+
 auto_flush_stdio := true
 
 print :: #match #locked {
@@ -42,15 +43,15 @@ printf :: (format: str, va: ..any) {
 }
 
 // Print to standard error, if available.
-#if #defined((package runtime).__output_error) {
+#if #defined(runtime.__output_error) {
     eprintf :: (format: str, va: ..any) -> str {
         flush :: (_, to_output) => {
-            (package runtime).__output_error(to_output);
+            runtime.__output_error(to_output);
             return true;
         }
 
         buffer: [1024] u8;
-        (package runtime).__output_error(conv.format_va(buffer, format, va, .{null, flush}));
+        runtime.__output_error(conv.format_va(buffer, format, va, .{null, flush}));
     }
 }
 
@@ -157,5 +158,3 @@ __flush_stdio :: () {
         return .None, buf[0];
     }
 }
-
-stdin: io.Stream;
index ef876113696f1cb31aad274f5d4d763f0856ffbd..b4134f09382569f92344073f57d9ab03bd49307f 100644 (file)
@@ -2,6 +2,9 @@ package core.string
 
 use package core
 
+as_str :: #match {}
+
+free :: (s: str, allocator := context.allocator) do raw_free(allocator, s.data);
 
 alloc_copy :: (original: str, allocator := context.allocator) -> str {
     new_str : str;
@@ -24,131 +27,117 @@ copy :: (orig: str, dest: str) {
     memory.copy(dest.data, orig.data, len);
 }
 
+#match as_str from_cstr
 from_cstr :: (s: cstr) -> str {
     return .{ data = s, count = length(s) };
 }
 
-free :: (s: str, allocator := context.allocator) do raw_free(allocator, s.data);
-
-length :: #match {
-    (s: str) -> u32 {
-        return s.count;
-    },
-
-    (s: cstr) -> u32 {
-        len := 0;
-        c := s;
-        while *c != #char "\0" {
-            len += 1;
-            c += 1;
-        }
-
-        return len;
-    },
-}
-
-concat :: #match {
-    (s1: str, s2: str, allocator := context.allocator) -> str {
-        len1 := length(s1);
-        len2 := length(s2);
 
-        data := cast(^u8) raw_alloc(allocator, len1 + len2);
-        memory.copy(data, s1.data, len1);
-        memory.copy(data + len1, s2.data, len2);
+length :: #match #local {}
 
-        return str.{ data, len1 + len2 };
-    },
+#overload
+length :: (s: str) => s.count;
 
-    @Cleanup // Don't love that the allocator is necessary here,
-    // but it is impossible to specify a default value for the
-    // allocator while having a variadic number of strings. This
-    // is only due to the languages constraints however. This
-    // could easily be changed since there is no ambiguity.
-    (allocator: Allocator, strings: ..str) -> str {
-        total_length := 0;
-        for s: strings do total_length += s.count;
+#overload
+length :: (s: cstr) -> u32 {
+    len := 0;
+    c := s;
+    while *c != #char "\0" {
+        len += 1;
+        c += 1;
+    }
 
-        data := cast(^u8) raw_alloc(allocator, total_length);
-        offset := 0;
-        for s: strings {
-            memory.copy(data + offset, s.data, s.count);
-            offset += s.count;
-        }
+    return len;
+}
 
-        return str.{ data, total_length };
-    },
 
-    (buffer: [] u8, strings: ..str) -> str {
-        total_copied := 0;
-        for s: strings {
-            // Should never greater than, but better safe than sorry.
-            if total_copied >= buffer.count do break;
+concat :: #match #local {}
 
-            bytes_to_copy := math.min(s.count, buffer.count - total_copied);
-            memory.copy(buffer.data + total_copied, s.data, bytes_to_copy);
-            total_copied += bytes_to_copy;
-        }
+#overload
+concat :: (s1: str, s2: str, allocator := context.allocator) -> str {
+    len1 := length(s1);
+    len2 := length(s2);
 
-        return buffer[0 .. total_copied];
-    },
+    data := cast(^u8) raw_alloc(allocator, len1 + len2);
+    memory.copy(data, s1.data, len1);
+    memory.copy(data + len1, s2.data, len2);
 
-    (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);
-            into.count += s.count;
-        }
-        return .{ into.data, into.count };
-    }
+    return str.{ data, len1 + len2 };
 }
 
+@Cleanup // Don't love that the allocator is necessary here,
+// but it is impossible to specify a default value for the
+// allocator while having a variadic number of strings. This
+// is only due to the languages constraints however. This
+// could easily be changed since there is no ambiguity.
+#overload
+concat :: (allocator: Allocator, strings: ..str) -> str {
+    total_length := 0;
+    for s: strings do total_length += s.count;
+
+    data := cast(^u8) raw_alloc(allocator, total_length);
+    offset := 0;
+    for s: strings {
+        memory.copy(data + offset, s.data, s.count);
+        offset += s.count;
+    }
 
-split :: (s: str, delim: u8, allocator := context.allocator) -> []str {
-    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));
+    return str.{ data, total_length };
+}
 
-    curr_str := 0;
-    begin := 0;
+#overload
+concat :: (buffer: [] u8, strings: ..str) -> str {
+    total_copied := 0;
+    for s: strings {
+        // Should never greater than, but better safe than sorry.
+        if total_copied >= buffer.count do break;
 
-    for i: 0 .. s.count {
-        if s[i] == delim {
-            strarr[curr_str] = s.data[begin .. i];
-            begin = i + 1;
-            curr_str += 1;
-        }
+        bytes_to_copy := math.min(s.count, buffer.count - total_copied);
+        memory.copy(buffer.data + total_copied, s.data, bytes_to_copy);
+        total_copied += bytes_to_copy;
     }
 
-    strarr[curr_str] = s.data[begin .. s.count];
+    return buffer[0 .. total_copied];
+}
 
-    return strarr[0 .. delim_count + 1];
+#overload
+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);
+        into.count += s.count;
+    }
+    return .{ into.data, into.count };
 }
 
-contains :: #match {
-    (s: str, c: u8) -> bool {
-        for ch: s do if ch == c do return true;
-        return false;
-    },
 
-    (s: str, substr: str) -> bool {
-        while i := 0; i < s.count {
-            while j := 0; j < substr.count {
-                if s[i + j] != substr[j] {
-                    i += j + 1;
-                    continue continue;
-                }
+contains :: #match #local {}
+
+#overload
+contains :: (s: str, c: u8) -> bool {
+    for ch: s do if ch == c do return true;
+    return false;
+}
 
-                j += 1;
+#overload
+contains :: (s: str, substr: str) -> bool {
+    while i := 0; i < s.count {
+        while j := 0; j < substr.count {
+            if s[i + j] != substr[j] {
+                i += j + 1;
+                continue continue;
             }
 
-            return true;
+            j += 1;
         }
 
-        return false;
-    },
+        return true;
+    }
+
+    return false;
 }
 
+
 @TODO
 // Check this for edge cases and other bugs. I'm not confident
 // it will work perfectly yet.                   - brendanfh 2020/12/21
@@ -209,46 +198,61 @@ last_index_of :: (s: str, c: u8) -> i32 {
     return -1;
 }
 
-strip_whitespace :: #match {
-    (s: ^str) { strip_leading_whitespace(s); strip_trailing_whitespace(s); },
-    (s:  str) => s |> strip_leading_whitespace() |> strip_trailing_whitespace()
+
+strip_whitespace :: #match #local {}
+
+#overload
+strip_whitespace :: (s: ^str) {
+    strip_leading_whitespace(s);
+    strip_trailing_whitespace(s);
 }
 
-strip_leading_whitespace :: #match {
-    (s: ^str) {
-        while s.count > 0 do switch s.data[0] {
-            case #char " ", #char "\t", #char "\n", #char "\r" {
-                s.data += 1;
-                s.count -= 1;
-            }
+#overload
+strip_whitespace :: (s:  str) =>
+    s |> strip_leading_whitespace()
+      |> strip_trailing_whitespace()
+
+
+strip_leading_whitespace :: #match #local {}
 
-            case #default do return;
+#overload
+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;
+            s.count -= 1;
         }
-    },
-    
-    (s: str) -> str {
-        out := s;
-        strip_leading_whitespace(^out);
-        return out;
-    },
-}
-
-strip_trailing_whitespace :: #match {
-    (s: ^str) {
-        while s.count >= 1 do switch s.data[s.count - 1] {
-            case #char " ", #char "\t", #char "\n", #char "\r" {
-                s.count -= 1;
-            }
 
-            case #default do return;
+        case #default do return;
+    }
+}
+
+#overload
+strip_leading_whitespace :: (s: str) -> str {
+    out := s;
+    strip_leading_whitespace(^out);
+    return out;
+}
+
+
+strip_trailing_whitespace :: #match #local {}
+
+#overload
+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;
         }
-    },
 
-    (s: str) -> str {
-        out := s;
-        strip_trailing_whitespace(^out);
-        return out;
-    },
+        case #default do return;
+    }
+}
+
+#overload
+strip_trailing_whitespace :: (s: str) -> str {
+    out := s;
+    strip_trailing_whitespace(^out);
+    return out;
 }
 
 to_uppercase :: (s: str) -> str {
@@ -271,52 +275,61 @@ to_lowercase :: (s: str) -> str {
     return s;
 }
 
-trim_start :: #match {
-    (s: ^str, char: u8) {
-        while s.data[0] == char {
-            s.data += 1;
-            s.count -= 1;
-        }
-    },
 
-    (s: str, char: u8) -> str {
-        out := s;
-        trim_start(^out, char);
-        return out;
+trim_start :: #match #local {}
+
+#overload
+trim_start :: (s: ^str, char: u8) {
+    while s.data[0] == char {
+        s.data += 1;
+        s.count -= 1;
     }
 }
 
-trim_end :: #match {
-    (s: ^str, char: u8) {
-        while s.data[s.count - 1] == char {
-            s.count -= 1;
-        }
-    },
+#overload
+trim_start :: (s: str, char: u8) -> str {
+    out := s;
+    trim_start(^out, char);
+    return out;
+}
+
 
-    (s: str, char: u8) -> str {
-        out := s;
-        trim_end(^out, char);
-        return out;
+trim_end :: #match #local {}
+
+#overload
+trim_end :: (s: ^str, char: u8) {
+    while s.data[s.count - 1] == char {
+        s.count -= 1;
     }
 }
 
-advance :: #match {
-    (s: ^str, chars := 1) {
-        chars = math.min(chars, s.count);
+#overload
+trim_end :: (s: str, char: u8) -> str {
+    out := s;
+    trim_end(^out, char);
+    return out;
+}
+
 
-        s.data += chars;
-        s.count -= chars;
-    },
+advance :: #match #local {}
 
-    (s: str, chars := 1) -> str {
-        chars = math.min(chars, s.count);
-        out := s;
+#overload
+advance :: (s: ^str, chars := 1) {
+    chars = math.min(chars, s.count);
 
-        out.data += chars;
-        out.count -= chars;
+    s.data += chars;
+    s.count -= chars;
+}
 
-        return out;
-    }
+#overload
+advance :: (s: str, chars := 1) -> str {
+    chars = math.min(chars, s.count);
+    out := s;
+
+    out.data += chars;
+    out.count -= chars;
+
+    return out;
 }
 
 replace :: (s: str, to_replace: u8, replace_with: u8) {
@@ -325,70 +338,72 @@ replace :: (s: str, to_replace: u8, replace_with: u8) {
     }
 }
 
-read_until :: #match #locked {
-    (s: ^str, upto: u8, skip := 0) -> str {
-        if s.count == 0 do return "";
+read_until :: #match #local {}
 
-        out : str;
-        out.data = s.data;
-        out.count = 0;
+#overload
+read_until :: (s: ^str, upto: u8, skip := 0) -> str {
+    if s.count == 0 do return "";
 
-        rem := skip;
-        for ch: *s {
-            if ch == upto {
-                if rem <= 0 do break;
-                else do rem -= 1;
-            }
+    out : str;
+    out.data = s.data;
+    out.count = 0;
 
-            out.count += 1;
+    rem := skip;
+    for ch: *s {
+        if ch == upto {
+            if rem <= 0 do break;
+            else do rem -= 1;
         }
 
-        s.data += out.count;
-        s.count -= out.count;
+        out.count += 1;
+    }
 
-        return out;
-    },
+    s.data += out.count;
+    s.count -= out.count;
 
-    (s: ^str, upto: str, skip := 0) -> str {
-        if s.count == 0 do return "";
+    return out;
+}
 
-        out := str.{ data = s.data };
+#overload
+read_until :: (s: ^str, upto: str, skip := 0) -> str {
+    if s.count == 0 do return "";
 
-        rem := skip;
-        i := 0;
-        while i <= s.count - upto.count {
-            match := true;
-            j := i;
-            for upto {
-                if s.data[j] != it {
-                    match = false;
-                    break;
-                }
+    out := str.{ data = s.data };
 
-                j += 1;
+    rem := skip;
+    i := 0;
+    while i <= s.count - upto.count {
+        match := true;
+        j := i;
+        for upto {
+            if s.data[j] != it {
+                match = false;
+                break;
             }
 
-            if match {
-                if rem <= 0 do break;
-                else do rem -= 1;
-            }
+            j += 1;
+        }
 
-            i += 1;
+        if match {
+            if rem <= 0 do break;
+            else do rem -= 1;
         }
 
-        if i > s.count - upto.count {
-            out = *s;
-            s.data  += out.count;
-            s.count  = 0;
+        i += 1;
+    }
 
-        } else {
-            out.count = i - 1;
-            s.data  += out.count + (upto.count - 1);
-            s.count -= out.count + (upto.count - 1);
-        }
+    if i > s.count - upto.count {
+        out = *s;
+        s.data  += out.count;
+        s.count  = 0;
 
-        return out;
+    } else {
+        out.count = i - 1;
+        s.data  += out.count + (upto.count - 1);
+        s.count -= out.count + (upto.count - 1);
     }
+
+    return out;
 }
 
 read_until_any :: (s: ^str, skip: u32, uptos: ..u8) -> str {
@@ -426,6 +441,24 @@ advance_line :: (s: ^str) {
     s.count -= adv + 1;
 }
 
-as_str :: #match {
-    from_cstr
+split :: (s: str, delim: u8, allocator := context.allocator) -> []str {
+    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));
+
+    curr_str := 0;
+    begin := 0;
+
+    for i: 0 .. s.count {
+        if s[i] == delim {
+            strarr[curr_str] = s.data[begin .. i];
+            begin = i + 1;
+            curr_str += 1;
+        }
+    }
+
+    strarr[curr_str] = s.data[begin .. s.count];
+
+    return strarr[0 .. delim_count + 1];
 }
diff --git a/core/time/time.onyx b/core/time/time.onyx
new file mode 100644 (file)
index 0000000..6021e27
--- /dev/null
@@ -0,0 +1,57 @@
+package core.time
+
+//
+// This module provides a thin wrapper for the builtin POSIX
+// time functionality of:
+//      - localtime, gmtime
+//      - strptime, strftime
+//
+
+#if runtime.runtime != .Onyx {
+    #error "'core.time' should only be used with the Onyx runtime.";
+}
+
+//
+// This structure has to match the 'struct tm'
+// defined in time.h of POSIX.
+Timestamp :: struct #size (sizeof u32 * 12) {
+    sec:   u32;
+    min:   u32;
+    hour:  u32;
+    mday:  u32;
+    mon:   u32;
+    year:  u32;
+    wday:  u32;
+    yday:  u32;
+    isdst: u32;
+}
+
+localtime :: __time_localtime
+gmtime    :: __time_gmtime
+
+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;
+
+    len := __time_strftime(buf, f, tm);
+    return buf[0..len];
+}
+
+strptime :: (buf: [] u8, format: [] u8, tm: ^Timestamp) -> bool {
+    f := cast(cstr) core.alloc.from_stack(format.length + 1);
+    core.memory.copy(f, format.data, format.length);
+    f[format.length] = 0;
+
+    return __time_strptime(buf, f, tm); 
+}
+
+#local {
+    #foreign "onyx_runtime" {
+        __time_localtime :: (time: u64, tm: ^Timestamp) -> void ---
+        __time_gmtime    :: (time: u64, tm: ^Timestamp) -> void ---
+        __time_strftime  :: (buf: [] u8, format: cstr, tm: ^Timestamp) -> u32 ---
+        __time_strptime  :: (buf: [] u8, format: cstr, tm: ^Timestamp) -> bool ---
+    }
+}
+
index 51acba0ab0103374181f21b6a12426c003ad1504..3f2069571c62a060756d9571a06912ccb9f0c2d0 100644 (file)
@@ -1064,6 +1064,7 @@ struct AstOverloadedFunction {
     bh_imap            all_overloads;
 
     b32 locked : 1;
+    b32 only_local_functions : 1;
 };
 
 // @CLEANUP: Is this really necessary?
index f8d5d1c555cc14fb45c527483ca1fa2c1577c422..f1395b72e29b02a0a5f07da3cee7b7c250bfd47d 100644 (file)
@@ -118,5 +118,6 @@ void onyx_lex_tokens(OnyxTokenizer* tokenizer);
 
 b32 token_equals(OnyxToken* tkn1, OnyxToken* tkn2);
 b32 token_text_equals(OnyxToken* tkn, char* text);
+b32 token_same_file(OnyxToken *tkn1, OnyxToken *tkn2);
 
 #endif
index b0c4194a20e9a4f295029e662d261a5aeded9c2c..71d36652906ff6d02d784a0cedab5a2c589b8c68 100644 (file)
@@ -796,7 +796,7 @@ TypeMatch unify_node_and_type_(AstTyped** pnode, Type* type, b32 permanent) {
     else if (node->kind == Ast_Kind_Zero_Value) {
         if (node_type == NULL) {
             node->type = type;
-            return TYPE_MATCH_SUCCESS;
+            return TYPE_MATCH_SUCCESS; // Shouldn't this be on the next line? And have node_type == node->type checked?
         }
     }
 
index 1f0dc6a337d54366a24c94fdf146d396b96c4fc6..c34cc951b1e44fdbb5acc915c7726c77cb2625ec 100644 (file)
--- a/src/lex.c
+++ b/src/lex.c
@@ -539,3 +539,12 @@ b32 token_text_equals(OnyxToken* tkn, char* text) {
         
     return 1;
 }
+
+b32 token_same_file(OnyxToken *tkn1, OnyxToken *tkn2) {
+    if (!tkn1 || !tkn2) return 0;
+    
+    if (tkn1->pos.filename == tkn2->pos.filename) return 1;
+
+    // :Security?
+    return strcmp(tkn1->pos.filename, tkn2->pos.filename) == 0;
+}
index 10f3a82ade22cc9453877fe5810b7594a0b30a02..7827e1d3f0ff6d33a47b52871c8aa2127b96d43e 100644 (file)
@@ -914,6 +914,36 @@ ONYX_DEF(__time, (), (WASM_I64)) {
 
 
 
+
+//
+// Dates and Times
+//
+ONYX_DEF(__time_localtime, (WASM_I64, WASM_I32), ()) {
+    u64 t = params->data[0].of.i64;
+    localtime_r(&t, ONYX_PTR(params->data[1].of.i32));
+    return NULL;
+}
+
+ONYX_DEF(__time_gmtime, (WASM_I64, WASM_I32), ()) {
+    u64 t = params->data[0].of.i64;
+    gmtime_r(&t, ONYX_PTR(params->data[1].of.i32));
+    return NULL;
+}
+
+ONYX_DEF(__time_strftime, (WASM_I32, WASM_I32, WASM_I32, WASM_I32), (WASM_I32)) {
+    u32 len = strftime(ONYX_PTR(params->data[0].of.i32), params->data[1].of.i32, ONYX_PTR(params->data[2].of.i32), ONYX_PTR(params->data[3].of.i32));
+    results->data[0] = WASM_I32_VAL(len); 
+    return NULL;
+}
+
+ONYX_DEF(__time_strptime, (WASM_I32, WASM_I32, WASM_I32, WASM_I32), (WASM_I32)) {
+    char *rem = strptime(ONYX_PTR(params->data[0].of.i32), params->data[1].of.i32, ONYX_PTR(params->data[2].of.i32), ONYX_PTR(params->data[3].of.i32));
+    results->data[0] = WASM_I32_VAL(rem != NULL); 
+    return NULL;
+}
+
+
+
 //
 // Networking
 //
@@ -1336,6 +1366,11 @@ ONYX_LIBRARY {
     ONYX_FUNC(__sleep)
     ONYX_FUNC(__time)
 
+    ONYX_FUNC(__time_localtime)
+    ONYX_FUNC(__time_gmtime)
+    ONYX_FUNC(__time_strftime)
+    ONYX_FUNC(__time_strptime)
+
     ONYX_FUNC(__net_create_socket)
     ONYX_FUNC(__net_close_socket)
     ONYX_FUNC(__net_setting)
index e7a08a2a8e5bcb695c4631b44c4672bbc48fa78d..fae5d2b8a0205180e4ed5142150d5fe268c9b974 100644 (file)
@@ -2342,12 +2342,23 @@ static AstOverloadedFunction* parse_overloaded_function(OnyxParser* parser, Onyx
         locked = 1;
     }
 
+    b32 local = 0;
+    if (parse_possible_directive(parser, "local")) {
+        local = 1;
+    }
+
+    // This could be checked elsewhere?
+    if (locked && local) {
+        onyx_report_error(token->pos, Error_Critical, "Only one of '#locked' and '#local' can because use at a time.");
+    }
+
     expect_token(parser, '{');
 
     AstOverloadedFunction* ofunc = make_node(AstOverloadedFunction, Ast_Kind_Overloaded_Function);
     ofunc->token = token;
     ofunc->flags |= Ast_Flag_Comptime;
     ofunc->locked = locked;
+    ofunc->only_local_functions = local;
 
     bh_arr_new(global_heap_allocator, ofunc->overloads, 4);
 
@@ -3175,14 +3186,10 @@ static void parse_top_level_statement(OnyxParser* parser) {
                 ENTITY_SUBMIT(operator);
                 return;
             }
-            else if (parse_possible_directive(parser, "match")) {
+            else if (parse_possible_directive(parser, "match") || parse_possible_directive(parser, "overload")) {
                 AstDirectiveAddOverload *add_overload = make_node(AstDirectiveAddOverload, Ast_Kind_Directive_Add_Overload);
                 add_overload->token = dir_token;
 
-                parser->parse_calls = 0;
-                add_overload->overloaded_function = (AstNode *) parse_expression(parser, 0);
-                parser->parse_calls = 1;
-
                 if (parse_possible_directive(parser, "precedence")) {
                     AstNumLit* pre = parse_int_literal(parser);
                     if (parser->hit_unexpected_token) return;
@@ -3192,6 +3199,21 @@ static void parse_top_level_statement(OnyxParser* parser) {
                     add_overload->precedence = 0;
                 }
 
+                parser->parse_calls = 0;
+                add_overload->overloaded_function = (AstNode *) parse_expression(parser, 0);
+                parser->parse_calls = 1;
+
+                // Allow for
+                //      #match
+                //      something :: (....) {
+                //      }
+                // 
+                // This will make converting something to a overloaded
+                // function easier and require less copying by the programmer.
+                if (next_tokens_are(parser, 2, ':', ':')) {
+                    consume_tokens(parser, 2);
+                }
+
                 add_overload->overload = parse_expression(parser, 0);
 
                 ENTITY_SUBMIT(add_overload);
index f006c7648242eacb32467d9fc0052850086efb16..50b87b61281bfdb85bfac9099fd4975e164ca2ce 100644 (file)
@@ -1374,6 +1374,13 @@ static SymresStatus symres_process_directive(AstNode* directive) {
                 return Symres_Error;
             }
 
+            if (ofunc->only_local_functions) {
+                if (!token_same_file(add_overload->token, ofunc->token)) {
+                    onyx_report_error(add_overload->token->pos, Error_Critical, "Cannot add match option here as this option is not within the same file as the original #match declared with #local.");
+                    onyx_report_error(ofunc->token->pos, Error_Critical, "Here is the original #match.");
+                }
+            }
+
             SYMRES(expression, (AstTyped **) &add_overload->overload);
             add_overload_option(&ofunc->overloads, add_overload->precedence, add_overload->overload);
             break;
index 1073532406fb5244dfb6fe2950ed5b3478416d47..091f6e31e7287794175b028a5b6111fe89e1c430 100644 (file)
@@ -8,7 +8,7 @@ test_macro :: macro () {
     }
 }
 
-time :: macro (name: str) {
+time_block :: macro (name: str) {
     start := 10;
     defer {
         end := 1010;
@@ -18,5 +18,5 @@ time :: macro (name: str) {
 
 main :: (args) => {
     test_macro();
-    time("main");
+    time_block("main");
 }
index b5dad3874f7f1c18b842f648248c5be67083d5a4..b4b2ecc00dc3968bc39652938cf94723daf0b656 100644 (file)
@@ -15,6 +15,6 @@ main :: (args: [] cstr) {
     overloaded(z=10);
 }
 
-#match overloaded #precedence 3 (q: i32) { println("Option Q"); }
-#match overloaded #precedence 2 (r: i32) { println("Option R"); }
-#match overloaded #precedence 1 (m: i32) { println("Option M"); }
+#match #precedence 3 overloaded (q: i32) { println("Option Q"); }
+#match #precedence 2 overloaded (r: i32) { println("Option R"); }
+#match #precedence 1 overloaded (m: i32) { println("Option M"); }