Skip to content

Commit

Permalink
Rework how associated function meta is structured
Browse files Browse the repository at this point in the history
  • Loading branch information
udoprog committed May 10, 2023
1 parent 8029aca commit 9a7c5d4
Show file tree
Hide file tree
Showing 15 changed files with 304 additions and 407 deletions.
6 changes: 4 additions & 2 deletions crates/rune/src/cli/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,10 @@ pub(super) async fn run(
if args.dump_native_functions {
writeln!(io.stdout, "# functions")?;

for (i, (hash, f)) in context.iter_functions().enumerate() {
writeln!(io.stdout, "{:04} = {} ({})", i, f, hash)?;
for (i, (meta, _)) in context.iter_functions().enumerate() {
if let Some(item) = &meta.item {
writeln!(io.stdout, "{:04} = {} ({})", i, item, meta.hash)?;
}
}
}

Expand Down
132 changes: 49 additions & 83 deletions crates/rune/src/compile/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ use crate::compile::{
ComponentRef, ContextError, Docs, IntoComponent, Item, ItemBuf, MetaInfo, Names,
};
use crate::module::{
AssociatedKind, Fields, Function, InternalEnum, Module, ModuleAssociated, ModuleConstant,
ModuleFunction, ModuleMacro, ModuleType, TypeSpecification, UnitType,
Fields, Function, InternalEnum, Module, ModuleAssociated, ModuleConstant, ModuleFunction,
ModuleMacro, ModuleType, TypeSpecification, UnitType,
};
use crate::runtime::{
ConstValue, FunctionHandler, MacroHandler, Protocol, RuntimeContext, StaticType, TypeCheck,
Expand Down Expand Up @@ -80,14 +80,6 @@ impl fmt::Display for ContextType {
}
}

#[cfg(feature = "doc")]
pub(crate) enum ContextAssociated {
/// Associated self-receiver.
Associated(ModuleAssociated),
/// A simple module function.
Function(Hash),
}

/// [Context] used for the Rune language.
///
/// See [Build::with_context][crate::Build::with_context].
Expand Down Expand Up @@ -115,7 +107,7 @@ pub struct Context {
functions: HashMap<Hash, Arc<FunctionHandler>>,
/// Information on associated types.
#[cfg(feature = "doc")]
associated: HashMap<Hash, Vec<ContextAssociated>>,
associated: HashMap<Hash, Vec<Hash>>,
/// Registered native macro handlers.
macros: HashMap<Hash, Arc<MacroHandler>>,
/// Registered types.
Expand Down Expand Up @@ -264,10 +256,10 @@ impl Context {

/// Iterate over all available functions in the [Context].
#[cfg(feature = "cli")]
pub(crate) fn iter_functions(&self) -> impl Iterator<Item = (Hash, &meta::Signature)> {
pub(crate) fn iter_functions(&self) -> impl Iterator<Item = (&ContextMeta, &meta::Signature)> {
self.meta.iter().flat_map(|meta| {
let signature = meta.kind.as_signature()?;
Some((meta.hash, signature))
Some((meta, signature))
})
}

Expand Down Expand Up @@ -337,12 +329,13 @@ impl Context {

/// Get all associated types for the given hash.
#[cfg(feature = "doc")]
pub(crate) fn associated(&self, hash: Hash) -> impl Iterator<Item = &ContextAssociated> + '_ {
pub(crate) fn associated(&self, hash: Hash) -> impl Iterator<Item = Hash> + '_ {
self.associated
.get(&hash)
.map(Vec::as_slice)
.unwrap_or_default()
.iter()
.copied()
}

/// Lookup the given macro handler.
Expand Down Expand Up @@ -385,6 +378,21 @@ impl Context {
.insert(meta.hash);
}

#[cfg(feature = "doc")]
if let Some(h) = meta.associated_container {
let assoc = self.associated.entry(h).or_default();

match &meta.kind {
meta::Kind::Variant { .. } => {
assoc.push(meta.hash);
}
meta::Kind::Function { .. } => {
assoc.push(meta.hash);
}
_ => {}
}
}

let hash = meta.hash;
let index = self.meta.len();
self.meta.push(meta);
Expand Down Expand Up @@ -472,32 +480,28 @@ impl Context {

let constructor = if let (Some(c), Some(args)) = (constructor, args) {
let signature = meta::Signature {
item: item.clone(),
is_async: false,
args: Some(args),
return_type: Some(ty.hash),
argument_types: Box::from([]),
kind: meta::SignatureKind::Function,
};

self.insert_native_fn(hash, &signature, c)?;
self.insert_native_fn(hash, c)?;
Some(signature)
} else {
None
};

let kind = meta::Kind::Variant {
enum_hash: ty.hash,
index,
fields,
constructor,
};

self.install_meta(ContextMeta::new(
hash,
Some(ty.hash),
Some(item),
kind,
meta::Kind::Variant {
enum_hash: ty.hash,
index,
fields,
constructor,
},
variant.docs.clone(),
))?;
}
Expand Down Expand Up @@ -565,7 +569,6 @@ impl Context {
);

let signature = meta::Signature {
item: item.clone(),
is_async: f.is_async,
args: f.args,
return_type: f.return_type.as_ref().map(|f| f.hash),
Expand All @@ -574,35 +577,23 @@ impl Context {
.iter()
.map(|f| f.as_ref().map(|f| f.hash))
.collect(),
kind: meta::SignatureKind::Function,
};

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

self.install_meta(ContextMeta::new(
hash,
None,
f.associated_container,
Some(item),
meta::Kind::Function {
is_async: f.is_async,
args: f.args,
is_test: false,
is_bench: false,
instance_function: false,
signature: Some(signature),
signature,
parameters: Hash::EMPTY,
},
f.docs.clone(),
))?;

#[cfg(feature = "doc")]
if let Some(container_hash) = f.associated_container {
self.associated
.entry(container_hash)
.or_default()
.push(ContextAssociated::Function(hash));
}

Ok(())
}

Expand Down Expand Up @@ -660,7 +651,6 @@ impl Context {
.with_parameters(assoc.name.parameters);

let signature = meta::Signature {
item: info.item.clone(),
is_async: assoc.is_async,
args: assoc.args,
return_type: assoc.return_type.as_ref().map(|f| f.hash),
Expand All @@ -669,36 +659,24 @@ impl Context {
.iter()
.map(|f| f.as_ref().map(|f| f.hash))
.collect(),
kind: meta::SignatureKind::Instance {
name: assoc.name.kind.clone(),
self_type_info: info.type_info.clone(),
},
};

self.insert_native_fn(hash, &signature, &assoc.handler)?;
self.insert_native_fn(hash, &assoc.handler)?;

self.install_meta(ContextMeta::new(
hash,
Some(assoc.container.hash),
None,
meta::Kind::Function {
is_async: assoc.is_async,
args: assoc.args,
is_test: false,
is_bench: false,
instance_function: true,
signature: Some(signature),
meta::Kind::AssociatedFunction {
kind: assoc.name.kind.clone(),
signature,
parameters: assoc.name.parameters,
#[cfg(feature = "doc")]
parameter_types: assoc.name.parameter_types.clone(),
},
assoc.docs.clone(),
))?;

#[cfg(feature = "doc")]
self.associated
.entry(assoc.container.hash)
.or_default()
.push(ContextAssociated::Associated(assoc.clone()));

// These are currently only usable if parameters hash is empty.
if info.parameters_hash.is_empty() {
// If the associated function is a named instance function - register it
Expand All @@ -707,8 +685,8 @@ impl Context {
//
// The other alternatives are protocol functions (which are not free)
// and plain hashes.
if let AssociatedKind::Instance(name) = &assoc.name.kind {
let item = info.item.extended(name);
if let meta::AssociatedKind::Instance(name) = &assoc.name.kind {
let item = info.item.extended(name.as_ref());
let hash = Hash::type_hash(&item).with_parameters(assoc.name.parameters);

self.constants.insert(
Expand All @@ -717,7 +695,6 @@ impl Context {
);

let signature = meta::Signature {
item: item.clone(),
is_async: assoc.is_async,
args: assoc.args,
return_type: assoc.return_type.as_ref().map(|f| f.hash),
Expand All @@ -726,23 +703,20 @@ impl Context {
.iter()
.map(|f| f.as_ref().map(|f| f.hash))
.collect(),
kind: meta::SignatureKind::Function,
};

self.insert_native_fn(hash, &signature, &assoc.handler)?;
self.insert_native_fn(hash, &assoc.handler)?;

self.install_meta(ContextMeta::new(
hash,
Some(assoc.container.hash),
Some(item),
meta::Kind::Function {
is_async: assoc.is_async,
args: assoc.args,
is_test: false,
is_bench: false,
instance_function: true,
signature: Some(signature),
meta::Kind::AssociatedFunction {
kind: assoc.name.kind.clone(),
signature,
parameters: assoc.name.parameters,
#[cfg(feature = "doc")]
parameter_types: assoc.name.parameter_types.clone(),
},
assoc.docs.clone(),
))?;
Expand Down Expand Up @@ -818,15 +792,13 @@ impl Context {
})?;

let signature = meta::Signature {
item: item.clone(),
is_async: false,
args: Some(variant.args),
return_type: Some(enum_hash),
argument_types: Box::from([]),
kind: meta::SignatureKind::Function,
};

self.insert_native_fn(hash, &signature, &variant.constructor)?;
self.insert_native_fn(hash, &variant.constructor)?;

self.install_meta(ContextMeta::new(
hash,
Expand All @@ -848,14 +820,10 @@ impl Context {
fn insert_native_fn(
&mut self,
hash: Hash,
signature: &meta::Signature,
handler: &Arc<FunctionHandler>,
) -> Result<(), ContextError> {
if self.functions.contains_key(&hash) {
return Err(ContextError::ConflictingFunction {
signature: Box::new(signature.clone()),
hash,
});
return Err(ContextError::ConflictingFunction { hash });
}

self.functions.insert(hash, handler.clone());
Expand All @@ -879,18 +847,16 @@ impl Context {
let hash = Hash::type_hash(&item);

let signature = meta::Signature {
item: item.clone(),
is_async: false,
args: Some(args),
return_type: Some(type_hash),
argument_types: Box::from([]),
kind: meta::SignatureKind::Function,
};

let handler: Arc<FunctionHandler> =
Arc::new(move |stack, args| constructor.fn_call(stack, args));

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

let (associated_container, kind) = match enum_item {
Some((enum_hash, index)) => (
Expand Down
8 changes: 2 additions & 6 deletions crates/rune/src/compile/context_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ use crate::no_std::thiserror;

use thiserror::Error;

use crate::compile::meta;
use crate::compile::ItemBuf;
use crate::runtime::{TypeInfo, VmError};
use crate::Hash;
Expand All @@ -18,11 +17,8 @@ pub enum ContextError {
UnitAlreadyPresent,
#[error("Type for name `{name}` is already present")]
InternalAlreadyPresent { name: &'static str },
#[error("Function `{signature}` ({hash}) already exists")]
ConflictingFunction {
signature: Box<meta::Signature>,
hash: Hash,
},
#[error("Function with hash `{hash}` already exists")]
ConflictingFunction { hash: Hash },
#[error("Function `{item}` already exists with hash `{hash}`")]
ConflictingFunctionName { item: ItemBuf, hash: Hash },
#[error("Macro `{item}` already exists with hash `{hash}`")]
Expand Down
Loading

0 comments on commit 9a7c5d4

Please sign in to comment.