mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-29 04:24:43 +00:00
WIP
This commit is contained in:
parent
32f6cbe7fb
commit
a95568ee48
2 changed files with 83 additions and 79 deletions
|
@ -201,6 +201,16 @@ impl CodeGenerator {
|
||||||
&self.toplevel_block().codeobj
|
&self.toplevel_block().codeobj
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn stack_len(&self) -> u32 {
|
||||||
|
self.cur_block().stack_len
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn lasti(&self) -> usize {
|
||||||
|
self.cur_block().lasti
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn emit_print_expr(&mut self) {
|
fn emit_print_expr(&mut self) {
|
||||||
|
@ -221,12 +231,12 @@ impl CodeGenerator {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn jump_delta(&self, jump_to: usize) -> usize {
|
fn jump_delta(&self, jump_to: usize) -> usize {
|
||||||
if self.py_version.minor >= Some(10) {
|
if self.py_version.minor >= Some(10) {
|
||||||
if self.cur_block().lasti <= jump_to * 2 {
|
if self.lasti() <= jump_to * 2 {
|
||||||
3
|
3
|
||||||
} else {
|
} else {
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
} else if self.cur_block().lasti <= jump_to {
|
} else if self.lasti() <= jump_to {
|
||||||
6
|
6
|
||||||
} else {
|
} else {
|
||||||
0
|
0
|
||||||
|
@ -306,7 +316,7 @@ impl CodeGenerator {
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
let delta = self.jump_delta(code);
|
let delta = self.jump_delta(code);
|
||||||
let bytes = u32::try_from(code + delta).unwrap().to_be_bytes();
|
let bytes = u32::try_from(code + delta).unwrap().to_be_bytes();
|
||||||
let before_instr = self.cur_block().lasti.saturating_sub(1);
|
let before_instr = self.lasti().saturating_sub(1);
|
||||||
self.mut_cur_block_codeobj().code.push(bytes[3]);
|
self.mut_cur_block_codeobj().code.push(bytes[3]);
|
||||||
self.mut_cur_block().lasti += 1;
|
self.mut_cur_block().lasti += 1;
|
||||||
self.extend_arg(before_instr, &bytes);
|
self.extend_arg(before_instr, &bytes);
|
||||||
|
@ -321,14 +331,14 @@ impl CodeGenerator {
|
||||||
|
|
||||||
fn stack_inc(&mut self) {
|
fn stack_inc(&mut self) {
|
||||||
self.mut_cur_block().stack_len += 1;
|
self.mut_cur_block().stack_len += 1;
|
||||||
if self.cur_block().stack_len > self.cur_block_codeobj().stacksize {
|
if self.stack_len() > self.cur_block_codeobj().stacksize {
|
||||||
self.mut_cur_block_codeobj().stacksize = self.cur_block().stack_len;
|
self.mut_cur_block_codeobj().stacksize = self.stack_len();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn stack_dec(&mut self) {
|
fn stack_dec(&mut self) {
|
||||||
if self.cur_block().stack_len == 0 {
|
if self.stack_len() == 0 {
|
||||||
let lasti = self.cur_block().lasti;
|
let lasti = self.lasti();
|
||||||
let last = self.cur_block_codeobj().code.last().unwrap();
|
let last = self.cur_block_codeobj().code.last().unwrap();
|
||||||
self.crash(&format!(
|
self.crash(&format!(
|
||||||
"the stack size becomes -1\nlasti: {lasti}\nlast code: {last}"
|
"the stack size becomes -1\nlasti: {lasti}\nlast code: {last}"
|
||||||
|
@ -342,14 +352,14 @@ impl CodeGenerator {
|
||||||
/// This is because the stack size will not increase correctly.
|
/// This is because the stack size will not increase correctly.
|
||||||
fn stack_inc_n(&mut self, n: usize) {
|
fn stack_inc_n(&mut self, n: usize) {
|
||||||
self.mut_cur_block().stack_len += n as u32;
|
self.mut_cur_block().stack_len += n as u32;
|
||||||
if self.cur_block().stack_len > self.cur_block_codeobj().stacksize {
|
if self.stack_len() > self.cur_block_codeobj().stacksize {
|
||||||
self.mut_cur_block_codeobj().stacksize = self.cur_block().stack_len;
|
self.mut_cur_block_codeobj().stacksize = self.stack_len();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn stack_dec_n(&mut self, n: usize) {
|
fn stack_dec_n(&mut self, n: usize) {
|
||||||
if n > 0 && self.cur_block().stack_len == 0 {
|
if n > 0 && self.stack_len() == 0 {
|
||||||
let lasti = self.cur_block().lasti;
|
let lasti = self.lasti();
|
||||||
let last = self.cur_block_codeobj().code.last().unwrap();
|
let last = self.cur_block_codeobj().code.last().unwrap();
|
||||||
self.crash(&format!(
|
self.crash(&format!(
|
||||||
"the stack size becomes -1\nlasti: {lasti}\nlast code: {last}"
|
"the stack size becomes -1\nlasti: {lasti}\nlast code: {last}"
|
||||||
|
@ -919,9 +929,9 @@ impl CodeGenerator {
|
||||||
self.emit_load_const(ValueObj::None);
|
self.emit_load_const(ValueObj::None);
|
||||||
self.write_instr(RETURN_VALUE);
|
self.write_instr(RETURN_VALUE);
|
||||||
self.write_arg(0);
|
self.write_arg(0);
|
||||||
if self.cur_block().stack_len > 1 {
|
if self.stack_len() > 1 {
|
||||||
let block_id = self.cur_block().id;
|
let block_id = self.cur_block().id;
|
||||||
let stack_len = self.cur_block().stack_len;
|
let stack_len = self.stack_len();
|
||||||
CompileError::stack_bug(
|
CompileError::stack_bug(
|
||||||
self.input().clone(),
|
self.input().clone(),
|
||||||
Location::Unknown,
|
Location::Unknown,
|
||||||
|
@ -1387,6 +1397,9 @@ impl CodeGenerator {
|
||||||
| TokenKind::Closed
|
| TokenKind::Closed
|
||||||
| TokenKind::InOp => {
|
| TokenKind::InOp => {
|
||||||
self.stack_dec();
|
self.stack_dec();
|
||||||
|
if self.py_version.minor >= Some(11) {
|
||||||
|
self.stack_dec();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
@ -1413,10 +1426,10 @@ impl CodeGenerator {
|
||||||
|
|
||||||
fn emit_if_instr(&mut self, mut args: Args) {
|
fn emit_if_instr(&mut self, mut args: Args) {
|
||||||
log!(info "entered {}", fn_name!());
|
log!(info "entered {}", fn_name!());
|
||||||
let init_stack_len = self.cur_block().stack_len;
|
let init_stack_len = self.stack_len();
|
||||||
let cond = args.remove(0);
|
let cond = args.remove(0);
|
||||||
self.emit_expr(cond);
|
self.emit_expr(cond);
|
||||||
let idx_pop_jump_if_false = self.cur_block().lasti;
|
let idx_pop_jump_if_false = self.lasti();
|
||||||
self.write_instr(Opcode310::POP_JUMP_IF_FALSE);
|
self.write_instr(Opcode310::POP_JUMP_IF_FALSE);
|
||||||
// cannot detect where to jump to at this moment, so put as 0
|
// cannot detect where to jump to at this moment, so put as 0
|
||||||
self.write_arg(0);
|
self.write_arg(0);
|
||||||
|
@ -1434,7 +1447,7 @@ impl CodeGenerator {
|
||||||
self.write_instr(JUMP_FORWARD); // jump to end
|
self.write_instr(JUMP_FORWARD); // jump to end
|
||||||
self.write_arg(0);
|
self.write_arg(0);
|
||||||
// else block
|
// else block
|
||||||
let idx_else_begin = self.cur_block().lasti;
|
let idx_else_begin = self.lasti();
|
||||||
self.calc_edit_jump(idx_pop_jump_if_false + 1, idx_else_begin);
|
self.calc_edit_jump(idx_pop_jump_if_false + 1, idx_else_begin);
|
||||||
match args.remove(0) {
|
match args.remove(0) {
|
||||||
Expr::Lambda(lambda) => {
|
Expr::Lambda(lambda) => {
|
||||||
|
@ -1446,22 +1459,22 @@ impl CodeGenerator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let idx_jump_forward = idx_else_begin - 2;
|
let idx_jump_forward = idx_else_begin - 2;
|
||||||
let idx_end = self.cur_block().lasti;
|
let idx_end = self.lasti();
|
||||||
self.calc_edit_jump(idx_jump_forward + 1, idx_end - idx_jump_forward - 2);
|
self.calc_edit_jump(idx_jump_forward + 1, idx_end - idx_jump_forward - 2);
|
||||||
// FIXME: this is a hack to make sure the stack is balanced
|
// FIXME: this is a hack to make sure the stack is balanced
|
||||||
while self.cur_block().stack_len != init_stack_len + 1 {
|
while self.stack_len() != init_stack_len + 1 {
|
||||||
self.stack_dec();
|
self.stack_dec();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// no else block
|
// no else block
|
||||||
let idx_end = if self.py_version.minor >= Some(11) {
|
let idx_end = if self.py_version.minor >= Some(11) {
|
||||||
self.cur_block().lasti - idx_pop_jump_if_false
|
self.lasti() - idx_pop_jump_if_false
|
||||||
} else {
|
} else {
|
||||||
self.cur_block().lasti
|
self.lasti()
|
||||||
};
|
};
|
||||||
self.calc_edit_jump(idx_pop_jump_if_false + 1, idx_end);
|
self.calc_edit_jump(idx_pop_jump_if_false + 1, idx_end);
|
||||||
self.emit_load_const(ValueObj::None);
|
self.emit_load_const(ValueObj::None);
|
||||||
while self.cur_block().stack_len != init_stack_len + 1 {
|
while self.stack_len() != init_stack_len + 1 {
|
||||||
self.stack_dec();
|
self.stack_dec();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1473,7 +1486,7 @@ impl CodeGenerator {
|
||||||
self.emit_expr(iterable);
|
self.emit_expr(iterable);
|
||||||
self.write_instr(GET_ITER);
|
self.write_instr(GET_ITER);
|
||||||
self.write_arg(0);
|
self.write_arg(0);
|
||||||
let idx_for_iter = self.cur_block().lasti;
|
let idx_for_iter = self.lasti();
|
||||||
self.write_instr(FOR_ITER);
|
self.write_instr(FOR_ITER);
|
||||||
self.stack_inc();
|
self.stack_inc();
|
||||||
// FOR_ITER pushes a value onto the stack, but we can't know how many
|
// FOR_ITER pushes a value onto the stack, but we can't know how many
|
||||||
|
@ -1481,16 +1494,16 @@ impl CodeGenerator {
|
||||||
// cannot detect where to jump to at this moment, so put as 0
|
// cannot detect where to jump to at this moment, so put as 0
|
||||||
self.write_arg(0);
|
self.write_arg(0);
|
||||||
let lambda = enum_unwrap!(args.remove(0), Expr::Lambda);
|
let lambda = enum_unwrap!(args.remove(0), Expr::Lambda);
|
||||||
let init_stack_len = self.cur_block().stack_len;
|
let init_stack_len = self.stack_len();
|
||||||
let params = self.gen_param_names(&lambda.params);
|
let params = self.gen_param_names(&lambda.params);
|
||||||
self.emit_frameless_block(lambda.body, params);
|
self.emit_frameless_block(lambda.body, params);
|
||||||
if self.cur_block().stack_len >= init_stack_len {
|
if self.stack_len() >= init_stack_len {
|
||||||
self.emit_pop_top();
|
self.emit_pop_top();
|
||||||
}
|
}
|
||||||
match self.py_version.minor {
|
match self.py_version.minor {
|
||||||
Some(11) => {
|
Some(11) => {
|
||||||
self.write_instr(Opcode311::JUMP_BACKWARD);
|
self.write_instr(Opcode311::JUMP_BACKWARD);
|
||||||
self.write_arg((self.cur_block().lasti - idx_for_iter + 2) / 2);
|
self.write_arg((self.lasti() - idx_for_iter + 2) / 2);
|
||||||
},
|
},
|
||||||
Some(10) => {
|
Some(10) => {
|
||||||
self.write_instr(Opcode310::JUMP_ABSOLUTE);
|
self.write_instr(Opcode310::JUMP_ABSOLUTE);
|
||||||
|
@ -1502,7 +1515,7 @@ impl CodeGenerator {
|
||||||
},
|
},
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
}
|
}
|
||||||
let idx_end = self.cur_block().lasti;
|
let idx_end = self.lasti();
|
||||||
self.calc_edit_jump(idx_for_iter + 1, idx_end - idx_for_iter - 2);
|
self.calc_edit_jump(idx_for_iter + 1, idx_end - idx_for_iter - 2);
|
||||||
self.stack_dec();
|
self.stack_dec();
|
||||||
self.emit_load_const(ValueObj::None);
|
self.emit_load_const(ValueObj::None);
|
||||||
|
@ -1512,15 +1525,15 @@ impl CodeGenerator {
|
||||||
log!(info "entered {} ({})", fn_name!(), args);
|
log!(info "entered {} ({})", fn_name!(), args);
|
||||||
let cond = args.remove(0);
|
let cond = args.remove(0);
|
||||||
self.emit_expr(cond.clone());
|
self.emit_expr(cond.clone());
|
||||||
let idx_while = self.cur_block().lasti;
|
let idx_while = self.lasti();
|
||||||
self.write_instr(Opcode310::POP_JUMP_IF_FALSE);
|
self.write_instr(Opcode310::POP_JUMP_IF_FALSE);
|
||||||
self.write_arg(0);
|
self.write_arg(0);
|
||||||
self.stack_dec();
|
self.stack_dec();
|
||||||
let lambda = enum_unwrap!(args.remove(0), Expr::Lambda);
|
let lambda = enum_unwrap!(args.remove(0), Expr::Lambda);
|
||||||
let init_stack_len = self.cur_block().stack_len;
|
let init_stack_len = self.stack_len();
|
||||||
let params = self.gen_param_names(&lambda.params);
|
let params = self.gen_param_names(&lambda.params);
|
||||||
self.emit_frameless_block(lambda.body, params);
|
self.emit_frameless_block(lambda.body, params);
|
||||||
if self.cur_block().stack_len > init_stack_len {
|
if self.stack_len() > init_stack_len {
|
||||||
self.emit_pop_top();
|
self.emit_pop_top();
|
||||||
}
|
}
|
||||||
self.emit_expr(cond);
|
self.emit_expr(cond);
|
||||||
|
@ -1533,9 +1546,9 @@ impl CodeGenerator {
|
||||||
self.write_arg(arg);
|
self.write_arg(arg);
|
||||||
self.stack_dec();
|
self.stack_dec();
|
||||||
let idx_end = if self.py_version.minor >= Some(11) {
|
let idx_end = if self.py_version.minor >= Some(11) {
|
||||||
self.cur_block().lasti - idx_while
|
self.lasti() - idx_while
|
||||||
} else {
|
} else {
|
||||||
self.cur_block().lasti
|
self.lasti()
|
||||||
};
|
};
|
||||||
self.calc_edit_jump(idx_while + 1, idx_end);
|
self.calc_edit_jump(idx_while + 1, idx_end);
|
||||||
self.emit_load_const(ValueObj::None);
|
self.emit_load_const(ValueObj::None);
|
||||||
|
@ -1570,17 +1583,17 @@ impl CodeGenerator {
|
||||||
self.emit_frameless_block(lambda.body, Vec::new());
|
self.emit_frameless_block(lambda.body, Vec::new());
|
||||||
for pop_jump_point in pop_jump_points.into_iter() {
|
for pop_jump_point in pop_jump_points.into_iter() {
|
||||||
let idx = if self.py_version.minor >= Some(11) {
|
let idx = if self.py_version.minor >= Some(11) {
|
||||||
self.cur_block().lasti - pop_jump_point // - 2
|
self.lasti() - pop_jump_point // - 2
|
||||||
} else {
|
} else {
|
||||||
self.cur_block().lasti + 2
|
self.lasti() + 2
|
||||||
};
|
};
|
||||||
self.calc_edit_jump(pop_jump_point + 1, idx); // jump to POP_TOP
|
self.calc_edit_jump(pop_jump_point + 1, idx); // jump to POP_TOP
|
||||||
absolute_jump_points.push(self.cur_block().lasti);
|
absolute_jump_points.push(self.lasti());
|
||||||
self.write_instr(JUMP_FORWARD); // jump to the end
|
self.write_instr(JUMP_FORWARD); // jump to the end
|
||||||
self.write_arg(0);
|
self.write_arg(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let lasti = self.cur_block().lasti;
|
let lasti = self.lasti();
|
||||||
for absolute_jump_point in absolute_jump_points.into_iter() {
|
for absolute_jump_point in absolute_jump_points.into_iter() {
|
||||||
self.calc_edit_jump(absolute_jump_point + 1, lasti - absolute_jump_point - 1);
|
self.calc_edit_jump(absolute_jump_point + 1, lasti - absolute_jump_point - 1);
|
||||||
}
|
}
|
||||||
|
@ -1601,7 +1614,7 @@ impl CodeGenerator {
|
||||||
};
|
};
|
||||||
self.emit_load_const(value);
|
self.emit_load_const(value);
|
||||||
self.emit_compare_op(CompareOp::EQ);
|
self.emit_compare_op(CompareOp::EQ);
|
||||||
pop_jump_points.push(self.cur_block().lasti);
|
pop_jump_points.push(self.lasti());
|
||||||
// in 3.11, POP_JUMP_IF_FALSE is replaced with POP_JUMP_FORWARD_IF_FALSE
|
// in 3.11, POP_JUMP_IF_FALSE is replaced with POP_JUMP_FORWARD_IF_FALSE
|
||||||
// but the numbers are the same, only the way the jumping points are calculated is different.
|
// but the numbers are the same, only the way the jumping points are calculated is different.
|
||||||
self.write_instr(Opcode310::POP_JUMP_IF_FALSE); // jump to the next case
|
self.write_instr(Opcode310::POP_JUMP_IF_FALSE); // jump to the next case
|
||||||
|
@ -1613,7 +1626,7 @@ impl CodeGenerator {
|
||||||
let len = arr.len();
|
let len = arr.len();
|
||||||
self.write_instr(Opcode310::MATCH_SEQUENCE);
|
self.write_instr(Opcode310::MATCH_SEQUENCE);
|
||||||
self.write_arg(0);
|
self.write_arg(0);
|
||||||
pop_jump_points.push(self.cur_block().lasti);
|
pop_jump_points.push(self.lasti());
|
||||||
self.write_instr(Opcode310::POP_JUMP_IF_FALSE);
|
self.write_instr(Opcode310::POP_JUMP_IF_FALSE);
|
||||||
self.write_arg(0);
|
self.write_arg(0);
|
||||||
self.stack_dec();
|
self.stack_dec();
|
||||||
|
@ -1621,7 +1634,7 @@ impl CodeGenerator {
|
||||||
self.write_arg(0);
|
self.write_arg(0);
|
||||||
self.emit_load_const(len);
|
self.emit_load_const(len);
|
||||||
self.emit_compare_op(CompareOp::EQ);
|
self.emit_compare_op(CompareOp::EQ);
|
||||||
pop_jump_points.push(self.cur_block().lasti);
|
pop_jump_points.push(self.lasti());
|
||||||
self.write_instr(Opcode310::POP_JUMP_IF_FALSE);
|
self.write_instr(Opcode310::POP_JUMP_IF_FALSE);
|
||||||
self.write_arg(0);
|
self.write_arg(0);
|
||||||
self.stack_dec();
|
self.stack_dec();
|
||||||
|
@ -1652,7 +1665,7 @@ impl CodeGenerator {
|
||||||
let lambda = enum_unwrap!(args.remove(0), Expr::Lambda);
|
let lambda = enum_unwrap!(args.remove(0), Expr::Lambda);
|
||||||
let params = self.gen_param_names(&lambda.params);
|
let params = self.gen_param_names(&lambda.params);
|
||||||
self.emit_expr(expr);
|
self.emit_expr(expr);
|
||||||
let idx_setup_with = self.cur_block().lasti;
|
let idx_setup_with = self.lasti();
|
||||||
self.write_instr(Opcode310::SETUP_WITH);
|
self.write_instr(Opcode310::SETUP_WITH);
|
||||||
self.write_arg(0);
|
self.write_arg(0);
|
||||||
// push __exit__, __enter__() to the stack
|
// push __exit__, __enter__() to the stack
|
||||||
|
@ -1674,27 +1687,27 @@ impl CodeGenerator {
|
||||||
self.write_arg(3);
|
self.write_arg(3);
|
||||||
self.stack_dec_n((1 + 3) - 1);
|
self.stack_dec_n((1 + 3) - 1);
|
||||||
self.emit_pop_top();
|
self.emit_pop_top();
|
||||||
let idx_jump_forward = self.cur_block().lasti;
|
let idx_jump_forward = self.lasti();
|
||||||
self.write_instr(JUMP_FORWARD);
|
self.write_instr(JUMP_FORWARD);
|
||||||
self.write_arg(0);
|
self.write_arg(0);
|
||||||
self.edit_code(
|
self.edit_code(
|
||||||
idx_setup_with + 1,
|
idx_setup_with + 1,
|
||||||
(self.cur_block().lasti - idx_setup_with - 2) / 2,
|
(self.lasti() - idx_setup_with - 2) / 2,
|
||||||
);
|
);
|
||||||
self.write_instr(Opcode310::WITH_EXCEPT_START);
|
self.write_instr(Opcode310::WITH_EXCEPT_START);
|
||||||
self.write_arg(0);
|
self.write_arg(0);
|
||||||
let idx_pop_jump_if_true = self.cur_block().lasti;
|
let idx_pop_jump_if_true = self.lasti();
|
||||||
self.write_instr(Opcode310::POP_JUMP_IF_TRUE);
|
self.write_instr(Opcode310::POP_JUMP_IF_TRUE);
|
||||||
self.write_arg(0);
|
self.write_arg(0);
|
||||||
self.write_instr(Opcode310::RERAISE);
|
self.write_instr(Opcode310::RERAISE);
|
||||||
self.write_arg(1);
|
self.write_arg(1);
|
||||||
self.edit_code(idx_pop_jump_if_true + 1, self.cur_block().lasti / 2);
|
self.edit_code(idx_pop_jump_if_true + 1, self.lasti() / 2);
|
||||||
// self.emit_pop_top();
|
// self.emit_pop_top();
|
||||||
// self.emit_pop_top();
|
// self.emit_pop_top();
|
||||||
self.emit_pop_top();
|
self.emit_pop_top();
|
||||||
self.write_instr(Opcode310::POP_EXCEPT);
|
self.write_instr(Opcode310::POP_EXCEPT);
|
||||||
self.write_arg(0);
|
self.write_arg(0);
|
||||||
let idx_end = self.cur_block().lasti;
|
let idx_end = self.lasti();
|
||||||
self.edit_code(idx_jump_forward + 1, (idx_end - idx_jump_forward - 2) / 2);
|
self.edit_code(idx_jump_forward + 1, (idx_end - idx_jump_forward - 2) / 2);
|
||||||
self.emit_load_name_instr(stash);
|
self.emit_load_name_instr(stash);
|
||||||
}
|
}
|
||||||
|
@ -1706,7 +1719,7 @@ impl CodeGenerator {
|
||||||
let lambda = enum_unwrap!(args.remove(0), Expr::Lambda);
|
let lambda = enum_unwrap!(args.remove(0), Expr::Lambda);
|
||||||
let params = self.gen_param_names(&lambda.params);
|
let params = self.gen_param_names(&lambda.params);
|
||||||
self.emit_expr(expr);
|
self.emit_expr(expr);
|
||||||
let idx_setup_with = self.cur_block().lasti;
|
let idx_setup_with = self.lasti();
|
||||||
self.write_instr(Opcode308::SETUP_WITH);
|
self.write_instr(Opcode308::SETUP_WITH);
|
||||||
self.write_arg(0);
|
self.write_arg(0);
|
||||||
// push __exit__, __enter__() to the stack
|
// push __exit__, __enter__() to the stack
|
||||||
|
@ -1723,7 +1736,7 @@ impl CodeGenerator {
|
||||||
self.write_arg(0);
|
self.write_arg(0);
|
||||||
self.edit_code(
|
self.edit_code(
|
||||||
idx_setup_with + 1,
|
idx_setup_with + 1,
|
||||||
(self.cur_block().lasti - idx_setup_with - 2) / 2,
|
(self.lasti() - idx_setup_with - 2) / 2,
|
||||||
);
|
);
|
||||||
self.write_instr(Opcode308::WITH_CLEANUP_FINISH);
|
self.write_instr(Opcode308::WITH_CLEANUP_FINISH);
|
||||||
self.write_arg(0);
|
self.write_arg(0);
|
||||||
|
@ -1890,7 +1903,7 @@ impl CodeGenerator {
|
||||||
fn emit_assert_instr(&mut self, mut args: Args) {
|
fn emit_assert_instr(&mut self, mut args: Args) {
|
||||||
log!(info "entered {}", fn_name!());
|
log!(info "entered {}", fn_name!());
|
||||||
self.emit_expr(args.remove(0));
|
self.emit_expr(args.remove(0));
|
||||||
let pop_jump_point = self.cur_block().lasti;
|
let pop_jump_point = self.lasti();
|
||||||
self.write_instr(Opcode310::POP_JUMP_IF_TRUE);
|
self.write_instr(Opcode310::POP_JUMP_IF_TRUE);
|
||||||
self.write_arg(0);
|
self.write_arg(0);
|
||||||
self.stack_dec();
|
self.stack_dec();
|
||||||
|
@ -1914,9 +1927,9 @@ impl CodeGenerator {
|
||||||
self.write_arg(1);
|
self.write_arg(1);
|
||||||
self.stack_dec();
|
self.stack_dec();
|
||||||
let idx = match self.py_version.minor {
|
let idx = match self.py_version.minor {
|
||||||
Some(11) => (self.cur_block().lasti - pop_jump_point - 2) / 2,
|
Some(11) => (self.lasti() - pop_jump_point - 2) / 2,
|
||||||
Some(10) => self.cur_block().lasti / 2,
|
Some(10) => self.lasti() / 2,
|
||||||
Some(_) => self.cur_block().lasti,
|
Some(_) => self.lasti(),
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
};
|
};
|
||||||
self.edit_code(pop_jump_point + 1, idx);
|
self.edit_code(pop_jump_point + 1, idx);
|
||||||
|
@ -2031,7 +2044,7 @@ impl CodeGenerator {
|
||||||
fn emit_expr(&mut self, expr: Expr) {
|
fn emit_expr(&mut self, expr: Expr) {
|
||||||
log!(info "entered {} ({expr})", fn_name!());
|
log!(info "entered {} ({expr})", fn_name!());
|
||||||
if expr.ln_begin().unwrap_or_else(|| panic!("{expr}")) > self.cur_block().prev_lineno {
|
if expr.ln_begin().unwrap_or_else(|| panic!("{expr}")) > self.cur_block().prev_lineno {
|
||||||
let sd = self.cur_block().lasti - self.cur_block().prev_lasti;
|
let sd = self.lasti() - self.cur_block().prev_lasti;
|
||||||
let ld = expr.ln_begin().unwrap() - self.cur_block().prev_lineno;
|
let ld = expr.ln_begin().unwrap() - self.cur_block().prev_lineno;
|
||||||
if ld != 0 {
|
if ld != 0 {
|
||||||
if sd != 0 {
|
if sd != 0 {
|
||||||
|
@ -2048,7 +2061,7 @@ impl CodeGenerator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.mut_cur_block().prev_lineno += ld;
|
self.mut_cur_block().prev_lineno += ld;
|
||||||
self.mut_cur_block().prev_lasti = self.cur_block().lasti;
|
self.mut_cur_block().prev_lasti = self.lasti();
|
||||||
} else {
|
} else {
|
||||||
CompileError::compiler_bug(
|
CompileError::compiler_bug(
|
||||||
0,
|
0,
|
||||||
|
@ -2170,10 +2183,10 @@ impl CodeGenerator {
|
||||||
Name,
|
Name,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
let init_stack_len = self.cur_block().stack_len;
|
let init_stack_len = self.stack_len();
|
||||||
for expr in block.into_iter() {
|
for expr in block.into_iter() {
|
||||||
self.emit_expr(expr);
|
self.emit_expr(expr);
|
||||||
if self.cur_block().stack_len > init_stack_len {
|
if self.stack_len() > init_stack_len {
|
||||||
self.emit_pop_top();
|
self.emit_pop_top();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2189,11 +2202,11 @@ impl CodeGenerator {
|
||||||
Name,
|
Name,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
let init_stack_len = self.cur_block().stack_len;
|
let init_stack_len = self.stack_len();
|
||||||
for expr in block.into_iter() {
|
for expr in block.into_iter() {
|
||||||
self.emit_expr(expr);
|
self.emit_expr(expr);
|
||||||
// __exit__, __enter__() are on the stack
|
// __exit__, __enter__() are on the stack
|
||||||
if self.cur_block().stack_len > init_stack_len {
|
if self.stack_len() > init_stack_len {
|
||||||
self.emit_pop_top();
|
self.emit_pop_top();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2228,14 +2241,14 @@ impl CodeGenerator {
|
||||||
if !class.methods.is_empty() {
|
if !class.methods.is_empty() {
|
||||||
self.emit_frameless_block(class.methods, vec![]);
|
self.emit_frameless_block(class.methods, vec![]);
|
||||||
}
|
}
|
||||||
if self.cur_block().stack_len == 0 {
|
if self.stack_len() == 0 {
|
||||||
self.emit_load_const(ValueObj::None);
|
self.emit_load_const(ValueObj::None);
|
||||||
}
|
}
|
||||||
self.write_instr(RETURN_VALUE);
|
self.write_instr(RETURN_VALUE);
|
||||||
self.write_arg(0);
|
self.write_arg(0);
|
||||||
if self.cur_block().stack_len > 1 {
|
if self.stack_len() > 1 {
|
||||||
let block_id = self.cur_block().id;
|
let block_id = self.cur_block().id;
|
||||||
let stack_len = self.cur_block().stack_len;
|
let stack_len = self.stack_len();
|
||||||
CompileError::stack_bug(
|
CompileError::stack_bug(
|
||||||
self.input().clone(),
|
self.input().clone(),
|
||||||
Location::Unknown,
|
Location::Unknown,
|
||||||
|
@ -2367,22 +2380,22 @@ impl CodeGenerator {
|
||||||
self.write_instr(Opcode311::RESUME);
|
self.write_instr(Opcode311::RESUME);
|
||||||
self.write_arg(0);
|
self.write_arg(0);
|
||||||
}
|
}
|
||||||
let init_stack_len = self.cur_block().stack_len;
|
let init_stack_len = self.stack_len();
|
||||||
for expr in block.into_iter() {
|
for expr in block.into_iter() {
|
||||||
self.emit_expr(expr);
|
self.emit_expr(expr);
|
||||||
// NOTE: 各行のトップレベルでは0個または1個のオブジェクトが残っている
|
// NOTE: 各行のトップレベルでは0個または1個のオブジェクトが残っている
|
||||||
// Pythonの場合使わなかったオブジェクトはそのまま捨てられるが、Ergではdiscardを使う必要がある
|
// Pythonの場合使わなかったオブジェクトはそのまま捨てられるが、Ergではdiscardを使う必要がある
|
||||||
// TODO: discard
|
// TODO: discard
|
||||||
if self.cur_block().stack_len > init_stack_len {
|
if self.stack_len() > init_stack_len {
|
||||||
self.emit_pop_top();
|
self.emit_pop_top();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.cancel_pop_top(); // 最後の値は戻り値として取っておく
|
self.cancel_pop_top(); // 最後の値は戻り値として取っておく
|
||||||
if self.cur_block().stack_len == init_stack_len {
|
if self.stack_len() == init_stack_len {
|
||||||
self.emit_load_const(ValueObj::None);
|
self.emit_load_const(ValueObj::None);
|
||||||
} else if self.cur_block().stack_len > init_stack_len + 1 {
|
} else if self.stack_len() > init_stack_len + 1 {
|
||||||
let block_id = self.cur_block().id;
|
let block_id = self.cur_block().id;
|
||||||
let stack_len = self.cur_block().stack_len;
|
let stack_len = self.stack_len();
|
||||||
CompileError::stack_bug(
|
CompileError::stack_bug(
|
||||||
self.input().clone(),
|
self.input().clone(),
|
||||||
Location::Unknown,
|
Location::Unknown,
|
||||||
|
@ -2510,22 +2523,22 @@ impl CodeGenerator {
|
||||||
for expr in hir.module.into_iter() {
|
for expr in hir.module.into_iter() {
|
||||||
self.emit_expr(expr);
|
self.emit_expr(expr);
|
||||||
// TODO: discard
|
// TODO: discard
|
||||||
if self.cur_block().stack_len == 1 {
|
if self.stack_len() == 1 {
|
||||||
self.emit_pop_top();
|
self.emit_pop_top();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.cancel_pop_top(); // 最後の値は戻り値として取っておく
|
self.cancel_pop_top(); // 最後の値は戻り値として取っておく
|
||||||
if self.input().is_repl() {
|
if self.input().is_repl() {
|
||||||
if self.cur_block().stack_len == 1 {
|
if self.stack_len() == 1 {
|
||||||
self.emit_print_expr();
|
self.emit_print_expr();
|
||||||
}
|
}
|
||||||
self.stack_dec_n(self.cur_block().stack_len as usize);
|
self.stack_dec_n(self.stack_len() as usize);
|
||||||
}
|
}
|
||||||
if self.cur_block().stack_len == 0 {
|
if self.stack_len() == 0 {
|
||||||
self.emit_load_const(ValueObj::None);
|
self.emit_load_const(ValueObj::None);
|
||||||
} else if self.cur_block().stack_len > 1 {
|
} else if self.stack_len() > 1 {
|
||||||
let block_id = self.cur_block().id;
|
let block_id = self.cur_block().id;
|
||||||
let stack_len = self.cur_block().stack_len;
|
let stack_len = self.stack_len();
|
||||||
CompileError::stack_bug(
|
CompileError::stack_bug(
|
||||||
self.input().clone(),
|
self.input().clone(),
|
||||||
Location::Unknown,
|
Location::Unknown,
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
print! "OK1"
|
|
||||||
|
|
||||||
Point = Class {x = Int; y = Int}
|
Point = Class {x = Int; y = Int}
|
||||||
Point.
|
Point.
|
||||||
new x, y = Point::__new__ {x; y}
|
new x, y = Point::__new__ {x; y}
|
||||||
|
@ -16,19 +14,12 @@ Point|Point <: Eq|.
|
||||||
__eq__ self, other: Point =
|
__eq__ self, other: Point =
|
||||||
self::x == other::x and self::y == other::y
|
self::x == other::x and self::y == other::y
|
||||||
|
|
||||||
print! "OK2"
|
|
||||||
|
|
||||||
p = Point.new 1, 2
|
p = Point.new 1, 2
|
||||||
|
|
||||||
print! "OK2.5"
|
|
||||||
|
|
||||||
q = Point.new 3, 4
|
q = Point.new 3, 4
|
||||||
|
|
||||||
print! "OK3"
|
|
||||||
|
|
||||||
r: Point = p + q
|
r: Point = p + q
|
||||||
s: Nat = p * q
|
s: Nat = p * q
|
||||||
assert s == 11
|
assert s == 11
|
||||||
assert r == Point.new 4, 6
|
assert r == Point.new 4, 6
|
||||||
assert r.norm() == 52
|
assert r.norm() == 52
|
||||||
print! "OK4"
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue