Skip to content

Commit

Permalink
Support associated constants
Browse files Browse the repository at this point in the history
  • Loading branch information
udoprog committed Oct 5, 2023
1 parent 7fd3cd6 commit 9c0c709
Show file tree
Hide file tree
Showing 4 changed files with 247 additions and 141 deletions.
99 changes: 58 additions & 41 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 @@ -741,23 +741,6 @@ impl Context {
.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.
Expand All @@ -771,35 +754,69 @@ impl Context {
.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.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()?,
},
item: item.map(|(_, item)| item),
kind,
#[cfg(feature = "doc")]
docs: assoc.docs.try_clone()?,
})?;
Expand Down
30 changes: 23 additions & 7 deletions crates/rune/src/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,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 @@ -205,26 +206,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: AssociatedName,
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
18 changes: 9 additions & 9 deletions crates/rune/src/module/function_meta.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,15 @@ impl Associated {
container_type_info: T::type_info(),
})
}

/// Get unique key for the associated item.
pub(crate) fn as_key(&self) -> alloc::Result<AssociatedKey> {
Ok(AssociatedKey {
type_hash: self.container.hash,
kind: self.name.kind.try_clone()?,
parameters: self.name.function_parameters,
})
}
}

/// Runtime data for an associated function.
Expand Down Expand Up @@ -337,15 +346,6 @@ impl AssociatedFunctionData {
argument_types: A::into_box()?,
})
}

/// Get associated key.
pub(crate) fn assoc_key(&self) -> alloc::Result<AssociatedKey> {
Ok(AssociatedKey {
type_hash: self.associated.container.hash,
kind: self.associated.name.kind.try_clone()?,
parameters: self.associated.name.function_parameters,
})
}
}

/// The kind of a [`FunctionMeta`].
Expand Down
Loading

0 comments on commit 9c0c709

Please sign in to comment.