Skip to content

Commit 6eb4e57

Browse files
authored
<code object>::replace() (RustPython#4207)
1 parent f1e1046 commit 6eb4e57

File tree

1 file changed

+113
-2
lines changed

1 file changed

+113
-2
lines changed

vm/src/builtins/code.rs

Lines changed: 113 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,39 @@
55
use super::{PyStrRef, PyTupleRef, PyType, PyTypeRef};
66
use crate::{
77
builtins::PyStrInterned,
8-
bytecode::{self, BorrowedConstant, Constant, ConstantBag},
8+
bytecode::{self, BorrowedConstant, CodeFlags, Constant, ConstantBag},
99
class::{PyClassImpl, StaticType},
1010
convert::ToPyObject,
11-
function::FuncArgs,
11+
function::{FuncArgs, OptionalArg},
1212
AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
1313
};
1414
use num_traits::Zero;
1515
use std::{borrow::Borrow, fmt, ops::Deref};
1616

17+
#[derive(FromArgs)]
18+
pub struct ReplaceArgs {
19+
#[pyarg(named, optional)]
20+
co_posonlyargcount: OptionalArg<usize>,
21+
#[pyarg(named, optional)]
22+
co_argcount: OptionalArg<usize>,
23+
#[pyarg(named, optional)]
24+
co_kwonlyargcount: OptionalArg<usize>,
25+
#[pyarg(named, optional)]
26+
co_filename: OptionalArg<PyStrRef>,
27+
#[pyarg(named, optional)]
28+
co_firstlineno: OptionalArg<usize>,
29+
#[pyarg(named, optional)]
30+
co_consts: OptionalArg<Vec<PyObjectRef>>,
31+
#[pyarg(named, optional)]
32+
co_name: OptionalArg<PyStrRef>,
33+
#[pyarg(named, optional)]
34+
co_names: OptionalArg<Vec<PyObjectRef>>,
35+
#[pyarg(named, optional)]
36+
co_flags: OptionalArg<u16>,
37+
#[pyarg(named, optional)]
38+
co_varnames: OptionalArg<Vec<PyObjectRef>>,
39+
}
40+
1741
#[derive(Clone)]
1842
pub struct Literal(PyObjectRef);
1943

@@ -237,6 +261,93 @@ impl PyRef<PyCode> {
237261
let varnames = self.code.varnames.iter().map(|s| s.to_object()).collect();
238262
vm.ctx.new_tuple(varnames)
239263
}
264+
265+
#[pymethod]
266+
pub fn replace(self, args: ReplaceArgs, vm: &VirtualMachine) -> PyResult<PyCode> {
267+
let posonlyarg_count = match args.co_posonlyargcount {
268+
OptionalArg::Present(posonlyarg_count) => posonlyarg_count,
269+
OptionalArg::Missing => self.code.posonlyarg_count,
270+
};
271+
272+
let arg_count = match args.co_argcount {
273+
OptionalArg::Present(arg_count) => arg_count,
274+
OptionalArg::Missing => self.code.arg_count,
275+
};
276+
277+
let source_path = match args.co_filename {
278+
OptionalArg::Present(source_path) => source_path,
279+
OptionalArg::Missing => self.code.source_path.to_owned(),
280+
};
281+
282+
let first_line_number = match args.co_firstlineno {
283+
OptionalArg::Present(first_line_number) => first_line_number,
284+
OptionalArg::Missing => self.code.first_line_number,
285+
};
286+
287+
let kwonlyarg_count = match args.co_kwonlyargcount {
288+
OptionalArg::Present(kwonlyarg_count) => kwonlyarg_count,
289+
OptionalArg::Missing => self.code.kwonlyarg_count,
290+
};
291+
292+
let constants = match args.co_consts {
293+
OptionalArg::Present(constants) => constants,
294+
OptionalArg::Missing => self.code.constants.iter().map(|x| x.0.clone()).collect(),
295+
};
296+
297+
let obj_name = match args.co_name {
298+
OptionalArg::Present(obj_name) => obj_name,
299+
OptionalArg::Missing => self.code.obj_name.to_owned(),
300+
};
301+
302+
let names = match args.co_names {
303+
OptionalArg::Present(names) => names,
304+
OptionalArg::Missing => self
305+
.code
306+
.names
307+
.deref()
308+
.iter()
309+
.map(|name| name.to_pyobject(vm))
310+
.collect(),
311+
};
312+
313+
let flags = match args.co_flags {
314+
OptionalArg::Present(flags) => flags,
315+
OptionalArg::Missing => self.code.flags.bits(),
316+
};
317+
318+
let varnames = match args.co_varnames {
319+
OptionalArg::Present(varnames) => varnames,
320+
OptionalArg::Missing => self.code.varnames.iter().map(|s| s.to_object()).collect(),
321+
};
322+
323+
Ok(PyCode {
324+
code: CodeObject {
325+
flags: CodeFlags::from_bits_truncate(flags),
326+
posonlyarg_count,
327+
arg_count,
328+
kwonlyarg_count,
329+
source_path: source_path.as_object().as_interned_str(vm).unwrap(),
330+
first_line_number,
331+
obj_name: obj_name.as_object().as_interned_str(vm).unwrap(),
332+
333+
max_stackdepth: self.code.max_stackdepth,
334+
instructions: self.code.instructions.clone(),
335+
locations: self.code.locations.clone(),
336+
constants: constants.into_iter().map(Literal).collect(),
337+
names: names
338+
.into_iter()
339+
.map(|o| o.as_interned_str(vm).unwrap())
340+
.collect(),
341+
varnames: varnames
342+
.into_iter()
343+
.map(|o| o.as_interned_str(vm).unwrap())
344+
.collect(),
345+
cellvars: self.code.cellvars.clone(),
346+
freevars: self.code.freevars.clone(),
347+
cell2arg: self.code.cell2arg.clone(),
348+
},
349+
})
350+
}
240351
}
241352

242353
impl fmt::Display for PyCode {

0 commit comments

Comments
 (0)