Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix C3 hot reloading #2

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions plugs/c3/future.c3
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ fn any! FutureDone.poll(&self, any data) @dynamic {
}

macro Future done(value) {
return @tclone(FutureDone{@tclone(value)});
return @clone(FutureDone{@clone(value)});
}

struct FutureReject(Future) {
Expand All @@ -27,7 +27,7 @@ fn any! FutureReject.poll(&self, any data) @dynamic {
fn Future reject(anyfault excuse) {
FutureReject r = {};
r.excuse = excuse;
return @tclone(r);
return @clone(r);
}

def FutureThenFunction = fn Future(any result);
Expand All @@ -53,7 +53,7 @@ fn any! FutureThen.poll(&self, any data) @dynamic {
}

macro Future Future.then(Future left, FutureThenFunction f) {
return @tclone(FutureThen {
return @clone(FutureThen {
.left = left,
.f = f
});
Expand Down Expand Up @@ -86,7 +86,7 @@ fn any! FutureCatch.poll(&self, any data) @dynamic {
// inline macro or something?), but since catch is a C3 keyword we decided to call
// @catch. If it causes any problems in the future we should consider a different naming.
macro Future Future.@catch(Future left, FutureCatchFunction f) {
return @tclone(FutureCatch {
return @clone(FutureCatch {
.left = left,
.f = f
});
Expand Down
74 changes: 66 additions & 8 deletions plugs/c3/plug.c3
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import std::io;
import std::math;
import std::collections::list;
import raylib5::rl;
import future;

Expand Down Expand Up @@ -36,7 +37,7 @@ fn any! Lerp.poll(&self, any env) @dynamic {
}

fn Future lerp(float *place, float a, float b, float duration) {
return @tclone(Lerp {
return @clone(Lerp {
.place = place,
.a = a,
.b = b,
Expand All @@ -60,7 +61,7 @@ fn any! Parallel.poll(&urmom, any env) @dynamic {
}

fn Future parallel(Future[] futures) {
return @tclone(Parallel {
return @clone(Parallel {
.futures = futures,
});
}
Expand All @@ -82,33 +83,88 @@ fn any! Seq.poll(&urmom, any env) @dynamic {
}

fn Future seq(Future[] futures) {
return @tclone(Seq {
return @clone(Seq {
.futures = futures,
});
}

struct Patcher {
List(<Future*>) lerp;
List(<Future*>) par;
List(<Future*>) seq;
}

fn void Patcher.add(&urmom, Future *f) {
switch(f.type) {
case Lerp.typeid:
urmom.lerp.push(f);
case Parallel.typeid:
urmom.par.push(f);
case Seq.typeid:
urmom.seq.push(f);
default:
unreachable("unexpected type");
}
}

macro @list_patch(list, $Type) {
for (usz i = 0; i < list.len(); i++) {
*list[i] = (Future) any_make(list[i].ptr, $Type.typeid);
}
}

fn void Patcher.patch(&urmom) {
io::printfn("Patching futures");
@list_patch(urmom.lerp, Lerp);
@list_patch(urmom.par, Parallel);
@list_patch(urmom.seq, Seq);
}

fn void Patcher.clear(&urmom) {
urmom.lerp.clear();
urmom.par.clear();
urmom.seq.clear();
}

struct State {
float t1, t2;
bool finished;
Future anim;
Patcher patcher;
}

State *state = null;

fn void reset_anim()
{
// TODO: clean up allocator::temp() here
state.anim = parallel(@tclone(Future[*] {
// TODO: Tuck the whole @tclone(Future[*]{ ... }) under the future constructors
// TODO: clean up allocator::heap() here
// Leaky-leaky
state.anim = parallel(@clone(Future[*] {
// TODO: Tuck the whole @clone(Future[*]{ ... }) under the future constructors
// See if variadic args can be applied here
seq(@tclone(Future[*] {
seq(@clone(Future[*] {
lerp(&state.t1, 0, 1, CYCLE_DURATION),
lerp(&state.t1, 1, 0, CYCLE_DURATION/4),
})),
seq(@tclone(Future[*] {
seq(@clone(Future[*] {
lerp(&state.t2, 0, 1, CYCLE_DURATION + CYCLE_DURATION/4),
}))
}));

state.patcher.clear();

// TODO: reflection to do this automatically or something
// Maybe Future.traverse(fn void FutureTraverseFn(void *env, Future *f))?

state.patcher.add(&state.anim);
Parallel *p = anycast(state.anim, Parallel)!!;
foreach(&s: p.futures) {
state.patcher.add(s);
Seq *s1 = anycast(*s, Seq)!!;
foreach(&l: s1.futures) {
state.patcher.add(l);
}
}
}

fn void plug_init() @export("plug_init")
Expand All @@ -125,6 +181,8 @@ fn void* plug_pre_reload() @export("plug_pre_reload")
fn void plug_post_reload(void *old_state) @export("plug_post_reload")
{
state = old_state;

state.patcher.patch();
}

fn void orbit_circle(Env env, float t, float radius, float orbit, Color color)
Expand Down