| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent d88c344 commit c8d63e8
8 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -8,7 +8,7 @@ use crate::convert::ToPyException; | |||
| 8 | 8 | use crate::{ | |
| 9 | 9 | AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine, | |
| 10 | 10 | builtins::PyStrInterned, | |
| 11 | - bytecode::{self, AsBag, BorrowedConstant, CodeFlags, Constant, ConstantBag, Instruction}, | ||
| 11 | + bytecode::{self, BorrowedConstant, CodeFlags, Constant, ConstantBag, Instruction}, | ||
| 12 | 12 | class::{PyClassImpl, StaticType}, | |
| 13 | 13 | convert::ToPyObject, | |
| 14 | 14 | frozen, | |
@@ -263,16 +263,6 @@ impl Constant for Literal { | |||
| 263 | 263 | } | |
| 264 | 264 | } | |
| 265 | 265 | ||
| 266 | - impl<'a> AsBag for &'a Context { | ||
| 267 | - type Bag = PyObjBag<'a>; | ||
| 268 | - fn as_bag(self) -> PyObjBag<'a> { | ||
| 269 | - PyObjBag(self) | ||
| 270 | - } | ||
| 271 | - } | ||
| 272 | - | ||
| 273 | - #[derive(Clone, Copy)] | ||
| 274 | - pub struct PyObjBag<'a>(pub &'a Context); | ||
| 275 | - | ||
| 276 | 266 | /// Whether a string constant reads as a name. Those are the ones interned, | |
| 277 | 267 | /// the way `all_name_chars` picks them out. | |
| 278 | 268 | fn is_name_chars(value: &crate::common::wtf8::Wtf8) -> bool { | |
@@ -282,77 +272,6 @@ fn is_name_chars(value: &crate::common::wtf8::Wtf8) -> bool { | |||
| 282 | 272 | .all(|&b| b.is_ascii_alphanumeric() || b == b'_') | |
| 283 | 273 | } | |
| 284 | 274 | ||
| 285 | - impl ConstantBag for PyObjBag<'_> { | ||
| 286 | - type Constant = Literal; | ||
| 287 | - | ||
| 288 | - fn make_constant<C: Constant>(&self, constant: BorrowedConstant<'_, C>) -> Self::Constant { | ||
| 289 | - let ctx = self.0; | ||
| 290 | - let obj = match constant { | ||
| 291 | - BorrowedConstant::Integer { value } => ctx.new_bigint(value).into(), | ||
| 292 | - BorrowedConstant::Float { value } => ctx.new_float(value).into(), | ||
| 293 | - BorrowedConstant::Complex { value } => ctx.new_complex(value).into(), | ||
| 294 | - BorrowedConstant::Str { value } if is_name_chars(value) => { | ||
| 295 | - ctx.intern_str(value).to_object() | ||
| 296 | - } | ||
| 297 | - BorrowedConstant::Str { value } => ctx.new_str(value).into(), | ||
| 298 | - BorrowedConstant::Bytes { value } => ctx.new_bytes(value.to_vec()).into(), | ||
| 299 | - BorrowedConstant::Boolean { value } => ctx.new_bool(value).into(), | ||
| 300 | - BorrowedConstant::Code { code } => ctx.new_code(code.map_clone_bag(self)).into(), | ||
| 301 | - BorrowedConstant::Tuple { elements } => { | ||
| 302 | - let elements = elements | ||
| 303 | - .iter() | ||
| 304 | - .map(|constant| self.make_constant(constant.borrow_constant()).0) | ||
| 305 | - .collect(); | ||
| 306 | - ctx.new_tuple(elements).into() | ||
| 307 | - } | ||
| 308 | - BorrowedConstant::Slice { elements } => { | ||
| 309 | - let [start, stop, step] = elements; | ||
| 310 | - let start_obj = self.make_constant(start.borrow_constant()).0; | ||
| 311 | - let stop_obj = self.make_constant(stop.borrow_constant()).0; | ||
| 312 | - let step_obj = self.make_constant(step.borrow_constant()).0; | ||
| 313 | - // Store as PySlice with Some() for all fields (even None values) | ||
| 314 | - // so borrow_obj_constant can reference them. | ||
| 315 | - use crate::builtins::PySlice; | ||
| 316 | - PySlice { | ||
| 317 | - start: Some(start_obj), | ||
| 318 | - stop: stop_obj, | ||
| 319 | - step: Some(step_obj), | ||
| 320 | - } | ||
| 321 | - .into_ref(ctx) | ||
| 322 | - .into() | ||
| 323 | - } | ||
| 324 | - BorrowedConstant::Frozenset { elements: _ } => { | ||
| 325 | - // Creating a frozenset requires VirtualMachine for element hashing. | ||
| 326 | - // PyObjBag only has Context, so we cannot construct PyFrozenSet here. | ||
| 327 | - // Frozenset constants from .pyc are handled by PyMarshalBag which has VM access. | ||
| 328 | - unimplemented!( | ||
| 329 | - "frozenset constant in PyObjBag::make_constant requires VirtualMachine" | ||
| 330 | - ) | ||
| 331 | - } | ||
| 332 | - BorrowedConstant::None => ctx.none(), | ||
| 333 | - BorrowedConstant::Ellipsis => ctx.ellipsis.clone().into(), | ||
| 334 | - }; | ||
| 335 | - | ||
| 336 | - Literal(obj) | ||
| 337 | - } | ||
| 338 | - | ||
| 339 | - fn make_name(&self, name: &str) -> &'static PyStrInterned { | ||
| 340 | - self.0.intern_str(name) | ||
| 341 | - } | ||
| 342 | - | ||
| 343 | - fn make_int(&self, value: BigInt) -> Self::Constant { | ||
| 344 | - Literal(self.0.new_int(value).into()) | ||
| 345 | - } | ||
| 346 | - | ||
| 347 | - fn make_tuple(&self, elements: impl Iterator<Item = Self::Constant>) -> Self::Constant { | ||
| 348 | - Literal(self.0.new_tuple(elements.map(|lit| lit.0).collect()).into()) | ||
| 349 | - } | ||
| 350 | - | ||
| 351 | - fn make_code(&self, code: CodeObject) -> Self::Constant { | ||
| 352 | - Literal(self.0.new_code(code).into()) | ||
| 353 | - } | ||
| 354 | - } | ||
| 355 | - | ||
| 356 | 275 | #[derive(Clone, Copy)] | |
| 357 | 276 | pub(crate) struct PyVmBag<'a>(pub &'a VirtualMachine); | |
| 358 | 277 | ||
@@ -437,24 +356,24 @@ impl ConstantBag for PyVmBag<'_> { | |||
| 437 | 356 | pub(crate) type CodeObject = bytecode::CodeObject<Literal>; | |
| 438 | 357 | ||
| 439 | 358 | pub trait IntoCodeObject { | |
| 440 | - fn into_code_object(self, ctx: &Context) -> CodeObject; | ||
| 359 | + fn into_code_object(self, vm: &VirtualMachine) -> CodeObject; | ||
| 441 | 360 | } | |
| 442 | 361 | ||
| 443 | 362 | impl IntoCodeObject for CodeObject { | |
| 444 | - fn into_code_object(self, _ctx: &Context) -> Self { | ||
| 363 | + fn into_code_object(self, _vm: &VirtualMachine) -> Self { | ||
| 445 | 364 | self | |
| 446 | 365 | } | |
| 447 | 366 | } | |
| 448 | 367 | ||
| 449 | 368 | impl IntoCodeObject for bytecode::CodeObject { | |
| 450 | - fn into_code_object(self, ctx: &Context) -> CodeObject { | ||
| 451 | - self.map_bag(PyObjBag(ctx)) | ||
| 369 | + fn into_code_object(self, vm: &VirtualMachine) -> CodeObject { | ||
| 370 | + self.map_bag(PyVmBag(vm)) | ||
| 452 | 371 | } | |
| 453 | 372 | } | |
| 454 | 373 | ||
| 455 | 374 | impl<B: AsRef<[u8]>> IntoCodeObject for frozen::FrozenCodeObject<B> { | |
| 456 | - fn into_code_object(self, ctx: &Context) -> CodeObject { | ||
| 457 | - self.decode(ctx) | ||
| 375 | + fn into_code_object(self, vm: &VirtualMachine) -> CodeObject { | ||
| 376 | + self.decode(PyVmBag(vm)) | ||
| 458 | 377 | } | |
| 459 | 378 | } | |
| 460 | 379 | ||
@@ -1645,7 +1564,7 @@ impl Py<PyCode> { | |||
| 1645 | 1564 | ||
| 1646 | 1565 | impl ToPyObject for CodeObject { | |
| 1647 | 1566 | fn to_pyobject(self, vm: &VirtualMachine) -> PyObjectRef { | |
| 1648 | - vm.ctx.new_code(self).into() | ||
| 1567 | + vm.new_code(self).into() | ||
| 1649 | 1568 | } | |
| 1650 | 1569 | } | |
| 1651 | 1570 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -931,7 +931,7 @@ mod _testinternalcapi { | |||
| 931 | 931 | let unit = super::metadata_to_code_unit(&metadata, vm)?; | |
| 932 | 932 | let code = rustpython_codegen::ir::assemble_for_tests(filename, rust_seq, unit, true) | |
| 933 | 933 | .map_err(|err| super::internal_error_to_py(err, vm))?; | |
| 934 | - Ok(vm.ctx.new_code(code)) | ||
| 934 | + Ok(vm.new_code(code)) | ||
| 935 | 935 | } | |
| 936 | 936 | ||
| 937 | 937 | #[cfg(feature = "codegen")] | |
@@ -1736,7 +1736,7 @@ fn constant_data_to_py( | |||
| 1736 | 1736 | ) | |
| 1737 | 1737 | .map_or_else(|_| vm.ctx.none(), |set| set.to_pyobject(vm)), | |
| 1738 | 1738 | ConstantData::Ellipsis => vm.ctx.ellipsis.clone().into(), | |
| 1739 | - ConstantData::Code { code } => vm.ctx.new_code(*code).into(), | ||
| 1739 | + ConstantData::Code { code } => vm.new_code(*code).into(), | ||
| 1740 | 1740 | ConstantData::Slice { elements } => { | |
| 1741 | 1741 | let [start, stop, step] = *elements; | |
| 1742 | 1742 | crate::builtins::PySlice { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -5,7 +5,6 @@ use crate::{ | |||
| 5 | 5 | PyFrozenSet, PyInt, PyIntRef, PyList, PyListRef, PyNone, PyNotImplemented, PyStr, | |
| 6 | 6 | PyStrInterned, PyTuple, PyTupleRef, PyType, PyTypeRef, PyUtf8Str, | |
| 7 | 7 | bool_::PyBool, | |
| 8 | - code::{self, PyCode}, | ||
| 9 | 8 | descriptor::{ | |
| 10 | 9 | MemberAccess, MemberKind, PyDescriptorOwned, PyMemberDef, PyMemberDescriptor, | |
| 11 | 10 | PyMemberFlags, | |
@@ -781,11 +780,6 @@ impl Context { | |||
| 781 | 780 | PyRef::new_ref(object::PyBaseObject, class, dict).into() | |
| 782 | 781 | } | |
| 783 | 782 | ||
| 784 | - pub fn new_code(&self, code: impl code::IntoCodeObject) -> PyRef<PyCode> { | ||
| 785 | - let code = code.into_code_object(self); | ||
| 786 | - PyRef::new_ref(PyCode::new(code), self.types.code_type.to_owned(), None) | ||
| 787 | - } | ||
| 788 | - | ||
| 789 | 783 | pub fn new_capsule( | |
| 790 | 784 | &self, | |
| 791 | 785 | ptr: *mut c_void, | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -2163,4 +2163,34 @@ for _ in range(40): | |||
| 2163 | 2163 | assert!(result.try_to_bool(vm).unwrap()); | |
| 2164 | 2164 | }); | |
| 2165 | 2165 | } | |
| 2166 | + | ||
| 2167 | + /// Set and `for` literals become frozenset constants. Materializing them | ||
| 2168 | + /// needs the VM so element hashing can run. | ||
| 2169 | + #[cfg(feature = "compiler")] | ||
| 2170 | + #[test] | ||
| 2171 | + fn new_code_materializes_frozenset_constants() { | ||
| 2172 | + Interpreter::without_stdlib(Default::default()).enter(|vm| { | ||
| 2173 | + let source = "\ | ||
| 2174 | + a = 2 in {1, 2, 3} | ||
| 2175 | + n = 0 | ||
| 2176 | + for e in {1, 2, 3}: | ||
| 2177 | + n += e | ||
| 2178 | + "; | ||
| 2179 | + let code = crate::compiler::compile( | ||
| 2180 | + source, | ||
| 2181 | + crate::compiler::Mode::Exec, | ||
| 2182 | + "<test>", | ||
| 2183 | + vm.compile_opts(), | ||
| 2184 | + ) | ||
| 2185 | + .unwrap(); | ||
| 2186 | + let code = vm.new_code(code); | ||
| 2187 | + let scope = vm.new_scope_with_builtins(); | ||
| 2188 | + vm.run_code_obj(code, scope.clone()).unwrap(); | ||
| 2189 | + | ||
| 2190 | + let a = scope.globals.get_item("a", vm).unwrap(); | ||
| 2191 | + assert!(a.is(&vm.ctx.true_value)); | ||
| 2192 | + let n = scope.globals.get_item("n", vm).unwrap(); | ||
| 2193 | + assert_eq!(*int::get_value(&n), 6_i32.to_bigint().unwrap()); | ||
| 2194 | + }) | ||
| 2195 | + } | ||
| 2166 | 2196 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -18,6 +18,7 @@ use crate::{ | |||
| 18 | 18 | PyImportError, PyMemoryError, PyModule, PyNameError, PyOSError, PyStopIteration, PyStrRef, | |
| 19 | 19 | PySyntaxError, PySystemExit, PyType, PyTypeRef, | |
| 20 | 20 | builtin_func::PyNativeFunction, | |
| 21 | + code::{IntoCodeObject, PyCode}, | ||
| 21 | 22 | descriptor::PyMethodDescriptor, | |
| 22 | 23 | tuple::{IntoPyTuple, PyTupleRef}, | |
| 23 | 24 | }, | |
@@ -311,6 +312,11 @@ impl VirtualMachine { | |||
| 311 | 312 | value.to_pyobject(self) | |
| 312 | 313 | } | |
| 313 | 314 | ||
| 315 | + pub fn new_code(&self, code: impl IntoCodeObject) -> PyRef<PyCode> { | ||
| 316 | + let code = code.into_code_object(self); | ||
| 317 | + PyRef::new_ref(PyCode::new(code), self.ctx.types.code_type.to_owned(), None) | ||
| 318 | + } | ||
| 319 | + | ||
| 314 | 320 | pub fn new_tuple(&self, value: impl IntoPyTuple) -> PyTupleRef { | |
| 315 | 321 | value.into_pytuple(self) | |
| 316 | 322 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -11,7 +11,7 @@ fn run(vm: &vm::VirtualMachine) -> vm::PyResult<()> { | |||
| 11 | 11 | // the file parameter is relative to the current file. | |
| 12 | 12 | let module = vm::py_compile!(file = "freeze.py"); | |
| 13 | 13 | ||
| 14 | - let res = vm.run_code_obj(vm.ctx.new_code(module), scope); | ||
| 14 | + let res = vm.run_code_obj(vm.new_code(module), scope); | ||
| 15 | 15 | ||
| 16 | 16 | if let Err(exc) = res { | |
| 17 | 17 | vm.print_exception(&exc); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -16,7 +16,7 @@ macro_rules! add_python_function { | |||
| 16 | 16 | // compile the code to bytecode | |
| 17 | 17 | let code = vm::py_compile!(source = $src); | |
| 18 | 18 | // convert the rustpython_compiler_core::CodeObject to a PyRef<PyCode> | |
| 19 | - let code = $vm.ctx.new_code(code); | ||
| 19 | + let code = $vm.new_code(code); | ||
| 20 | 20 | ||
| 21 | 21 | // run the python code in the scope to store the function | |
| 22 | 22 | $vm.run_code_obj(code, $scope.clone()) | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -143,7 +143,7 @@ __import__("io").TextIOWrapper( | |||
| 143 | 143 | mode = "eval" | |
| 144 | 144 | ); | |
| 145 | 145 | eprintln!("downloading get-pip.py..."); | |
| 146 | - let getpip_code = vm.run_code_obj(vm.ctx.new_code(get_getpip), vm.new_scope_with_builtins())?; | ||
| 146 | + let getpip_code = vm.run_code_obj(vm.new_code(get_getpip), vm.new_scope_with_builtins())?; | ||
| 147 | 147 | let getpip_code: rustpython_vm::builtins::PyStrRef = getpip_code | |
| 148 | 148 | .downcast() | |
| 149 | 149 | .expect("TextIOWrapper.read() should return str"); | |
| Back | FazBrowse Home | New Git URL |
0 commit comments