Skip to content

Commit 746299d

Browse files
committed
Fix C3 hot reloading
1 parent fb77e5e commit 746299d

File tree

2 files changed

+72
-12
lines changed

2 files changed

+72
-12
lines changed

plugs/c3/future.c3

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ fn any! FutureDone.poll(&self, any data) @dynamic {
1313
}
1414

1515
macro Future done(value) {
16-
return @tclone(FutureDone{@tclone(value)});
16+
return @clone(FutureDone{@clone(value)});
1717
}
1818

1919
struct FutureReject(Future) {
@@ -27,7 +27,7 @@ fn any! FutureReject.poll(&self, any data) @dynamic {
2727
fn Future reject(anyfault excuse) {
2828
FutureReject r = {};
2929
r.excuse = excuse;
30-
return @tclone(r);
30+
return @clone(r);
3131
}
3232

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

5555
macro Future Future.then(Future left, FutureThenFunction f) {
56-
return @tclone(FutureThen {
56+
return @clone(FutureThen {
5757
.left = left,
5858
.f = f
5959
});
@@ -86,7 +86,7 @@ fn any! FutureCatch.poll(&self, any data) @dynamic {
8686
// inline macro or something?), but since catch is a C3 keyword we decided to call
8787
// @catch. If it causes any problems in the future we should consider a different naming.
8888
macro Future Future.@catch(Future left, FutureCatchFunction f) {
89-
return @tclone(FutureCatch {
89+
return @clone(FutureCatch {
9090
.left = left,
9191
.f = f
9292
});

plugs/c3/plug.c3

Lines changed: 68 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import std::io;
22
import std::math;
3+
import std::collections::list;
34
import raylib5::rl;
45
import future;
56

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

3839
fn Future lerp(float *place, float a, float b, float duration) {
39-
return @tclone(Lerp {
40+
return @clone(Lerp {
4041
.place = place,
4142
.a = a,
4243
.b = b,
@@ -60,7 +61,7 @@ fn any! Parallel.poll(&urmom, any env) @dynamic {
6061
}
6162

6263
fn Future parallel(Future[] futures) {
63-
return @tclone(Parallel {
64+
return @clone(Parallel {
6465
.futures = futures,
6566
});
6667
}
@@ -82,33 +83,90 @@ fn any! Seq.poll(&urmom, any env) @dynamic {
8283
}
8384

8485
fn Future seq(Future[] futures) {
85-
return @tclone(Seq {
86+
return @clone(Seq {
8687
.futures = futures,
8788
});
8889
}
8990

91+
struct Patcher {
92+
List(<Future*>) lerp;
93+
List(<Future*>) par;
94+
List(<Future*>) seq;
95+
}
96+
97+
fn void Patcher.add(&urmom, Future *f) {
98+
switch(f.type) {
99+
case Lerp.typeid:
100+
urmom.lerp.push(f);
101+
case Parallel.typeid:
102+
urmom.par.push(f);
103+
case Seq.typeid:
104+
urmom.seq.push(f);
105+
default:
106+
unreachable("unexpected type");
107+
}
108+
}
109+
110+
macro @list_patch(list, $Type) {
111+
for (usz i = 0; i < list.len(); i++) {
112+
*list[i] = (Future) any_make(list[i].ptr, $Type.typeid);
113+
$Type *ft = anycast(*list[i], $Type)!!; // Some dirty trickery
114+
(void)ft;
115+
}
116+
}
117+
118+
fn void Patcher.patch(&urmom) {
119+
io::printfn("Patching futures");
120+
@list_patch(urmom.lerp, Lerp);
121+
@list_patch(urmom.par, Parallel);
122+
@list_patch(urmom.seq, Seq);
123+
}
124+
125+
fn void Patcher.clear(&urmom) {
126+
urmom.lerp.clear();
127+
urmom.par.clear();
128+
urmom.seq.clear();
129+
}
130+
90131
struct State {
91132
float t1, t2;
92133
bool finished;
93134
Future anim;
135+
Patcher patcher;
94136
}
95137

96138
State *state = null;
97139

98140
fn void reset_anim()
99141
{
100-
// TODO: clean up allocator::temp() here
101-
state.anim = parallel(@tclone(Future[*] {
102-
// TODO: Tuck the whole @tclone(Future[*]{ ... }) under the future constructors
142+
// TODO: clean up allocator::heap() here
143+
// Leaky-leaky
144+
state.anim = parallel(@clone(Future[*] {
145+
// TODO: Tuck the whole @clone(Future[*]{ ... }) under the future constructors
103146
// See if variadic args can be applied here
104-
seq(@tclone(Future[*] {
147+
seq(@clone(Future[*] {
105148
lerp(&state.t1, 0, 1, CYCLE_DURATION),
106149
lerp(&state.t1, 1, 0, CYCLE_DURATION/4),
107150
})),
108-
seq(@tclone(Future[*] {
151+
seq(@clone(Future[*] {
109152
lerp(&state.t2, 0, 1, CYCLE_DURATION + CYCLE_DURATION/4),
110153
}))
111154
}));
155+
156+
state.patcher.clear();
157+
158+
// TODO: reflection to do this automatically or something
159+
// Maybe Future.traverse(fn void FutureTraverseFn(void *env, Future *f))?
160+
161+
state.patcher.add(&state.anim);
162+
Parallel *p = anycast(state.anim, Parallel)!!;
163+
foreach(&s: p.futures) {
164+
state.patcher.add(s);
165+
Seq *s1 = anycast(*s, Seq)!!;
166+
foreach(&l: s1.futures) {
167+
state.patcher.add(l);
168+
}
169+
}
112170
}
113171

114172
fn void plug_init() @export("plug_init")
@@ -125,6 +183,8 @@ fn void* plug_pre_reload() @export("plug_pre_reload")
125183
fn void plug_post_reload(void *old_state) @export("plug_post_reload")
126184
{
127185
state = old_state;
186+
187+
state.patcher.patch();
128188
}
129189

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

0 commit comments

Comments
 (0)