mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-30 12:51:10 +00:00
fix a bug with closures
This commit is contained in:
parent
a28ca96d80
commit
f15305c287
2 changed files with 25 additions and 12 deletions
|
@ -480,9 +480,14 @@ impl CodeGenerator {
|
||||||
}
|
}
|
||||||
Some(StoreLoadKind::Deref) => {
|
Some(StoreLoadKind::Deref) => {
|
||||||
self.mut_cur_block_codeobj().freevars.push(name.clone());
|
self.mut_cur_block_codeobj().freevars.push(name.clone());
|
||||||
// TODO: in 3.11 freevars are unified with varnames
|
if self.py_version.minor >= Some(11) {
|
||||||
// cellvarsのpushはrec_search()で行われる
|
// in 3.11 freevars are unified with varnames
|
||||||
Name::deref(self.cur_block_codeobj().freevars.len() - 1)
|
self.mut_cur_block_codeobj().varnames.push(name);
|
||||||
|
Name::deref(self.cur_block_codeobj().varnames.len() - 1)
|
||||||
|
} else {
|
||||||
|
// cellvarsのpushはrec_search()で行われる
|
||||||
|
Name::deref(self.cur_block_codeobj().freevars.len() - 1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
// new variable
|
// new variable
|
||||||
|
@ -2473,6 +2478,7 @@ impl CodeGenerator {
|
||||||
}
|
}
|
||||||
let freevars_len = self.cur_block_codeobj().freevars.len();
|
let freevars_len = self.cur_block_codeobj().freevars.len();
|
||||||
if freevars_len > 0 {
|
if freevars_len > 0 {
|
||||||
|
self.mut_cur_block_codeobj().flags += CodeObjFlags::Nested as u32;
|
||||||
self.edit_code(idx_copy_free_vars + 1, freevars_len);
|
self.edit_code(idx_copy_free_vars + 1, freevars_len);
|
||||||
} else if self.py_version.minor >= Some(11) {
|
} else if self.py_version.minor >= Some(11) {
|
||||||
self.edit_code(idx_copy_free_vars, CommonOpcode::NOP as usize);
|
self.edit_code(idx_copy_free_vars, CommonOpcode::NOP as usize);
|
||||||
|
|
|
@ -5,6 +5,8 @@ use std::io::{BufReader, Read, Write as _};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use erg_common::impl_display_from_debug;
|
use erg_common::impl_display_from_debug;
|
||||||
|
#[allow(unused_imports)]
|
||||||
|
use erg_common::log;
|
||||||
use erg_common::opcode::CommonOpcode;
|
use erg_common::opcode::CommonOpcode;
|
||||||
use erg_common::opcode308::Opcode308;
|
use erg_common::opcode308::Opcode308;
|
||||||
use erg_common::opcode310::Opcode310;
|
use erg_common::opcode310::Opcode310;
|
||||||
|
@ -32,12 +34,13 @@ pub fn consts_into_bytes(consts: Vec<ValueObj>, python_ver: PythonVersion) -> Ve
|
||||||
tuple
|
tuple
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Kind can be multiple (e.g. Local + Cell = 0x60)
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
pub enum LocalKind {
|
pub enum FastKind {
|
||||||
Local = 0x20,
|
Local = 0x20,
|
||||||
Free = 0x40,
|
Cell = 0x40,
|
||||||
Cell = 0x80,
|
Free = 0x80,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Bit masks for CodeObj.flags
|
/// Bit masks for CodeObj.flags
|
||||||
|
@ -192,7 +195,7 @@ impl Default for CodeObj {
|
||||||
kwonlyargcount: 0,
|
kwonlyargcount: 0,
|
||||||
nlocals: 0,
|
nlocals: 0,
|
||||||
stacksize: 2, // Seems to be the default in CPython, but not sure why
|
stacksize: 2, // Seems to be the default in CPython, but not sure why
|
||||||
flags: CodeObjFlags::NoFree as u32,
|
flags: 0, //CodeObjFlags::NoFree as u32,
|
||||||
code: Vec::new(),
|
code: Vec::new(),
|
||||||
consts: Vec::new(),
|
consts: Vec::new(),
|
||||||
names: Vec::new(),
|
names: Vec::new(),
|
||||||
|
@ -223,7 +226,7 @@ impl CodeObj {
|
||||||
kwonlyargcount: 0,
|
kwonlyargcount: 0,
|
||||||
nlocals: params.len() as u32,
|
nlocals: params.len() as u32,
|
||||||
stacksize: 2, // Seems to be the default in CPython, but not sure why
|
stacksize: 2, // Seems to be the default in CPython, but not sure why
|
||||||
flags: CodeObjFlags::NoFree as u32,
|
flags: 0, // CodeObjFlags::NoFree as u32,
|
||||||
code: Vec::with_capacity(8),
|
code: Vec::with_capacity(8),
|
||||||
consts: Vec::with_capacity(4),
|
consts: Vec::with_capacity(4),
|
||||||
names: Vec::with_capacity(3),
|
names: Vec::with_capacity(3),
|
||||||
|
@ -350,10 +353,14 @@ impl CodeObj {
|
||||||
python_ver: PythonVersion,
|
python_ver: PythonVersion,
|
||||||
) {
|
) {
|
||||||
if python_ver.minor >= Some(11) {
|
if python_ver.minor >= Some(11) {
|
||||||
|
let varnames = varnames
|
||||||
|
.into_iter()
|
||||||
|
.filter(|n| !freevars.contains(n) && !cellvars.contains(n))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
let localspluskinds = [
|
let localspluskinds = [
|
||||||
vec![LocalKind::Local as u8; varnames.len()],
|
vec![FastKind::Local as u8; varnames.len()],
|
||||||
vec![LocalKind::Free as u8; freevars.len()],
|
vec![FastKind::Free as u8; freevars.len()],
|
||||||
vec![LocalKind::Cell as u8; cellvars.len()],
|
vec![FastKind::Cell as u8 + FastKind::Local as u8; cellvars.len()],
|
||||||
]
|
]
|
||||||
.concat();
|
.concat();
|
||||||
let localsplusnames = [varnames, freevars, cellvars].concat();
|
let localsplusnames = [varnames, freevars, cellvars].concat();
|
||||||
|
@ -577,7 +584,7 @@ impl CodeObj {
|
||||||
write!(
|
write!(
|
||||||
instrs,
|
instrs,
|
||||||
"{arg} ({})",
|
"{arg} ({})",
|
||||||
self.freevars.get(*arg as usize).unwrap()
|
self.varnames.get(*arg as usize).unwrap()
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue