From 6eb4e57a5bd2d722cd35fce3eb9e5f39185471c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dan=20N=C3=A4sman?= <30578250+dannasman@users.noreply.github.com> Date: Sat, 15 Oct 2022 08:10:36 +0300 Subject: [PATCH] ::replace() (#4207) --- vm/src/builtins/code.rs | 115 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 113 insertions(+), 2 deletions(-) diff --git a/vm/src/builtins/code.rs b/vm/src/builtins/code.rs index e3e9bd9ee..deb5f576c 100644 --- a/vm/src/builtins/code.rs +++ b/vm/src/builtins/code.rs @@ -5,15 +5,39 @@ use super::{PyStrRef, PyTupleRef, PyType, PyTypeRef}; use crate::{ builtins::PyStrInterned, - bytecode::{self, BorrowedConstant, Constant, ConstantBag}, + bytecode::{self, BorrowedConstant, CodeFlags, Constant, ConstantBag}, class::{PyClassImpl, StaticType}, convert::ToPyObject, - function::FuncArgs, + function::{FuncArgs, OptionalArg}, AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine, }; use num_traits::Zero; use std::{borrow::Borrow, fmt, ops::Deref}; +#[derive(FromArgs)] +pub struct ReplaceArgs { + #[pyarg(named, optional)] + co_posonlyargcount: OptionalArg, + #[pyarg(named, optional)] + co_argcount: OptionalArg, + #[pyarg(named, optional)] + co_kwonlyargcount: OptionalArg, + #[pyarg(named, optional)] + co_filename: OptionalArg, + #[pyarg(named, optional)] + co_firstlineno: OptionalArg, + #[pyarg(named, optional)] + co_consts: OptionalArg>, + #[pyarg(named, optional)] + co_name: OptionalArg, + #[pyarg(named, optional)] + co_names: OptionalArg>, + #[pyarg(named, optional)] + co_flags: OptionalArg, + #[pyarg(named, optional)] + co_varnames: OptionalArg>, +} + #[derive(Clone)] pub struct Literal(PyObjectRef); @@ -237,6 +261,93 @@ impl PyRef { let varnames = self.code.varnames.iter().map(|s| s.to_object()).collect(); vm.ctx.new_tuple(varnames) } + + #[pymethod] + pub fn replace(self, args: ReplaceArgs, vm: &VirtualMachine) -> PyResult { + let posonlyarg_count = match args.co_posonlyargcount { + OptionalArg::Present(posonlyarg_count) => posonlyarg_count, + OptionalArg::Missing => self.code.posonlyarg_count, + }; + + let arg_count = match args.co_argcount { + OptionalArg::Present(arg_count) => arg_count, + OptionalArg::Missing => self.code.arg_count, + }; + + let source_path = match args.co_filename { + OptionalArg::Present(source_path) => source_path, + OptionalArg::Missing => self.code.source_path.to_owned(), + }; + + let first_line_number = match args.co_firstlineno { + OptionalArg::Present(first_line_number) => first_line_number, + OptionalArg::Missing => self.code.first_line_number, + }; + + let kwonlyarg_count = match args.co_kwonlyargcount { + OptionalArg::Present(kwonlyarg_count) => kwonlyarg_count, + OptionalArg::Missing => self.code.kwonlyarg_count, + }; + + let constants = match args.co_consts { + OptionalArg::Present(constants) => constants, + OptionalArg::Missing => self.code.constants.iter().map(|x| x.0.clone()).collect(), + }; + + let obj_name = match args.co_name { + OptionalArg::Present(obj_name) => obj_name, + OptionalArg::Missing => self.code.obj_name.to_owned(), + }; + + let names = match args.co_names { + OptionalArg::Present(names) => names, + OptionalArg::Missing => self + .code + .names + .deref() + .iter() + .map(|name| name.to_pyobject(vm)) + .collect(), + }; + + let flags = match args.co_flags { + OptionalArg::Present(flags) => flags, + OptionalArg::Missing => self.code.flags.bits(), + }; + + let varnames = match args.co_varnames { + OptionalArg::Present(varnames) => varnames, + OptionalArg::Missing => self.code.varnames.iter().map(|s| s.to_object()).collect(), + }; + + Ok(PyCode { + code: CodeObject { + flags: CodeFlags::from_bits_truncate(flags), + posonlyarg_count, + arg_count, + kwonlyarg_count, + source_path: source_path.as_object().as_interned_str(vm).unwrap(), + first_line_number, + obj_name: obj_name.as_object().as_interned_str(vm).unwrap(), + + max_stackdepth: self.code.max_stackdepth, + instructions: self.code.instructions.clone(), + locations: self.code.locations.clone(), + constants: constants.into_iter().map(Literal).collect(), + names: names + .into_iter() + .map(|o| o.as_interned_str(vm).unwrap()) + .collect(), + varnames: varnames + .into_iter() + .map(|o| o.as_interned_str(vm).unwrap()) + .collect(), + cellvars: self.code.cellvars.clone(), + freevars: self.code.freevars.clone(), + cell2arg: self.code.cell2arg.clone(), + }, + }) + } } impl fmt::Display for PyCode {