Token_Type_Keyword_Macro,
Token_Type_Keyword_Interface,
Token_Type_Keyword_Where,
+ Token_Type_Keyword_As,
+ Token_Type_Keyword_In,
Token_Type_Keyword_End,
Token_Type_Right_Arrow,
builtin_range_type_type = type_build_from_ast(context.ast_alloc, builtin_range_type);
if (builtin_range_type_type == NULL) YIELD(fornode->token->pos, "Waiting for 'range' structure to be built.");
+ Type* given_type = NULL;
+
fornode->loop_type = For_Loop_Invalid;
if (types_are_compatible(iter_type, &basic_types[Basic_Kind_I32])) {
if (fornode->by_pointer) {
CHECK(range_literal, &rl);
fornode->iter = (AstTyped *) rl;
- fornode->var->type = builtin_range_type_type->Struct.memarr[0]->type;
+ given_type = builtin_range_type_type->Struct.memarr[0]->type;
fornode->var->flags |= Ast_Flag_Cannot_Take_Addr;
fornode->loop_type = For_Loop_Range;
}
// NOTE: Blindly copy the first range member's type which will
// be the low value. - brendanfh 2020/09/04
- fornode->var->type = builtin_range_type_type->Struct.memarr[0]->type;
+ given_type = builtin_range_type_type->Struct.memarr[0]->type;
fornode->var->flags |= Ast_Flag_Cannot_Take_Addr;
fornode->loop_type = For_Loop_Range;
}
else if (iter_type->kind == Type_Kind_Array) {
- if (fornode->by_pointer) fornode->var->type = type_make_pointer(context.ast_alloc, iter_type->Array.elem);
- else fornode->var->type = iter_type->Array.elem;
+ if (fornode->by_pointer) given_type = type_make_pointer(context.ast_alloc, iter_type->Array.elem);
+ else given_type = iter_type->Array.elem;
fornode->loop_type = For_Loop_Array;
}
else if (iter_type->kind == Type_Kind_Slice) {
- if (fornode->by_pointer) fornode->var->type = type_make_pointer(context.ast_alloc, iter_type->Slice.elem);
- else fornode->var->type = iter_type->Slice.elem;
+ if (fornode->by_pointer) given_type = type_make_pointer(context.ast_alloc, iter_type->Slice.elem);
+ else given_type = iter_type->Slice.elem;
fornode->loop_type = For_Loop_Slice;
ERROR_(error_loc, "Cannot iterate by pointer over '%s'.", type_get_name(iter_type));
}
- fornode->var->type = iter_type->VarArgs.elem;
+ given_type = iter_type->VarArgs.elem;
// NOTE: Slices are VarArgs are being treated the same here.
fornode->loop_type = For_Loop_Slice;
}
else if (iter_type->kind == Type_Kind_DynArray) {
- if (fornode->by_pointer) fornode->var->type = type_make_pointer(context.ast_alloc, iter_type->DynArray.elem);
- else fornode->var->type = iter_type->DynArray.elem;
+ if (fornode->by_pointer) given_type = type_make_pointer(context.ast_alloc, iter_type->DynArray.elem);
+ else given_type = iter_type->DynArray.elem;
fornode->loop_type = For_Loop_DynArr;
}
}
// HACK: This assumes the Iterator type only has a single type argument.
- fornode->var->type = iter_type->Struct.poly_sln[0].type;
+ given_type = iter_type->Struct.poly_sln[0].type;
fornode->loop_type = For_Loop_Iterator;
}
+ assert(given_type);
+
+ if (fornode->var->type_node) {
+ fill_in_type((AstTyped *) fornode->var);
+ TYPE_CHECK((AstTyped **) &fornode->var, given_type) {
+ ERROR_(error_loc, "Mismatched type for loop variable. You specified '%s', but it should be '%s'.", type_get_name(fornode->var->type), type_get_name(given_type));
+ }
+
+ } else {
+ fornode->var->type = given_type;
+ }
+
if (fornode->by_pointer)
fornode->var->flags |= Ast_Flag_Cannot_Take_Addr;
"macro",
"interface",
"where",
+ "as",
+ "in",
"", // end
"->",
char curr = *tokenizer->curr;
switch (curr) {
case 'a':
+ LITERAL_TOKEN("as", 1, Token_Type_Keyword_As);
LITERAL_TOKEN("alignof", 1, Token_Type_Keyword_Alignof);
break;
case 'b':
break;
case 'i':
LITERAL_TOKEN("if", 1, Token_Type_Keyword_If);
+ LITERAL_TOKEN("in", 1, Token_Type_Keyword_In);
LITERAL_TOKEN("interface", 1, Token_Type_Keyword_Interface);
break;
case 'm':
if (parse_possible_array_literal(parser, retval, &retval)) return retval;
consume_token(parser);
- AstFieldAccess* field = make_node(AstFieldAccess, Ast_Kind_Field_Access);
- field->token = expect_token(parser, Token_Type_Symbol);
- field->expr = retval;
+ if (parser->curr->type == '*') {
+ AstDereference* deref_node = make_node(AstDereference, Ast_Kind_Dereference);
+ deref_node->token = expect_token(parser, '*');
+ deref_node->expr = retval;
+
+ retval = (AstTyped *) deref_node;
+
+ } else {
+ AstFieldAccess* field = make_node(AstFieldAccess, Ast_Kind_Field_Access);
+ field->token = expect_token(parser, Token_Type_Symbol);
+ field->expr = retval;
- retval = (AstTyped *) field;
+ retval = (AstTyped *) field;
+ }
break;
}
for_node->by_pointer = 1;
}
- if (next_tokens_are(parser, 2, Token_Type_Symbol, ':')) {
+ if (next_tokens_are(parser, 2, Token_Type_Symbol, Token_Type_Keyword_In)
+ || next_tokens_are(parser, 2, Token_Type_Symbol, ':')
+ ) {
OnyxToken* local_sym = expect_token(parser, Token_Type_Symbol);
AstLocal* var_node = make_local(parser->allocator, local_sym, NULL);
for_node->var = var_node;
+ if (peek_token(0)->type == ':') {
+ expect_token(parser, ':');
+ var_node->type_node = parse_type(parser);
+ }
- expect_token(parser, ':');
+ expect_token(parser, Token_Type_Keyword_In);
} else {
// HACK
static char it_name[] = "it ";
sc_node->is_default = 1;
} else {
- if ( next_tokens_are(parser, 3, '&', Token_Type_Symbol, ':')
- || next_tokens_are(parser, 3, '^', Token_Type_Symbol, ':')
- || next_tokens_are(parser, 2, Token_Type_Symbol, ':')
- ) {
- b32 is_pointer = 0;
- if (consume_token_if_next(parser, '&') || consume_token_if_next(parser, '^'))
- is_pointer = 1;
-
- OnyxToken *capture_symbol = expect_token(parser, Token_Type_Symbol);
- AstLocal *capture = make_local(parser->allocator, capture_symbol, NULL);
-
- sc_node->capture = capture;
- sc_node->capture_is_by_pointer = is_pointer;
-
- expect_token(parser, ':');
- }
-
bh_arr_new(global_heap_allocator, sc_node->values, 1);
parser->parse_quick_functions = 0;
}
parser->parse_quick_functions = 1;
+
+ if ( next_tokens_are(parser, 3, Token_Type_Keyword_As, '&', Token_Type_Symbol)
+ || next_tokens_are(parser, 3, Token_Type_Keyword_As, '^', Token_Type_Symbol)
+ || next_tokens_are(parser, 2, Token_Type_Keyword_As, Token_Type_Symbol)
+ ) {
+ expect_token(parser, Token_Type_Keyword_As);
+
+ b32 is_pointer = 0;
+ if (consume_token_if_next(parser, '&') || consume_token_if_next(parser, '^'))
+ is_pointer = 1;
+
+ OnyxToken *capture_symbol = expect_token(parser, Token_Type_Symbol);
+ AstLocal *capture = make_local(parser->allocator, capture_symbol, NULL);
+
+ sc_node->capture = capture;
+ sc_node->capture_is_by_pointer = is_pointer;
+ }
}
if (consume_token_if_next(parser, Token_Type_Fat_Right_Arrow)) {
}
#doc """
- Moves a value on to the heap. Useful for cases like this:
+ Moves a value on to the heap. Useful for cases like this in
f :: () -> &Foo {
return alloc.on_heap(Foo.{
stack_trace := runtime.info.get_stack_trace();
if stack_trace {
slice.init(&trace, stack_trace.count, context.temp_allocator);
- for i: stack_trace.count {
+ for i in stack_trace.count {
info := stack_trace[i].info;
trace[i] = .{
info.file, info.line, stack_trace[i].current_line, info.func_name
make :: (buffer: [] $Elem) -> PoolAllocator(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 {
+ for i in 0 .. buffer.count - 1 {
*(cast(&rawptr) &buffer[i]) = cast(rawptr) &buffer[i + 1];
}
// This is a special type that the compiler knows how to iterator through.
// So, one can simply write:
//
-// for x: 1 .. 5 { ... }
+// for x in 1 .. 5 { ... }
//
// Although not controllable from the literal syntax, there is a `step`
// member that allows you control how many numbers to advance each iteration.
init(&new_arr, arr.count, allocator);
new_arr.count = arr.count;
- for i: 0 .. arr.count do new_arr.data[i] = arr.data[i];
+ for i in 0 .. arr.count do new_arr.data[i] = arr.data[i];
return new_arr;
},
(arr: [] $T, allocator := context.allocator) -> [] T {
new_arr := builtin.make([] T, arr.count);
- for i: 0 .. arr.count do new_arr.data[i] = arr.data[i];
+ for i in 0 .. arr.count do new_arr.data[i] = arr.data[i];
return new_arr;
}
}
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];
+ for i in r do new_arr.data[i] = arr.data[i];
return new_arr;
}
i -= 1;
}
- for i: 0 .. new_arr.count {
+ for i in 0 .. new_arr.count {
arr.data[i + idx] = new_arr[i];
}
return true;
if idx >= arr.count do return .{};
to_return := arr.data[idx];
- for i: idx .. arr.count - 1 {
+ for i in idx .. arr.count - 1 {
arr.data[i] = arr.data[i + 1];
}
// Frees all the buckets
clear :: (use b: &Bucket_Array($T)) {
- for &bucket: &buckets {
+ for &bucket in &buckets {
raw_free(bucket_allocator, bucket.data);
bucket.count = 0;
}
// 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_index: bucket.count {
+ for &bucket in b.buckets {
+ for bucket_index in bucket.count {
it := &bucket.data[bucket_index];
#unquote body(it);
#overload
find :: (it: Iterator($T), predicate: (T) -> bool) -> ? T {
- for v: it {
+ for v in it {
if predicate(v) {
return v;
}
fold :: (it: Iterator($T), initial_value: $R, combine: (T, R) -> R) -> R {
result := initial_value;
- for value: it {
+ for value in it {
result = combine(value, result);
}
result, valid := next(it);
if !valid do return .None;
- for value: it {
+ for value in it {
result = combine(value, result);
}
#overload
count :: (it: Iterator($T), cond: (T) -> bool) -> i32 {
c := 0;
- for value: it do if cond(value) do c += 1;
+ for value in it do if cond(value) do c += 1;
return c;
}
#overload
some :: (it: Iterator($T), cond: (T) -> bool) -> bool {
- for value: it do if cond(value) do return true;
+ for value in it do if cond(value) do return true;
return false;
}
#overload
every :: (it: Iterator($T), cond: (T) -> bool) -> bool {
- for value: it do if !cond(value) do return false;
+ for value in it do if !cond(value) do return false;
return true;
}
sum :: (it: Iterator($T)) -> T {
val := T.{};
- for v: it {
+ for v in it {
val = val + v;
}
"""
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 in it do array.push(&arr, v);
return arr;
}
"""
to_map :: (it: Iterator(Pair($K, $V)), allocator := context.allocator) -> Map(K, V) {
m := builtin.make(Map(K, V), allocator=allocator);
- for p: it {
+ for p in it {
m->put(p.first, p.second);
}
return m;
it: V;
a := make([..] typeof #unquote value);
- for __it: i {
+ for __it in i {
it := *__it;
a << (#unquote value(it));
}
modify memory, so be wary of dangling pointers!
"""
clear :: (use map: &Map) {
- for i: 0 .. hashes.count do hashes.data[i] = -1;
+ for i in 0 .. hashes.count do hashes.data[i] = -1;
entries.count = 0;
}
hashes = builtin.make([] u32, new_size, allocator=allocator);
array.fill(hashes, -1);
- for &entry: entries do entry.next = -1;
+ for &entry in entries do entry.next = -1;
index := 0;
- for &entry: entries {
+ for &entry in entries {
defer index += 1;
hash_index := entry.hash % hashes.count;
no value is present.
"""
value_or :: (o: ?$T, default: T) => switch o {
- case v: .Some => v;
+ case .Some as v => v;
case #default => default;
}
// @Bug should be able to say ? ? $T here.
flatten :: (o1: ? Optional($T)) -> ? T {
switch o1 {
- case o2: .Some {
+ case .Some as o2 {
return o2;
}
#doc "Monadic chaining operation."
and_then :: (o: ?$T, transform: (T) -> ?$R) -> ?R {
return switch o {
- case v: .Some => transform(v);
+ case .Some as v => transform(v);
case #default => .None;
};
}
#doc "Changes the value inside the optional, if present."
transform :: (o: ?$T, transform: (T) -> $R) -> ?R {
switch o {
- case v: .Some do return .{ Some = transform(v) };
+ case .Some as v do return .{ Some = transform(v) };
case #default do return .None;
}
}
"""
unwrap :: (o: ?$T) -> T {
switch o {
- case v: .Some do return v;
+ case .Some as v do return v;
case #default {
assert(false, "Unwrapping empty Optional.");
}
"""
unwrap_ptr :: (o: & ?$T) -> &T {
switch o {
- case &v: .Some do return v;
+ case .Some as &v do return v;
case #default {
assert(false, "Unwrapping empty Optional.");
}
"""
expect :: (o: ?$T, message: str) -> T {
switch o {
- case v: .Some do return v;
+ case .Some as v do return v;
case #default {
assert(false, message);
}
"""
expect_ptr :: (o: & ?$T, message: str) -> &T {
switch o {
- case &v: .Some do return v;
+ case .Some as &v do return v;
case #default {
assert(false, message);
}
or_return :: #match {
macro (o: ?$T) -> T {
switch value := o; value {
- case v: .Some do return v;
+ case .Some as v do return v;
case #default {
return return .{};
}
},
macro (o: ?$T, return_value: $R) -> T {
switch value := o; value {
- case v: .Some do return v;
+ case .Some as v do return v;
case #default {
return return return_value;
}
catch :: macro (o: ?$T, body: Code) -> T {
switch value := o; value {
- case v: .Some do return v;
+ case .Some as v do return v;
case .None {
#unquote body;
}
with :: macro (o: ?$T, body: Code) {
switch o {
case .None ---;
- case it: .Some {
+ case .Some as it {
#unquote body(it);
}
}
hash :: (o: ?$T/core.hash.Hashable) => switch o {
- case v: .Some => core.hash.hash(v);
+ case .Some as v => core.hash.hash(v);
case #default => 0;
}
}
return switch o1 {
case .None => true;
- case v1: .Some => v1 == o2->unwrap();
+ case .Some as v1 => v1 == o2->unwrap();
};
}
#operator ?? macro (opt: ?$T, default: T) -> T {
return switch value := opt; value {
- case v: .Some => v;
+ case .Some as v => v;
case #default => default;
};
}
#operator ?? macro (opt: ?$T, catch: Code) -> T {
switch value := opt; value {
- case v: .Some do return v;
+ case .Some as v do return v;
case #default ---
}
#operator ? macro (opt: ?$T) -> T {
switch value := opt; value {
- case v: .Some do return v;
+ case .Some as v do return v;
case #default do return return .{};
}
}
#doc "Returns an Optional of the Ok type."
ok :: (r: #Self) -> Optional(r.Ok_Type) {
return switch r {
- case v: .Ok => Optional.make(v);
+ case .Ok as v => Optional.make(v);
case #default => .{};
};
}
#doc "Returns an Optional of the Err type."
err :: (r: #Self) -> Optional(r.Err_Type) {
return switch r {
- case v: .Err => Optional.make(v);
+ case .Err as v => Optional.make(v);
case #default => .{};
};
}
"""
unwrap :: (r: #Self) -> r.Ok_Type {
switch r {
- case v: .Ok do return v;
- case err: .Err {
+ case .Ok as v do return v;
+ case .Err as err {
msg := tprintf("Unwrapping Result with error '{}'.", err);
assert(false, msg);
return .{};
"""
unwrap_or_default :: (r: #Self) -> r.Ok_Type {
return switch r {
- case v: .Ok => v;
+ case .Ok as v => v;
case #default => .{};
};
}
"""
expect :: (r: #Self, msg: str) -> r.Ok_Type {
switch r {
- case v: .Ok do return v;
+ case .Ok as v do return v;
case #default {
assert(false, msg);
}
"""
transform :: (r: Result($T, $E), f: (T) -> $R) -> Result(R, E) {
return switch r {
- case v: .Ok => .{ Ok = f(v) };
- case v: .Err => .{ Err = v };
+ case .Ok as v => .{ Ok = f(v) };
+ case .Err as v => .{ Err = v };
};
}
#doc "Monadic chaining operation."
and_then :: (r: #Self, f: (r.Ok_Type) -> Result($R, r.Err_Type)) -> Result(R, r.Err_Type) {
return switch r {
- case v: .Ok => f(v);
- case v: .Err => .{ Err = v };
+ case .Ok as v => f(v);
+ case .Err as v => .{ Err = v };
};
}
#doc "If the Result contains Err, generate is called to make a value"
or_else :: (r: #Self, generate: () -> typeof r) => {
return switch r {
- case v: .Ok => v;
+ case .Ok as v => v;
case #default => generate();
};
}
"""
forward_err :: macro (r: Result($T, $E)) -> T {
switch res := r; res {
- case v: .Ok do return v;
- case v: .Err do return return .{ Err = v };
+ case .Ok as v do return v;
+ case .Err as v do return return .{ Err = v };
}
}
"""
or_return :: macro (r: Result($T, $E), v: $V) -> T {
switch res := r; res {
- case v: .Ok do return v;
+ case .Ok as v do return v;
case .Err do return return v;
}
}
"""
catch :: macro (r: Result($T, $E), on_err: Code) -> T {
switch res := r; res {
- case v: .Ok do return v;
- case err: .Err {
+ case .Ok as v do return v;
+ case .Err as err {
#unquote on_err(err);
}
}
#operator ? macro (r: Result($T, $E)) -> T {
switch res := r; res {
- case v: .Ok do return v;
- case v: .Err do return return .{ Err = v };
+ case .Ok as v do return v;
+ case .Err as v do return return .{ Err = v };
}
}
#operator ?? macro (r: Result($T, $E), v: T) -> T {
return switch res := r; res {
- case val: .Ok => val;
+ case .Ok as val => val;
case .Err => v;
};
}
hashes = builtin.make([] u32, new_size, allocator=allocator);
array.fill(hashes, -1);
- for &entry: entries do entry.next = -1;
+ for &entry in entries do entry.next = -1;
index := 0;
- for &entry: entries {
+ for &entry in entries {
defer index += 1;
hash_index := entry.hash % hashes.count;
contains :: #match #locked {
(arr: [] $T, x: T) -> bool {
- for it: arr do if it == x do return true;
+ for it in arr do if it == x do return true;
return false;
},
macro (arr: [] $T, $cmp: Code) -> bool {
- for it: arr do if #unquote cmp(it) do return true;
+ for it in arr do if #unquote cmp(it) do return true;
return false;
}
}
#doc "Uses `+` to sum all elements in the slice."
sum :: (arr: [] $T, start: T = 0) -> T {
sum := start;
- for it: arr do sum += it;
+ for it in arr do sum += it;
return sum;
}
#doc "Uses `*` to multiply all elements in the slice."
product :: (arr: [] $T, start: T = 1) -> T {
prod := start;
- for it: arr do prod *= it;
+ for it in arr do prod *= it;
return prod;
}
"""
average :: (arr: [] $T) -> T {
sum := cast(T) 0;
- for it: *arr do sum += it;
+ for it in *arr do sum += it;
return sum / cast(T) arr.count;
}
Reverses a slice in-place.
"""
reverse :: (arr: [] $T) {
- for i: arr.count / 2 {
+ for i in arr.count / 2 {
tmp := arr[i];
arr[i] = arr[arr.count - 1 - i];
arr[arr.count - 1 - i] = tmp;
#overload
sort :: (arr: [] $T, cmp: (T, T) -> i32) -> [] T {
- for i: 1 .. arr.count {
+ for i in 1 .. arr.count {
x := arr.data[i];
j := i - 1;
#overload
sort :: (arr: [] $T, cmp: (&T, &T) -> i32) -> [] T {
- for i: 1 .. arr.count {
+ for i in 1 .. arr.count {
j := i;
while j > 0 {
pivot := arr[hi];
i := lo - 1;
- for j: lo .. hi+1 {
+ for j in lo .. hi+1 {
if cmp(arr[j], pivot) <= 0 {
i += 1;
tmp := arr[i];
pivot := &arr[hi];
i := lo - 1;
- for j: lo .. hi+1 {
+ for j in lo .. hi+1 {
if cmp(&arr[j], pivot) <= 0 {
i += 1;
tmp := arr[i];
#overload
fold :: (arr: [] $T, init: $R, f: (T, R) -> R) -> R {
val := init;
- for it: arr do val = f(it, val);
+ for it in arr do val = f(it, val);
return val;
}
#overload
fold :: macro (arr: [] $T, init: $R, body: Code) -> R {
acc := init;
- for it: arr do acc = #unquote body(it, acc);
+ for it in arr do acc = #unquote body(it, acc);
return acc;
}
Sets all elements in a slice to be `value`.
"""
fill :: (arr: [] $T, value: T) {
- for i: arr.count {
+ for i in arr.count {
arr[i] = value;
}
}
Sets all elements in the range to be `value`.
"""
fill_range :: (arr: [] $T, r: range, value: T) {
- for i: r {
+ for i in r {
if i >= arr.count || i < 0 do continue;
arr[i] = value;
}
to_list :: (arr: [] $T, allocator := context.allocator) -> List(T) {
new_list := list.make(T, allocator);
- for &it: arr {
+ for &it in arr {
list.push_end(&new_list, *it);
}
#overload
find :: (arr: [] $T, value: T) -> i32 {
- for i: arr.count {
+ for i in arr.count {
if value == arr.data[i] do return i;
}
#overload
find :: macro (arr: [] $T/type_is_struct, pred: Code) -> i32 {
- for i: arr.count {
+ for i in arr.count {
it := &arr[i];
if #unquote pred(it) do return i;
}
#overload
find :: macro (arr: [] $T, pred: Code) -> i32 {
- for i: arr.count {
+ for i in arr.count {
it := arr[i];
if #unquote pred(it) do return i;
}
Returns `null` if no matching element is found.
"""
find_ptr :: (arr: [] $T, value: T) -> &T {
- for &it: arr {
+ for &it in arr {
if value == *it do return it;
}
"""
find_opt :: #match {
macro (arr: [] $T/type_is_struct, cond: Code) -> ? T {
- for& it: arr {
+ for& it in arr {
if #unquote cond(it) {
return *it;
}
},
macro (arr: [] $T, cond: Code) -> ? T {
- for it: arr {
+ for it in arr {
if #unquote cond(it) {
return it;
}
// 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 in arr {
it := *it_ptr;
if #unquote predicate_body(it) do return it_ptr;
}
start := 0;
arr := arr_;
- for i: 1 .. arr.count {
+ for i in 1 .. arr.count {
if !#unquote comp(arr[start], arr[i]) {
out << arr[start .. i];
start = i;
equal :: (arr1: [] $T/HasEquals, arr2: [] T) -> bool {
if arr1.count != arr2.count do return false;
- for i: arr1.count {
+ for i in arr1.count {
if !(arr1[i] == arr2[i]) do return false;
}
idx := 0;
elem := arr[0];
- for i: 1 .. arr.count {
+ for i in 1 .. arr.count {
A := &arr[i];
B := &elem;
if #unquote cmp {
}
if min_length > 0 && len < min_length {
- for i: min_length - len {
+ for i in min_length - len {
c[0] = #char "0";
len += 1;
c -= 1;
}
if min_length > 0 && len < min_length {
- for i: min_length - len {
+ for i in min_length - len {
c[0] = #char "0";
len += 1;
c -= 1;
dec_part = math.abs(dec_part);
s1 := i64_to_str(~~int_part, 10, buf);
- for i: 0 .. s1.count do buf.data[i + len] = s1.data[i];
+ for i in 0 .. s1.count do buf.data[i + len] = s1.data[i];
len += s1.count;
if digits_after_decimal > 0 {
digits := "0123456789";
- for i: digits_after_decimal {
+ for i in digits_after_decimal {
dec_part *= 10;
v := math.trunc(dec_part);
dec_part -= v;
#if Enable_Custom_Formatters {
use runtime.info {*};
- for type_idx: type_table.count {
+ for type_idx in type_table.count {
type := type_table[type_idx];
if type.kind != .Struct do continue;
format_procedures := get_procedures_with_tag(Custom_Format_Proc);
defer delete(&format_procedures);
- for p: format_procedures {
+ for p in format_procedures {
custom_format := p.tag;
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);
- for p: parse_procedures {
+ for p in parse_procedures {
custom_parse := p.tag;
custom_parsers[custom_parse.type] = *cast(&(rawptr, str, Allocator) -> bool, &p.func);
}
},
(use output: &Format_Output, s: str) {
- for c: s {
+ for c in s {
if count >= capacity {
if flush.func == null_proc do return;
if !flush.func(flush.data, data[0 .. count]) do return;
format.indentation += 4;
}
- for &member: s.members {
+ for &member in s.members {
if member != s.members.data do output->write(", ");
if formatting.pretty_printing {
output->write(#char "\n");
- for i: format.indentation do output->write(#char " ");
+ for i in format.indentation do output->write(#char " ");
}
output->write(member.name);
if formatting.pretty_printing {
output->write(#char "\n");
- for i: formatting.indentation do output->write(#char " ");
+ for i in formatting.indentation do output->write(#char " ");
output->write("}");
} else {
format.quote_strings = true;
if format.pretty_printing do format.indentation += 4;
- for i: count {
+ for i in count {
if i != 0 do output->write(", ");
if formatting.pretty_printing {
output->write("\n");
- for _: format.indentation do output->write(#char " ");
+ for _ in format.indentation do output->write(#char " ");
}
format_any(output, &format, .{ cast([&] u8) data + get_type_info(a.of).size * i, a.of });
if formatting.pretty_printing {
format.indentation -= 4;
output->write("\n");
- for _: format.indentation do output->write(#char " ");
+ for _ in format.indentation do output->write(#char " ");
output->write(#char "]");
} else {
a := cast(&Type_Info_Array) info;
data := v.data;
- for i: a.count {
+ for i in a.count {
if i != 0 do output->write(", ");
format_any(output, formatting, .{ cast([&] u8) data + get_type_info(a.of).size * i, a.of });
}
if !e.is_flags {
- for &member: e.members {
+ for &member in e.members {
if value == member.value {
output->write(member.name);
break break;
} else {
first := true;
- for &member: e.members {
+ for &member in e.members {
if value & member.value != 0 {
if !first do output->write(" | ");
output->write(member.name);
encode :: (data: [] u8, allocator := context.allocator) -> [] u8 {
out := array.make(u8, allocator=allocator);
- for i: range.{0, data.count - 2, 3} {
+ for i in range.{0, data.count - 2, 3} {
c1 := data[i + 0];
c2 := data[i + 1];
c3 := data[i + 2];
out := array.make(u8, allocator=allocator);
- for i: range.{0, data.count, 4} {
+ for i in range.{0, data.count, 4} {
c1 := data[i + 0];
c2 := data[i + 1];
c3 := data[i + 2];
header_line := reader->read_line(allocator=context.temp_allocator)
|> string.strip_trailing_whitespace();
- for header: string.split_iter(header_line, #char ",") {
+ for header in string.split_iter(header_line, #char ",") {
member := array.first(output_type_info.members, [](do {
if tag := array.first(it.tags, [t](t.type == CSV_Column)); tag {
return any_as(*tag, CSV_Column).name == header;
}
} else {
- for &member: output_type_info.members {
+ for &member in output_type_info.members {
any_headers << .{ member.type, member.offset };
}
}
- for line: reader->lines(allocator = context.temp_allocator) {
+ for line in reader->lines(allocator = context.temp_allocator) {
out: csv.Output_Type;
- for entry: string.split_iter(string.strip_trailing_whitespace(line), #char ",")
+ for entry in string.split_iter(string.strip_trailing_whitespace(line), #char ",")
|> iter.enumerate()
{
header := &any_headers[entry.index];
output_type_info: &Type_Info_Struct = ~~ get_type_info(csv.Output_Type);
if include_headers {
- for &member: output_type_info.members {
+ for &member in output_type_info.members {
if !#first do io.write(writer, ",");
if tag := array.first(member.tags, [t](t.type == CSV_Column)); tag {
io.write(writer, "\n");
}
- for &it: csv.entries {
- for &member: output_type_info.members {
+ for &it in csv.entries {
+ for &member in output_type_info.members {
if !#first do io.write(writer, ",");
io.write_format_va(writer, "{}", .[ .{cast([&] u8) it + member.offset, member.type} ]);
#persist encode_map := u8.['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'];
new_str := make([] u8, s.count * 2, allocator);
- for i: s.count {
+ for i in s.count {
new_str[2 * i + 0] = encode_map[(s[i] & 0xf0) >> 4];
new_str[2 * i + 1] = encode_map[s[i] & 0xf];
}
assert(s.count & 1 == 0, "Expected string of even length");
new_str := make([] u8, s.count >> 1, allocator);
- for i: range.{0, s.count, 2} {
+ for i in range.{0, s.count, 2} {
new_str[i >> 1] = ~~((digit_to_value(s[i + 0]) << 4) | (digit_to_value(s[i + 1])));
}
continue;
}
- for& prop: member_info.members {
+ for& prop in member_info.members {
if !leave_empty_strings && prop.type == str {
if cast(&str, member_data + prop.offset).length == 0 {
continue;
(w: ^io.Writer, v: [] $T) -> Encoding_Error {
io.write_byte(w, #char "[");
- for i: v.count {
+ for i in v.count {
if i > 0 do io.write_byte(w, #char ",");
err := encode(w, v[i]);
(w: ^io.Writer, v: [..] $T) -> Encoding_Error {
io.write_byte(w, #char "[");
- for i: v.count {
+ for i in v.count {
if i > 0 do io.write_byte(w, #char ",");
err := encode(w, v[i]);
(w: ^io.Writer, v: Map(str, $T)) -> Encoding_Error {
io.write_byte(w, #char "{");
- for i: v.entries.count {
+ for i in v.entries.count {
if i > 0 do io.write_byte(w, #char ",");
entry := ^v.entries[i];
io.write_byte(w, #char "{");
obj := cast(^_Value_Object) cast(^_Value) v;
- for i: obj.object_.count {
+ for i in obj.object_.count {
if i > 0 do io.write_byte(w, #char ",");
io.write_escaped_str(w, obj.object_[i].key);
a := cast(^Type_Info_Array) info;
arr := data.data;
- for i: a.count {
+ for i in a.count {
if i != 0 do io.write(w, ",");
encode(w, misc.any_subscript(data, i));
arr := cast(^core.array.Untyped_Array) data.data;
count := arr.count;
- for i: count {
+ for i in count {
if i != 0 do io.write(w, ",");
encode(w, misc.any_subscript(data, i));
io.write(w, "{");
- for ^member: s.members {
+ for ^member in s.members {
key := member.name;
if tag := array.first(member.tags, [t](t.type == Custom_Key)); tag != null {
key = (cast(^Custom_Key) tag.data).key;
from_any :: #match #local {}
#overload
-from_any :: macro (in: ^$T, allocator := context.allocator) -> Value {
+from_any :: macro (v: ^$T, allocator := context.allocator) -> Value {
from_any :: from_any
- return from_any(T, in, allocator);
+ return from_any(T, v, allocator);
}
#overload
-from_any :: (type: type_expr, in: rawptr, allocator := context.allocator) -> Value {
+from_any :: (type: type_expr, v: rawptr, allocator := context.allocator) -> Value {
use runtime.info;
t_info := get_type_info(type);
case .Basic do switch type {
// These functions handle the cases where the types do
// not match, so no additional checks are needed here.
- case bool { v := new(_Value_Bool, allocator); v.bool_ = *cast(^bool) in; return Value.{v}; }
- case i32, u32 { v := new(_Value_Integer, allocator); v.int_ = ~~ *cast(^i32) in; return Value.{v}; }
- case i64, u64 { v := new(_Value_Integer, allocator); v.int_ = *cast(^i64) in; return Value.{v}; }
- case f32 { v := new(_Value_Float, allocator); v.float_ = ~~ *cast(^f32) in; return Value.{v}; }
- case f64 { v := new(_Value_Float, allocator); v.float_ = *cast(^f64) in; return Value.{v}; }
+ case bool { v := new(_Value_Bool, allocator); v.bool_ = *cast(^bool) v; return Value.{v}; }
+ case i32, u32 { v := new(_Value_Integer, allocator); v.int_ = ~~ *cast(^i32) v; return Value.{v}; }
+ case i64, u64 { v := new(_Value_Integer, allocator); v.int_ = *cast(^i64) v; return Value.{v}; }
+ case f32 { v := new(_Value_Float, allocator); v.float_ = ~~ *cast(^f32) v; return Value.{v}; }
+ case f64 { v := new(_Value_Float, allocator); v.float_ = *cast(^f64) v; return Value.{v}; }
}
case .Array {
v := new(_Value_Array, allocator);
array.init(^v.array_, a_info.count, allocator);
- for i: a_info.count {
- v.array_ << from_any(a_info.of, memory.ptr_add(in, size_of(a_info.of) * i));
+ for i in a_info.count {
+ v.array_ << from_any(a_info.of, memory.ptr_add(v, size_of(a_info.of) * i));
}
return Value.{v};
// Strings are handled differently
if type == str {
v := new(_Value_String, allocator);
- v.str_ = string.alloc_copy(*cast(^str) in, allocator);
+ v.str_ = string.alloc_copy(*cast(^str) v, allocator);
return Value.{v};
}
s_info := cast(^Type_Info_Slice) t_info;
- s := cast(^core.array.Untyped_Array) in;
+ s := cast(^core.array.Untyped_Array) v;
v := new(_Value_Array, allocator);
array.init(^v.array_, s.count, allocator);
- for i: s.count {
+ for i in s.count {
v.array_ << from_any(s_info.of, memory.ptr_add(s.data, size_of(s_info.of) * i));
}
v := new(_Value_Object, allocator);
array.init(^v.object_, s_info.members.count, allocator);
- for^ member: s_info.members {
+ for^ member in s_info.members {
key := member.name;
if tag := array.first(member.tags, [t](t.type == Custom_Key)); tag != null {
key = (cast(^Custom_Key) tag.data).key;
}
}
- json.set(Value.{v}, key, from_any(member.type, memory.ptr_add(in, member.offset)), dont_copy_key=true);
+ json.set(Value.{v}, key, from_any(member.type, memory.ptr_add(v, member.offset)), dont_copy_key=true);
}
return Value.{v};
case .Distinct {
if type == Value {
- return *cast(^Value) in;
+ return *cast(^Value) v;
}
d_info := cast(^Type_Info_Distinct) t_info;
- return from_any(d_info.base_type, in);
+ return from_any(d_info.base_type, v);
}
case .Union {
}
u := t_info->as_union();
- tag := *cast(&Optional(void).tag_enum) in;
+ tag := *cast(&Optional(void).tag_enum) v;
if tag != .Some {
return null_value();
} else {
- return from_any(u.variants[1].type, memory.ptr_add(in, u.alignment), allocator);
+ return from_any(u.variants[1].type, memory.ptr_add(v, u.alignment), allocator);
}
}
}
case .Array {
a_info := cast(^Type_Info_Array) t_info;
- for i: a_info.count {
+ for i in a_info.count {
to_any(value[i], a_info.of, memory.ptr_add(out, size_of(a_info.of) * i));
}
}
s.count = to_copy.count;
}
- for i: s.count {
+ for i in s.count {
to_any(value[i], s_info.of, memory.ptr_add(s.data, size_of(s_info.of) * i));
}
}
case .Struct {
s_info := cast(^Type_Info_Struct) t_info;
- for^ member: s_info.members {
+ for^ member in s_info.members {
key := member.name;
if tag := array.first(member.tags, [t](t.type == Custom_Key)); tag != null {
key = (cast(^Custom_Key) tag.data).key;
// This uses the context allocators because the array resizing needs to happen in a general purpose heap allocator
arr := array.make(Value, allocator=context.allocator);
defer if err.kind != .None {
- for elem: arr {
+ for elem in arr {
free(elem, allocator);
}
// Checking for duplicate keys. I have it disabled for the moment.
#if false {
- for elem: value.object_ {
+ for elem in value.object_ {
if elem.key == key {
err.kind = .Duplicate_Keys;
err.pos = key_token.pos;
s = s.data[1 .. s.count - 1];
i := 0;
- for c: s {
+ for c in s {
if c == #char "\\" || c == #char "\"" || c < #char " " {
break;
}
chars := 0;
codepoint: u32 = 0;
- for c: s[0 .. 4] {
+ for c in s[0 .. 4] {
codepoint = codepoint << 4;
codepoint |= digit_to_hex(c);
}
second_codepoint: u32 = 0;
if s[4 .. 6] != "\\u" do return 0, 0;
- for c: s[6 .. 10] {
+ for c in s[6 .. 10] {
second_codepoint = second_codepoint << 4;
second_codepoint |= digit_to_hex(c);
}
skip_escape :: (use tkn: ^Tokenizer) {
switch data[offset] {
case #char "u" {
- for i: 4 {
+ for i in 4 {
ch, _ := next_character(tkn);
switch ch {
case #char "0" .. #char "9",
v_ := cast(^_Value) v;
if v_.type != .Object do return Value.{^_null_value};
- for ^entry: (cast(^_Value_Object) v_).object_ {
+ for ^entry in (cast(^_Value_Object) v_).object_ {
if entry.key == key do return entry.value;
}
return Value.{^_null_value};
case .Array {
v_arr := cast(^_Value_Array) v_;
- for elem: v_arr.array_ {
+ for elem in v_arr.array_ {
free(elem, allocator);
}
array.free(^v_arr.array_);
case .Object {
v_obj := cast(^_Value_Object) v_;
- for ^entry: v_obj.object_ {
+ for ^entry in v_obj.object_ {
if !entry.dont_free_key do raw_free(allocator, entry.key.data);
free(entry.value, allocator);
}
});
switch v.data {
- case s: .String {
+ case .String as s {
io.write_format(w, "{\"}", s);
}
- case n: .Number do switch n {
- case i: .Integer do io.write_format(w, "{}", i);
- case f: .Float do io.write_format(w, "{}", f);
- case s: .String do io.write_format(w, "{\"}", s);
+ case .Number as n do switch n {
+ case .Integer as i do io.write_format(w, "{}", i);
+ case .Float as f do io.write_format(w, "{}", f);
+ case .String as s do io.write_format(w, "{\"}", s);
}
- case b: .Boolean {
+ case .Boolean as b {
io.write_format(w, "{}", b);
}
string.free(n.node, al);
n.type_annotation->with([t] { string.free(t, al); });
- for& v: n.values do free_value(al, v);
+ for& v in n.values do free_value(al, v);
delete(&n.values); // This should use the allocator inside of the array
for n.props->as_iter() {
v.type_annotation->with([t] { string.free(t, al); });
switch v.data {
- case s: .String {
+ case .String as s {
string.free(s, al);
}
- case num: .Number do switch num {
- case s: .String {
+ case .Number as num do switch num {
+ case .String as s {
string.free(s, al);
}
}
node_index -= 1;
- for segment: s.segments[1 .. s.segments.length] {
+ for segment in s.segments[1 .. s.segments.length] {
switch segment.op->unwrap() {
case .Child, .Descendant {
while node_index >= 0 {
skip_whitespace(p);
switch parse_matcher(p) {
- case matcher: .Some {
+ case .Some as matcher {
segment := p.al->move(SelectorSegment.{
matcher = matcher
});
parse_value :: (self: &#Self, token: Token) -> ? Value {
switch token {
- case s: .Raw_String {
+ case .Raw_String as s {
return Value.{
data = .{ String = string.alloc_copy(s, self.result_allocator) }
};
}
- case s: .String {
+ case .String as s {
// TODO: Handle escaped strings here
return Value.{
data = .{ String = string.alloc_copy(s, self.result_allocator) }
};
}
- case w: .Word {
+ case .Word as w {
if w == "null" {
return Value.{
data = .{ Null = .{} }
base: [&] u8 = ~~v.data;
- for& member: s_info.members {
+ for& member in s_info.members {
try(serialize(any.{ base + member.offset, member.type }, w));
}
}
base: [&] u8 = target;
- for& member: s_info.members {
+ for& member in s_info.members {
try(deserialize(base + member.offset, member.type, r, allocator));
}
}
(key: i64) -> u32 { return cast(u32) (cast(u64) 0xcbf29ce7 ^ cast(u64) key); },
(key: str) -> u32 {
hash: u32 = 5381;
- for ch: key do hash += (hash << 5) + ~~ch;
+ for ch in key do hash += (hash << 5) + ~~ch;
return hash;
},
(key: type_expr) -> u32 { return hash(cast(u32) key); },
#doc "Returns a temporary byte array of the hash."
as_str :: (self: #Self) -> [] u8 {
result := make_temp([] u8, 16);
- for i: 0 .. 4 do result[i] = ~~((self.a & (0xff << shift(i))) >> shift(i));
- for i: 4 .. 8 do result[i] = ~~((self.b & (0xff << shift(i))) >> shift(i));
- for i: 8 .. 12 do result[i] = ~~((self.c & (0xff << shift(i))) >> shift(i));
- for i: 12 .. 16 do result[i] = ~~((self.d & (0xff << shift(i))) >> shift(i));
+ for i in 0 .. 4 do result[i] = ~~((self.a & (0xff << shift(i))) >> shift(i));
+ for i in 4 .. 8 do result[i] = ~~((self.b & (0xff << shift(i))) >> shift(i));
+ for i in 8 .. 12 do result[i] = ~~((self.c & (0xff << shift(i))) >> shift(i));
+ for i in 12 .. 16 do result[i] = ~~((self.d & (0xff << shift(i))) >> shift(i));
return result;
}
#doc "Returns a temporary string of the hash."
as_hex_str :: (self: #Self) -> str {
result := make_temp([..] u8, 32);
- for i: 0 .. 4 do conv.format(&result, "{w2b16}", (self.a & (0xff << shift(i)) >> shift(i)));
- for i: 4 .. 8 do conv.format(&result, "{w2b16}", (self.b & (0xff << shift(i)) >> shift(i)));
- for i: 8 .. 12 do conv.format(&result, "{w2b16}", (self.c & (0xff << shift(i)) >> shift(i)));
- for i: 12 .. 16 do conv.format(&result, "{w2b16}", (self.d & (0xff << shift(i)) >> shift(i)));
+ for i in 0 .. 4 do conv.format(&result, "{w2b16}", (self.a & (0xff << shift(i)) >> shift(i)));
+ for i in 4 .. 8 do conv.format(&result, "{w2b16}", (self.b & (0xff << shift(i)) >> shift(i)));
+ for i in 8 .. 12 do conv.format(&result, "{w2b16}", (self.c & (0xff << shift(i)) >> shift(i)));
+ for i in 12 .. 16 do conv.format(&result, "{w2b16}", (self.d & (0xff << shift(i)) >> shift(i)));
return result;
}
}
c := digest.c;
d := digest.d;
- for i: 0 .. 64 {
+ for i in 0 .. 64 {
F, g: u32;
if 0 <= i && i <= 15 {
F = (b & c) | (~b & d);
}
update :: (self: &#Self, data: [] u8) {
- for i: 0 .. data.count {
+ for i in 0 .. data.count {
self.data[self.data_length] = data[i];
self.data_length += 1;
self.data[56] = cast(u8, self.bit_length >> 56);
do_cycle(self, self.data);
- for i: 0 .. 4 {
+ for i in 0 .. 4 {
out[i + 0] = ~~((self.state[0] >> (24 - i * 8)) & 0xff);
out[i + 4] = ~~((self.state[1] >> (24 - i * 8)) & 0xff);
out[i + 8] = ~~((self.state[2] >> (24 - i * 8)) & 0xff);
do_cycle :: (self: &Hasher, data: [] u8) {
m: [64] u32;
- for i: 0 .. 16 {
+ for i in 0 .. 16 {
j := 4 * i;
m[i] = (cast(u32, data[j]) << 24)
| (cast(u32, data[j + 1]) << 16)
| (cast(u32, data[j + 3]));
}
- for i: 16 .. 64 {
+ for i in 16 .. 64 {
m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16];
}
g := self.state[6];
h := self.state[7];
- for i: 0 .. 64 {
+ for i in 0 .. 64 {
t1 := h + EP1(e) + CH(e, f, g) + k[i] + m[i];
t2 := EP0(a) + MAJ(a, b, c);
h = g;
temp: [3] u8;
u8_ptr := cast([&] u8) ptr;
- for i: byte_count {
+ for i in byte_count {
val := u8_ptr[i];
temp[0] = map_to_ascii(val >> 4);
// BufferStream
//
// In older times of the standard library, there were two string
-// streams that existed for different purposes: StringStream and
+// streams that existed for different purposes in StringStream and
// DynamicStringStream. I have since merged them into one stream
// called, BufferStream. Besides the names being confusing and
// long, I thought it was needlessly complicated to have two
}
write_range :: (use writer: &Writer, r: range, sep := " ") {
- for i: r {
+ for i in r {
write_i32(writer, i);
if i + r.step < r.high do write_str(writer, sep);
}
assert(T == i32 || T == i64 || T == u32 || T == u64, "bad type for choose function");
ret := 1;
- for i: (n - k + 1) .. (n + 1) {
+ for i in (n - k + 1) .. (n + 1) {
ret *= i;
}
- for i: 1 .. (k + 1) {
+ for i in 1 .. (k + 1) {
ret /= i;
}
data_base := *cast(&rawptr) output.data;
- for #no_close arg: arg_iter {
- for &member: arg_type.members {
- for &tag: member.tags {
+ for #no_close arg in arg_iter {
+ for &member in arg_type.members {
+ for &tag in member.tags {
if tag.type != str do continue;
to_match := *cast(&str) tag.data;
#inject
SocketAddress.addr_as_str :: (this: &SocketAddress, allocator := context.allocator) -> str {
return switch *this {
- case path: .Unix => string.as_str(cast(cstr) path);
- case inet: .Inet => do {
+ case .Unix as path => string.as_str(cast(cstr) path);
+ case .Inet as inet => do {
str_addr := ipv4_to_str(inet.addr);
out := make(dyn_str, allocator);
return conv.format(&out, "{}:{}", str_addr, inet.port);
}
- case inet6: .Inet6 => do {
+ case .Inet6 as inet6 => do {
str_addr := ipv6_to_str(inet6.addr);
out := make(dyn_str, allocator);
return conv.format(&out, "{}:{}", str_addr, inet6.port);
}
- case host: .HostPort => do {
+ case .HostPort as host => do {
out := make(dyn_str, allocator);
return conv.format(&out, "{}:{}", host.host, host.port);
}
if sockets.count > stat_buff.count do return;
handles := alloc.array_from_stack(runtime.platform.PollDescription, sockets.count);
- for i: sockets.count {
+ for i in sockets.count {
handles[i] = .{
~~cast(i32) sockets[i].handle, .Read
};
}
runtime.platform.__poll(handles, timeout);
- for i: sockets.count {
- stat_buff[i] = switch handles[i].out {
+ for i in sockets.count {
+ stat_buff[i] = switch handles[i].out_events {
case .None => .No_Change
case .Read => .Readable
case .Closed => .Closed
runtime.platform.__poll(fds, timeout);
- return switch fds[0].out {
+ return switch fds[0].out_events {
case .None => .No_Change
case .Read => .Readable
case .Closed => .Closed
socket_poll_all(cast([] &Socket) active_clients, status_buffer, pulse_time_ms);
recv_clients: [..] &TCP_Server.Client;
- for it: client_count {
+ for it in client_count {
if status_buffer[it] == .Readable {
//
// If there is already a Ready event present for this client,
generate_c_binding :: (use binding_config: Binding_Config) -> bool {
wrote := false;
- for file: os.with_file(output_file, .Write) {
+ for file in os.with_file(output_file, .Write) {
writer := io.writer_make(file);
defer io.writer_free(&writer);
write_file_introduction(&writer, preamble, fb.module_name);
for fb.funcs {
- for impl: custom_implementations {
+ for impl in custom_implementations {
if impl.name == it.name {
io.write(&writer, impl.impl);
io.write(&writer, "\n");
io.write_format(writer, "// THIS FILE WAS AUTOMATICALLY GENERATED.\n");
io.write_format(writer, "//\n");
- for text: preamble {
+ for text in preamble {
io.write_format(writer, "{}\n", text);
}
switch slice.find_opt(ff.tags, [it](it.type == func_body))
->transform(x => misc.any_as(x, func_body).body)
{
- case body: .Some {
+ case .Some as body {
io.write(writer, body);
io.write(writer, " return NULL;");
}
defer delete(&call_signature);
func_info := it_info->as_function();
- for p: func_info.parameter_types {
+ for p in func_info.parameter_types {
map_to_dyncall(p, &call_signature);
}
} else {
matched := false;
- for& m: cast_map {
+ for& m in cast_map {
if m.type == it {
io.write_format(&callw, "({}) P({}, {})", m.name, param_num, type_to_wasm_type(it));
matched = true;
return ~~(this.data - mem_base_ptr + 1);
}
- as :: (this: cptr($T), $new_type: type_expr) -> cptr(new_type) {
+ as_unsafe :: (this: cptr($T), $new_type: type_expr) -> cptr(new_type) {
return .{ this.data };
}
path_join :: (path: ..str) -> str {
out := make(dyn_str, allocator=context.temp_allocator);
- for p: path {
+ for p in path {
conv.format(&out, "{}{}", p, PATH_SEP);
}
path_extension("foo/bar.txt") -> "txt"
"""
path_extension :: (path: str) -> str {
- for i: range.{ path.length - 1, 0, -1 } {
+ for i in range.{ path.length - 1, 0, -1 } {
if path[i] == PATH_SEP do break;
if path[i] == '.' do return path[i .. path.length];
}
get_globals_with_tag :: ($tag_type: type_expr) -> [] GGWT_Result(tag_type) {
results := make([..] GGWT_Result(tag_type));
- for glob: tagged_globals {
+ for glob in tagged_globals {
slice.find_opt(glob.tags, [v](v.type == tag_type))->with([tag] {
array.push(&results, .{
data = glob.data,
io.write_str(writer, "(");
i := 0;
- for type: comp.components {
+ for type in comp.components {
if i != 0 do io.write_str(writer, ", ");
write_type_name(writer, type);
io.write_str(writer, "(");
i := 0;
- for type: f.parameter_types {
+ for type in f.parameter_types {
if i != 0 do io.write_str(writer, ", ");
write_type_name(writer, type);
if info.kind != .Struct do return 0;
struct_info := cast(&Type_Info_Struct) info;
- for &m: struct_info.members {
+ for &m in struct_info.members {
if m.name == member_name do return m.offset;
}
if info.kind != .Enum do return null_str;
etype := cast(&Type_Info_Enum) info;
- for &member: etype.members {
+ for &member in etype.members {
if member.value == ~~value do return member.name;
}
if info.kind != .Enum do return ~~0;
etype := cast(&Type_Info_Enum) info;
- for &member: etype.members {
+ for &member in etype.members {
if member.name == name do return ~~member.value;
}
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 in v_info.members {
if get_type_info(member.type).kind != .Function do continue;
struct_method := get_struct_method(struct_type, member.name);
get_procedures_with_tag :: ($tag_type: type_expr) -> [] GPWT_Result(tag_type) {
results := make([..] GPWT_Result(tag_type));
- for proc: tagged_procedures {
+ for proc in tagged_procedures {
if tag := array.first(proc.tags, [v](v.type == tag_type)); tag != null {
array.push(&results, .{
func = proc.func,
PollDescription :: struct {
fd: u64;
- in: io.PollEvent;
- out: io.PollEvent;
+ in_events: io.PollEvent;
+ out_events: io.PollEvent;
}
#foreign "onyx_runtime" {
fds: [1] PollDescription;
fds[0] = .{
fd = ~~data,
- in = ev
+ in_events = ev
};
__poll(fds, timeout);
- if fds[0].out == .Closed {
+ if fds[0].out_events == .Closed {
return .EOF, ev == .Closed;
}
- return .None, fds[0].out == ev;
+ return .None, fds[0].out_events == ev;
}
};
__net_sock_bind :: (s: SocketData, addr: &SocketAddress) -> bool {
switch *addr {
- case &path: .Unix {
+ case .Unix as &path {
return __net_bind_unix(s, ~~path);
}
- case ipv4: .Inet {
+ case .Inet as ipv4 {
return __net_bind_ipv4(s, ipv4.addr, ipv4.port);
}
- case host: .HostPort {
+ case .HostPort as host {
return __net_bind_host(s, host.host, host.port);
}
__net_sock_connect :: (s: SocketData, addr: &SocketAddress) -> io.Error {
switch *addr {
- case &path: .Unix {
+ case .Unix as &path {
return __net_connect_unix(s, ~~path)
|> translate_error();
}
- case i: .Inet {
+ case .Inet as i {
return __net_connect_ipv4(s, i.addr, i.port)
|> translate_error();
}
- case i: .Inet6 {
+ case .Inet6 as i {
return __net_connect_ipv6(s, i.addr, i.port)
|> translate_error();
}
- case h: .HostPort {
+ case .HostPort as h {
return __net_connect_host(s, h.host, h.port)
|> translate_error();
}
__net_sock_send_to :: (s: SocketData, buf: [] u8, addr: &SocketAddress) -> Result(i32, io.Error) {
sent := switch *addr {
- case &path: .Unix => __net_sendto_unix(s, buf, ~~path);
- case i: .Inet => __net_sendto_ipv4(s, buf, i.addr, i.port);
- case i: .Inet6 => __net_sendto_ipv6(s, buf, i.addr, i.port);
- case h: .HostPort => __net_sendto_host(s, buf, h.host, h.port);
+ case .Unix as &path => __net_sendto_unix(s, buf, ~~path);
+ case .Inet as i => __net_sendto_ipv4(s, buf, i.addr, i.port);
+ case .Inet6 as i => __net_sendto_ipv6(s, buf, i.addr, i.port);
+ case .HostPort as h => __net_sendto_host(s, buf, h.host, h.port);
};
if sent == -1
}
subs := core.alloc.array_from_stack(wasi.Subscription, count);
- for i: fds.count {
+ for i in fds.count {
subs[i].userdata = ~~ i;
subs[i].u.tag = switch fds[i].in {
case .None => .FDRead;
if error_code != .Success do return;
if number_of_events == 0 do return;
- for ev: events[0 .. number_of_events] {
+ for ev in events[0 .. number_of_events] {
if ev.type !=.Clock {
if ev.fd_readwrite.nbytes > 0 {
i := cast(i32) ev.userdata;
}
result := make([..] Pair(str, str), env_count, allocator);
- for env: env_var {
+ for env in env_var {
s := string.from_cstr(env);
var, val := string.bisect(s, '=');
result << .{var, val};
// Currently the directory's file descriptor appears to always be 3
// However, this is not necessarily correct, so also try a preopened directory
- for DIR_FD: .[ 3, 4 ] {
+ for DIR_FD in .[ 3, 4 ] {
if err := wasi.path_open(
DIR_FD,
.SymLinkFollow,
#package {
socket_addr_to_wasix_addr :: (in: &SocketAddress, out: &wasi.AddrPort) {
switch *in {
- case &path: .Unix {
+ case .Unix as &path {
*out = .{ Unix = .{ *cast(&[108] u8) path } };
}
- case &inet: .Inet {
+ case .Inet as &inet {
*out = .{ Ipv4 = .{ inet.port, *cast(&wasi.AddrIPv4)&inet.addr } };
}
- case &inet: .Inet6 {
+ case .Inet6 as &inet {
// Not entirely right...
*out = .{ Ipv6 = .{ inet.port, *cast(&wasi.AddrIPv6)&inet.addr } };
}
switch *in {
case .Unspec ---
- case &inet: .Ipv4 {
+ case .Ipv4 as &inet {
*out = .{ Inet = .{ inet.port, *cast(&u32)&inet.addr } };
}
- case &inet: .Ipv6 {
+ case .Ipv6 as &inet {
*out = .{ Inet6 = .{ inet.port, *cast(&[16] u8)&inet.addr } };
}
- case &unix: .Unix {
+ case .Unix as &unix {
p: [256] u8 = *cast(&[256] u8) &unix.path;
*out = .{ Unix = p };
}
initial_length := math.min(initial_str.count, buffer.capacity);
buffer.count += initial_length;
- for i: initial_length {
+ for i in initial_length {
buffer.data[i] = initial_str.data[i];
}
}
buffer_append :: (use buffer: &String_Buffer, end: str) -> bool {
if count + end.count > capacity do return false;
- for i: end.count {
+ for i in end.count {
data[i + count] = end[i];
}
#overload
concat :: (allocator: Allocator, strings: ..str) -> str {
total_length := 0;
- for s: strings do total_length += s.count;
+ for s in strings do total_length += s.count;
data := cast([&] u8) raw_alloc(allocator, total_length);
offset := 0;
- for s: strings {
+ for s in strings {
memory.copy(data + offset, s.data, s.count);
offset += s.count;
}
#overload
concat :: (buffer: [] u8, strings: ..str) -> str {
total_copied := 0;
- for s: strings {
+ for s in strings {
// Should never greater than, but better safe than sorry.
if total_copied >= buffer.count do break;
#overload
concat :: (into: &[..] u8, strings: ..str) -> str {
- for s: strings {
+ for s in strings {
array.ensure_capacity(into, into.count + s.count);
memory.copy(into.data + into.count, s.data, s.count);
into.count += s.count;
#overload
concat :: (into: &[..] u8, chars: ..u8) -> str {
array.ensure_capacity(into, into.count + chars.count);
- for c: chars {
+ for c in chars {
memory.copy(into.data + into.count, cast(rawptr) &.[c], 1);
into.count += 1;
}
#overload
contains :: (s: str, c: u8) -> bool {
- for ch: s do if ch == c do return true;
+ for ch in s do if ch == c do return true;
return false;
}
}
to_uppercase :: (s: str) -> str {
- for& ch: s {
+ for& ch in s {
if *ch >= #char "a" && *ch <= #char "z" {
*ch -= 32;
}
}
to_lowercase :: (s: str) -> str {
- for& ch: s {
+ for& ch in s {
if *ch >= #char "A" && *ch <= #char "Z" {
*ch += 32;
}
}
replace :: (s: str, to_replace: u8, replace_with: u8) {
- for &c: s {
+ for &c in s {
if *c == to_replace do *c = replace_with;
}
}
out.count = 0;
rem := skip;
- for ch: *s {
+ for ch in *s {
if ch == upto {
if rem <= 0 do break;
else do rem -= 1;
out.data = s.data;
out.count = 0;
- for ch: *s {
+ for ch in *s {
switch ch {
case #char "a" .. #char "z",
#char "A" .. #char "Z",
out.count = 0;
rem := skip;
- for ch: *s {
- for upto: uptos {
+ for ch in *s {
+ for upto in uptos {
if ch == upto {
if rem <= 0 do break break;
else do rem -= 1;
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;
+ for i in 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 {
+ for i in 0 .. s.count {
if s[i] == delim {
strarr[curr_str] = s.data[begin .. i];
begin = i + 1;
string.advance(&format);
switch format[0] {
case #char "a", #char "A" {
- for i: weekdays.count {
+ for i in weekdays.count {
w := weekdays[i];
if string.equal_insensitive(w, buf[0 .. w.length]) {
string.advance(&buf, w.length);
}
case #char "b", #char "B", #char "h" {
- for i: monthnames.count {
+ for i in monthnames.count {
m := monthnames[i];
if string.equal_insensitive(m, buf[0 .. m.length]) {
string.advance(&buf, m.length);
// of creating and using a fixed size array. This uses a for-loop which we have not
// looked at yet, but the example should be self-explanatory.
fixed_arr : [10] i32;
- for i: 0 .. 10 {
+ for i in 0 .. 10 {
fixed_arr[i] = i * i;
}
core.printf("fixed_arr[3] is {}\n", fixed_arr[3]);
core.array.init(^dyn_arr);
defer core.array.free(^dyn_arr);
- for i: 0 .. 10 {
+ for i in 0 .. 10 {
core.array.push(^dyn_arr, i * i * i);
}
// with a for loop. Note, the `^` after the for keyword means we are iterating by
// pointer.
arr : [10] i32;
- for ^elem: arr do *elem = 0;
+ for ^elem in arr do *elem = 0;
// To access certain elements of the array, simply use the array access operator,
// [...], as so. This sets the fourth element of the array to be 1234.
printf("arr[3] is {}\n", arr[3]);
// Fixed-size arrays can be iterated over using a `for` loop as so.
- for element: arr {
+ for element in arr {
printf("{} ", element);
}
print("\n");
// the array `arr` is passed by reference so when the for loop changes the
// contents of `array_param`, the contents of `arr` are changed as well.
array_proc :: (array_param: [10] i32) {
- for i: 0 .. 10 {
+ for i in 0 .. 10 {
array_param[i] = 1000 + i;
}
}
array_proc(arr);
- for element: arr {
+ for element in arr {
printf("{} ", element);
}
// array. Slices and dynamic arrays do not operate this way.
other_arr : [10] i32;
other_arr = arr;
- for other_element: other_arr do printf("{} ", other_element);
+ for other_element in other_arr do printf("{} ", other_element);
print("\n");
// This does mean that the following pattern of double buffering arrays (which
// OR
arr_lit := i32.[ 2, 3, 5, 7, 11 ];
- for elem: arr_lit do printf("{} ", elem);
+ for elem in arr_lit do printf("{} ", elem);
print("\n");
// The type of the elements of the array is given right before the `.`. The
slice.count = 4;
// You can iterate over slices directly using a for-loop.
- for elem: slice do printf("{} ", elem);
+ for elem in slice do printf("{} ", elem);
print("\n");
// Another equivalent way of writing lines 22 and 23 is to
slice = arr[3 .. 7];
// Printing it out to verify it is the same.
- for elem: slice do printf("{} ", elem);
+ for elem in slice do printf("{} ", elem);
print("\n");
// Since strings are represented as slices in Onyx, substrings
// to use it. The most common function you will probably use
// is array.push. It simply appends a new element to end of
// the array.
- for i: 0 .. 10 do array.push(^arr, i);
+ for i in 0 .. 10 do array.push(^arr, i);
// Now if we print the array, we will see the numbers from 0 to 9.
println(arr);
// We can remove elements from the end using array.pop.
- for i: 0 .. 4 do array.pop(^arr);
+ for i in 0 .. 4 do array.pop(^arr);
println(arr);
// We can insert elements at the beginning using array.insert.
- for i: 6 .. 10 do array.insert(^arr, 0, i);
+ for i in 6 .. 10 do array.insert(^arr, 0, i);
println(arr);
// There are many other useful functions in the core.array package.
println("param_struct_instance values:");
println(param_struct_instance.t_member);
- for elem: param_struct_instance.array_of_T do printf("{} ", elem);
+ for elem in param_struct_instance.array_of_T do printf("{} ", elem);
print("\n");
use core {package, *}
main :: (args: [] cstr) {
- // Currently, for loops can iterate over five kinds of data structures in Onyx:
+ // Currently, for loops can iterate over five kinds of data structures in Onyx in
// * Ranges
// * Fixed arrays
// * Slices
// * Dynamic arrays
// * Custom iterators
- // The syntax of for loops is very simple:
- // for ^? <iteration variable>: <iterator> <block>
+ // The syntax of for loops is very simple in
+ // for ^? <iteration variable> in <iterator> <block>
// For example, this will print out the numbers in the array literal:
- for i: u32.[ 10, 20, 30, 40, 50 ] {
+ for i in u32.[ 10, 20, 30, 40, 50 ] {
println(i);
}
print("\n\n");
// so:
primes := u32.[ 2, 3, 5, 7, 11, 13, 17 ];
- for ^prime: primes {
+ for ^prime in primes {
*prime *= 2;
}
iterator: Iterator(i32) = .{ data = ^value, next = next, close = close };
// Simply use the iterator.
- for v: iterator {
+ for v in iterator {
println(v);
}
}
// and will "disappear" when the procedure returns.
typed_varargs :: (args: ..i32) {
print("Typed variadic arguments: ");
- for x: args {
+ for x in args {
printf("{} ", x);
}
print("\n");
any_varargs :: (args: ..any) {
print("Any variadic arguments: ");
- for arg: args {
+ for arg in args {
printf("{}, ", arg.type);
}
person_set << .{ "Joe", 38 };
// "Joe" will only be printed once.
- for person: set.as_iter(^person_set) {
+ for person in set.as_iter(^person_set) {
println(person);
}
}
// print_type is a little silly to have in this language because Onyx has complete
// type knowledge at runtime. To rectify this, let's add a new case that makes
-// this work for any type:
+// this work for any type in
#match #order 10 print_type (x: $T) {
printf("Fallback case: called with a {} ({})\n", T, x);
Person :: struct { name: str; age: i32; }
-// The overload option for hashing a person:
+// The overload option for hashing a person in
#match hash.to_u32 (use p: Person) -> u32 {
return hash.to_u32(name) * 16239563 + age;
}
// If you are unfamiliar, polymorphic procedures allow you to write code that applies
// to all types, instead of to only a particular type. For example, you will probably
// want something like a max function that returns the larger of its two arguments.
-// You might start by writing it for just integer types as so:
+// You might start by writing it for just integer types as so in
max :: (a: i32, b: i32) -> i32 {
return a if a > b else b;
}
// You can then use the '#unquote' directive to place the code wherever you need it.
- // We can paste it 3 times for examples:
+ // We can paste it 3 times for examples in
#unquote simple_code;
#unquote simple_code;
#unquote simple_code;
// I forget that it exists. It isn't something that is very useful,
// and can lead to some code-smells, if do-blocks are used in strange
// places, like as arguments. However, during the Advent of Code 2021
- // I had a real use-case for them and it looked like this:
+ // I had a real use-case for them and it looked like this in
#if false {
left, right := do {
consume :: (it: $T) -> #auto where iter.Iterable(T) {
consume_inner :: macro (it: Iterator($V)) -> [] V {
arr: [..] V;
- for v: it do arr << v;
+ for v in it do arr << v;
return arr;
}
#tag Command.{ "help", "Show help.", "", require_config_file=false }
run_help_command :: (args: [] cstr) {
printf("onyx pkg version {}\n", Version);
- printf("Package dependency resolver and synchronizer for Onyx.\n\nUsage:\n");
+ printf("Package dependency resolver and synchronizer for Onyx.\n\nUsage in\n");
command_procedures := runtime.info.get_procedures_with_tag(Command);
defer delete(&command_procedures);
lines := string.split(it.tag.argument_descriptions, #char "\n", context.temp_allocator);
print("\n");
- for line: lines {
+ for line in lines {
if line.count == 0 do continue;
printf(" {}\n", line);
}
Git :: struct {
get_full_repo_uri :: (package_search: str) -> str {
for Known_Repositories {
- for proto: Protocols {
+ for proto in Protocols {
r := tprintf("{}{}", proto, tprintf(it, package_search));
git_proc := os.process_spawn(git_path, .["ls-remote", "--tags", r]);
if os.process_wait(&git_proc) == .Success {
os.remove_directory(temporary_dest);
successfully_cloned := do -> bool {
- for proto: Protocols {
+ for proto in Protocols {
// Use 'git clone' to clone the bare minimum amount to get the released version.
proto_repo := tprintf("{}{}", proto, repo);
git_proc := os.process_spawn(git_path, .["clone", "--single-branch", "--depth", "1", "-b", version_str, proto_repo, temporary_dest]);
dep_node->add_value(.{ String = tprintf("{}", it.value.version) });
switch it.value.source {
- case s: .Git {
+ case .Git as s {
dep_node.props["git"] = .{ data = .{ String = s } };
}
if thread_data.compile_only do continue;
- for expected_file: os.with_file(it.expected_file) {
+ for expected_file in os.with_file(it.expected_file) {
expected_reader := io.reader_make(expected_file);
expected_output := io.read_all(&expected_reader);
if num != 0 do array.push(&nums, num);
}
- for i: nums do for j: nums do for k: nums {
+ for i in nums do for j in nums do for k in nums {
if j + i + k == 2020 {
printf("Answer: {}\n", i * j * k);
tally := array.make(u64, nums.count);
defer array.free(&tally);
- for &t: tally do *t = 0;
+ for &t in tally do *t = 0;
tally[nums.count - 1] = 1;
while i := cast(i32) (nums.count - 2); i >= 0 {
- for diff: 1 .. 4 {
+ for diff in 1 .. 4 {
if i + diff >= nums.count do continue;
if nums[i + diff] - nums[i] <= 3 do tally[i] += tally[i + diff];
array.sort(nums, (a, b) => a - b);
diffs: [3] u32;
- for &d: diffs do *d = 0;
- for i: 1 .. nums.count do diffs[nums[i] - nums[i - 1] - 1] += 1;
+ for &d in diffs do *d = 0;
+ for i in 1 .. nums.count do diffs[nums[i] - nums[i - 1] - 1] += 1;
diffs[2] += 1;
printf("Diff prod: {}\n", diffs[0] * diffs[2]);
gos_neighbors :: (use gos: &GameOfSeats, x: i32, y: i32, state := SeatState.Occupied) -> u32 {
count := 0;
- for dy: -1 .. 2 {
- for dx: -1 .. 2 {
+ for dy in -1 .. 2 {
+ for dx in -1 .. 2 {
if dy == 0 && dx == 0 do continue;
t := 1;
}
gos_iter :: (use gos: &GameOfSeats) -> bool {
- for i: 0 .. seats.count do temp[i] = seats[i];
+ for i in 0 .. seats.count do temp[i] = seats[i];
changed := false;
- for y: 0 .. height {
- for x: 0 .. width {
+ for y in 0 .. height {
+ for x in 0 .. width {
occ_neighbors := gos_neighbors(gos, x, y);
switch gos_get_seat(gos, x, y) {
}
}
- for i: 0 .. seats.count do seats[i] = temp[i];
+ for i in 0 .. seats.count do seats[i] = temp[i];
return changed;
}
while !string.empty(file) {
line, file~ := string.bisect(file, #char "\n");
- for ch: line do switch ch {
+ for ch in line do switch ch {
case #char "." do array.push(&gos.seats, SeatState.Floor);
case #char "L" do array.push(&gos.seats, SeatState.Empty);
case #char "#" do array.push(&gos.seats, SeatState.Occupied);
while gos_iter(&gos) ---
occupied := 0;
- for s: gos.seats do if s == SeatState.Occupied do occupied += 1;
+ for s in gos.seats do if s == SeatState.Occupied do occupied += 1;
printf("Occupied: {}\n", occupied);
}
chinese_remainder_theorem :: (mods: [..] i64, rems: [..] i64) -> i64 {
N: i64 = 1;
- for n: mods do N *= n;
+ for n in mods do N *= n;
res: i64 = 0;
- for i: 0 .. mods.count {
+ for i in 0 .. mods.count {
n := N / mods[i];
res += rems[i] * inv_mod(n, mods[i]) * n;
}
// take_bus := 0;
// depart := 0;
- // for i: 0 .. min {
- // for bus: buses {
+ // for i in 0 .. min {
+ // for bus in buses {
// if (i + est) % bus == 0 {
// take_bus = bus;
// depart = i + est;
bitmask_p1 :: (mask: Bitmask, val: u64) -> u64 {
res: u64 = 0;
bit: u64 = 1;
- for m: mask {
+ for m in mask {
switch m {
case 1 do res |= bit;
case 2 do res |= (val & bit);
bmi := cast(&BitmaskIter) data;
if bmi.done do return 0, false;
- for ind: bmi.floating_indicies {
+ for ind in bmi.floating_indicies {
is_set := (bmi.val & (1 << cast(u64) ind)) != 0;
bmi.val ^= 1 << cast(u64) ind;
array.init(&bmi.floating_indicies, 8);
v := val;
- for i: 0 .. MASK_SIZE {
+ for i in 0 .. MASK_SIZE {
if mask[i] == 1 do v |= 1 << cast(u64) i;
if mask[i] == 2 {
defer map.free(&mem);
mask : Bitmask;
- for &m: mask do *m = 2;
+ for &m in mask do *m = 2;
while !string.empty(file) {
word := string.read_alphanum(&file);
i := 35;
m, file~ := string.bisect(file, #char "\n");
- for ch: m {
+ for ch in m {
switch ch {
case #char "0" do mask[i] = 0;
case #char "1" do mask[i] = 1;
// map.put(&mem, addr, bitmask_p1(mask, val));
// Part 2
- for real_addr: bitmask_p2(mask, addr) {
+ for real_addr in bitmask_p2(mask, addr) {
map.put(&mem, real_addr, val);
}
}
s: u64 = 0;
- for e: mem.entries do s += e.value;
+ for e in mem.entries do s += e.value;
printf("Sum: {}\n", s);
}
turn := 1;
last_num := 0;
- for n: initial_numbers {
+ for n in initial_numbers {
map.put(&nums, n, .{ recent = turn });
turn += 1;
last_num = n;
read_ticket_and_validate :: (file: &str, fields: [..] Field, ticket_store: [&] u32) -> bool {
retval := true;
- for i: 0 .. fields.count {
+ for i in 0 .. fields.count {
n := cast(u32, conv.parse_int(file));
ticket_store[i] = n;
if file.data[0] == #char "," do string.advance(file, 1);
valid_count := 0;
- for &field: fields {
+ for &field in fields {
if field_valid(field, n) do valid_count += 1;
}
array.push(&fields, field);
}
- for i: 0 .. 2 do string.advance_line(&file);
+ for i in 0 .. 2 do string.advance_line(&file);
my_ticket := array.make(u32, fields.count);
defer array.free(&my_ticket);
read_ticket_and_validate(&file, fields, my_ticket.data);
- for i: 0 .. 2 do string.advance_line(&file);
+ for i in 0 .. 2 do string.advance_line(&file);
ticket_data := array.make(u32, 1024);
defer array.free(&ticket_data);
cols_to_assign := array.make(u32, fields.count);
defer array.free(&cols_to_assign);
- for i: 0 .. fields.count do array.push(&cols_to_assign, i);
+ for i in 0 .. fields.count do array.push(&cols_to_assign, i);
while cols_to_assign.count > 0 {
- for col: cols_to_assign {
+ for col in cols_to_assign {
work_count := 0;
recent_work: &Field = null;
- for &field: fields {
+ for &field in fields {
if field.column != -1 do continue;
works := true;
- for row: 0 .. (ticket_data.count / fields.count) {
+ for row in 0 .. (ticket_data.count / fields.count) {
if !field_valid(field, ticket_data[col + fields.count * row]) {
works = false;
break;
}
prod: u64 = 1;
- for &field: fields {
+ for &field in fields {
if string.starts_with(field.name, "departure") do prod *= ~~my_ticket[field.column];
}
get_neighbor_count :: (cubes: &Map(CubePos, CubeState), pos: CubePos) -> u32 {
count := 0;
- for x: -1 .. 2 do for y: -1 .. 2 do for z: -1 .. 2 do for w: -1 .. 2 {
+ for x in -1 .. 2 do for y in -1 .. 2 do for z in -1 .. 2 do for w in -1 .. 2 {
if x == 0 && y == 0 && z == 0 && w == 0 do continue;
key := CubePos.{ pos.x + x, pos.y + y, pos.z + z, pos.w + w };
map.get(cubes, key)->with([s] {
line, file~ := string.bisect(file, #char "\n");
x := 0;
- for ch: line {
+ for ch in line {
if ch == #char "#" do map.put(&cubes, .{ x, 0, z, 0 }, .{ alive = true });
x += 1;
cubes_to_consider := array.make(CubePos);
defer array.free(&cubes_to_consider);
- for i: 0 .. 6 {
- for &cube_entry: cubes.entries {
+ for i in 0 .. 6 {
+ for &cube_entry in cubes.entries {
if cube_entry.value.alive {
- for x: -1 .. 2 do for y: -1 .. 2 do for z: -1 .. 2 do for w: -1 .. 2 {
+ for x in -1 .. 2 do for y in -1 .. 2 do for z in -1 .. 2 do for w in -1 .. 2 {
array.push(&cubes_to_consider, .{
cube_entry.key.x + x,
cube_entry.key.y + y,
}
}
- for &cube: cubes_to_consider {
+ for &cube in cubes_to_consider {
state := map.get(&cubes, *cube) ?? .{};
ncount := get_neighbor_count(&cubes, *cube);
map.put(&cubes, *cube, state);
}
- for &cube: cubes_to_consider {
+ for &cube in cubes_to_consider {
state := map.get(&cubes, *cube) ?? .{};
state.alive = state.next;
map.put(&cubes, *cube, state);
}
active_count := 0;
- for &cube_entry: cubes.entries do if cube_entry.value.alive do active_count += 1;
+ for &cube_entry in cubes.entries do if cube_entry.value.alive do active_count += 1;
printf("Active count: {}\n", active_count);
}
grammar_prepare :: (use g: &Grammar) {
// Not full-proof, but good enough for AOC.
- for &solo: unit_rules {
- for &prod: production_rules {
+ for &solo in unit_rules {
+ for &prod in production_rules {
if prod.nt0 == solo.nt1 {
array.push(&production_rules, Prod.{ solo.nt0, prod.nt1, prod.nt2 });
}
}
- for &unit: terminate_rules {
+ for &unit in terminate_rules {
if unit.nt == solo.nt1 {
array.push(&terminate_rules, Term.{ solo.nt0, unit.t });
}
defer cfree(T);
memory.set(T, ~~false, mem_size);
- for s: 0 .. input.count {
- for &term: terminate_rules {
+ for s in 0 .. input.count {
+ for &term in terminate_rules {
if term.t == input[s] {
T[0 * dim_0 + s * dim_1 + term.nt * dim_2] = true;
}
}
}
- for l: 1 .. input.count {
- for s: 0 .. input.count - l {
- for p: 1 .. l + 1 {
- for &prod: production_rules {
+ for l in 1 .. input.count {
+ for s in 0 .. input.count - l {
+ for p in 1 .. l + 1 {
+ for &prod in production_rules {
if T[(p - 1) * dim_0 + s * dim_1 + prod.nt1 * dim_2]
&& T[(l - p) * dim_0 + (s + p) * dim_1 + prod.nt2 * dim_2] {
T[l * dim_0 + s * dim_1 + prod.nt0 * dim_2] = true;
// Part 1
// count := 0;
- // for c: pw do if c == ch do count += 1;
+ // for c in pw do if c == ch do count += 1;
// if count >= lo && count <= hi do valid += 1;
// Part 2
reverse_binary :: (n_: u32, digits := TILE_DATA_WIDTH) -> u32 {
res := 0;
n := n_;
- for _: 0 .. digits {
+ for _ in 0 .. digits {
res <<= 1;
res |= (n & 1);
n >>= 1;
edges : [..] u32;
array.init(&edges, 8, allocator=a);
- for y: u32.[0, 9] {
+ for y in u32.[0, 9] {
edge := 0;
- for x: 0 .. 10 {
+ for x in 0 .. 10 {
edge <<= 1;
if tile[x + y * TILE_DATA_WIDTH] do edge |= 1;
}
array.push(&edges, edge);
}
- for x: u32.[0, 9] {
+ for x in u32.[0, 9] {
edge := 0;
- for y: 0 .. 10 {
+ for y in 0 .. 10 {
edge <<= 1;
if tile[x + y * TILE_DATA_WIDTH] do edge |= 1;
}
array.push(&edges, edge);
}
- for i: 0 .. 4 do array.push(&edges, reverse_binary(edges[i]));
+ for i in 0 .. 4 do array.push(&edges, reverse_binary(edges[i]));
return edges.data[0 .. 8];
}
has_matching_edges :: (t1: &Tile, t2: &Tile) -> bool {
match := false;
- for e_idx: 0 .. t1.edges.count / 2 do for e2_idx: 0 .. t2.edges.count {
+ for e_idx in 0 .. t1.edges.count / 2 do for e2_idx in 0 .. t2.edges.count {
if t1.edges[e_idx] == t2.edges[e2_idx] {
match = true;
scan_for_monsters :: (forest: [&] u8, ori: TO, width: u32, height: u32) -> bool {
found_monsters := false;
- for y: 0 .. height - sea_monster_height {
- for x: 0 .. width - sea_monster_width {
+ for y in 0 .. height - sea_monster_height {
+ for x in 0 .. width - sea_monster_width {
is_monster := true;
- for my: 0 .. sea_monster_height {
- for mx: 0 .. sea_monster_width {
+ for my in 0 .. sea_monster_height {
+ for mx in 0 .. sea_monster_width {
if sea_monster[mx + my * sea_monster_width] != #char "#" do continue;
if *index_square_with_orientation(forest, ori, width, x + mx, y + my) != #char "." do continue;
}
if is_monster {
- for my: 0 .. sea_monster_height {
- for mx: 0 .. sea_monster_width {
+ for my in 0 .. sea_monster_height {
+ for mx in 0 .. sea_monster_width {
if sea_monster[mx + my * sea_monster_width] != #char "#" do continue;
if *index_square_with_orientation(forest, ori, width, x + mx, y + my) != #char "#" do continue;
td := cast([&] bool) raw_alloc(tile_allocator, sizeof TileData);
- for y: 0 .. 10 {
+ for y in 0 .. 10 {
line, file~ := string.bisect(file, #char "\n");
- for x: 0 .. 10 {
+ for x in 0 .. 10 {
td[x + y * TILE_DATA_WIDTH] = (line[x] == #char "#");
}
}
string.advance_line(&file);
}
- for &t: tiles do map.put(&tile_map, t.id, t);
+ for &t in tiles do map.put(&tile_map, t.id, t);
prod: u64 = 1;
top_left_id := 0;
- for i: 0 .. tiles.count - 1 {
+ for i in 0 .. tiles.count - 1 {
matching_count := 0;
- for j: 0 .. tiles.count {
+ for j in 0 .. tiles.count {
if i == j do continue;
if has_matching_edges(&tiles[i], &tiles[j]) {
matching_count += 1;
}
forest : [12 * 8 * 12 * 8] u8;
- for y: 0 .. 12 {
- for x: 0 .. 12 {
+ for y in 0 .. 12 {
+ for x in 0 .. 12 {
tile := map.get(&tile_map, grid[y * 12 + x])->unwrap();
- for fy: 0 .. 8 {
- for fx: 0 .. 8 {
+ for fy in 0 .. 8 {
+ for fx in 0 .. 8 {
res := *index_square_with_orientation(cast([&] bool) tile.data.data, tile.orientation, 10, fx + 1, fy + 1);
loc := (y * 12 * 8 * 8) + (fy * 12 * 8) + (x * 8) + fx;
if res do forest[loc] = #char "#";
}
}
- for ori: .[ TO.N, TO.R90, TO.R180, TO.R270, TO.F, TO.FR90, TO.FR180, TO.FR270 ] {
+ for ori in .[ TO.N, TO.R90, TO.R180, TO.R270, TO.F, TO.FR90, TO.FR180, TO.FR270 ] {
if scan_for_monsters(cast([&] u8) forest, ori, 12 * 8, 12 * 8) do break;
}
safe_count := 0;
- for c: forest do if c == #char "#" do safe_count += 1;
+ for c in forest do if c == #char "#" do safe_count += 1;
printf("Safe count: {}\n", safe_count);
}
definitely_safe := array.make(str);
defer array.free(&definitely_safe);
- for &ingredient_entry: ingredient_map.entries {
+ for &ingredient_entry in ingredient_map.entries {
potential_allergens := array.make(str);
defer array.free(&potential_allergens);
- for food_num: ingredient_entry.value.appears_on {
- for &allergen_name: foods[food_num].allergens {
+ for food_num in ingredient_entry.value.appears_on {
+ for &allergen_name in foods[food_num].allergens {
array.push(&potential_allergens, *allergen_name);
}
}
potential_allergen_count := 0;
- for &allergen_name: potential_allergens {
+ for &allergen_name in potential_allergens {
c := array_count_contains(&potential_allergens, *allergen_name, string.equal);
allergen := map.get(&allergen_map, *allergen_name)->unwrap();
if c == allergen.appears_on.count {
}
total_safe := 0;
- for safe: definitely_safe {
+ for safe in definitely_safe {
ingredient := map.get(&ingredient_map, safe)->unwrap();
total_safe += ingredient.appears_on.count;
defer array.free(&matched_ingredients);
while !map.empty(&ingredient_map) {
- for &allergen_entry: allergen_map.entries {
+ for &allergen_entry in allergen_map.entries {
match_count := 0;
matching_ingredient_name := str.{ null, 0 };
- for &ingredient_entry: ingredient_map.entries {
+ for &ingredient_entry in ingredient_map.entries {
matches := true;
- for ap: allergen_entry.value.appears_on {
+ for ap in allergen_entry.value.appears_on {
if !array.contains(ingredient_entry.value.appears_on, ap) do matches = false;
}
array.sort(matched_ingredients, (i1: &Ingredient, i2: &Ingredient) => string.compare(i1.allergen, i2.allergen));
- for &mi: matched_ingredients do printf("{} -> {}\n", mi.name, mi.allergen);
- for &mi: matched_ingredients do printf("{},", mi.name);
+ for &mi in matched_ingredients do printf("{} -> {}\n", mi.name, mi.allergen);
+ for &mi in matched_ingredients do printf("{},", mi.name);
println("\n(Don't copy the last ','!)");
}
array_count_contains :: (arr: &[..] $T, x: T, equal: (T, T) -> bool) -> u32 {
count := 0;
- for &it: *arr do if equal(*it, x) do count += 1;
+ for &it in *arr do if equal(*it, x) do count += 1;
return count;
}
score_player :: (p: &[..] u32) -> u32 {
count := 0;
mul := p.count;
- for c: *p {
+ for c in *p {
count += c * mul;
mul -= 1;
}
stream := io.buffer_stream_make(256, alloc);
writer := io.writer_make(&stream, 0);
- for n: *p1 {
+ for n in *p1 {
io.write_i64(&writer, ~~n, 64);
io.write_str(&writer, ",");
}
io.write_str(&writer, "|");
- for n: *p2 {
+ for n in *p2 {
io.write_i64(&writer, ~~n, 64);
io.write_str(&writer, ",");
}
}
get_idx :: (cups: [] i32, cup: i32) -> i32 {
- for i: 0 .. cups.count do if cups[i] == cup do return i;
+ for i in 0 .. cups.count do if cups[i] == cup do return i;
return -1;
}
cw := memory.make_slice(i32, cups.count);
defer cfree(cw.data);
- for i: 0 .. cups.count do cw[cups[i]] = cups[w(i + 1)];
+ for i in 0 .. cups.count do cw[cups[i]] = cups[w(i + 1)];
current_cup := cups[0];
- for move: 0 .. moves {
+ for move in 0 .. moves {
next_1 := cw[current_cup];
next_2 := cw[next_1];
next_3 := cw[next_2];
}
cup := 0;
- for i: 0 .. cups.count {
+ for i in 0 .. cups.count {
cups[i] = cup;
cup = cw[cup];
}
cups_data := i32.[ 9, 6, 2, 7, 1, 3, 8, 5, 4 ];
// Easier think about in zero-indexed
- for &cup: cups_data do *cup -= 1;
+ for &cup in cups_data do *cup -= 1;
array.init(&cups, 1000000);
defer array.free(&cups);
- for cup: cups_data do array.push(&cups, cup);
+ for cup in cups_data do array.push(&cups, cup);
// Part 1
// simulate(array.to_slice(&cups));
// Part 2
- for i: 9 .. 1000000 do array.push(&cups, i);
+ for i in 9 .. 1000000 do array.push(&cups, i);
simulate(cups, 10000000);
// Undo the zero-indexing
- for &cup: cups do *cup += 1;
+ for &cup in cups do *cup += 1;
// Part 1
// one_idx := get_idx(array.to_slice(&cups), 1);
- // for i: 1 .. 9 {
+ // for i in 1 .. 9 {
// printf("{}", cast(i32) cups[w(one_idx + i)]);
// }
// printf("\n");
loc := Vec2.{ 0, 0 };
s := 0;
- for ch: line do switch s {
+ for ch in line do switch s {
case 0 do switch ch {
case #char "e" do loc.x += 1;
case #char "w" do loc.x -= 1;
// Part 1
black_count := 0;
- for &cell: grid.entries {
+ for &cell in grid.entries {
if cell.value.alive do black_count += 1;
}
printf("Black count: {}\n", black_count);
cells_to_consider := array.make(Vec2);
defer array.free(&cells_to_consider);
- for i: 0 .. 100 {
- for &cell: grid.entries {
+ for i in 0 .. 100 {
+ for &cell in grid.entries {
if cell.value.alive {
array.push(&cells_to_consider, cell.key);
- for &dir: Hex_Directions {
+ for &dir in Hex_Directions {
array.push(&cells_to_consider, .{
x = cell.key.x + dir.x,
y = cell.key.y + dir.y,
}
}
- for &cell: cells_to_consider {
+ for &cell in cells_to_consider {
state := map.get(&grid, *cell) ?? .{};
ncount := get_neighbor_count(&grid, *cell);
map.put(&grid, *cell, state);
}
- for &cell: cells_to_consider {
+ for &cell in cells_to_consider {
map.update(&grid, *cell, [v]{ v.alive = v.next; });
}
}
black_count = 0;
- for &cell: grid.entries {
+ for &cell in grid.entries {
if cell.value.alive do black_count += 1;
}
printf("GOL black count: {}\n", black_count);
get_neighbor_count :: (grid: &map.Map(Vec2, Cell), pos: Vec2) -> u32 {
count := 0;
- for &dir: Hex_Directions {
+ for &dir in Hex_Directions {
cell := map.get(grid, Vec2.{ x = pos.x + dir.x, y = pos.y + dir.y }) ?? .{};
if cell.alive do count += 1;
}
defer map.free(&t);
tmp: u64 = 1;
- for i: 0 .. m {
+ for i in 0 .. m {
map.put(&t, ~~tmp, i);
tmp = (tmp * ~~a) % ~~n;
}
f := power_mod(a, n - 1 - m, n);
tmp = ~~b;
- for i: 0 .. m {
+ for i in 0 .. m {
if map.has(&t, ~~tmp) {
v := map.get(&t, ~~tmp) ?? 0;
return i * m + v;
transform_subject :: (subject: u32, loop_size: u32) -> u32 {
value: u64 = 1;
- for i: 0 .. loop_size do value = (value * ~~subject) % 20201227;
+ for i in 0 .. loop_size do value = (value * ~~subject) % 20201227;
return cast(u32) value;
}
width = line.count;
height = height + 1;
- for ch: line do array.push(&forest, ch);
+ for ch in line do array.push(&forest, ch);
}
lis := LineInterp.[
tree_prod: u64 = 1;
- for li: lis {
+ for li in lis {
tree_count: u64 = 0;
while i := 0; true {
p := line_interp_at(li, i);
fields := string.split(line, #char " ");
defer cfree(fields.data);
- for field: fields {
+ for field in fields {
data := string.split(field, #char ":");
defer cfree(data.data);
if line.count == 0 do break;
val := 0;
- for ch: line {
+ for ch in line {
val *= 2;
if ch == #char "B" || ch == #char "R" do val += 1;
}
missing := 0;
array.sort(vals, cmp_asc);
- for i: 0 .. vals.count - 1 {
+ for i in 0 .. vals.count - 1 {
if vals[i + 1] - vals[i] != 1 do missing = vals[i] + 1;
}
part_1 :: (contents: &str) -> u32 {
chars : [26] bool;
- for &ch: chars do *ch = false;
+ for &ch in chars do *ch = false;
while true {
line := string.read_until(contents, #char "\n");
string.advance(contents, 1);
if line.count == 0 do break;
- for ch: line do chars[~~ch - cast(u32) #char "a"] = true;
+ for ch in line do chars[~~ch - cast(u32) #char "a"] = true;
}
sum := 0;
- for ch: chars do if ch do sum += 1;
+ for ch in chars do if ch do sum += 1;
return sum;
}
part_2 :: (contents: &str) -> u32 {
chars : [26] u32;
- for &ch: chars do *ch = 0;
+ for &ch in chars do *ch = 0;
person_count := 0;
while true {
person_count += 1;
- for ch: line do chars[~~ch - cast(u32) #char "a"] += 1;
+ for ch in line do chars[~~ch - cast(u32) #char "a"] += 1;
}
sum := 0;
- for ch: chars do if ch == person_count do sum += 1;
+ for ch in chars do if ch == person_count do sum += 1;
return sum;
}
// bag := array.pop(&to_process_bags);
// array.push(&processed_bags, bag);
//
- // for container: bag.contained_in {
+ // for container in bag.contained_in {
// if !array.contains(&processed_bags, container.bag) && !array.contains(&to_process_bags, container.bag) {
// // printf("Adding {} to process.\n", container.bag.color);
// array.push(&to_process_bags, container.bag);
mul := array.pop(&multiplier);
count += mul;
- for bc: bag.contain {
+ for bc in bag.contain {
array.push(&to_process, bc.bag);
array.push(&multiplier, bc.count * mul);
}
}
acc: i32;
- for &instr: instrs {
+ for &instr in instrs {
if instr.opcode == OpCode.Nop do instr.opcode = OpCode.Jmp;
elseif instr.opcode == OpCode.Jmp do instr.opcode = OpCode.Nop;
end := 0;
con_sum: u64 = nums[0];
- for i: 1 .. nums.count {
+ for i in 1 .. nums.count {
end += 1;
con_sum += nums[end];
preamble_length :: 25;
invalid: u64;
- for i: 0 .. nums.count {
+ for i in 0 .. nums.count {
if i < preamble_length do continue;
success := false;
- for j: 0 .. preamble_length - 1 {
- for k: j + 1 .. preamble_length {
+ for j in 0 .. preamble_length - 1 {
+ for k in j + 1 .. preamble_length {
if nums[i - j - 1] + nums[i - k - 1] == nums[i] {
success = true;
break break;
{ // Part 2
windows: [..] i32;
- for i: range.{ 0, nums.count - 2 } {
+ for i in range.{ 0, nums.count - 2 } {
sum := 0;
- for k: i .. i+3 do sum += nums[k];
+ for k in i .. i+3 do sum += nums[k];
windows << sum;
}
use core {*}
main :: (args) => {
- for file: os.with_file("tests/aoc-2021/input/day02.txt") {
+ for file in os.with_file("tests/aoc-2021/input/day02.txt") {
reader := io.reader_make(file);
#if PART == 1 {
num1 := 0;
for BITS {
one_count := 0;
- for num: nums {
+ for num in nums {
if num & (1 << it) != 0 do one_count += 1;
}
winning_board: &Board = null;
worst_board : &Board = null;
- for called: numbers {
- for & board: boards {
+ for called in numbers {
+ for & board in boards {
if board.has_won do continue;
// Whatever the last board we touch is must be the worst one.
#operator == (p1, p2: Point) => p1.x == p2.x && p1.y == p2.y;
main :: (args) => {
- for file: os.with_file("./tests/aoc-2021/input/day05.txt") {
+ for file in os.with_file("./tests/aoc-2021/input/day05.txt") {
reader := io.reader_make(file);
lines: [..] Line;
point_count: Map(Point, u32);
- for &line: lines {
- for p: line_points(*line) {
+ for &line in lines {
+ for p in line_points(*line) {
point_count[p] = (point_count[p] ?? 0) + 1;
}
}
use core {*}
main :: (args) => {
- for file: os.with_file("./tests/aoc-2021/input/day06.txt") {
+ for file in os.with_file("./tests/aoc-2021/input/day06.txt") {
reader := io.reader_make(file);
start_str := io.read_all(&reader);
fish[value] += 1;
}
- for day: 256 {
+ for day in 256 {
new_fish := fish[0];
for 8 do fish[it] = fish[it + 1];
fish[6] += new_fish;
use core {*}
main :: (args) => {
- for file: os.with_file("./tests/aoc-2021/input/day07.txt") {
+ for file in os.with_file("./tests/aoc-2021/input/day07.txt") {
reader := io.reader_make(file);
nums := io.read_all(&reader)
|> string.split(#char ",")
min_cost := 0x7fffffff;
best_middle := 0;
- for middle: min .. max {
+ for middle in min .. max {
total_cost := 0;
for nums {
dist := math.abs(it - middle);
seven_data := *array.first(left_segments, (x) => x.count == 3);
// Solve the top segment
- for s: seven_data {
+ for s in seven_data {
if !array.contains(one_data, s) {
solved_segments[s] = 1;
}
if it.count != 5 do continue;
in_count := 0;
- for a: one_data do if array.contains(it, a) do in_count += 1;
+ for a in one_data do if array.contains(it, a) do in_count += 1;
if in_count == 2 {
three_data = it;
four_data := *array.first(left_segments, (x) => x.count == 4);
// Solve for middle segment
- for f: four_data {
- for t: three_data {
+ for f in four_data {
+ for t in three_data {
if t == f {
if !array.contains(one_data, t) {
solved_segments[t] = 4;
for three_data {
if solved_segments[it] ?? 0 == 4 do continue;
if solved_segments[it] ?? 0 == 1 do continue;
- for o: one_data do if it == o do continue continue;
+ for o in one_data do if it == o do continue continue;
solved_segments[it] = 7;
break;
// Look for 5.
five_data: str;
- for seg: left_segments {
+ for seg in left_segments {
if seg.count != 5 do continue;
for four_data {
if solved_segments[it] ?? 0 == 4 do continue;
- for o: one_data do if it == o do continue continue;
+ for o in one_data do if it == o do continue continue;
if array.contains(seg, it) {
five_data = seg;
}
for five_data {
- for o: one_data do if it == o {
+ for o in one_data do if it == o {
solved_segments[it] = 6;
break;
}
string.strip_whitespace(it);
num_segments : [7] bool;
- for w: *it do num_segments[solved_segments[w] ?? 0 - 1] = true;
+ for w in *it do num_segments[solved_segments[w] ?? 0 - 1] = true;
sum *= 10;
- for i: 10 {
+ for i in 10 {
if segments[i] == num_segments {
sum += i;
break;
// Nicer way of printing a Map.
#match io.write (w: &io.Writer, x: &Map($K, $V)) {
io.write(w, "{\n");
- for e: x.entries {
+ for e in x.entries {
io.write(w, " {} => {}\n", e.key, e.value);
}
io.write(w, "}");
#operator == (a, b: [] $T) -> bool {
if a.count != b.count do return false;
- for i: a.count do if a[i] != b[i] do return false;
+ for i in a.count do if a[i] != b[i] do return false;
return true;
}
main :: (args) => {
- for file: os.with_file("./tests/aoc-2021/input/day08.txt") {
+ for file in os.with_file("./tests/aoc-2021/input/day08.txt") {
reader := io.reader_make(file);
answer := 0;
}
}
- for p: potential {
+ for p in potential {
if !array.contains(included, p) && !array.contains(queued, p) {
queued << p;
}
#match io.write (w: &io.Writer, x: &Map($K, $V)) {
io.write(w, "{\n");
- for e: x.entries {
+ for e in x.entries {
io.write(w, " {} => {}\n", e.key, e.value);
}
io.write(w, "}");
}
main :: (args) => {
- for file: os.with_file("./tests/aoc-2021/input/day09.txt") {
+ for file in os.with_file("./tests/aoc-2021/input/day09.txt") {
reader := io.reader_make(file);
heightmap: Map(Pos, Cell);
height += 1;
}
- for y: height - 1 do for x: width {
+ for y in height - 1 do for x in width {
map.update(&heightmap, .{x,y}) {
it.dy = it.height - heightmap[Pos.{x,y+1}]->unwrap().height;
}
}
- for x: width - 1 do for y: height {
+ for x in width - 1 do for y in height {
map.update(&heightmap, .{x,y}) {
it.dx = it.height - heightmap[Pos.{x+1,y}]->unwrap().height;
}
lowest: [..] Pos;
risk_sum := 0;
- for y: height do for x: width {
+ for y in height do for x in width {
h := &heightmap[Pos.{x,y}];
if x < width - 1 && h.dx >= 0 do continue;
if y < height - 1 && h.dy >= 0 do continue;
printf("Part 1: {}\n", risk_sum);
lowest_count: Map(Pos, i32);
- for low: lowest do lowest_count[low] = find_span(low);
+ for low in lowest do lowest_count[low] = find_span(low);
array.quicksort(lowest_count.entries, (a, b) => b.value - a.value);
use core {*}
main :: (args) => {
- for file: os.with_file("./tests/aoc-2021/input/day10.txt") {
+ for file in os.with_file("./tests/aoc-2021/input/day10.txt") {
reader := io.reader_make(file);
bracket_map: Map(u8, u8);
char_stack: [..] u8;
defer array.free(&char_stack);
- for ch: line {
+ for ch in line {
switch ch {
case #char "(", #char "[", #char "<", #char "{" {
char_stack << bracket_map[ch]->unwrap();
#operator == (p1, p2: Pos) => p1.x == p2.x && p1.y == p2.y;
main :: (args) => {
- for file: os.with_file("./tests/aoc-2021/input/day11.txt") {
+ for file in os.with_file("./tests/aoc-2021/input/day11.txt") {
reader := io.reader_make(file);
octopuses: [..] u32;
line := io.read_line(&reader, consume_newline=false, inplace=true);
io.skip_whitespace(&reader);
- for ch: line do octopuses << ~~(ch - #char "0");
+ for ch in line do octopuses << ~~(ch - #char "0");
}
get_octopus :: macro (x, y) => {
sync_step := 0;
while true {
step += 1;
- for &o: octopuses do *o += 1;
+ for &o in octopuses do *o += 1;
#persist to_flash: Set(Pos);
- for y: 10 do for x: 10 {
+ for y in 10 do for x in 10 {
if get_octopus(x, y) >= 10 {
to_flash << .{x, y};
}
}
- for flash: iter.as_iter(&to_flash) {
- for y: -1 .. 2 do for x: -1 .. 2 {
+ for flash in iter.as_iter(&to_flash) {
+ for y in -1 .. 2 do for x in -1 .. 2 {
if y == 0 && x == 0 do continue;
if inc_octopus(flash.x + x, flash.y + y) >= 10 {
}
}
- for flash: iter.as_iter(&to_flash) {
+ for flash in iter.as_iter(&to_flash) {
set_octopus(flash.x, flash.y, 0);
if step <= 100 do flash_count += 1;
}
}
main :: (args) => {
- for file: os.with_file("./tests/aoc-2021/input/day12.txt") {
+ for file in os.with_file("./tests/aoc-2021/input/day12.txt") {
reader := io.reader_make(file);
verticies: Set(str);
}
edge_map: Map(str, [] str);
- for v: iter.as_iter(&verticies) {
+ for v in iter.as_iter(&verticies) {
edge_map[*v] = children_of(&edges, *v) |> iter.to_array();
}
}
main :: (args) => {
- for file: os.with_file("./tests/aoc-2021/input/day13.txt") {
+ for file in os.with_file("./tests/aoc-2021/input/day13.txt") {
reader := io.reader_make(file);
dots: [..] Point;
printf("Part 1: {}\n", part_1_answer);
printf("Part 2:\n");
- for y: 7 {
- for x: 50 {
+ for y in 7 {
+ for x in 50 {
print("X" if array.contains(dots, .{x, y}) else " ");
}
// Nicer way of printing a Map.
#match io.write (w: &io.Writer, x: &Map($K, $V)) {
io.write(w, "{\n");
- for e: x.entries {
+ for e in x.entries {
io.write(w, " {} => {}\n", e.key, e.value);
}
io.write(w, "}");
}
main :: (args) => {
- for file: os.with_file("./tests/aoc-2021/input/day14.txt") {
+ for file in os.with_file("./tests/aoc-2021/input/day14.txt") {
reader := io.reader_make(file);
start_polymer := io.read_line(&reader, consume_newline=false);
step_state();
for 40 {
- for& rule: rules {
+ for& rule in rules {
pair_count := &polymer_state[rule.pair];
if pair_count != null {
if pair_count.now > 0 {
#operator == (p1, p2: pos) => p1.x == p2.x && p1.y == p2.y;
main :: (args) => {
- for file: os.with_file("./tests/aoc-2021/input/day15.txt") {
+ for file in os.with_file("./tests/aoc-2021/input/day15.txt") {
reader := io.reader_make(file);
cells: [..] u8;
min_paths.count = cells.count * 25;
memory.set(min_paths.data, 0, sizeof u32 * min_paths.count * 25);
- for y: height * 5 do for x: width * 5 {
+ for y in height * 5 do for x in width * 5 {
if y == 0 && x == 0 do continue;
a, b := 100000, 100000;
main :: (args) => {
- for file: os.with_file("./tests/aoc-2021/input/day16.txt") {
+ for file in os.with_file("./tests/aoc-2021/input/day16.txt") {
reader := io.reader_make(file);
line := io.read_line(&reader, consume_newline=false, inplace=true);
transmission: [..] u8;
- for i: range.{ 0, line.count, 2 } {
+ for i in range.{ 0, line.count, 2 } {
transmission << ~~(base16_to_hex(line[i .. i + 2]));
}
main :: (args) => {
- for file: os.with_file("./tests/aoc-2021/input/day17.txt") {
+ for file in os.with_file("./tests/aoc-2021/input/day17.txt") {
reader := io.reader_make(file);
io.skip_bytes(&reader, 15);
max := 0;
count := 0;
- for dx: 1 .. 1000 {
- for dy: -1000 .. 1000 {
+ for dx in 1 .. 1000 {
+ for dy in -1000 .. 1000 {
my, s := simulate(dx, dy);
if s {
max = math.max(my, max);
conv.register_custom_formatter(SnailNum.format);
- for file: os.with_file("./tests/aoc-2021/input/day18.txt") {
+ for file in os.with_file("./tests/aoc-2021/input/day18.txt") {
r := io.reader_make(file);
#if PART == 1 {
s: &SnailNum = null;
- for line: r->lines() {
+ for line in r->lines() {
n := SnailNum.parse(&line);
s = s->add(n);
}
#if PART == 2 {
nums := make([..] &SnailNum);
- for line: r->lines() {
+ for line in r->lines() {
nums << SnailNum.parse(&line);
}
maximum := 0;
max_i, max_j : i32;
- for i: nums.count {
- for j: nums.count {
+ for i in nums.count {
+ for j in nums.count {
if i == j do continue;
n1 := nums[i]->clone();
vecs : [4] Vec2;
i := n;
- for &v: vecs {
+ for &v in vecs {
v.x = i * i;
v.y = i * i * i;
i += 1;
{
println("Array of structs on the stack.");
vecs : [8] Vec2;
- for &v: vecs {
+ for &v in vecs {
v.x = 4039;
v.y = 7782;
}
{
println("Array of structs from function call.");
vecs := calc_vecs();
- for &v: vecs do println(*v);
+ for &v in vecs do println(*v);
}
// Array of structs on a struct
nums : [100] u32;
i := 1;
- for &n: nums {
+ for &n in nums {
*n = i * i;
i += 5;
}
set_vecs :: (vecs: &[2][4] Vec2) {
i := 0;
- for &row: *vecs {
- for &v: *row {
+ for &row in *vecs {
+ for &v in *row {
*v = .{ 1000 + i, 2000 + i * i };
i += 1;
}
set_vecs(vecs);
print_vecs :: (vecs: &[4] Vec2) {
- for &v: *vecs do println(*v);
+ for &v in *vecs do println(*v);
}
print_vecs(&(*vecs)[0]);
print_from_other_thread :: (sd) => {
// Creating high contention for the shared resource
- for i: 10000 {
+ for i in 10000 {
sync.scoped_mutex(&shared_mutex);
- for &v: sd.arr {
+ for &v in sd.arr {
*v += 1;
}
}
// Using the thread-local variable
partial_arr = make([] i32, 5);
- for i: 5 do partial_arr[i] = i * i;
+ for i in 5 do partial_arr[i] = i * i;
// Not printing on threads since the test case looks for EXACT string matches
// printf("On a worker thread: {}\n", partial_arr);
array.fill(sd.arr, 0);
threads : [4] thread.Thread;
- for &t: threads {
+ for &t in threads {
thread.spawn(t, &sd, print_from_other_thread);
printf("Spawned thread {}\n", t.id);
}
memory.alloc_slice(&partial_arr, 10);
- for i: 10 do partial_arr[i] = i;
+ for i in 10 do partial_arr[i] = i;
printf("Waiting...\n");
- for &t: threads {
+ for &t in threads {
thread.join(t);
printf("Thread {} joined!\n", t.id);
}
use core {*}
count_to :: ($N: i32) {
- for i: 0 .. N do printf("{} ", i);
+ for i in 0 .. N do printf("{} ", i);
print("\n");
}
main :: (args: [] cstr) {
ba := bucket_array.make(i32, 4);
- for i: 24 do ba << i;
+ for i in 24 do ba << i;
printf("ba[10] is {}.\n", ba[10]);
sum += *value;
});
- for it: bucket_array.as_iter(&ba) {
+ for it in bucket_array.as_iter(&ba) {
printf("{}\n", it);
}
case 10 {
count := 5;
- for i: custom_iterator() {
+ for i in custom_iterator() {
println(i);
defer println("World");
// "-1e-500000",
];
- for s: strings {
+ for s in strings {
value := conv.str_to_f64(s);
println(value);
}
|> iter.map((x, [addition]) => x + ~~addition)
|> iter.take(5);
- for v: quick_iterator {
+ for v in quick_iterator {
println(v);
}
}
|> iter.map((x: i32) -> i32 { return x + 42; });
println("Starting the iteration...");
- for i: iterator do println(i);
+ for i in iterator do println(i);
arr := count_iterator(1, 10)
|> iter.map((x: i32) -> i32 { return x * 2; })
|> iter.map(x => x + 42)
|> iter.zip(iter.const(42.0f));
- for value: zipped_iterator {
+ for value in zipped_iterator {
printf("{} {}\n", value.first, value.second);
}
}
min := arr[0];
max := arr[0];
- for e: arr {
+ for e in arr {
if e < min do min = e;
if e > max do max = e;
}
array_print(farr);
array_print :: (arr: [$N] $T) {
- for &e: arr {
+ for &e in arr {
print(*e);
print(" ");
}
println(x);
println(y);
- for elem: z do printf("{} ", elem);
+ for elem in z do printf("{} ", elem);
print("\n");
}
#operator+ (a: Vec($T, $N), b: Vec(T, N)) -> Vec(T, N) {
out : Vec(T, N);
- for i: 0 .. N do out.data[i] = a.data[i] + b.data[i];
+ for i in 0 .. N do out.data[i] = a.data[i] + b.data[i];
return out;
}
#operator- (a: Vec($T, $N), b: Vec(T, N)) -> Vec(T, N) {
out : Vec(T, N);
- for i: 0 .. N do out.data[i] = a.data[i] - b.data[i];
+ for i in 0 .. N do out.data[i] = a.data[i] - b.data[i];
return out;
}
#operator* (a: Vec($T, $N), s: T) -> Vec(T, N) {
out : Vec(T, N);
- for i: 0 .. N do out.data[i] = a.data[i] * s;
+ for i in 0 .. N do out.data[i] = a.data[i] * s;
return out;
}
#operator* (a: Vec($T, $N), b: Vec(T, N)) -> T {
res := T.{};
- for i: 0 .. N do res += a.data[i] * b.data[i];
+ for i in 0 .. N do res += a.data[i] * b.data[i];
return res;
}
join :: (a: Vec($T, $N), b: Vec(T, $M)) -> Vec(T, N + M) {
out : Vec(T, N + M);
- for i: 0 .. N do out.data[i] = a.data[i];
- for i: 0 .. M do out.data[i + N] = b.data[i];
+ for i in 0 .. N do out.data[i] = a.data[i];
+ for i in 0 .. M do out.data[i + N] = b.data[i];
return out;
}
d := make_vec(f32.[2, 3, 5, 7]);
e := join(d, c);
- for v: e.data do printf("{} ", v);
+ for v in e.data do printf("{} ", v);
print("\n");
}
nps : NewPolyStruct(i32, 4);
- for &x: nps.x do *x = 12345;
- for &y: nps.y do *y = 67890;
+ for &x in nps.x do *x = 12345;
+ for &y in nps.y do *y = 67890;
- for x: nps.x do println(x);
+ for x in nps.x do println(x);
main :: (args: [] cstr) {
arr := u32.[ 1, 2, 3, 4, 5 ];
- for elem: array_to_slice(arr) do printf("{} ", elem);
+ for elem in array_to_slice(arr) do printf("{} ", elem);
roots : [20] f32;
compute_roots(roots);
- for root: roots do println(root);
+ for root in roots do println(root);
array_to_slice :: (arr: [$N] $T) -> [] T {
return (#type [] T).{ ~~arr, N };
}
compute_roots :: (arr: [$N] f32) {
- for i: 0 .. N {
+ for i in 0 .. N {
arr[i] = math.sqrt(cast(f32) i);
}
}
set.insert(&S, 5);
set.insert(&S, 5);
set.insert(&S, 6);
- for entry: S.entries do println(entry.value);
+ for entry in S.entries do println(entry.value);
println(set.has(&S, 5));
println("--------------");
set.remove(&S, 5);
- for entry: S.entries do println(entry.value);
+ for entry in S.entries do println(entry.value);
println(set.has(&S, 5));
}
\ No newline at end of file
use core {*}
main :: () {
- for t: Pair(str, str).[
+ for t in Pair(str, str).[
.{"", "."},
.{"abc", "abc"},
.{"..", ".."},
sstream := io.buffer_stream_make(some_string);
sreader := io.reader_make(&sstream);
- for i: 0 .. 2 {
+ for i in 0 .. 2 {
word := io.read_word(&sreader, allocator=context.temp_allocator);
println(word);
}
}
quick_map :: (v: $T) => switch v {
- case val: .z => val;
- case val: .y => conv.format("{}", val);
- case val: .x => conv.format("{}", val);
+ case .z as val => val;
+ case .y as val => conv.format("{}", val);
+ case .x as val => conv.format("{}", val);
}
}
*val_ptr = 5678;
printf("New value is: {*}\n", val_ptr);
- for t: it.tags {
+ for t in it.tags {
if t.type == str {
printf("{*}\n", misc.any_as(t, str));
}
extract_variant :: macro (u: $U, $variant: U.tag_enum) => {
switch u {
- case v: variant {
+ case variant as v {
return Optional.make(v);
}
}
value := Extraction.{ string = "This works" };
switch value {
- case int_value: .int {
+ case .int as int_value {
printf("This is an integer: {}\n", int_value);
}
- case float_value: .float {
+ case .float as float_value {
printf("This is a float: {}\n", float_value);
}
- case string_value: .string {
+ case .string as string_value {
printf("This is a string: {}\n", string_value);
}
}
do_the_thing :: (value: &Methoded) {
switch *value {
- case int_value: .int {
+ case .int as int_value {
printf("This is an integer: {}\n", int_value);
}
- case float_value: .float {
+ case .float as float_value {
printf("This is a float: {}\n", float_value);
}
- case string_value: .string {
+ case .string as string_value {
printf("This is a string: {}\n", string_value);
}
}
switch walker {
case .End do break break;
- case &next: .Next {
+ case .Next as &next {
printf("{}\n", next.data);
walker = next.next;
}
output := make(dyn_str);
defer delete(&output);
- for i: 0x1F0A0 .. 0x1F0E0 {
+ for i in 0x1F0A0 .. 0x1F0E0 {
utf8.append_rune(&output, i);
}
old_va_test :: (prefix: str, va: ..i32) {
println(prefix);
- for v: va do println(v);
+ for v in va do println(v);
}
new_va_test :: (prefix: str, va: ..any) {
println(prefix);
- for i: 0 .. va.count {
+ for i in 0 .. va.count {
// The right way to do it is this:
// x := * misc.any_as(va[i], i32);