Skip to content

Commit 4e5fef6

Browse files
committed
implement async for function
1 parent 2dade29 commit 4e5fef6

File tree

1 file changed

+44
-20
lines changed

1 file changed

+44
-20
lines changed

compiler/src/compile.rs

Lines changed: 44 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ enum CallType {
3333
Keyword { nargs: u32 },
3434
Ex { has_kwargs: bool },
3535
}
36+
3637
impl CallType {
3738
fn normal_call(self) -> Instruction {
3839
match self {
@@ -69,6 +70,7 @@ pub struct CompileOpts {
6970
/// not emit assert statements
7071
pub optimize: u8,
7172
}
73+
7274
impl Default for CompileOpts {
7375
fn default() -> Self {
7476
CompileOpts { optimize: 0 }
@@ -1608,7 +1610,7 @@ impl Compiler {
16081610
"starred assignment target must be in a list or tuple".to_owned(),
16091611
),
16101612
_ => CompileErrorType::Assign(target.node.name()),
1611-
}))
1613+
}));
16121614
}
16131615
}
16141616

@@ -1907,10 +1909,10 @@ impl Compiler {
19071909
YieldFrom { value } => {
19081910
match self.ctx.func {
19091911
FunctionContext::NoFunction => {
1910-
return Err(self.error(CompileErrorType::InvalidYieldFrom))
1912+
return Err(self.error(CompileErrorType::InvalidYieldFrom));
19111913
}
19121914
FunctionContext::AsyncFunction => {
1913-
return Err(self.error(CompileErrorType::AsyncYieldFrom))
1915+
return Err(self.error(CompileErrorType::AsyncYieldFrom));
19141916
}
19151917
FunctionContext::Function => {}
19161918
}
@@ -2295,37 +2297,48 @@ impl Compiler {
22952297
}
22962298

22972299
let mut loop_labels = vec![];
2300+
let mut is_async = false;
22982301
for generator in generators {
2299-
if generator.is_async {
2300-
unimplemented!("async for comprehensions");
2301-
}
2302-
23032302
let loop_block = self.new_block();
23042303
let after_block = self.new_block();
23052304

23062305
// Setup for loop:
2307-
self.emit(Instruction::SetupLoop {
2308-
break_target: after_block,
2309-
});
2306+
if !generator.is_async {
2307+
self.emit(Instruction::SetupLoop {
2308+
break_target: after_block,
2309+
});
2310+
}
23102311

23112312
if loop_labels.is_empty() {
23122313
// Load iterator onto stack (passed as first argument):
23132314
self.emit(Instruction::LoadFast(arg0));
23142315
} else {
23152316
// Evaluate iterated item:
23162317
self.compile_expression(&generator.iter)?;
2317-
2318-
// Get iterator / turn item into an iterator
2319-
self.emit(Instruction::GetIter);
2318+
if generator.is_async {
2319+
self.emit(Instruction::GetAIter);
2320+
} else {
2321+
// Get iterator / turn item into an iterator
2322+
self.emit(Instruction::GetIter);
2323+
}
23202324
}
23212325

23222326
loop_labels.push((loop_block, after_block));
2323-
23242327
self.switch_to_block(loop_block);
2325-
self.emit(Instruction::ForIter {
2326-
target: after_block,
2327-
});
2328-
2328+
if generator.is_async {
2329+
is_async = true;
2330+
self.emit(Instruction::SetupFinally {
2331+
handler: after_block,
2332+
});
2333+
self.emit(Instruction::GetANext);
2334+
self.emit_constant(ConstantData::None);
2335+
self.emit(Instruction::YieldFrom);
2336+
self.emit(Instruction::PopBlock);
2337+
} else {
2338+
self.emit(Instruction::ForIter {
2339+
target: after_block,
2340+
});
2341+
}
23292342
self.compile_store(&generator.target)?;
23302343

23312344
// Now evaluate the ifs:
@@ -2379,10 +2392,19 @@ impl Compiler {
23792392
self.compile_expression(&generators[0].iter)?;
23802393

23812394
// Get iterator / turn item into an iterator
2382-
self.emit(Instruction::GetIter);
2395+
if is_async {
2396+
self.emit(Instruction::GetAIter);
2397+
} else {
2398+
self.emit(Instruction::GetIter);
2399+
}
23832400

23842401
// Call just created <listcomp> function:
23852402
self.emit(Instruction::CallFunctionPositional { nargs: 1 });
2403+
if is_async {
2404+
self.emit(Instruction::GetAwaitable);
2405+
self.emit_constant(ConstantData::None);
2406+
self.emit(Instruction::YieldFrom);
2407+
}
23862408
Ok(())
23872409
}
23882410

@@ -2398,7 +2420,9 @@ impl Compiler {
23982420
// "generator_stop" => {}
23992421
// "annotations" => {}
24002422
other => {
2401-
return Err(self.error(CompileErrorType::InvalidFutureFeature(other.to_owned())))
2423+
return Err(
2424+
self.error(CompileErrorType::InvalidFutureFeature(other.to_owned()))
2425+
);
24022426
}
24032427
}
24042428
}

0 commit comments

Comments
 (0)