Implement while instructions

This commit is contained in:
Shunsuke Shibayama 2022-10-21 21:28:44 +09:00
parent 4fb43e520e
commit 4eae5788ca
2 changed files with 28 additions and 4 deletions

View file

@ -394,10 +394,10 @@ fn format_code_and_pointer<E: ErrorDisplay + ?Sized>(
let mut pointer = " ".repeat(lineno.to_string().len() + 2); // +2 means `| `
if i == 0 && i == final_step {
pointer += &" ".repeat(col_begin);
pointer += &"^".repeat(cmp::max(1, col_end - col_begin));
pointer += &"^".repeat(cmp::max(1, col_end.saturating_sub(col_begin)));
} else if i == 0 {
pointer += &" ".repeat(col_begin);
pointer += &"^".repeat(cmp::max(1, codes[i].len() - col_begin));
pointer += &"^".repeat(cmp::max(1, codes[i].len().saturating_sub(col_begin)));
} else if i == final_step {
pointer += &"^".repeat(col_end);
} else {
@ -406,7 +406,7 @@ fn format_code_and_pointer<E: ErrorDisplay + ?Sized>(
writeln!(
res,
"{lineno}{VBAR_UNICODE} {code}\n{pointer}",
code = codes[i]
code = codes.get(i).unwrap_or(&String::new()),
)
.unwrap();
}

View file

@ -1138,11 +1138,34 @@ impl CodeGenerator {
self.write_arg((idx_for_iter / 2) as u8);
let idx_end = self.cur_block().lasti;
self.edit_code(idx_for_iter + 1, (idx_end - idx_for_iter - 2) / 2);
// self.emit_pop_top();
self.stack_dec();
self.emit_load_const(ValueObj::None);
}
fn emit_while_instr(&mut self, mut args: Args) {
log!(info "entered {} ({})", fn_name!(), args);
let cond = args.remove(0);
self.emit_expr(cond.clone());
let idx_while = self.cur_block().lasti;
self.write_instr(POP_JUMP_IF_FALSE);
self.write_arg(0);
self.stack_dec();
let lambda = enum_unwrap!(args.remove(0), Expr::Lambda);
let init_stack_len = self.cur_block().stack_len;
let params = self.gen_param_names(&lambda.params);
self.emit_frameless_block(lambda.body, params);
if self.cur_block().stack_len > init_stack_len {
self.emit_pop_top();
}
self.emit_expr(cond);
self.write_instr(POP_JUMP_IF_TRUE);
self.write_arg(((idx_while + 2) / 2) as u8);
self.stack_dec();
let idx_end = self.cur_block().lasti;
self.edit_code(idx_while + 1, idx_end / 2);
self.emit_load_const(ValueObj::None);
}
fn emit_match_instr(&mut self, mut args: Args, _use_erg_specific: bool) {
log!(info "entered {}", fn_name!());
let expr = args.remove(0);
@ -1316,6 +1339,7 @@ impl CodeGenerator {
"Del" => self.emit_del_instr(args),
"discard" => self.emit_discard_instr(args),
"for" | "for!" => self.emit_for_instr(args),
"while!" => self.emit_while_instr(args),
"if" | "if!" => self.emit_if_instr(args),
"match" | "match!" => self.emit_match_instr(args, true),
"with!" => self.emit_with_instr(args),