This commit is contained in:
Shunsuke Shibayama 2022-11-02 12:05:59 +09:00
parent 617480cba6
commit 5e73048367
4 changed files with 99 additions and 45 deletions

1
.gitignore vendored
View file

@ -24,3 +24,4 @@ result
# Erg
test.er
test.py

View file

@ -67,15 +67,15 @@ pub enum DataTypePrefix {
StopIter = b'S', // 0x53
Ref = b'r',
/* unsized objects (ref counted) */
Long = b'l', // 0x6C + len: u32 + payload: 2*len+3byte (~ -2^31-1 && 2^31 ~)
Str = b's', // 0x73 + len: u32 + payload
ShortAscii = b'z', // 0x7A + len: u8 + payload
ShortAsciiInterned = b'Z', // 0x5A + len: u8 + payload
Unicode = b'u', // 0x75 + len: u32 + payload
Interned = b't', // 0x74 + len + payload
Long = b'l', // 0x6C + len: u32 + payload: 2*len+3byte (~ -2^31-1 && 2^31 ~)
Str = b's', // 0x73 + len: u32 + payload
ShortAscii = b'z' + 0x80, // 0x7A (0xFA) + len: u8 + payload
ShortAsciiInterned = b'Z' + 0x80, // 0x5A (0xDA) + len: u8 + payload
Unicode = b'u', // 0x75 + len: u32 + payload
Interned = b't', // 0x74 + len + payload
SmallTuple = b')', // 0x29 + len: u8 + payload
Tuple = b'(', // 0x28 + len: u32 + payload
Code = b'c', // 0x63
Tuple = b'(', // 0x28 + len: u32 + payload
Code = b'c' + 0x80, // 0x63 (0xE3)
/* Erg specific prefix */
Builtin = b'b', // 0x62 + str
Nat = b'n',

View file

@ -297,6 +297,11 @@ impl CodeGenerator {
}
}
fn write_bytes(&mut self, bytes: &[u8]) {
self.mut_cur_block_codeobj().code.extend_from_slice(bytes);
self.mut_cur_block().lasti += bytes.len();
}
fn stack_inc(&mut self) {
self.mut_cur_block().stack_len += 1;
if self.cur_block().stack_len > self.cur_block_codeobj().stacksize {
@ -306,10 +311,11 @@ impl CodeGenerator {
fn stack_dec(&mut self) {
if self.cur_block().stack_len == 0 {
println!("current block: {}", self.cur_block());
let lasti = self.cur_block().lasti;
let last = self.cur_block_codeobj().code.last().unwrap();
self.crash(&format!("the stack size becomes -1\nlasti: {lasti}\nlast code: {last}"));
self.crash(&format!(
"the stack size becomes -1\nlasti: {lasti}\nlast code: {last}"
));
} else {
self.mut_cur_block().stack_len -= 1;
}
@ -328,7 +334,9 @@ impl CodeGenerator {
if n > 0 && self.cur_block().stack_len == 0 {
let lasti = self.cur_block().lasti;
let last = self.cur_block_codeobj().code.last().unwrap();
self.crash(&format!("the stack size becomes -1\nlasti: {lasti}\nlast code: {last}"));
self.crash(&format!(
"the stack size becomes -1\nlasti: {lasti}\nlast code: {last}"
));
} else {
self.mut_cur_block().stack_len -= n as u32;
}
@ -486,9 +494,21 @@ impl CodeGenerator {
StoreLoadKind::Deref | StoreLoadKind::DerefConst => LOAD_DEREF,
StoreLoadKind::Local | StoreLoadKind::LocalConst => LOAD_NAME,
};
let null_idx = self.cur_block_codeobj().code.len() - 2;
if instr == LOAD_GLOBAL
&& self.cur_block_codeobj().code.get(null_idx) == Some(&(Opcode311::PUSH_NULL as u8))
{
self.mut_cur_block_codeobj().code.pop();
self.mut_cur_block_codeobj().code.pop();
self.mut_cur_block().lasti -= 2;
}
self.write_instr(instr);
self.write_arg(name.idx);
self.stack_inc();
if instr == LOAD_GLOBAL && self.py_version.minor >= Some(11) {
self.write_bytes(&[0; 2]);
self.write_bytes(&[0; 8]);
}
}
fn emit_load_global_instr(&mut self, ident: Identifier) {
@ -582,6 +602,9 @@ impl CodeGenerator {
};
self.write_instr(instr);
self.write_arg(name.idx);
if self.py_version.minor >= Some(11) {
self.write_bytes(&[0; 8]);
}
}
fn emit_load_method_instr(&mut self, ident: Identifier) {
@ -601,6 +624,9 @@ impl CodeGenerator {
};
self.write_instr(instr);
self.write_arg(name.idx);
if self.py_version.minor >= Some(11) {
self.write_bytes(&[0; 20]);
}
}
fn emit_store_instr(&mut self, ident: Identifier, acc_kind: AccessKind) {
@ -686,6 +712,7 @@ impl CodeGenerator {
/// 極力使わないこと
fn crash(&mut self, description: &str) -> ! {
if cfg!(feature = "debug") {
println!("current block: {}", self.cur_block());
panic!("internal error: {description}");
} else {
process::exit(1);
@ -756,14 +783,7 @@ impl CodeGenerator {
self.write_arg(0);
self.write_instr(Opcode311::CALL);
self.write_arg(argc);
self.write_arg(0);
self.write_arg(0);
self.write_arg(0);
self.write_arg(0);
self.write_arg(0);
self.write_arg(0);
self.write_arg(0);
self.write_arg(0);
self.write_bytes(&[0; 8]);
}
fn emit_call_instr(&mut self, argc: usize, kind: AccessKind) {
@ -807,7 +827,11 @@ impl CodeGenerator {
self.stack_inc();
let code = self.emit_trait_block(def.def_kind(), &def.sig, def.body.block);
self.emit_load_const(code);
self.emit_load_const(def.sig.ident().inspect().clone());
if self.py_version.minor < Some(11) {
self.emit_load_const(def.sig.ident().inspect().clone());
} else {
self.stack_inc();
}
self.write_instr(MAKE_FUNCTION);
self.write_arg(0);
self.emit_load_const(def.sig.ident().inspect().clone());
@ -942,10 +966,14 @@ impl CodeGenerator {
unit.codeobj
};
self.emit_load_const(code);
if let Some(class) = class_name {
self.emit_load_const(Str::from(format!("{class}.{}", ident.name.inspect())));
if self.py_version.minor < Some(11) {
if let Some(class) = class_name {
self.emit_load_const(Str::from(format!("{class}.{}", ident.name.inspect())));
} else {
self.emit_load_const(ident.name.inspect().clone());
}
} else {
self.emit_load_const(ident.name.inspect().clone());
self.stack_inc();
}
self.write_instr(MAKE_FUNCTION);
self.write_arg(0);
@ -969,7 +997,11 @@ impl CodeGenerator {
self.stack_inc();
let code = self.emit_class_block(class_def);
self.emit_load_const(code);
self.emit_load_const(ident.inspect().clone());
if self.py_version.minor < Some(11) {
self.emit_load_const(ident.inspect().clone());
} else {
self.stack_inc();
}
self.write_instr(MAKE_FUNCTION);
self.write_arg(0);
self.emit_load_const(ident.inspect().clone());
@ -1041,10 +1073,14 @@ impl CodeGenerator {
make_function_flag += 8;
}
self.emit_load_const(code);
if let Some(class) = class_name {
self.emit_load_const(Str::from(format!("{class}.{name}")));
if self.py_version.minor < Some(11) {
if let Some(class) = class_name {
self.emit_load_const(Str::from(format!("{class}.{name}")));
} else {
self.emit_load_const(name);
}
} else {
self.emit_load_const(name);
self.stack_inc();
}
self.write_instr(MAKE_FUNCTION);
self.write_arg(make_function_flag);
@ -1084,7 +1120,11 @@ impl CodeGenerator {
make_function_flag += MakeFunctionFlags::Closure as usize;
}
self.emit_load_const(code);
self.emit_load_const("<lambda>");
if self.py_version.minor < Some(11) {
self.emit_load_const("<lambda>");
} else {
self.stack_inc();
}
self.write_instr(MAKE_FUNCTION);
self.write_arg(make_function_flag);
// stack_dec: <lambda code obj> + <name "<lambda>"> -> <function>
@ -1302,15 +1342,15 @@ impl CodeGenerator {
};
self.write_instr(instr);
self.write_arg(arg);
if instr == Opcode311::CALL {
self.write_arg(0);
self.write_arg(0);
self.write_arg(0);
self.write_arg(0);
self.write_arg(0);
self.write_arg(0);
self.write_arg(0);
self.write_arg(0);
match instr {
Opcode311::CALL => {
self.write_bytes(&[0; 8]);
}
Opcode311::BINARY_OP => {
self.write_arg(0);
self.write_arg(0);
}
_ => {}
}
self.stack_dec();
match &binop.kind {
@ -2271,6 +2311,10 @@ impl CodeGenerator {
&name,
firstlineno,
));
if self.py_version.minor >= Some(11) {
self.write_instr(Opcode311::RESUME);
self.write_arg(0);
}
let init_stack_len = self.cur_block().stack_len;
for expr in block.into_iter() {
self.emit_expr(expr);

View file

@ -323,7 +323,13 @@ impl CodeObj {
bytes.append(&mut raw_string_into_bytes(self.code));
bytes.append(&mut consts_into_bytes(self.consts, python_ver)); // write as PyTupleObject
bytes.append(&mut strs_into_bytes(self.names));
Self::dump_locals(self.varnames, self.freevars, self.cellvars, &mut bytes, python_ver);
Self::dump_locals(
self.varnames,
self.freevars,
self.cellvars,
&mut bytes,
python_ver,
);
bytes.append(&mut str_into_bytes(self.filename, false));
bytes.append(&mut str_into_bytes(self.name, true));
bytes.append(&mut str_into_bytes(self.qualname, true));
@ -336,18 +342,21 @@ impl CodeObj {
bytes
}
fn dump_locals(varnames: Vec<Str>, freevars: Vec<Str>, cellvars: Vec<Str>, bytes: &mut Vec<u8>, python_ver: PythonVersion) {
fn dump_locals(
varnames: Vec<Str>,
freevars: Vec<Str>,
cellvars: Vec<Str>,
bytes: &mut Vec<u8>,
python_ver: PythonVersion,
) {
if python_ver.minor >= Some(11) {
let localspluskinds = [
vec![LocalKind::Local as u8; varnames.len()],
vec![LocalKind::Free as u8; freevars.len()],
vec![LocalKind::Cell as u8; cellvars.len()],
].concat();
let localsplusnames = [
varnames,
freevars,
cellvars,
].concat();
]
.concat();
let localsplusnames = [varnames, freevars, cellvars].concat();
bytes.append(&mut strs_into_bytes(localsplusnames));
bytes.append(&mut raw_string_into_bytes(localspluskinds));
} else {