Skip to content

Commit

Permalink
Introduce dedicated instruction for loop else
Browse files Browse the repository at this point in the history
  • Loading branch information
mitsuhiko committed Nov 19, 2022
1 parent 6e60023 commit d53160d
Show file tree
Hide file tree
Showing 3 changed files with 11 additions and 7 deletions.
9 changes: 3 additions & 6 deletions minijinja/src/compiler/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,16 +136,13 @@ impl<'source> CodeGenerator<'source> {
}

/// Ends the open for loop
pub fn end_for_loop(&mut self, push_did_iterate: bool) {
pub fn end_for_loop(&mut self, push_did_not_iterate: bool) {
match self.pending_block.pop() {
Some(PendingBlock::Loop(iter_instr)) => {
self.add(Instruction::Jump(iter_instr));
let loop_end = self.next_instruction();
if push_did_iterate {
self.add(Instruction::Lookup("loop"));
self.add(Instruction::GetAttr("index0"));
self.add(Instruction::LoadConst(Value::from(0)));
self.add(Instruction::Eq);
if push_did_not_iterate {
self.add(Instruction::PushDidNotIterate);
};
self.add(Instruction::PopFrame);
if let Some(Instruction::Iterate(ref mut jump_target)) =
Expand Down
3 changes: 3 additions & 0 deletions minijinja/src/compiler/instructions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,9 @@ pub enum Instruction<'source> {
/// ends and must point to a `PopFrame` instruction.
Iterate(usize),

/// Push a bool that indicates that the loop iterated.
PushDidNotIterate,

/// Pops the topmost frame
PopFrame,

Expand Down
6 changes: 5 additions & 1 deletion minijinja/src/vm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ impl<'env> Vm<'env> {
ctx_ok!(self.push_loop(state, a, *flags, pc, next_loop_recursion_jump.take()));
}
Instruction::Iterate(jump_target) => {
let l = state.ctx.current_loop().expect("not inside a loop");
let l = state.ctx.current_loop().unwrap();
l.object.idx.fetch_add(1, Ordering::Relaxed);
match l.iterator.next() {
Some(item) => stack.push(item),
Expand All @@ -360,6 +360,10 @@ impl<'env> Vm<'env> {
}
};
}
Instruction::PushDidNotIterate => {
let l = state.ctx.current_loop().unwrap();
stack.push(Value::from(l.object.idx.load(Ordering::Relaxed) == 0));
}
Instruction::Jump(jump_target) => {
pc = *jump_target;
continue;
Expand Down

0 comments on commit d53160d

Please sign in to comment.