resolved merge conflict

This commit is contained in:
jesse 2025-05-20 20:12:33 -07:00
commit b19cda86be
4 changed files with 149 additions and 20 deletions

1
TODO Normal file
View file

@ -0,0 +1 @@
- Add easing module

View file

@ -7,8 +7,8 @@
#import,file "./hash/module.jai"(true); #import,file "./hash/module.jai"(true);
rmath :: #import,file "./math/module.jai"(.radians, true); rmath :: #import,file "./math/module.jai"(.radians, true);
dmath :: #import,file "./math/module.jai"(.degrees, true); // dmath :: #import,file "./math/module.jai"(.degrees, true);
tmath :: #import,file "./math/module.jai"(.turns, true); // tmath :: #import,file "./math/module.jai"(.turns, true);
} }

View file

@ -71,25 +71,49 @@ operator | :: with;
/* /*
Creates a named block that can exit early (via 'break' or 'continue'). Creates a named block that can exit early (via 'break' or 'continue').
This mostly replaces the case where you'd like to jump to This mostly replaces the case where you'd like to jump to
the end of a scope based on some logic within. Without the end of a scope based on some logic within. Without
gotos, this is the next best thing. gotos, this is the next best thing.
Usage: Usage:
// within a loop // within a loop
for this_block() { // this is named 'block' by default for this_block() { // this is named 'block' by default
if !moving break; if !moving break;
// do movement here // do movement here
} }
for this_block("render_player") { for this_block("render_player") {
if invisible break render_player; if invisible break render_player;
// do rendering here // do rendering here
} }
*/ */
this_block :: ($name: string = Default_Name) -> Named_Block(name) #expand { return .{}; } this_block :: ($name: string = Default_Name) -> Named_Block(name) #expand { return .{}; }
/*
Drop-in loop unrolling macro.
Usage:
for unroll(5) {
// duplicates this body 5 times exactly
}
known_size: [3]float;
for unroll(known_size) {
// duplicates this body 3 times exactly
}
var_size: []float;
for unroll(var_size) {
// duplicates this body a set number of times,
// falling back to a regular for loop to handle
// the remaining iterations.
}
*/
unroll :: ($count: int) -> Unrolled_Loop(count) { return .{}; }
unroll :: (arr: [$N]$T) -> Unrolled_Loop(N, T) { return .{ array = arr }; }
unroll :: (arr: []$T) -> Unrolled_Loop(-1, T) { return .{ array = arr }; }
// Call #c_call procedures inline with the current context: 'c_call(some_c_call_proc(10, 20))' // Call #c_call procedures inline with the current context: 'c_call(some_c_call_proc(10, 20))'
c_call :: (call: Code) #expand { c_call :: (call: Code) #expand {
push_context context { #insert,scope(call) call; } push_context context { #insert,scope(call) call; }
@ -100,10 +124,7 @@ c_call :: (call: Code, ctx: #Context) #expand {
push_context ctx { #insert,scope(call) call; } push_context ctx { #insert,scope(call) call; }
} }
#scope_file; // @note(judah): for_expansions have to be exported
Default_Name :: "block";
Named_Block :: struct(NAME: string) {}
for_expansion :: (v: *Named_Block, code: Code, _: For_Flags) #expand { for_expansion :: (v: *Named_Block, code: Code, _: For_Flags) #expand {
#insert #run basic.tprint(#string END #insert #run basic.tprint(#string END
@ -118,6 +139,109 @@ for_expansion :: (v: *Named_Block, code: Code, _: For_Flags) #expand {
ifx v.NAME.count != 0 v.NAME else Default_Name); ifx v.NAME.count != 0 v.NAME else Default_Name);
} }
for_expansion :: (loop: *Unrolled_Loop, body: Code, flags: For_Flags, loc := #caller_location) #expand {
#assert flags & .REVERSE == 0 "reverse iteration not supported with loop unrolling (for now)";
#assert flags & .POINTER == 0 "pointer iteration not supported with loop unrolling (for now)";
// runtime unroll
#if loop.N == -1 {
for i: 0..loop.array.count - 1 {
`it := #no_abc loop.array[i];
`it_index := i;
#insert,scope(body) body;
}
// @todo(judah): below doesn't properly handle counts not divisible by 4,
// so we end up going over the bounds of the array.
// UNROLL_AMOUNT :: 4; // @todo(judah): make this configurable?
// unrolled_loops := loop.array.count / UNROLL_AMOUNT;
// remainder_loops := loop.array.count % UNROLL_AMOUNT;
// `it: loop.T;
// for i: 0..unrolled_loops #no_abc {
// basic.print("I: %\n", i);
// index := i * UNROLL_AMOUNT;
// it_index = index + 0;
// it = loop.array[it_index];
// #insert,scope(body) body;
// it_index = index + 1;
// it = loop.array[it_index];
// #insert,scope(body) body;
// it_index = index + 2;
// it = loop.array[it_index];
// #insert,scope(body) body;
// it_index = index + 3;
// it = loop.array[it_index];
// #insert,scope(body) body;
// }
// after_big_loop := it_index;
// for i: 0..remainder_loops #no_abc {
// it_index = after_big_loop + i;
// it = loop.array[it_index];
// #insert,scope(body) body;
// }
}
// compile-time unroll
else {
`it_index := 0;
#insert -> string {
b: basic.String_Builder;
basic.print_to_builder(*b, "// inserted unrolled loop (N = %) at %:%\n", loop.N, loc.fully_pathed_filename, loc.line_number);
if loop.T == void {
basic.append(*b, "`it: int = ---;\n");
}
else {
basic.append(*b, "`it: loop.T = ---;\n");
}
for 0..loop.N - 1 {
basic.append(*b, "{\n");
if loop.T == void {
basic.print_to_builder(*b, "\tit = %;\n", it);
}
else {
basic.print_to_builder(*b, "\tit = #no_abc loop.array[%];\n", it);
}
basic.print_to_builder(*b, "\tit_index = %;\n", it);
basic.append(*b, "\t#insert,scope(body) body;\n");
basic.append(*b, "}\n");
}
return basic.builder_to_string(*b);
}
}
}
#scope_file;
Default_Name :: "block";
Named_Block :: struct(NAME: string) {}
Unrolled_Loop :: struct(N: int, T: Type = void) {
// Only store arrays when we absolutely have to.
#if T != void {
// @todo(judah): because this will only be created via 'unroll',
// should these be pointers to the underlying arrays so we don't
// pay for a copy?
#if N == -1 {
array: []T = ---;
}
else {
array: [N]T = ---;
}
}
}
pp :: #import "Program_Print"; pp :: #import "Program_Print";
compiler :: #import "Compiler"; compiler :: #import "Compiler";

View file

@ -97,24 +97,28 @@ for_expansion :: (v: *Vec, body: Code, flags: For_Flags) #expand {
operator + :: inline (l: Vec, r: Vec(l.N, l.T)) -> Vec(l.N, l.T) #no_abc { operator + :: inline (l: Vec, r: Vec(l.N, l.T)) -> Vec(l.N, l.T) #no_abc {
res: Vec(l.N, l.T) = ---; res: Vec(l.N, l.T) = ---;
// @todo(judah): unroll for N <= 4
for l res[it_index] = it + r[it_index]; for l res[it_index] = it + r[it_index];
return res; return res;
} }
operator - :: inline (l: Vec, r: Vec(l.N, l.T)) -> Vec(l.N, l.T) #no_abc { operator - :: inline (l: Vec, r: Vec(l.N, l.T)) -> Vec(l.N, l.T) #no_abc {
res: Vec(l.N, l.T) = ---; res: Vec(l.N, l.T) = ---;
// @todo(judah): unroll for N <= 4
for l res[it_index] = it - r[it_index]; for l res[it_index] = it - r[it_index];
return res; return res;
} }
operator * :: inline (l: Vec, r: Vec(l.N, l.T)) -> Vec(l.N, l.T) #no_abc { operator * :: inline (l: Vec, r: Vec(l.N, l.T)) -> Vec(l.N, l.T) #no_abc {
res: Vec(l.N, l.T) = ---; res: Vec(l.N, l.T) = ---;
// @todo(judah): unroll for N <= 4
for l res[it_index] = it * r[it_index]; for l res[it_index] = it * r[it_index];
return res; return res;
} }
operator / :: inline (l: Vec, r: Vec(l.N, l.T)) -> Vec(l.N, l.T) #no_abc { operator / :: inline (l: Vec, r: Vec(l.N, l.T)) -> Vec(l.N, l.T) #no_abc {
res: Vec(l.N, l.T) = ---; res: Vec(l.N, l.T) = ---;
// @todo(judah): unroll for N <= 4
for l res[it_index] = it / r[it_index]; for l res[it_index] = it / r[it_index];
return res; return res;
} }