}
}
+ new_temp :: macro (T: type_expr) => {
+ return new(T, allocator=context.temp_allocator);
+ }
+
make :: #match {
macro ($T: type_expr, allocator := context.allocator) => {
return __make_overload(cast(^T) null, allocator=allocator);
},
}
+ make_temp :: macro (T: type_expr) => {
+ return make(T, allocator=context.temp_allocator);
+ }
+
//
// This is a rather unique way of using the type matching system
// to select an overload. What is desired here is that when you say:
#overload
as_iterator :: from_array
-from_array :: (arr: [] $T) -> Iterator(^T) {
- Context :: struct (T: type_expr) {
- data: ^T;
- count: u32;
- current: u32;
- }
+from_array :: (arr: [] $T) => generator(
+ ^.{ data = arr.data, count = arr.count, current = 0 },
- c := make(Context(T), allocator=context.temp_allocator);
- c.data = arr.data;
- c.count = arr.count;
- c.current = 0;
-
- next :: (use _: ^Context($T)) -> (^T, bool) {
+ (use ctx: ^$T) -> (typeof ctx.data, bool) {
if current < count {
defer current += 1;
return ^data[current], true;
-
- } else {
- return null, false;
}
- }
- return .{
- data = c,
- next = #solidify next { T = T },
- };
-}
+ return null, false;
+ }
+);
#overload
as_iterator :: (x: ^[..] $T) -> Iterator(T) {
last: ^ListElem(Elem_Type) = null;
// "Method" like things
+}
+
+#inject List {
free :: free
push_end :: push_end
push_begin :: push_begin
contains :: contains
fold :: fold
map :: map
- get_iterator :: get_iterator
+ as_iter :: as_iter
}
make :: ($T: type_expr, allocator := context.allocator) -> List(T) {
}
}
-#match core.iter.as_iterator get_iterator
-get_iterator :: (list: ^List($T)) -> Iterator(T) {
+#match core.iter.as_iterator as_iter
+as_iter :: (list: ^List($T)) -> Iterator(T) {
iterator_next :: (list_iter: ^ListIterator($T)) -> (T, bool) {
if list_iter.current == null do return .{}, false;
current: ^ListElem(T);
}
- list_iterator := new(ListIterator(T));
+ list_iterator := new_temp(ListIterator(T));
list_iterator.current = list.first;
return .{
data = list_iterator,
next = #solidify iterator_next { T = T },
- close = cfree,
};
}
}
#inject Map {
- //
- // These need to have aliases because some of them like
- // 'delete', collide with the global 'delete', which
- // causes it to map to the wrong function.
init :: init
has :: has
get :: get
hash : u32;
value : T;
}
+}
+#inject Set {
init :: init
free :: free
has :: has
remove :: remove
clear :: clear
empty :: empty
- iterator :: iterator
+ as_iter :: as_iter
}
make :: ($T: type_expr, default := T.{}, allocator := context.allocator) -> Set(T) {
return entries.count == 0;
}
-#match core.iter.as_iterator iterator
-iterator :: (set: ^Set($T)) -> Iterator(T) {
- Context :: struct (T: type_expr) {
- set: ^Set(T);
- position: i32;
- }
-
- context := new(Context(T));
- context.set = set;
- context.position = 0;
+#overload core.iter.as_iterator as_iter
- next :: (use context: ^Context($T)) -> (T, bool) {
- if position < set.entries.count {
- defer position += 1;
- return set.entries[position].value, true;
+as_iter :: (s: ^Set) =>
+ core.iter.generator(
+ ^.{ s = s, i = 0 },
- } else {
- return .{}, false;
- }
- }
+ (ctx) => {
+ if ctx.i >= ctx.s.entries.count {
+ return (typeof ^ctx.s.entries.data.value).{}, false;
+ }
- return .{
- data = context,
- next = #solidify next { T = T },
- close = cfree,
- };
-}
+ defer ctx.i += 1;
+ return ^ctx.s.entries.data[ctx.i].value, true;
+ });
//
// Private symbols
node_stack << .{ "start", 0, false };
children_of :: (edges: ^$T, name: str) -> Iterator(str) {
- #persist NAME_HACK: str;
- NAME_HACK = name;
+ name_copy := make_temp(str);
+ *name_copy = name;
return iter.concat(
iter.as_iterator(edges)
- |> iter.filter((x) => x.a == NAME_HACK)
+ |> iter.filter(name_copy, (x, n) => x.a == *n)
|> iter.map((x) => x.b),
iter.as_iterator(edges)
- |> iter.filter((x) => x.b == NAME_HACK)
+ |> iter.filter(name_copy, (x, n) => x.b == *n)
|> iter.map((x) => x.a)
);
}
edge_map: Map(str, [] str);
for v: iter.as_iterator(^verticies) {
- edge_map[v] = children_of(^edges, v) |> iter.to_array();
+ edge_map[*v] = children_of(^edges, *v) |> iter.to_array();
}
paths_count := 0;
}
clone :: (n: ^SnailNum) -> ^SnailNum {
- if n == null do return null;
+ if !n do return null;
new_num := SnailNum.make();
new_num->set_left(SnailNum.clone(n.left));
}
add :: (a, b: ^SnailNum) => {
- if a == null do return b;
- if b == null do return a;
+ if !a do return b;
+ if !b do return a;
new_root := SnailNum.make();
new_root->set_left(a);
pleft := n->number_to_left();
pright := n->number_to_right();
- if pleft != null do *pleft += left_val;
- if pright != null do *pright += right_val;
+ if pleft do *pleft += left_val;
+ if pright do *pright += right_val;
left_val = 0;
right_val = 0;
}
reduce_splits :: (use n: ^SnailNum) -> (reduced_something: bool) {
- if left != null {
+ if left {
if left->reduce_splits() {
return true;
}
return true;
}
- if right != null {
+ if right {
if right->reduce_splits() {
return true;
}
split_number :: (n: u32) -> (u32, u32) {
h := n / 2;
- return h, h + (0 if n % 2 == 0 else 1);
+ return h, h + (n % 2);
}
}
set_left :: (parent, new_left: ^SnailNum) {
parent.left_val = 0;
parent.left = new_left;
- if new_left != null do new_left.parent = parent;
+ if new_left do new_left.parent = parent;
}
set_right :: (parent, new_right: ^SnailNum) {
parent.right_val = 0;
parent.right = new_right;
- if new_right != null do new_right.parent = parent;
+ if new_right do new_right.parent = parent;
}
number_to_left :: (n: ^SnailNum) -> ^u32 {
- while n.parent != null && n.parent.left == n {
+ while n.parent && n.parent.left == n {
n = n.parent;
}
- if n.parent == null do return null;
+ if !n.parent do return null;
- if n.parent.left == null do return ^n.parent.left_val;
+ if !n.parent.left do return ^n.parent.left_val;
n = n.parent.left;
- while n.right != null {
+ while n.right {
n = n.right;
}
}
number_to_right :: (n: ^SnailNum) -> ^u32 {
- while n.parent != null && n.parent.right == n {
+ while n.parent && n.parent.right == n {
n = n.parent;
}
- if n.parent == null do return null;
+ if !n.parent do return null;
- if n.parent.right == null do return ^n.parent.right_val;
+ if !n.parent.right do return ^n.parent.right_val;
n = n.parent.right;
- while n.left != null {
+ while n.left {
n = n.left;
}
}
magnitude :: (use n: ^SnailNum) => {
- if n == null {
+ if !n {
return 0;
}
}
format :: (output: ^conv.Format_Output, s: ^conv.Format, use n: ^SnailNum) {
- if left == null && right == null {
+ if !left && !right {
conv.format(output, "[{},{}]", left_val, right_val);
}
- elseif left == null && right != null {
+ elseif !left && right {
conv.format(output, "[{},{*}]", left_val, right);
}
- elseif left != null && right == null {
+ elseif left && !right {
conv.format(output, "[{*},{}]", left, right_val);
}
- elseif left != null && right != null {
+ elseif left && right {
conv.format(output, "[{*},{*}]", left, right);
}
}
#operator + (c1, c2: Complex) => Complex.{ c1.x + c2.x, c1.y + c2.y };
#operator * (c1, c2: Complex) => Complex.{ c1.x * c2.x - c1.y * c2.y, c1.x * c2.y + c1.y * c2.x };
-consume :: macro (x: $T) -> #auto where iter.Iterable(T) {
+consume :: macro (x: $T/iter.Iterable) => {
// This is a weird limitation of the Onyx type system.
// In order to be able tell what the iterator produces, you
// have to pattern match it in a procedure parameter. This means
use package core
count_iterator :: (lo: $T, hi: T, step: T = 1) -> Iterator(T) {
- next :: (ci: ^CountIterator($T)) -> (T, bool) {
- if ci.current > ci.high do return 0, false;
-
- defer ci.current += ci.step;
- return ci.current, true;
- }
-
- close :: (data: rawptr) {
- println("Closing the count iterator...");
- cfree(data);
- }
-
- CountIterator :: struct (T:type_expr) {
- low, high, step: T;
- current: T;
- }
-
- count_iterator := new(CountIterator(T));
- count_iterator.low = lo;
- count_iterator.high = hi;
- count_iterator.step = step;
- count_iterator.current = lo;
-
- return .{
- data = count_iterator,
- next = #solidify next {T=T},
- close = close,
- };
+ return iter.generator(
+ ^.{ low = lo, high = hi, step = step, current = lo },
+
+ (ctx) => {
+ if ctx.current <= ctx.high {
+ defer ctx.current += ctx.step;
+ return ctx.current, true;
+ }
+
+ return 0, false;
+ },
+
+ (ctx) => {
+ println("Closing the count iterator...");
+ }
+ );
}
main :: (args: [] cstr) {