This commit is contained in:
Shunsuke Shibayama 2022-11-01 19:42:36 +09:00
parent 2283f4a3b1
commit ed1afed052
4 changed files with 163 additions and 46 deletions

View file

@ -14,9 +14,9 @@ pub mod help_messages;
pub mod levenshtein; pub mod levenshtein;
pub mod macros; pub mod macros;
pub mod opcode; pub mod opcode;
pub mod opcode308;
pub mod opcode310; pub mod opcode310;
pub mod opcode311; pub mod opcode311;
pub mod opcode38;
pub mod python_util; pub mod python_util;
pub mod serialize; pub mod serialize;
pub mod set; pub mod set;

View file

@ -7,7 +7,7 @@
use crate::impl_u8_enum; use crate::impl_u8_enum;
impl_u8_enum! {Opcode38; impl_u8_enum! {Opcode308;
POP_TOP = 1, POP_TOP = 1,
ROT_TWO = 2, ROT_TWO = 2,
ROT_THREE = 3, ROT_THREE = 3,

View file

@ -13,9 +13,9 @@ use erg_common::config::{ErgConfig, Input};
use erg_common::env::erg_std_path; use erg_common::env::erg_std_path;
use erg_common::error::{ErrorDisplay, Location}; use erg_common::error::{ErrorDisplay, Location};
use erg_common::opcode::CommonOpcode; use erg_common::opcode::CommonOpcode;
use erg_common::opcode308::Opcode308;
use erg_common::opcode310::Opcode310; use erg_common::opcode310::Opcode310;
use erg_common::opcode311::{BinOpCode, Opcode311}; use erg_common::opcode311::{BinOpCode, Opcode311};
use erg_common::opcode38::Opcode38;
use erg_common::option_enum_unwrap; use erg_common::option_enum_unwrap;
use erg_common::python_util::{python_version, PythonVersion}; use erg_common::python_util::{python_version, PythonVersion};
use erg_common::traits::{Locational, Stream}; use erg_common::traits::{Locational, Stream};
@ -335,10 +335,11 @@ impl CodeGenerator {
let is_nat = value.is_nat(); let is_nat = value.is_nat();
let is_bool = value.is_bool(); let is_bool = value.is_bool();
if !self.cfg.no_std { if !self.cfg.no_std {
self.emit_push_null();
if is_bool { if is_bool {
self.emit_push_null();
self.emit_load_name_instr(Identifier::public("Bool")); self.emit_load_name_instr(Identifier::public("Bool"));
} else if is_nat { } else if is_nat {
self.emit_push_null();
self.emit_load_name_instr(Identifier::public("Nat")); self.emit_load_name_instr(Identifier::public("Nat"));
} }
} }
@ -355,7 +356,7 @@ impl CodeGenerator {
self.write_arg(idx); self.write_arg(idx);
self.stack_inc(); self.stack_inc();
if !self.cfg.no_std && is_nat { if !self.cfg.no_std && is_nat {
self.emit_call_instr(1); self.emit_call_instr(1, Name);
self.stack_dec(); self.stack_dec();
} }
} }
@ -740,18 +741,22 @@ impl CodeGenerator {
if self.py_version.minor >= Some(11) { if self.py_version.minor >= Some(11) {
self.write_instr(Opcode311::PUSH_NULL); self.write_instr(Opcode311::PUSH_NULL);
self.write_arg(0); self.write_arg(0);
self.stack_inc(); // self.stack_inc();
} }
} }
fn emit_call_instr(&mut self, argc: usize) { fn emit_call_instr(&mut self, argc: usize, kind: AccessKind) {
if self.py_version.minor >= Some(11) { if self.py_version.minor >= Some(11) {
self.write_instr(Opcode311::PRECALL); self.write_instr(Opcode311::PRECALL);
self.write_arg(argc); self.write_arg(argc);
self.write_instr(Opcode311::CALL); self.write_instr(Opcode311::CALL);
self.write_arg(argc); self.write_arg(argc);
// self.stack_dec();
} else { } else {
self.write_instr(Opcode310::CALL_FUNCTION); match kind {
AccessKind::Method => self.write_instr(Opcode310::CALL_METHOD),
_ => self.write_instr(Opcode310::CALL_FUNCTION),
}
self.write_arg(argc); self.write_arg(argc);
} }
} }
@ -761,6 +766,8 @@ impl CodeGenerator {
let idx = self.register_const(kws); let idx = self.register_const(kws);
self.write_instr(Opcode311::KW_NAMES); self.write_instr(Opcode311::KW_NAMES);
self.write_arg(idx); self.write_arg(idx);
self.write_instr(Opcode311::PRECALL);
self.write_arg(argc);
self.write_instr(Opcode311::CALL); self.write_instr(Opcode311::CALL);
self.write_arg(argc); self.write_arg(argc);
} else { } else {
@ -788,7 +795,12 @@ impl CodeGenerator {
self.emit_load_name_instr(Identifier::private("#ABCMeta")); self.emit_load_name_instr(Identifier::private("#ABCMeta"));
let subclasses_len = 1; let subclasses_len = 1;
self.emit_call_kw_instr(2 + subclasses_len, vec![ValueObj::from("metaclass")]); self.emit_call_kw_instr(2 + subclasses_len, vec![ValueObj::from("metaclass")]);
self.stack_dec_n((1 + 2 + 1 + subclasses_len) - 1); let sum = if self.py_version.minor >= Some(11) {
1 + 2 + subclasses_len
} else {
1 + 2 + 1 + subclasses_len
};
self.stack_dec_n(sum - 1);
self.emit_store_instr(def.sig.into_ident(), Name); self.emit_store_instr(def.sig.into_ident(), Name);
self.stack_dec(); self.stack_dec();
} }
@ -919,7 +931,7 @@ impl CodeGenerator {
self.write_instr(MAKE_FUNCTION); self.write_instr(MAKE_FUNCTION);
self.write_arg(0); self.write_arg(0);
if deco_is_some { if deco_is_some {
self.emit_call_instr(1); self.emit_call_instr(1, Name);
self.stack_dec(); self.stack_dec();
} }
// stack_dec: (<abstractmethod>) + <code obj> + <name> -> <function> // stack_dec: (<abstractmethod>) + <code obj> + <name> -> <function>
@ -944,7 +956,7 @@ impl CodeGenerator {
self.emit_load_const(ident.inspect().clone()); self.emit_load_const(ident.inspect().clone());
// LOAD subclasses // LOAD subclasses
let subclasses_len = self.emit_require_type(obj, *require_or_sup); let subclasses_len = self.emit_require_type(obj, *require_or_sup);
self.emit_call_instr(2 + subclasses_len); self.emit_call_instr(2 + subclasses_len, Name);
self.stack_dec_n((1 + 2 + subclasses_len) - 1); self.stack_dec_n((1 + 2 + subclasses_len) - 1);
self.emit_store_instr(ident, Name); self.emit_store_instr(ident, Name);
self.stack_dec(); self.stack_dec();
@ -1094,15 +1106,19 @@ impl CodeGenerator {
match &bin.op.kind { match &bin.op.kind {
// l..<r == range(l, r) // l..<r == range(l, r)
TokenKind::RightOpen => { TokenKind::RightOpen => {
self.emit_push_null();
self.emit_load_name_instr(Identifier::public("RightOpenRange")); self.emit_load_name_instr(Identifier::public("RightOpenRange"));
} }
TokenKind::LeftOpen => { TokenKind::LeftOpen => {
self.emit_push_null();
self.emit_load_name_instr(Identifier::public("LeftOpenRange")); self.emit_load_name_instr(Identifier::public("LeftOpenRange"));
} }
TokenKind::Closed => { TokenKind::Closed => {
self.emit_push_null();
self.emit_load_name_instr(Identifier::public("ClosedRange")); self.emit_load_name_instr(Identifier::public("ClosedRange"));
} }
TokenKind::Open => { TokenKind::Open => {
self.emit_push_null();
self.emit_load_name_instr(Identifier::public("OpenRange")); self.emit_load_name_instr(Identifier::public("OpenRange"));
} }
TokenKind::InOp => { TokenKind::InOp => {
@ -1126,6 +1142,7 @@ impl CodeGenerator {
); );
self.in_op_loaded = true; self.in_op_loaded = true;
} }
self.emit_push_null();
self.emit_load_name_instr(Identifier::private("#in_operator")); self.emit_load_name_instr(Identifier::private("#in_operator"));
} }
_ => {} _ => {}
@ -1133,7 +1150,11 @@ impl CodeGenerator {
let type_pair = TypePair::new(bin.lhs_t(), bin.rhs_t()); let type_pair = TypePair::new(bin.lhs_t(), bin.rhs_t());
self.emit_expr(*bin.lhs); self.emit_expr(*bin.lhs);
self.emit_expr(*bin.rhs); self.emit_expr(*bin.rhs);
self.emit_binop_instr_310(bin.op, type_pair); if self.py_version.minor >= Some(11) {
self.emit_binop_instr_311(bin.op, type_pair);
} else {
self.emit_binop_instr_310(bin.op, type_pair);
}
} }
fn emit_binop_instr_310(&mut self, binop: Token, type_pair: TypePair) { fn emit_binop_instr_310(&mut self, binop: Token, type_pair: TypePair) {
@ -1198,6 +1219,81 @@ impl CodeGenerator {
} }
} }
fn emit_binop_instr_311(&mut self, binop: Token, type_pair: TypePair) {
let instr = match &binop.kind {
TokenKind::Plus
| TokenKind::Minus
| TokenKind::Star
| TokenKind::Slash
| TokenKind::FloorDiv
| TokenKind::Pow
| TokenKind::Mod
| TokenKind::AndOp
| TokenKind::OrOp => Opcode311::BINARY_OP,
TokenKind::Less
| TokenKind::LessEq
| TokenKind::DblEq
| TokenKind::NotEq
| TokenKind::Gre
| TokenKind::GreEq => Opcode311::COMPARE_OP,
TokenKind::LeftOpen
| TokenKind::RightOpen
| TokenKind::Closed
| TokenKind::Open
| TokenKind::InOp => {
self.write_instr(Opcode311::PRECALL);
self.write_arg(2);
Opcode311::CALL
}
_ => {
CompileError::feature_error(
self.cfg.input.clone(),
binop.loc(),
&binop.inspect().clone(),
AtomicStr::from(binop.content),
)
.write_to_stderr();
Opcode311::NOT_IMPLEMENTED
}
};
let arg = match &binop.kind {
TokenKind::Plus => BinOpCode::Add as usize,
TokenKind::Minus => BinOpCode::Subtract as usize,
TokenKind::Star => BinOpCode::Multiply as usize,
TokenKind::Slash => BinOpCode::TrueDivide as usize,
TokenKind::FloorDiv => BinOpCode::FloorDiv as usize,
TokenKind::Pow => BinOpCode::Power as usize,
TokenKind::Mod => BinOpCode::Remainder as usize,
TokenKind::AndOp => BinOpCode::And as usize,
TokenKind::OrOp => BinOpCode::Or as usize,
TokenKind::Less => 0,
TokenKind::LessEq => 1,
TokenKind::DblEq => 2,
TokenKind::NotEq => 3,
TokenKind::Gre => 4,
TokenKind::GreEq => 5,
TokenKind::LeftOpen
| TokenKind::RightOpen
| TokenKind::Closed
| TokenKind::Open
| TokenKind::InOp => 2,
_ => type_pair as usize,
};
self.write_instr(instr);
self.write_arg(arg);
self.stack_dec();
match &binop.kind {
TokenKind::LeftOpen
| TokenKind::RightOpen
| TokenKind::Open
| TokenKind::Closed
| TokenKind::InOp => {
self.stack_dec();
}
_ => {}
}
}
fn emit_del_instr(&mut self, mut args: Args) { fn emit_del_instr(&mut self, mut args: Args) {
let ident = enum_unwrap!(args.remove_left_or_key("obj").unwrap(), Expr::Accessor:(Accessor::Ident:(_))); let ident = enum_unwrap!(args.remove_left_or_key("obj").unwrap(), Expr::Accessor:(Accessor::Ident:(_)));
log!(info "entered {} ({ident})", fn_name!()); log!(info "entered {} ({ident})", fn_name!());
@ -1490,7 +1586,7 @@ impl CodeGenerator {
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.cur_block().lasti;
self.write_instr(Opcode38::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
// self.stack_inc_n(2); // self.stack_inc_n(2);
@ -1500,17 +1596,17 @@ impl CodeGenerator {
self.emit_store_instr(stash.clone(), Name); self.emit_store_instr(stash.clone(), Name);
self.write_instr(POP_BLOCK); self.write_instr(POP_BLOCK);
self.write_arg(0); self.write_arg(0);
self.write_instr(Opcode38::BEGIN_FINALLY); self.write_instr(Opcode308::BEGIN_FINALLY);
self.write_arg(0); self.write_arg(0);
self.write_instr(Opcode38::WITH_CLEANUP_START); self.write_instr(Opcode308::WITH_CLEANUP_START);
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.cur_block().lasti - idx_setup_with - 2) / 2,
); );
self.write_instr(Opcode38::WITH_CLEANUP_FINISH); self.write_instr(Opcode308::WITH_CLEANUP_FINISH);
self.write_arg(0); self.write_arg(0);
self.write_instr(Opcode38::END_FINALLY); self.write_instr(Opcode308::END_FINALLY);
self.write_arg(0); self.write_arg(0);
self.emit_load_name_instr(stash); self.emit_load_name_instr(stash);
} }
@ -1593,7 +1689,7 @@ impl CodeGenerator {
} }
self.emit_expr(var_args.expr.clone()); self.emit_expr(var_args.expr.clone());
if pos_len > 0 { if pos_len > 0 {
self.write_instr(Opcode38::BUILD_TUPLE_UNPACK_WITH_CALL); self.write_instr(Opcode308::BUILD_TUPLE_UNPACK_WITH_CALL);
self.write_arg(2); self.write_arg(2);
} }
} }
@ -1627,18 +1723,8 @@ impl CodeGenerator {
} else { } else {
self.write_arg(1); self.write_arg(1);
} }
} else if self.py_version.minor >= Some(11) {
self.write_instr(Opcode311::PRECALL);
self.write_arg(argc);
self.write_instr(Opcode311::CALL);
self.write_arg(argc);
} else { } else {
if kind.is_method() { self.emit_call_instr(argc, kind);
self.write_instr(Opcode310::CALL_METHOD);
} else {
self.write_instr(Opcode310::CALL_FUNCTION);
}
self.write_arg(argc);
} }
0 0
}; };
@ -1753,7 +1839,7 @@ impl CodeGenerator {
other => todo!("{other}"), other => todo!("{other}"),
} }
if !self.cfg.no_std { if !self.cfg.no_std {
self.emit_call_instr(1); self.emit_call_instr(1, Name);
self.stack_dec(); self.stack_dec();
} }
} }
@ -1777,7 +1863,7 @@ impl CodeGenerator {
} else { } else {
self.stack_dec_n(attrs_len - 1); self.stack_dec_n(attrs_len - 1);
} }
self.emit_call_instr(2); self.emit_call_instr(2, Name);
// (1 (subroutine) + argc + kwsc) input objects -> 1 return object // (1 (subroutine) + argc + kwsc) input objects -> 1 return object
self.stack_dec_n((1 + 2 + 0) - 1); self.stack_dec_n((1 + 2 + 0) - 1);
let ident = Identifier::private("#rec"); let ident = Identifier::private("#rec");
@ -1788,7 +1874,7 @@ impl CodeGenerator {
for field in rec.attrs.into_iter() { for field in rec.attrs.into_iter() {
self.emit_frameless_block(field.body.block, vec![]); self.emit_frameless_block(field.body.block, vec![]);
} }
self.emit_call_instr(attrs_len); self.emit_call_instr(attrs_len, Name);
// (1 (subroutine) + argc + kwsc) input objects -> 1 return object // (1 (subroutine) + argc + kwsc) input objects -> 1 return object
self.stack_dec_n((1 + attrs_len + 0) - 1); self.stack_dec_n((1 + attrs_len + 0) - 1);
} }
@ -2218,11 +2304,11 @@ impl CodeGenerator {
Some(Identifier::private("#path")), Some(Identifier::private("#path")),
)], )],
); );
self.emit_push_null();
self.emit_load_name_instr(Identifier::private("#path")); self.emit_load_name_instr(Identifier::private("#path"));
self.emit_load_method_instr(Identifier::public("append")); self.emit_load_method_instr(Identifier::public("append"));
self.emit_load_const(erg_std_path().to_str().unwrap()); self.emit_load_const(erg_std_path().to_str().unwrap());
self.write_instr(Opcode310::CALL_METHOD); self.emit_call_instr(1, Method);
self.write_arg(1);
self.stack_dec(); self.stack_dec();
self.emit_pop_top(); self.emit_pop_top();
let erg_std_mod = if self.py_version.minor >= Some(10) { let erg_std_mod = if self.py_version.minor >= Some(10) {
@ -2319,7 +2405,7 @@ impl CodeGenerator {
} }
} else { } else {
self.stack_inc(); self.stack_inc();
self.emit_call_instr(1); self.emit_call_instr(1, Name);
} }
self.stack_dec_n(self.cur_block().stack_len as usize); self.stack_dec_n(self.cur_block().stack_len as usize);
} }

View file

@ -6,9 +6,10 @@ use std::path::Path;
use erg_common::impl_display_from_debug; use erg_common::impl_display_from_debug;
use erg_common::opcode::CommonOpcode; use erg_common::opcode::CommonOpcode;
use erg_common::opcode308::Opcode308;
use erg_common::opcode310::Opcode310; use erg_common::opcode310::Opcode310;
use erg_common::opcode38::Opcode38; use erg_common::opcode311::{BinOpCode, Opcode311};
use erg_common::python_util::{detect_magic_number, python_version, PythonVersion}; use erg_common::python_util::{detect_magic_number, PythonVersion};
use erg_common::serialize::*; use erg_common::serialize::*;
use erg_common::Str; use erg_common::Str;
@ -418,10 +419,12 @@ impl CodeObj {
ldelta = lnotab_iter.next().unwrap_or(&0); ldelta = lnotab_iter.next().unwrap_or(&0);
} }
if let (Some(op), Some(arg)) = (code_iter.next(), code_iter.next()) { if let (Some(op), Some(arg)) = (code_iter.next(), code_iter.next()) {
if py_ver.unwrap_or_else(python_version).minor_is(3, 8) { match py_ver.and_then(|pv| pv.minor) {
self.read_instr_3_8(op, arg, idx, &mut instrs); Some(8) => self.read_instr_3_8(op, arg, idx, &mut instrs),
} else { // Some(9) => self.read_instr_3_9(op, arg, idx, &mut instrs),
self.read_instr_3_10(op, arg, idx, &mut instrs); Some(10) => self.read_instr_3_10(op, arg, idx, &mut instrs),
Some(11) => self.read_instr_3_11(op, arg, idx, &mut instrs),
_ => {}
} }
idx += 2; idx += 2;
line_offset += 2; line_offset += 2;
@ -433,17 +436,17 @@ impl CodeObj {
} }
fn read_instr_3_8(&self, op: &u8, arg: &u8, idx: usize, instrs: &mut String) { fn read_instr_3_8(&self, op: &u8, arg: &u8, idx: usize, instrs: &mut String) {
let op38 = Opcode38::from(*op); let op38 = Opcode308::from(*op);
let s_op = op38.to_string(); let s_op = op38.to_string();
write!(instrs, "{:>15} {:<25}", idx, s_op).unwrap(); write!(instrs, "{:>15} {:<25}", idx, s_op).unwrap();
if let Ok(op) = CommonOpcode::try_from(*op) { if let Ok(op) = CommonOpcode::try_from(*op) {
self.dump_additional_info(op, arg, idx, instrs); self.dump_additional_info(op, arg, idx, instrs);
} }
match op38 { match op38 {
Opcode38::BINARY_ADD Opcode308::BINARY_ADD
| Opcode38::BINARY_SUBTRACT | Opcode308::BINARY_SUBTRACT
| Opcode38::BINARY_MULTIPLY | Opcode308::BINARY_MULTIPLY
| Opcode38::BINARY_TRUE_DIVIDE => { | Opcode308::BINARY_TRUE_DIVIDE => {
write!(instrs, "{} ({:?})", arg, TypePair::from(*arg)).unwrap(); write!(instrs, "{} ({:?})", arg, TypePair::from(*arg)).unwrap();
} }
_ => {} _ => {}
@ -473,6 +476,34 @@ impl CodeObj {
instrs.push('\n'); instrs.push('\n');
} }
fn read_instr_3_11(&self, op: &u8, arg: &u8, idx: usize, instrs: &mut String) {
let op311 = Opcode311::from(*op);
let s_op = op311.to_string();
write!(instrs, "{:>15} {:<25}", idx, s_op).unwrap();
if let Ok(op) = CommonOpcode::try_from(*op) {
self.dump_additional_info(op, arg, idx, instrs);
}
match op311 {
Opcode311::PRECALL | Opcode311::CALL => {
write!(instrs, "{}", arg).unwrap();
}
Opcode311::KW_NAMES => {
write!(
instrs,
"{} ({})",
arg,
self.consts.get(*arg as usize).unwrap()
)
.unwrap();
}
Opcode311::BINARY_OP => {
write!(instrs, "{} ({:?})", arg, BinOpCode::from(*arg)).unwrap();
}
_ => {}
}
instrs.push('\n');
}
fn dump_additional_info(&self, op: CommonOpcode, arg: &u8, idx: usize, instrs: &mut String) { fn dump_additional_info(&self, op: CommonOpcode, arg: &u8, idx: usize, instrs: &mut String) {
match op { match op {
CommonOpcode::COMPARE_OP => { CommonOpcode::COMPARE_OP => {