Skip to content

Commit

Permalink
Merge pull request #2238 from youknowone/static-type
Browse files Browse the repository at this point in the history
Trait for static type
  • Loading branch information
youknowone committed Oct 20, 2020
2 parents efa809b + 0c505f9 commit 2ebec89
Show file tree
Hide file tree
Showing 77 changed files with 849 additions and 749 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions common/src/lib.rs
Expand Up @@ -5,4 +5,5 @@ pub mod float_ops;
pub mod hash;
pub mod lock;
pub mod rc;
pub mod static_cell;
pub mod str;
76 changes: 76 additions & 0 deletions common/src/static_cell.rs
@@ -0,0 +1,76 @@
#[cfg(not(feature = "threading"))]
mod non_threading {
use crate::lock::OnceCell;
pub type StaticCell<T> = std::thread::LocalKey<OnceCell<&'static T>>;

#[macro_export]
macro_rules! static_cells {
// process multiple declarations
($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty;) => (
std::thread_local! {
$(#[$attr])* $vis static $name: $crate::lock::OnceCell<&'static $t> = $crate::lock::OnceCell::new();
}
);
}
}
#[cfg(not(feature = "threading"))]
pub use non_threading::*;

#[cfg(feature = "threading")]
mod threading {
use crate::lock::OnceCell;

pub struct StaticKey<T> {
inner: T,
}

impl<T> StaticKey<T> {
pub const fn new(inner: T) -> Self {
Self { inner }
}

pub fn with<F, R>(&self, f: F) -> R
where
F: FnOnce(&T) -> R,
{
f(&self.inner)
}
}

pub type StaticCell<T> = StaticKey<OnceCell<&'static T>>;

#[macro_export]
macro_rules! static_cells {
// process multiple declarations
($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty;) => (
$(#[$attr])* $vis static $name: $crate::static_cell::StaticKey<$crate::lock::OnceCell<&'static $t>> = $crate::static_cell::StaticKey::new($crate::lock::OnceCell::new());
);
}
}
#[cfg(feature = "threading")]
pub use threading::*;

pub fn get<T>(cell: &'static StaticCell<T>) -> Option<&'static T> {
cell.with(|cell| cell.get().copied())
}

pub fn init_expect<T>(cell: &'static StaticCell<T>, value: T, msg: &'static str) -> &'static T {
cell.with(|cell| {
let static_ref = Box::leak(Box::new(value)) as &_;
cell.set(static_ref)
.unwrap_or_else(|_| panic!("double initializing '{}'", msg));
static_ref
})
}

pub fn get_or_init<T, F>(cell: &'static StaticCell<T>, f: F) -> &'static T
where
F: FnOnce() -> T,
{
cell.with(|cell| {
*cell.get_or_init(|| {
let value = f();
Box::leak(Box::new(value))
})
})
}
1 change: 1 addition & 0 deletions derive/Cargo.toml
Expand Up @@ -20,3 +20,4 @@ rustpython-bytecode = { path = "../bytecode", version = "0.1.1" }
maplit = "1.0"
once_cell = "1.3.1"
textwrap = "0.12.1"
indexmap = "^1"
35 changes: 32 additions & 3 deletions derive/src/pyclass.rs
Expand Up @@ -133,6 +133,7 @@ fn generate_class_def(
ident: &Ident,
name: &str,
module_name: Option<&str>,
base: Option<String>,
attrs: &[Attribute],
) -> std::result::Result<TokenStream, Diagnostic> {
let doc = if let Some(doc) = attrs.doc() {
Expand All @@ -159,11 +160,27 @@ fn generate_class_def(
false
}
});
if base.is_some() && is_pystruct {
return Err(syn::Error::new_spanned(
ident,
"PyStructSequence cannot have `base` class attr",
)
.into());
}
let base = base.map(|name| Ident::new(&name, ident.span()));

let base_class = if is_pystruct {
quote! {
fn base_class(ctx: &::rustpython_vm::pyobject::PyContext) -> ::rustpython_vm::builtins::PyTypeRef {
ctx.types.tuple_type.clone()
fn static_baseclass() -> &'static ::rustpython_vm::builtins::PyTypeRef {
use rustpython_vm::pyobject::StaticType;
rustpython_vm::builtins::PyTuple::static_type()
}
}
} else if let Some(base) = base {
quote! {
fn static_baseclass() -> &'static ::rustpython_vm::builtins::PyTypeRef {
use rustpython_vm::pyobject::StaticType;
#base::static_type()
}
}
} else {
Expand All @@ -176,6 +193,17 @@ fn generate_class_def(
const MODULE_NAME: Option<&'static str> = #module_name;
const TP_NAME: &'static str = #module_class_name;
const DOC: Option<&'static str> = #doc;
}

impl ::rustpython_vm::pyobject::StaticType for #ident {
fn static_cell() -> &'static ::rustpython_common::static_cell::StaticCell<::rustpython_vm::builtins::PyTypeRef> {
use ::rustpython_common::static_cells;
static_cells! {
static CELL: ::rustpython_vm::builtins::PyTypeRef;
}
&CELL
}

#base_class
}
};
Expand All @@ -191,7 +219,8 @@ pub(crate) fn impl_pyclass(
let class_meta = ClassItemMeta::from_nested(ident.clone(), fake_ident, attr.into_iter())?;
let class_name = class_meta.class_name()?;
let module_name = class_meta.module()?;
let class_def = generate_class_def(&ident, &class_name, module_name.as_deref(), &attrs)?;
let base = class_meta.base()?;
let class_def = generate_class_def(&ident, &class_name, module_name.as_deref(), base, &attrs)?;

let ret = quote! {
#item
Expand Down
13 changes: 9 additions & 4 deletions derive/src/util.rs
@@ -1,3 +1,4 @@
use indexmap::map::IndexMap;
use proc_macro2::{Span, TokenStream};
use quote::{quote, ToTokens};
use std::collections::HashMap;
Expand All @@ -18,7 +19,7 @@ pub(crate) const ALL_ALLOWED_NAMES: &[&str] = &[
];

#[derive(Default)]
pub(crate) struct ItemNursery(HashMap<(String, Vec<Attribute>), TokenStream>);
pub(crate) struct ItemNursery(IndexMap<(String, Vec<Attribute>), TokenStream>);

impl ItemNursery {
pub fn add_item(
Expand All @@ -27,10 +28,10 @@ impl ItemNursery {
cfgs: Vec<Attribute>,
tokens: TokenStream,
) -> Result<()> {
if let Some(existing) = self.0.insert((name, cfgs), tokens) {
if let Some(existing) = self.0.insert((name.clone(), cfgs), tokens) {
Err(syn::Error::new_spanned(
existing,
"Duplicated #[py*] attribute found",
format!("Duplicated #[py*] attribute found for '{}'", name),
))
} else {
Ok(())
Expand Down Expand Up @@ -232,7 +233,7 @@ impl ItemMeta for SimpleItemMeta {
pub(crate) struct ClassItemMeta(ItemMetaInner);

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

fn from_inner(inner: ItemMetaInner) -> Self {
Self(inner)
Expand Down Expand Up @@ -267,6 +268,10 @@ impl ClassItemMeta {
Ok(value)
}

pub fn base(&self) -> Result<Option<String>> {
self.inner()._optional_str("base")
}

pub fn module(&self) -> Result<Option<String>> {
const KEY: &str = "module";
let inner = self.inner();
Expand Down
16 changes: 8 additions & 8 deletions vm/src/builtins/asyncgenerator.rs
Expand Up @@ -20,8 +20,8 @@ pub struct PyAsyncGen {
type PyAsyncGenRef = PyRef<PyAsyncGen>;

impl PyValue for PyAsyncGen {
fn class(vm: &VirtualMachine) -> PyTypeRef {
vm.ctx.types.async_generator.clone()
fn class(vm: &VirtualMachine) -> &PyTypeRef {
&vm.ctx.types.async_generator
}
}

Expand Down Expand Up @@ -118,8 +118,8 @@ impl PyAsyncGen {
#[derive(Debug)]
pub(crate) struct PyAsyncGenWrappedValue(pub PyObjectRef);
impl PyValue for PyAsyncGenWrappedValue {
fn class(vm: &VirtualMachine) -> PyTypeRef {
vm.ctx.types.async_generator_wrapped_value.clone()
fn class(vm: &VirtualMachine) -> &PyTypeRef {
&vm.ctx.types.async_generator_wrapped_value
}
}

Expand Down Expand Up @@ -167,8 +167,8 @@ pub(crate) struct PyAsyncGenASend {
}

impl PyValue for PyAsyncGenASend {
fn class(vm: &VirtualMachine) -> PyTypeRef {
vm.ctx.types.async_generator_asend.clone()
fn class(vm: &VirtualMachine) -> &PyTypeRef {
&vm.ctx.types.async_generator_asend
}
}

Expand Down Expand Up @@ -263,8 +263,8 @@ pub(crate) struct PyAsyncGenAThrow {
}

impl PyValue for PyAsyncGenAThrow {
fn class(vm: &VirtualMachine) -> PyTypeRef {
vm.ctx.types.async_generator_athrow.clone()
fn class(vm: &VirtualMachine) -> &PyTypeRef {
&vm.ctx.types.async_generator_athrow
}
}

Expand Down
8 changes: 4 additions & 4 deletions vm/src/builtins/builtinfunc.rs
Expand Up @@ -63,8 +63,8 @@ pub struct PyBuiltinFunction {
}

impl PyValue for PyBuiltinFunction {
fn class(vm: &VirtualMachine) -> PyTypeRef {
vm.ctx.types.builtin_function_or_method_type.clone()
fn class(vm: &VirtualMachine) -> &PyTypeRef {
&vm.ctx.types.builtin_function_or_method_type
}
}

Expand Down Expand Up @@ -139,8 +139,8 @@ pub struct PyBuiltinMethod {
}

impl PyValue for PyBuiltinMethod {
fn class(vm: &VirtualMachine) -> PyTypeRef {
vm.ctx.types.method_descriptor_type.clone()
fn class(vm: &VirtualMachine) -> &PyTypeRef {
&vm.ctx.types.method_descriptor_type
}
}

Expand Down
10 changes: 5 additions & 5 deletions vm/src/builtins/bytearray.rs
Expand Up @@ -83,8 +83,8 @@ impl From<Vec<u8>> for PyByteArray {
}

impl PyValue for PyByteArray {
fn class(vm: &VirtualMachine) -> PyTypeRef {
vm.ctx.types.bytearray_type.clone()
fn class(vm: &VirtualMachine) -> &PyTypeRef {
&vm.ctx.types.bytearray_type
}
}

Expand Down Expand Up @@ -562,7 +562,7 @@ impl PyByteArray {
fn reduce(zelf: PyRef<Self>, vm: &VirtualMachine) -> (PyTypeRef, PyTupleRef) {
let bytes = PyBytes::from(zelf.borrow_value().elements.clone()).into_pyobject(vm);
(
Self::class(vm),
Self::class(vm).clone(),
PyTupleRef::with_elements(vec![bytes], &vm.ctx),
)
}
Expand Down Expand Up @@ -650,8 +650,8 @@ pub struct PyByteArrayIterator {
}

impl PyValue for PyByteArrayIterator {
fn class(vm: &VirtualMachine) -> PyTypeRef {
vm.ctx.types.bytearray_iterator_type.clone()
fn class(vm: &VirtualMachine) -> &PyTypeRef {
&vm.ctx.types.bytearray_iterator_type
}
}

Expand Down
8 changes: 4 additions & 4 deletions vm/src/builtins/bytes.rs
Expand Up @@ -89,8 +89,8 @@ impl Deref for PyBytes {
}

impl PyValue for PyBytes {
fn class(vm: &VirtualMachine) -> PyTypeRef {
vm.ctx.types.bytes_type.clone()
fn class(vm: &VirtualMachine) -> &PyTypeRef {
&vm.ctx.types.bytes_type
}
}

Expand Down Expand Up @@ -537,8 +537,8 @@ pub struct PyBytesIterator {
}

impl PyValue for PyBytesIterator {
fn class(vm: &VirtualMachine) -> PyTypeRef {
vm.ctx.types.bytes_iterator_type.clone()
fn class(vm: &VirtualMachine) -> &PyTypeRef {
&vm.ctx.types.bytes_iterator_type
}
}

Expand Down
4 changes: 2 additions & 2 deletions vm/src/builtins/classmethod.rs
Expand Up @@ -38,8 +38,8 @@ impl From<PyObjectRef> for PyClassMethod {
}

impl PyValue for PyClassMethod {
fn class(vm: &VirtualMachine) -> PyTypeRef {
vm.ctx.types.classmethod_type.clone()
fn class(vm: &VirtualMachine) -> &PyTypeRef {
&vm.ctx.types.classmethod_type
}
}

Expand Down
7 changes: 5 additions & 2 deletions vm/src/builtins/code.rs
Expand Up @@ -37,11 +37,14 @@ impl fmt::Debug for PyCode {
}

impl PyValue for PyCode {
fn class(vm: &VirtualMachine) -> PyTypeRef {
vm.ctx.types.code_type.clone()
fn class(vm: &VirtualMachine) -> &PyTypeRef {
&vm.ctx.types.code_type
}
}

#[pyimpl(with(PyRef))]
impl PyCode {}

#[pyimpl]
impl PyCodeRef {
#[pyslot]
Expand Down
4 changes: 2 additions & 2 deletions vm/src/builtins/complex.rs
Expand Up @@ -22,8 +22,8 @@ pub struct PyComplex {
}

impl PyValue for PyComplex {
fn class(vm: &VirtualMachine) -> PyTypeRef {
vm.ctx.types.complex_type.clone()
fn class(vm: &VirtualMachine) -> &PyTypeRef {
&vm.ctx.types.complex_type
}
}

Expand Down
8 changes: 4 additions & 4 deletions vm/src/builtins/coroutine.rs
Expand Up @@ -16,8 +16,8 @@ pub struct PyCoroutine {
}

impl PyValue for PyCoroutine {
fn class(vm: &VirtualMachine) -> PyTypeRef {
vm.ctx.types.coroutine_type.clone()
fn class(vm: &VirtualMachine) -> &PyTypeRef {
&vm.ctx.types.coroutine_type
}
}

Expand Down Expand Up @@ -102,8 +102,8 @@ pub struct PyCoroutineWrapper {
}

impl PyValue for PyCoroutineWrapper {
fn class(vm: &VirtualMachine) -> PyTypeRef {
vm.ctx.types.coroutine_wrapper_type.clone()
fn class(vm: &VirtualMachine) -> &PyTypeRef {
&vm.ctx.types.coroutine_wrapper_type
}
}

Expand Down

0 comments on commit 2ebec89

Please sign in to comment.