diff --git a/compiler/erg_common/error.rs b/compiler/erg_common/error.rs index a76b9d21..2ebd3c94 100644 --- a/compiler/erg_common/error.rs +++ b/compiler/erg_common/error.rs @@ -394,10 +394,10 @@ fn format_code_and_pointer( 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( writeln!( res, "{lineno}{VBAR_UNICODE} {code}\n{pointer}", - code = codes[i] + code = codes.get(i).unwrap_or(&String::new()), ) .unwrap(); } diff --git a/compiler/erg_compiler/codegen.rs b/compiler/erg_compiler/codegen.rs index 83a8b072..77adbb5c 100644 --- a/compiler/erg_compiler/codegen.rs +++ b/compiler/erg_compiler/codegen.rs @@ -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),