Skip to content

Commit 5b32064

Browse files
committed
trait StaticType
1 parent 91eb4d4 commit 5b32064

File tree

13 files changed

+460
-356
lines changed

13 files changed

+460
-356
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

common/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ pub mod float_ops;
55
pub mod hash;
66
pub mod lock;
77
pub mod rc;
8+
pub mod static_cell;
89
pub mod str;

common/src/static_cell.rs

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
#[cfg(not(feature = "threading"))]
2+
mod non_threading {
3+
use crate::lock::OnceCell;
4+
pub type StaticCell<T> = std::thread::LocalKey<OnceCell<&'static T>>;
5+
6+
#[macro_export]
7+
macro_rules! static_cells {
8+
// process multiple declarations
9+
($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty;) => (
10+
std::thread_local! {
11+
$(#[$attr])* $vis static $name: $crate::lock::OnceCell<&'static $t> = $crate::lock::OnceCell::new();
12+
}
13+
);
14+
}
15+
}
16+
#[cfg(not(feature = "threading"))]
17+
pub use non_threading::*;
18+
19+
#[cfg(feature = "threading")]
20+
mod threading {
21+
use crate::lock::OnceCell;
22+
23+
pub struct StaticKey<T> {
24+
inner: T,
25+
}
26+
27+
impl<T> StaticKey<T> {
28+
pub const fn new(inner: T) -> Self {
29+
Self { inner }
30+
}
31+
32+
pub fn with<F, R>(&self, f: F) -> R
33+
where
34+
F: FnOnce(&T) -> R,
35+
{
36+
f(&self.inner)
37+
}
38+
}
39+
40+
pub type StaticCell<T> = StaticKey<OnceCell<&'static T>>;
41+
42+
#[macro_export]
43+
macro_rules! static_cells {
44+
// process multiple declarations
45+
($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty;) => (
46+
$(#[$attr])* $vis static $name: $crate::static_cell::StaticKey<$crate::lock::OnceCell<&'static $t>> = $crate::static_cell::StaticKey::new($crate::lock::OnceCell::new());
47+
);
48+
}
49+
}
50+
#[cfg(feature = "threading")]
51+
pub use threading::*;
52+
53+
pub fn get<T>(cell: &'static StaticCell<T>) -> Option<&'static T> {
54+
cell.with(|cell| cell.get().copied())
55+
}
56+
57+
pub fn init_expect<T>(cell: &'static StaticCell<T>, value: T, msg: &'static str) -> &'static T {
58+
cell.with(|cell| {
59+
let static_ref = Box::leak(Box::new(value)) as &_;
60+
cell.set(static_ref)
61+
.unwrap_or_else(|_| panic!("double initializing '{}'", msg));
62+
static_ref
63+
})
64+
}
65+
66+
pub fn get_or_init<T, F>(cell: &'static StaticCell<T>, f: F) -> &'static T
67+
where
68+
F: FnOnce() -> T,
69+
{
70+
cell.with(|cell| {
71+
*cell.get_or_init(|| {
72+
let value = f();
73+
Box::leak(Box::new(value))
74+
})
75+
})
76+
}

derive/src/pyclass.rs

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ fn generate_class_def(
133133
ident: &Ident,
134134
name: &str,
135135
module_name: Option<&str>,
136+
base: Option<String>,
136137
attrs: &[Attribute],
137138
) -> std::result::Result<TokenStream, Diagnostic> {
138139
let doc = if let Some(doc) = attrs.doc() {
@@ -159,11 +160,27 @@ fn generate_class_def(
159160
false
160161
}
161162
});
163+
if base.is_some() && is_pystruct {
164+
return Err(syn::Error::new_spanned(
165+
ident,
166+
"PyStructSequence cannot have `base` class attr",
167+
)
168+
.into());
169+
}
170+
let base = base.map(|name| Ident::new(&name, ident.span()));
162171

163172
let base_class = if is_pystruct {
164173
quote! {
165-
fn base_class(ctx: &::rustpython_vm::pyobject::PyContext) -> ::rustpython_vm::builtins::PyTypeRef {
166-
ctx.types.tuple_type.clone()
174+
fn static_baseclass() -> &'static ::rustpython_vm::builtins::PyTypeRef {
175+
use rustpython_vm::pyobject::StaticType;
176+
rustpython_vm::builtins::PyTuple::static_type()
177+
}
178+
}
179+
} else if let Some(base) = base {
180+
quote! {
181+
fn static_baseclass() -> &'static ::rustpython_vm::builtins::PyTypeRef {
182+
use rustpython_vm::pyobject::StaticType;
183+
#base::static_type()
167184
}
168185
}
169186
} else {
@@ -176,6 +193,17 @@ fn generate_class_def(
176193
const MODULE_NAME: Option<&'static str> = #module_name;
177194
const TP_NAME: &'static str = #module_class_name;
178195
const DOC: Option<&'static str> = #doc;
196+
}
197+
198+
impl ::rustpython_vm::pyobject::StaticType for #ident {
199+
fn static_cell() -> &'static ::rustpython_common::static_cell::StaticCell<::rustpython_vm::builtins::PyTypeRef> {
200+
use ::rustpython_common::static_cells;
201+
static_cells! {
202+
static CELL: ::rustpython_vm::builtins::PyTypeRef;
203+
}
204+
&CELL
205+
}
206+
179207
#base_class
180208
}
181209
};
@@ -191,7 +219,8 @@ pub(crate) fn impl_pyclass(
191219
let class_meta = ClassItemMeta::from_nested(ident.clone(), fake_ident, attr.into_iter())?;
192220
let class_name = class_meta.class_name()?;
193221
let module_name = class_meta.module()?;
194-
let class_def = generate_class_def(&ident, &class_name, module_name.as_deref(), &attrs)?;
222+
let base = class_meta.base()?;
223+
let class_def = generate_class_def(&ident, &class_name, module_name.as_deref(), base, &attrs)?;
195224

196225
let ret = quote! {
197226
#item

derive/src/util.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ impl ItemMeta for SimpleItemMeta {
233233
pub(crate) struct ClassItemMeta(ItemMetaInner);
234234

235235
impl ItemMeta for ClassItemMeta {
236-
const ALLOWED_NAMES: &'static [&'static str] = &["module", "name"];
236+
const ALLOWED_NAMES: &'static [&'static str] = &["module", "name", "base"];
237237

238238
fn from_inner(inner: ItemMetaInner) -> Self {
239239
Self(inner)
@@ -268,6 +268,10 @@ impl ClassItemMeta {
268268
Ok(value)
269269
}
270270

271+
pub fn base(&self) -> Result<Option<String>> {
272+
self.inner()._optional_str("base")
273+
}
274+
271275
pub fn module(&self) -> Result<Option<String>> {
272276
const KEY: &str = "module";
273277
let inner = self.inner();

vm/src/builtins/code.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ impl PyValue for PyCode {
4242
}
4343
}
4444

45+
#[pyimpl(with(PyRef))]
46+
impl PyCode {}
47+
4548
#[pyimpl]
4649
impl PyCodeRef {
4750
#[pyslot]

vm/src/builtins/frame.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,17 @@
55
use super::code::PyCodeRef;
66
use super::dict::PyDictRef;
77
use super::pystr::PyStrRef;
8-
use crate::frame::FrameRef;
9-
use crate::pyobject::{IdProtocol, PyClassImpl, PyContext, PyObjectRef, PyResult};
8+
use crate::frame::{Frame, FrameRef};
9+
use crate::pyobject::{IdProtocol, PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult};
1010
use crate::vm::VirtualMachine;
1111

1212
pub fn init(context: &PyContext) {
1313
FrameRef::extend_class(context, &context.types.frame_type);
1414
}
1515

16+
#[pyimpl(with(PyRef))]
17+
impl Frame {}
18+
1619
#[pyimpl]
1720
impl FrameRef {
1821
#[pyslot]

vm/src/builtins/pybool.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ pub fn boolval(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult<bool> {
7676
/// Returns True when the argument x is true, False otherwise.
7777
/// The builtins True and False are the only two instances of the class bool.
7878
/// The class bool is a subclass of the class int, and cannot be subclassed.
79-
#[pyclass(name = "bool", module = false)]
79+
#[pyclass(name = "bool", module = false, base = "PyInt")]
8080
pub struct PyBool;
8181

8282
#[pyimpl]

0 commit comments

Comments
 (0)