Skip to content

Commit bdd75e8

Browse files
committed
fix: Fix generator variable allocation bug
The code changes in `src/ast/node/control.rs` fix a bug related to variable allocation in generator functions. Previously, when a variable was used in a generator, it needed to be stored in the context. However, there was an issue where the variable was not properly allocated in the context, leading to incorrect behavior. This commit addresses the bug by correctly allocating the variable in the context when inside a generator. It also adds a check to ensure that the allocation is only performed when necessary. I also added some code in iter test, to digging deeper into possibility of implement effect system based on generator.
1 parent c153808 commit bdd75e8

File tree

4 files changed

+120
-16
lines changed

4 files changed

+120
-16
lines changed

src/ast/node/control.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,19 @@ impl MatchArmCondition {
434434
}
435435
MatchArmCondition::Var(a) => {
436436
ctx.push_semantic_token(a.range, SemanticTokenType::VARIABLE, 0);
437+
let v = if ctx.generator_data.is_some() {
438+
// special case: in generator, every variable needs to be stored in the context
439+
let alloca = builder.alloc(
440+
a.name.as_str(),
441+
&PLType::new_i8_ptr(),
442+
ctx,
443+
Some(range.start),
444+
);
445+
builder.build_store(alloca, v);
446+
alloca
447+
} else {
448+
v
449+
};
437450
_ = ctx.add_symbol(a.name, v, ty.clone(), a.range, false, false);
438451
ctx.push_type_hints(a.range, ty);
439452
let i = builder.int_value(&PriType::BOOL, 1, false);

src/ast/node/node_result.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ impl TerminatorEnum {
1818
self == TerminatorEnum::None || self == TerminatorEnum::YieldReturn
1919
}
2020
pub fn is_return(self) -> bool {
21-
self == TerminatorEnum::Return || self == TerminatorEnum::YieldReturn
21+
self == TerminatorEnum::Return
2222
}
2323
}
2424

test/main.pi

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,9 @@ pub fn main() i64 {
7171
_io::test_io();
7272
future_test::test_future();
7373
std_test::test_std();
74+
75+
7476

7577
return 0;
7678
}
79+

test/test/iter.pi

Lines changed: 103 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -46,18 +46,54 @@ gen fn generator(b: i64, c: i64) Iterator<i64> {
4646

4747
var effect1 = 1;
4848
var effect2 = 2;
49+
var eff_ret = 10086;
50+
51+
gen fn generator1() Iterator<(i64, |*||=>void,*||=>void| =>void)> {
52+
let retgen2 = 0;
53+
let generator = generator2();
54+
while true {
55+
let nx = generator.next();
56+
if nx is None {
57+
break;
58+
}
59+
let nx_v = nx as (i64, |*||=>void,*||=>void| =>void)!;
60+
match nx_v {
61+
(10086, f) => {
62+
let wrapped_f = |iter:*||=>void,handler:*||=>void| => {
63+
let real_handler = unsafe_cast<|||=>void|=>void>(handler);
64+
let ret_handler = |resolve:||=>void, ret|=>{
65+
retgen2 = ret;
66+
(*real_handler)(resolve);
67+
return;
68+
};
69+
let clp = &ret_handler;
70+
let arg2 = unsafe_cast<||=>void>(clp);
71+
f(iter,arg2);
72+
73+
return;
74+
};
75+
let yr= (eff_ret,wrapped_f);
76+
yield return yr;
77+
break;
78+
}
79+
yr => {
80+
yield return yr;
81+
}
82+
}
83+
}
84+
85+
println!("got retgen2 ", retgen2);
86+
4987

50-
gen fn generator1() Iterator<(i64, |*Iterator<()>,*||=>void| =>void)> {
5188
// executeGenerator(generator2());
52-
let a = 1;
89+
let a = retgen2;
5390
let re = 0;
5491

55-
let f = |iter:*Iterator<()>,handler:*||=>void| => {
92+
let f = |next:*||=>void,handler:*||=>void| => {
5693
let real_handler = unsafe_cast<||i64|=>void,i64|=>void>(handler);
5794
let resolve = |ret|=> {
5895
re = ret;
59-
println!(ret);
60-
(*iter).next();
96+
(*next)();
6197
return;
6298
};
6399
(*real_handler)(resolve,a);
@@ -70,26 +106,82 @@ gen fn generator1() Iterator<(i64, |*Iterator<()>,*||=>void| =>void)> {
70106
}
71107

72108

73-
fn executeGenerator(g:Iterator<(i64, |*Iterator<()>,*||=>void| =>void)>) void {
109+
gen fn generator2() Iterator<(i64, |*||=>void,*||=>void| =>void)> {
110+
// executeGenerator(generator2());
111+
let a = 1;
112+
let re = 0;
113+
114+
let f = |next:*||=>void,handler:*||=>void| => {
115+
let real_handler = unsafe_cast<||i64|=>void,i64|=>void>(handler);
116+
let resolve = |ret|=> {
117+
re = ret;
118+
(*next)();
119+
return;
120+
};
121+
(*real_handler)(resolve,a);
122+
123+
return;
124+
};
125+
let yr= (effect1,f);
126+
yield return yr;
127+
println!("g2 got re ", re);
128+
129+
f = |next:*||=>void,handler:*||=>void| => {
130+
let real_handler = unsafe_cast<|||=>void,i64|=>void>(handler);
131+
let resolve = ||=> {
132+
(*next)();
133+
return;
134+
};
135+
(*real_handler)(resolve,100);
136+
137+
return;
138+
};
139+
// return
140+
yr= (eff_ret,f);
141+
yield return yr;
142+
}
143+
144+
145+
fn executeGenerator(g:Iterator<(i64, |*||=>void,*||=>void| =>void)>) void {
74146
let eff = g.next();
75147
if eff is None {
148+
println!("ret none");
76149
return;
77150
}
78-
match eff as (i64, |*Iterator<()>,*||=>void| =>void)! {
151+
match eff as (i64, |*||=>void,*||=>void| =>void)! {
79152
(1,r) => {
153+
println!("handle eff1");
80154
let cl =|resolve, a| => {
81155
eff1handler(resolve, a);
82156
return;
83157
};
84-
let it = &g;
158+
let next = & ||=>{
159+
executeGenerator(g);
160+
return;
161+
};
85162
let clp = &cl;
86-
let arg1 = unsafe_cast<Iterator<()>>(it);
87163
let arg2 = unsafe_cast<||=>void>(clp);
88-
r(arg1,arg2);
164+
r(next,arg2);
89165
}
90166
(2,r) => {
167+
println!("handle eff2");
168+
}
169+
(10086,r) => {
170+
println!("handle effret");
171+
let cl =|resolve:||=>void| => {
172+
resolve();
173+
return;
174+
};
175+
let next = & ||=>{
176+
executeGenerator(g);
177+
return;
178+
};
179+
let clp = &cl;
180+
let arg2 = unsafe_cast<||=>void>(clp);
181+
r(next,arg2);
91182
}
92-
_ => {
183+
(n, f) => {
184+
println!("handle eff", n);
93185
}
94186
}
95187
return;
@@ -109,7 +201,3 @@ fn eff2handler(resolve: ||=>void) void {
109201
return;
110202
}
111203

112-
113-
gen fn generator2() Iterator<i64> {
114-
yield return effect2;
115-
}

0 commit comments

Comments
 (0)