Skip to content

Commit

Permalink
Change function registration to use builders (#639)
Browse files Browse the repository at this point in the history
  • Loading branch information
udoprog authored Oct 5, 2023
1 parent d4be8dd commit d4f6774
Show file tree
Hide file tree
Showing 26 changed files with 919 additions and 342 deletions.
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

0 comments on commit d4f6774

Please sign in to comment.