mirror of
https://github.com/RustPython/Parser.git
synced 2025-09-04 09:31:31 +00:00
Make Continue have the target it's continuing to
This commit is contained in:
parent
48ca658ba0
commit
74a917a72e
1 changed files with 29 additions and 23 deletions
|
@ -88,7 +88,8 @@ impl CodeInfo {
|
||||||
| SetupExcept { handler: l }
|
| SetupExcept { handler: l }
|
||||||
| SetupWith { end: l }
|
| SetupWith { end: l }
|
||||||
| SetupAsyncWith { end: l }
|
| SetupAsyncWith { end: l }
|
||||||
| SetupLoop { end: l } => {
|
| SetupLoop { end: l }
|
||||||
|
| Continue { target: l } => {
|
||||||
*l = label_map[l.0].expect("label never set");
|
*l = label_map[l.0].expect("label never set");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,7 +132,7 @@ impl Default for CompileOpts {
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
struct CompileContext {
|
struct CompileContext {
|
||||||
in_loop: bool,
|
loop_data: Option<(Label, Label)>,
|
||||||
in_class: bool,
|
in_class: bool,
|
||||||
func: FunctionContext,
|
func: FunctionContext,
|
||||||
}
|
}
|
||||||
|
@ -144,6 +145,9 @@ enum FunctionContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CompileContext {
|
impl CompileContext {
|
||||||
|
fn in_loop(self) -> bool {
|
||||||
|
self.loop_data.is_some()
|
||||||
|
}
|
||||||
fn in_func(self) -> bool {
|
fn in_func(self) -> bool {
|
||||||
self.func != FunctionContext::NoFunction
|
self.func != FunctionContext::NoFunction
|
||||||
}
|
}
|
||||||
|
@ -236,7 +240,7 @@ impl Compiler {
|
||||||
current_qualified_path: None,
|
current_qualified_path: None,
|
||||||
done_with_future_stmts: false,
|
done_with_future_stmts: false,
|
||||||
ctx: CompileContext {
|
ctx: CompileContext {
|
||||||
in_loop: false,
|
loop_data: None,
|
||||||
in_class: false,
|
in_class: false,
|
||||||
func: FunctionContext::NoFunction,
|
func: FunctionContext::NoFunction,
|
||||||
},
|
},
|
||||||
|
@ -737,19 +741,21 @@ impl Compiler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Break => {
|
Break => {
|
||||||
if !self.ctx.in_loop {
|
if !self.ctx.in_loop() {
|
||||||
return Err(self.error_loc(CompileErrorType::InvalidBreak, statement.location));
|
return Err(self.error_loc(CompileErrorType::InvalidBreak, statement.location));
|
||||||
}
|
}
|
||||||
self.emit(Instruction::Break);
|
self.emit(Instruction::Break);
|
||||||
}
|
}
|
||||||
Continue => {
|
Continue => match self.ctx.loop_data {
|
||||||
if !self.ctx.in_loop {
|
Some((start, _)) => {
|
||||||
|
self.emit(Instruction::Continue { target: start });
|
||||||
|
}
|
||||||
|
None => {
|
||||||
return Err(
|
return Err(
|
||||||
self.error_loc(CompileErrorType::InvalidContinue, statement.location)
|
self.error_loc(CompileErrorType::InvalidContinue, statement.location)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
self.emit(Instruction::Continue);
|
},
|
||||||
}
|
|
||||||
Return { value } => {
|
Return { value } => {
|
||||||
if !self.ctx.in_func() {
|
if !self.ctx.in_func() {
|
||||||
return Err(self.error_loc(CompileErrorType::InvalidReturn, statement.location));
|
return Err(self.error_loc(CompileErrorType::InvalidReturn, statement.location));
|
||||||
|
@ -1052,7 +1058,7 @@ impl Compiler {
|
||||||
let prev_ctx = self.ctx;
|
let prev_ctx = self.ctx;
|
||||||
|
|
||||||
self.ctx = CompileContext {
|
self.ctx = CompileContext {
|
||||||
in_loop: false,
|
loop_data: None,
|
||||||
in_class: prev_ctx.in_class,
|
in_class: prev_ctx.in_class,
|
||||||
func: if is_async {
|
func: if is_async {
|
||||||
FunctionContext::AsyncFunction
|
FunctionContext::AsyncFunction
|
||||||
|
@ -1258,7 +1264,7 @@ impl Compiler {
|
||||||
self.ctx = CompileContext {
|
self.ctx = CompileContext {
|
||||||
func: FunctionContext::NoFunction,
|
func: FunctionContext::NoFunction,
|
||||||
in_class: true,
|
in_class: true,
|
||||||
in_loop: false,
|
loop_data: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let qualified_name = self.create_qualified_name(name, "");
|
let qualified_name = self.create_qualified_name(name, "");
|
||||||
|
@ -1399,10 +1405,10 @@ impl Compiler {
|
||||||
|
|
||||||
self.compile_jump_if(test, false, else_label)?;
|
self.compile_jump_if(test, false, else_label)?;
|
||||||
|
|
||||||
let was_in_loop = self.ctx.in_loop;
|
let was_in_loop = self.ctx.loop_data;
|
||||||
self.ctx.in_loop = true;
|
self.ctx.loop_data = Some((start_label, end_label));
|
||||||
self.compile_statements(body)?;
|
self.compile_statements(body)?;
|
||||||
self.ctx.in_loop = was_in_loop;
|
self.ctx.loop_data = was_in_loop;
|
||||||
self.emit(Instruction::Jump {
|
self.emit(Instruction::Jump {
|
||||||
target: start_label,
|
target: start_label,
|
||||||
});
|
});
|
||||||
|
@ -1428,6 +1434,8 @@ impl Compiler {
|
||||||
let else_label = self.new_label();
|
let else_label = self.new_label();
|
||||||
let end_label = self.new_label();
|
let end_label = self.new_label();
|
||||||
|
|
||||||
|
self.emit(Instruction::SetupLoop { end: end_label });
|
||||||
|
|
||||||
// The thing iterated:
|
// The thing iterated:
|
||||||
self.compile_expression(iter)?;
|
self.compile_expression(iter)?;
|
||||||
|
|
||||||
|
@ -1437,7 +1445,6 @@ impl Compiler {
|
||||||
|
|
||||||
self.emit(Instruction::GetAIter);
|
self.emit(Instruction::GetAIter);
|
||||||
|
|
||||||
self.emit(Instruction::SetupLoop { end: end_label });
|
|
||||||
self.set_label(start_label);
|
self.set_label(start_label);
|
||||||
self.emit(Instruction::SetupExcept {
|
self.emit(Instruction::SetupExcept {
|
||||||
handler: check_asynciter_label,
|
handler: check_asynciter_label,
|
||||||
|
@ -1459,26 +1466,25 @@ impl Compiler {
|
||||||
self.emit(Instruction::JumpIfTrue { target: else_label });
|
self.emit(Instruction::JumpIfTrue { target: else_label });
|
||||||
self.emit(Instruction::Raise { argc: 0 });
|
self.emit(Instruction::Raise { argc: 0 });
|
||||||
|
|
||||||
let was_in_loop = self.ctx.in_loop;
|
let was_in_loop = self.ctx.loop_data;
|
||||||
self.ctx.in_loop = true;
|
self.ctx.loop_data = Some((start_label, end_label));
|
||||||
self.set_label(body_label);
|
self.set_label(body_label);
|
||||||
self.compile_statements(body)?;
|
self.compile_statements(body)?;
|
||||||
self.ctx.in_loop = was_in_loop;
|
self.ctx.loop_data = was_in_loop;
|
||||||
} else {
|
} else {
|
||||||
// Retrieve Iterator
|
// Retrieve Iterator
|
||||||
self.emit(Instruction::GetIter);
|
self.emit(Instruction::GetIter);
|
||||||
|
|
||||||
self.emit(Instruction::SetupLoop { end: end_label });
|
|
||||||
self.set_label(start_label);
|
self.set_label(start_label);
|
||||||
self.emit(Instruction::ForIter { target: else_label });
|
self.emit(Instruction::ForIter { target: else_label });
|
||||||
|
|
||||||
// Start of loop iteration, set targets:
|
// Start of loop iteration, set targets:
|
||||||
self.compile_store(target)?;
|
self.compile_store(target)?;
|
||||||
|
|
||||||
let was_in_loop = self.ctx.in_loop;
|
let was_in_loop = self.ctx.loop_data;
|
||||||
self.ctx.in_loop = true;
|
self.ctx.loop_data = Some((start_label, end_label));
|
||||||
self.compile_statements(body)?;
|
self.compile_statements(body)?;
|
||||||
self.ctx.in_loop = was_in_loop;
|
self.ctx.loop_data = was_in_loop;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.emit(Instruction::Jump {
|
self.emit(Instruction::Jump {
|
||||||
|
@ -2009,7 +2015,7 @@ impl Compiler {
|
||||||
Lambda { args, body } => {
|
Lambda { args, body } => {
|
||||||
let prev_ctx = self.ctx;
|
let prev_ctx = self.ctx;
|
||||||
self.ctx = CompileContext {
|
self.ctx = CompileContext {
|
||||||
in_loop: false,
|
loop_data: Option::None,
|
||||||
in_class: prev_ctx.in_class,
|
in_class: prev_ctx.in_class,
|
||||||
func: FunctionContext::Function,
|
func: FunctionContext::Function,
|
||||||
};
|
};
|
||||||
|
@ -2182,7 +2188,7 @@ impl Compiler {
|
||||||
let prev_ctx = self.ctx;
|
let prev_ctx = self.ctx;
|
||||||
|
|
||||||
self.ctx = CompileContext {
|
self.ctx = CompileContext {
|
||||||
in_loop: false,
|
loop_data: None,
|
||||||
in_class: prev_ctx.in_class,
|
in_class: prev_ctx.in_class,
|
||||||
func: FunctionContext::Function,
|
func: FunctionContext::Function,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue