mirror of
https://github.com/erg-lang/erg.git
synced 2025-10-01 05:11:09 +00:00
WIP
This commit is contained in:
parent
617480cba6
commit
5e73048367
4 changed files with 99 additions and 45 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -24,3 +24,4 @@ result
|
||||||
|
|
||||||
# Erg
|
# Erg
|
||||||
test.er
|
test.er
|
||||||
|
test.py
|
||||||
|
|
|
@ -67,15 +67,15 @@ pub enum DataTypePrefix {
|
||||||
StopIter = b'S', // 0x53
|
StopIter = b'S', // 0x53
|
||||||
Ref = b'r',
|
Ref = b'r',
|
||||||
/* unsized objects (ref counted) */
|
/* unsized objects (ref counted) */
|
||||||
Long = b'l', // 0x6C + len: u32 + payload: 2*len+3byte (~ -2^31-1 && 2^31 ~)
|
Long = b'l', // 0x6C + len: u32 + payload: 2*len+3byte (~ -2^31-1 && 2^31 ~)
|
||||||
Str = b's', // 0x73 + len: u32 + payload
|
Str = b's', // 0x73 + len: u32 + payload
|
||||||
ShortAscii = b'z', // 0x7A + len: u8 + payload
|
ShortAscii = b'z' + 0x80, // 0x7A (0xFA) + len: u8 + payload
|
||||||
ShortAsciiInterned = b'Z', // 0x5A + len: u8 + payload
|
ShortAsciiInterned = b'Z' + 0x80, // 0x5A (0xDA) + len: u8 + payload
|
||||||
Unicode = b'u', // 0x75 + len: u32 + payload
|
Unicode = b'u', // 0x75 + len: u32 + payload
|
||||||
Interned = b't', // 0x74 + len + payload
|
Interned = b't', // 0x74 + len + payload
|
||||||
SmallTuple = b')', // 0x29 + len: u8 + payload
|
SmallTuple = b')', // 0x29 + len: u8 + payload
|
||||||
Tuple = b'(', // 0x28 + len: u32 + payload
|
Tuple = b'(', // 0x28 + len: u32 + payload
|
||||||
Code = b'c', // 0x63
|
Code = b'c' + 0x80, // 0x63 (0xE3)
|
||||||
/* Erg specific prefix */
|
/* Erg specific prefix */
|
||||||
Builtin = b'b', // 0x62 + str
|
Builtin = b'b', // 0x62 + str
|
||||||
Nat = b'n',
|
Nat = b'n',
|
||||||
|
|
|
@ -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) {
|
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.cur_block().stack_len > self.cur_block_codeobj().stacksize {
|
||||||
|
@ -306,10 +311,11 @@ impl CodeGenerator {
|
||||||
|
|
||||||
fn stack_dec(&mut self) {
|
fn stack_dec(&mut self) {
|
||||||
if self.cur_block().stack_len == 0 {
|
if self.cur_block().stack_len == 0 {
|
||||||
println!("current block: {}", self.cur_block());
|
|
||||||
let lasti = self.cur_block().lasti;
|
let lasti = self.cur_block().lasti;
|
||||||
let last = self.cur_block_codeobj().code.last().unwrap();
|
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 {
|
} else {
|
||||||
self.mut_cur_block().stack_len -= 1;
|
self.mut_cur_block().stack_len -= 1;
|
||||||
}
|
}
|
||||||
|
@ -328,7 +334,9 @@ impl CodeGenerator {
|
||||||
if n > 0 && self.cur_block().stack_len == 0 {
|
if n > 0 && self.cur_block().stack_len == 0 {
|
||||||
let lasti = self.cur_block().lasti;
|
let lasti = self.cur_block().lasti;
|
||||||
let last = self.cur_block_codeobj().code.last().unwrap();
|
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 {
|
} else {
|
||||||
self.mut_cur_block().stack_len -= n as u32;
|
self.mut_cur_block().stack_len -= n as u32;
|
||||||
}
|
}
|
||||||
|
@ -486,9 +494,21 @@ impl CodeGenerator {
|
||||||
StoreLoadKind::Deref | StoreLoadKind::DerefConst => LOAD_DEREF,
|
StoreLoadKind::Deref | StoreLoadKind::DerefConst => LOAD_DEREF,
|
||||||
StoreLoadKind::Local | StoreLoadKind::LocalConst => LOAD_NAME,
|
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_instr(instr);
|
||||||
self.write_arg(name.idx);
|
self.write_arg(name.idx);
|
||||||
self.stack_inc();
|
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) {
|
fn emit_load_global_instr(&mut self, ident: Identifier) {
|
||||||
|
@ -582,6 +602,9 @@ impl CodeGenerator {
|
||||||
};
|
};
|
||||||
self.write_instr(instr);
|
self.write_instr(instr);
|
||||||
self.write_arg(name.idx);
|
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) {
|
fn emit_load_method_instr(&mut self, ident: Identifier) {
|
||||||
|
@ -601,6 +624,9 @@ impl CodeGenerator {
|
||||||
};
|
};
|
||||||
self.write_instr(instr);
|
self.write_instr(instr);
|
||||||
self.write_arg(name.idx);
|
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) {
|
fn emit_store_instr(&mut self, ident: Identifier, acc_kind: AccessKind) {
|
||||||
|
@ -686,6 +712,7 @@ impl CodeGenerator {
|
||||||
/// 極力使わないこと
|
/// 極力使わないこと
|
||||||
fn crash(&mut self, description: &str) -> ! {
|
fn crash(&mut self, description: &str) -> ! {
|
||||||
if cfg!(feature = "debug") {
|
if cfg!(feature = "debug") {
|
||||||
|
println!("current block: {}", self.cur_block());
|
||||||
panic!("internal error: {description}");
|
panic!("internal error: {description}");
|
||||||
} else {
|
} else {
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
|
@ -756,14 +783,7 @@ impl CodeGenerator {
|
||||||
self.write_arg(0);
|
self.write_arg(0);
|
||||||
self.write_instr(Opcode311::CALL);
|
self.write_instr(Opcode311::CALL);
|
||||||
self.write_arg(argc);
|
self.write_arg(argc);
|
||||||
self.write_arg(0);
|
self.write_bytes(&[0; 8]);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_call_instr(&mut self, argc: usize, kind: AccessKind) {
|
fn emit_call_instr(&mut self, argc: usize, kind: AccessKind) {
|
||||||
|
@ -807,7 +827,11 @@ impl CodeGenerator {
|
||||||
self.stack_inc();
|
self.stack_inc();
|
||||||
let code = self.emit_trait_block(def.def_kind(), &def.sig, def.body.block);
|
let code = self.emit_trait_block(def.def_kind(), &def.sig, def.body.block);
|
||||||
self.emit_load_const(code);
|
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_instr(MAKE_FUNCTION);
|
||||||
self.write_arg(0);
|
self.write_arg(0);
|
||||||
self.emit_load_const(def.sig.ident().inspect().clone());
|
self.emit_load_const(def.sig.ident().inspect().clone());
|
||||||
|
@ -942,10 +966,14 @@ impl CodeGenerator {
|
||||||
unit.codeobj
|
unit.codeobj
|
||||||
};
|
};
|
||||||
self.emit_load_const(code);
|
self.emit_load_const(code);
|
||||||
if let Some(class) = class_name {
|
if self.py_version.minor < Some(11) {
|
||||||
self.emit_load_const(Str::from(format!("{class}.{}", ident.name.inspect())));
|
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 {
|
} else {
|
||||||
self.emit_load_const(ident.name.inspect().clone());
|
self.stack_inc();
|
||||||
}
|
}
|
||||||
self.write_instr(MAKE_FUNCTION);
|
self.write_instr(MAKE_FUNCTION);
|
||||||
self.write_arg(0);
|
self.write_arg(0);
|
||||||
|
@ -969,7 +997,11 @@ impl CodeGenerator {
|
||||||
self.stack_inc();
|
self.stack_inc();
|
||||||
let code = self.emit_class_block(class_def);
|
let code = self.emit_class_block(class_def);
|
||||||
self.emit_load_const(code);
|
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_instr(MAKE_FUNCTION);
|
||||||
self.write_arg(0);
|
self.write_arg(0);
|
||||||
self.emit_load_const(ident.inspect().clone());
|
self.emit_load_const(ident.inspect().clone());
|
||||||
|
@ -1041,10 +1073,14 @@ impl CodeGenerator {
|
||||||
make_function_flag += 8;
|
make_function_flag += 8;
|
||||||
}
|
}
|
||||||
self.emit_load_const(code);
|
self.emit_load_const(code);
|
||||||
if let Some(class) = class_name {
|
if self.py_version.minor < Some(11) {
|
||||||
self.emit_load_const(Str::from(format!("{class}.{name}")));
|
if let Some(class) = class_name {
|
||||||
|
self.emit_load_const(Str::from(format!("{class}.{name}")));
|
||||||
|
} else {
|
||||||
|
self.emit_load_const(name);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
self.emit_load_const(name);
|
self.stack_inc();
|
||||||
}
|
}
|
||||||
self.write_instr(MAKE_FUNCTION);
|
self.write_instr(MAKE_FUNCTION);
|
||||||
self.write_arg(make_function_flag);
|
self.write_arg(make_function_flag);
|
||||||
|
@ -1084,7 +1120,11 @@ impl CodeGenerator {
|
||||||
make_function_flag += MakeFunctionFlags::Closure as usize;
|
make_function_flag += MakeFunctionFlags::Closure as usize;
|
||||||
}
|
}
|
||||||
self.emit_load_const(code);
|
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_instr(MAKE_FUNCTION);
|
||||||
self.write_arg(make_function_flag);
|
self.write_arg(make_function_flag);
|
||||||
// stack_dec: <lambda code obj> + <name "<lambda>"> -> <function>
|
// stack_dec: <lambda code obj> + <name "<lambda>"> -> <function>
|
||||||
|
@ -1302,15 +1342,15 @@ impl CodeGenerator {
|
||||||
};
|
};
|
||||||
self.write_instr(instr);
|
self.write_instr(instr);
|
||||||
self.write_arg(arg);
|
self.write_arg(arg);
|
||||||
if instr == Opcode311::CALL {
|
match instr {
|
||||||
self.write_arg(0);
|
Opcode311::CALL => {
|
||||||
self.write_arg(0);
|
self.write_bytes(&[0; 8]);
|
||||||
self.write_arg(0);
|
}
|
||||||
self.write_arg(0);
|
Opcode311::BINARY_OP => {
|
||||||
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.stack_dec();
|
self.stack_dec();
|
||||||
match &binop.kind {
|
match &binop.kind {
|
||||||
|
@ -2271,6 +2311,10 @@ impl CodeGenerator {
|
||||||
&name,
|
&name,
|
||||||
firstlineno,
|
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;
|
let init_stack_len = self.cur_block().stack_len;
|
||||||
for expr in block.into_iter() {
|
for expr in block.into_iter() {
|
||||||
self.emit_expr(expr);
|
self.emit_expr(expr);
|
||||||
|
|
|
@ -323,7 +323,13 @@ impl CodeObj {
|
||||||
bytes.append(&mut raw_string_into_bytes(self.code));
|
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 consts_into_bytes(self.consts, python_ver)); // write as PyTupleObject
|
||||||
bytes.append(&mut strs_into_bytes(self.names));
|
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.filename, false));
|
||||||
bytes.append(&mut str_into_bytes(self.name, true));
|
bytes.append(&mut str_into_bytes(self.name, true));
|
||||||
bytes.append(&mut str_into_bytes(self.qualname, true));
|
bytes.append(&mut str_into_bytes(self.qualname, true));
|
||||||
|
@ -336,18 +342,21 @@ impl CodeObj {
|
||||||
bytes
|
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) {
|
if python_ver.minor >= Some(11) {
|
||||||
let localspluskinds = [
|
let localspluskinds = [
|
||||||
vec![LocalKind::Local as u8; varnames.len()],
|
vec![LocalKind::Local as u8; varnames.len()],
|
||||||
vec![LocalKind::Free as u8; freevars.len()],
|
vec![LocalKind::Free as u8; freevars.len()],
|
||||||
vec![LocalKind::Cell as u8; cellvars.len()],
|
vec![LocalKind::Cell as u8; cellvars.len()],
|
||||||
].concat();
|
]
|
||||||
let localsplusnames = [
|
.concat();
|
||||||
varnames,
|
let localsplusnames = [varnames, freevars, cellvars].concat();
|
||||||
freevars,
|
|
||||||
cellvars,
|
|
||||||
].concat();
|
|
||||||
bytes.append(&mut strs_into_bytes(localsplusnames));
|
bytes.append(&mut strs_into_bytes(localsplusnames));
|
||||||
bytes.append(&mut raw_string_into_bytes(localspluskinds));
|
bytes.append(&mut raw_string_into_bytes(localspluskinds));
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue