Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ModuleFunctionBuilder #639

Merged
merged 6 commits into from
Oct 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions crates/rune-core/src/item/into_component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,41 @@ pub trait IntoComponent: Sized {
}
}

/// IntoCompoment implementation preserved for backwards compatibility.
impl<T> IntoComponent for [T; 1]
where
T: IntoComponent,
{
fn as_component_ref(&self) -> ComponentRef<'_> {
let [this] = self;
this.as_component_ref()
}

#[inline]
#[cfg(feature = "alloc")]
fn into_component(self) -> alloc::Result<Component> {
let [this] = self;
this.into_component()
}

#[inline]
#[doc(hidden)]
#[cfg(feature = "alloc")]
fn write_component<A: Allocator>(self, output: &mut Vec<u8, A>) -> alloc::Result<()> {
let [this] = self;
this.write_component(output)
}

#[inline]
fn hash_component<H>(self, hasher: &mut H)
where
H: hash::Hasher,
{
let [this] = self;
this.hash_component(hasher)
}
}

impl IntoComponent for ComponentRef<'_> {
#[inline]
fn as_component_ref(&self) -> ComponentRef<'_> {
Expand Down
21 changes: 4 additions & 17 deletions crates/rune-macros/src/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,10 +230,8 @@ impl Function {

let name_string = syn::LitStr::new(&self.sig.ident.to_string(), self.sig.ident.span());

let mut name;

if instance {
name = 'out: {
let name = if instance {
'out: {
syn::Expr::Lit(syn::ExprLit {
attrs: Vec::new(),
lit: syn::Lit::Str(match &attrs.path {
Expand All @@ -250,27 +248,16 @@ impl Function {
}
}),
})
};
}
} else {
name = match &attrs.path {
match &attrs.path {
Path::None => expr_lit(&self.sig.ident),
Path::Rename(last) => expr_lit(&last.ident),
Path::Protocol(protocol) => syn::Expr::Path(syn::ExprPath {
attrs: Vec::new(),
qself: None,
path: protocol.clone(),
}),
};

if attrs.self_type.is_none() {
let mut out = syn::ExprArray {
attrs: Vec::new(),
bracket_token: syn::token::Bracket::default(),
elems: Punctuated::default(),
};

out.elems.push(name);
name = syn::Expr::Array(out);
}
};

Expand Down
2 changes: 1 addition & 1 deletion crates/rune-modules/src/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ use rune::{Module, ContextError};
/// Construct the `fs` module.
pub fn module(_stdio: bool) -> Result<Module, ContextError> {
let mut module = Module::with_crate("fs")?;
module.function(["read_to_string"], read_to_string)?;
module.function("read_to_string", read_to_string).build()?;
Ok(module)
}

Expand Down
13 changes: 6 additions & 7 deletions crates/rune-modules/src/rand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,20 +40,19 @@ pub fn module(_stdio: bool) -> Result<Module, ContextError> {
let mut module = Module::with_crate("rand")?;

module.ty::<WyRand>()?;
module.function(["WyRand", "new"], WyRand::new)?;
module.function(["WyRand", "new_seed"], WyRand::new_seed)?;
module.function("new", WyRand::new).build_associated::<WyRand>()?;
module.function("new_seed", WyRand::new_seed).build_associated::<WyRand>()?;
module.associated_function("int", WyRand::int)?;
module.associated_function("int_range", WyRand::int_range)?;

module.ty::<Pcg64>()?;
module.function(["Pcg64", "new"], Pcg64::new)?;
module.function(["Pcg64", "new_seed"], Pcg64::new_seed)?;
module.function("new", Pcg64::new).build_associated::<Pcg64>()?;
module.function("new_seed", Pcg64::new_seed).build_associated::<Pcg64>()?;
module.associated_function("int", Pcg64::int)?;
module.associated_function("int_range", Pcg64::int_range)?;

module.function(["int"], int)?;
module.function(["int_range"], int_range)?;

module.function("int", int).build()?;
module.function("int_range", int_range).build()?;
Ok(module)
}

Expand Down
2 changes: 1 addition & 1 deletion crates/rune-wasm/src/http.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ pub fn module() -> Result<Module, ContextError> {
let mut module = Module::with_crate("http")?;
module.ty::<Response>()?;
module.ty::<Error>()?;
module.function(["get"], get)?;
module.function("get", get).build()?;
module.associated_function("text", Response::text)?;
Ok(module)
}
Expand Down
6 changes: 4 additions & 2 deletions crates/rune-wasm/src/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@ extern "C" {
pub fn module() -> Result<Module, ContextError> {
let mut module = Module::with_crate("time")?;
module.ty::<Duration>()?;
module.function(["Duration", "from_secs"], Duration::from_secs)?;
module.function(["delay_for"], delay_for)?;
module
.function("from_secs", Duration::from_secs)
.build_associated::<Duration>()?;
module.function("delay_for", delay_for).build()?;
Ok(module)
}

Expand Down
103 changes: 60 additions & 43 deletions crates/rune/src/compile/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ use crate::compile::MetaInfo;
use crate::compile::{ComponentRef, ContextError, IntoComponent, Item, ItemBuf, Names};
use crate::hash;
use crate::module::{
Fields, InternalEnum, Module, ModuleAssociated, ModuleAttributeMacro, ModuleConstant,
ModuleFunction, ModuleMacro, ModuleType, TypeSpecification,
Fields, InternalEnum, Module, ModuleAssociated, ModuleAssociatedKind, ModuleAttributeMacro,
ModuleConstant, ModuleFunction, ModuleMacro, ModuleType, TypeSpecification,
};
use crate::runtime::{
AttributeMacroHandler, ConstValue, FunctionHandler, MacroHandler, Protocol, RuntimeContext,
Expand Down Expand Up @@ -737,69 +737,86 @@ impl Context {
// should not be mixed in again.
let hash = assoc
.name
.associated
.kind
.hash(assoc.container.hash)
.with_function_parameters(assoc.name.function_parameters);

let signature = meta::Signature {
#[cfg(feature = "doc")]
is_async: assoc.is_async,
#[cfg(feature = "doc")]
deprecated: assoc.deprecated.try_clone()?,
#[cfg(feature = "doc")]
args: assoc.args,
#[cfg(feature = "doc")]
return_type: assoc.return_type.as_ref().map(|f| f.hash),
#[cfg(feature = "doc")]
argument_types: assoc
.argument_types
.iter()
.map(|f| f.as_ref().map(|f| f.hash))
.try_collect()?,
};

// If the associated function is a named instance function - register it
// under the name of the item it corresponds to unless it's a field
// function.
//
// The other alternatives are protocol functions (which are not free)
// and plain hashes.
let item = if let meta::AssociatedKind::Instance(name) = &assoc.name.associated {
let item = if let meta::AssociatedKind::Instance(name) = &assoc.name.kind {
let item = info.item.extended(name.as_ref())?;

let hash = Hash::type_hash(&item)
.with_type_parameters(info.type_parameters)
.with_function_parameters(assoc.name.function_parameters);

self.constants.try_insert(
Hash::associated_function(hash, Protocol::INTO_TYPE_NAME),
ConstValue::String(item.try_to_string()?),
)?;

self.insert_native_fn(hash, &assoc.handler)?;
Some(item)
Some((hash, item))
} else {
None
};

self.insert_native_fn(hash, &assoc.handler)?;
let kind = match &assoc.kind {
ModuleAssociatedKind::Constant(c) => {
if let Some((hash, ..)) = &item {
self.constants.try_insert(*hash, c.value.try_clone()?)?;
}

self.constants.try_insert(hash, c.value.try_clone()?)?;
meta::Kind::Const
}
ModuleAssociatedKind::Function(f) => {
let signature = meta::Signature {
#[cfg(feature = "doc")]
is_async: f.is_async,
#[cfg(feature = "doc")]
deprecated: assoc.deprecated.try_clone()?,
#[cfg(feature = "doc")]
args: f.args,
#[cfg(feature = "doc")]
return_type: f.return_type.as_ref().map(|f| f.hash),
#[cfg(feature = "doc")]
argument_types: f
.argument_types
.iter()
.map(|f| f.as_ref().map(|f| f.hash))
.try_collect()?,
};

if let Some((hash, item)) = &item {
self.constants.try_insert(
Hash::associated_function(*hash, Protocol::INTO_TYPE_NAME),
ConstValue::String(item.try_to_string()?),
)?;

self.insert_native_fn(*hash, &f.handler)?;
}

self.insert_native_fn(hash, &f.handler)?;

meta::Kind::Function {
associated: Some(assoc.name.kind.try_clone()?),
signature,
is_test: false,
is_bench: false,
parameters: Hash::EMPTY
.with_type_parameters(info.type_parameters)
.with_function_parameters(assoc.name.function_parameters),
#[cfg(feature = "doc")]
container: Some(assoc.container.hash),
#[cfg(feature = "doc")]
parameter_types: assoc.name.parameter_types.try_clone()?,
}
}
};

self.install_meta(ContextMeta {
hash,
item,
kind: meta::Kind::Function {
associated: Some(assoc.name.associated.try_clone()?),
signature,
is_test: false,
is_bench: false,
parameters: Hash::EMPTY
.with_type_parameters(info.type_parameters)
.with_function_parameters(assoc.name.function_parameters),
#[cfg(feature = "doc")]
container: Some(assoc.container.hash),
#[cfg(feature = "doc")]
parameter_types: assoc.name.parameter_types.try_clone()?,
},
item: item.map(|(_, item)| item),
kind,
#[cfg(feature = "doc")]
docs: assoc.docs.try_clone()?,
})?;
Expand Down
42 changes: 30 additions & 12 deletions crates/rune/src/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,16 @@ use crate::runtime::{
};
use crate::Hash;

pub(crate) use self::function_meta::{AssociatedFunctionName, ToFieldFunction, ToInstance};
pub(crate) use self::function_meta::{AssociatedName, ToFieldFunction, ToInstance};

#[doc(hidden)]
pub use self::function_meta::{FunctionMetaData, FunctionMetaKind, MacroMetaData, MacroMetaKind};
pub use self::function_traits::{Async, Function, FunctionKind, InstanceFunction, Plain};
#[doc(hidden)]
pub use self::module::{Module, ModuleMeta, ModuleMetaData};
pub use self::module::{
Module, ModuleConstantBuilder, ModuleFunctionBuilder, ModuleMeta, ModuleMetaData,
ModuleRawFunctionBuilder,
};

/// Trait to handle the installation of auxilliary functions for a type
/// installed into a module.
Expand Down Expand Up @@ -63,12 +66,11 @@ impl InternalEnum {
static_type: &'static StaticType,
) -> alloc::Result<Self>
where
N: IntoIterator,
N::Item: IntoComponent,
N: IntoComponent,
{
Ok(InternalEnum {
name,
base_type: ItemBuf::with_item(base_type)?,
base_type: ItemBuf::with_item([base_type])?,
static_type,
variants: Vec::new(),
docs: Docs::EMPTY,
Expand Down Expand Up @@ -195,6 +197,7 @@ pub(crate) struct AssociatedKey {
#[derive(TryClone)]
pub(crate) struct ModuleFunction {
pub(crate) item: ItemBuf,
pub(crate) docs: Docs,
pub(crate) handler: Arc<FunctionHandler>,
#[cfg(feature = "doc")]
pub(crate) is_async: bool,
Expand All @@ -206,26 +209,41 @@ pub(crate) struct ModuleFunction {
pub(crate) return_type: Option<FullTypeOf>,
#[cfg(feature = "doc")]
pub(crate) argument_types: Box<[Option<FullTypeOf>]>,
pub(crate) docs: Docs,
}

#[derive(TryClone)]
pub(crate) struct ModuleAssociated {
pub(crate) container: FullTypeOf,
pub(crate) container_type_info: TypeInfo,
pub(crate) name: AssociatedFunctionName,
pub(crate) struct ModuleAssociatedConstant {
pub(crate) value: ConstValue,
}

#[derive(TryClone)]
pub(crate) struct ModuleAssociatedFunction {
pub(crate) handler: Arc<FunctionHandler>,
#[cfg(feature = "doc")]
pub(crate) is_async: bool,
#[cfg(feature = "doc")]
pub(crate) deprecated: Option<Box<str>>,
#[cfg(feature = "doc")]
pub(crate) args: Option<usize>,
#[cfg(feature = "doc")]
pub(crate) return_type: Option<FullTypeOf>,
#[cfg(feature = "doc")]
pub(crate) argument_types: Box<[Option<FullTypeOf>]>,
}

#[derive(TryClone)]
pub(crate) enum ModuleAssociatedKind {
Constant(ModuleAssociatedConstant),
Function(ModuleAssociatedFunction),
}

#[derive(TryClone)]
pub(crate) struct ModuleAssociated {
pub(crate) container: FullTypeOf,
pub(crate) container_type_info: TypeInfo,
pub(crate) name: AssociatedName,
pub(crate) docs: Docs,
#[cfg(feature = "doc")]
pub(crate) deprecated: Option<Box<str>>,
pub(crate) kind: ModuleAssociatedKind,
}

/// Handle to a macro inserted into a module.
Expand Down
Loading