Skip to content

Commit

Permalink
Lookup generic parameters by hash
Browse files Browse the repository at this point in the history
  • Loading branch information
udoprog committed Apr 4, 2023
1 parent fc6a0b5 commit 96c64e8
Show file tree
Hide file tree
Showing 18 changed files with 181 additions and 126 deletions.
1 change: 1 addition & 0 deletions benches/benches/primes.rn
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const MAX_NUMBER_TO_CHECK = 1000;

/// Find prime numbers.
#[bench]
fn find_primes(b) {
let prime_mask = [];
Expand Down
5 changes: 1 addition & 4 deletions crates/rune-macros/src/any.rs
Original file line number Diff line number Diff line change
Expand Up @@ -444,10 +444,7 @@ where

#[inline]
fn type_info() -> #type_info {
#type_info::Any(#any_type_info::new(
#raw_str::from_str(std::any::type_name::<Self>()),
<Self as #any>::type_hash()
))
#type_info::Any(#any_type_info::new(#raw_str::from_str(std::any::type_name::<Self>())))
}
}

Expand Down
5 changes: 4 additions & 1 deletion crates/rune/src/compile/compile_visitor.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::ast::Span;
use crate::compile::{Item, Location, MetaRef};
use crate::hash::Hash;
use crate::SourceId;

/// A visitor that will be called for every language item compiled.
Expand All @@ -24,7 +25,8 @@ pub trait CompileVisitor {
///
/// This can be called in any order, before or after
/// [CompileVisitor::visit_meta] for any given item.
fn visit_doc_comment(&mut self, _location: Location, _item: &Item, _docstr: &str) {}
fn visit_doc_comment(&mut self, _location: Location, _item: &Item, _hash: Hash, _docstr: &str) {
}

/// Visit anterior `///`-style comments, and interior `//!`-style doc
/// comments for a field contained in a struct / enum variant struct.
Expand All @@ -35,6 +37,7 @@ pub trait CompileVisitor {
&mut self,
_location: Location,
_item: &Item,
_hash: Hash,
_field: &str,
_docstr: &str,
) {
Expand Down
20 changes: 12 additions & 8 deletions crates/rune/src/compile/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,9 @@ pub struct Context {
/// Whether or not to include the prelude when constructing a new unit.
has_default_modules: bool,
/// Item metadata in the context.
meta: HashMap<ItemBuf, PrivMeta>,
meta: HashMap<Hash, PrivMeta>,
/// Store item to hash mapping.
item_to_hash: HashMap<ItemBuf, Hash>,
/// Information on functions.
functions_info: HashMap<Hash, meta::Signature>,
/// Registered native function handlers.
Expand Down Expand Up @@ -283,13 +285,14 @@ impl Context {
}

/// Access the context meta for the given item.
pub(crate) fn lookup_meta(&self, name: &Item) -> Option<&PrivMeta> {
self.meta.get(name)
pub(crate) fn lookup_meta(&self, item: &Item) -> Option<&PrivMeta> {
let hash = self.item_to_hash.get(item)?;
self.meta.get(hash)
}

/// Lookup meta by its hash.
pub(crate) fn lookup_meta_by_hash(&self, hash: Hash) -> Option<&PrivMeta> {
todo!()
self.meta.get(&hash)
}

/// Look up signature of function.
Expand All @@ -299,8 +302,8 @@ impl Context {
}

/// Iterate over all metadata in the context.
pub fn iter_meta(&self) -> impl Iterator<Item = (&Item, &PrivMeta)> + '_ {
self.meta.iter().map(|(item, meta)| (item.as_ref(), meta))
pub fn iter_meta(&self) -> impl Iterator<Item = &PrivMeta> + '_ {
self.meta.values()
}

/// Check if unit contains the given name by prefix.
Expand Down Expand Up @@ -348,14 +351,15 @@ impl Context {

/// Install the given meta.
fn install_meta(&mut self, meta: PrivMeta) -> Result<(), ContextError> {
match self.meta.entry(meta.item.clone()) {
match self.meta.entry(meta.hash) {
hash_map::Entry::Occupied(e) => {
return Err(ContextError::ConflictingMeta {
existing: Box::new(e.get().info()),
current: Box::new(meta.info()),
});
}
hash_map::Entry::Vacant(e) => {
self.item_to_hash.insert(meta.item.clone(), meta.hash);
e.insert(meta);
}
}
Expand Down Expand Up @@ -674,7 +678,7 @@ impl Context {

self.functions.insert(hash, assoc.handler.clone());

if !self.meta.contains_key(&item) {
if !self.item_to_hash.contains_key(&item) {
self.install_meta(PrivMeta::new(
module,
type_hash,
Expand Down
6 changes: 6 additions & 0 deletions crates/rune/src/compile/pool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,12 @@ impl Pool {
self.item(id)
}

/// Get the hash associated with a module item.
pub(crate) fn module_item_hash(&self, id: ModId) -> Hash {
let id = self.module(id).item;
self.item_type_hash(id)
}

/// Get by item id.
pub(crate) fn module_by_item(&self, id: ItemId) -> Option<&ModMeta> {
Some(self.module(*self.item_to_mod.get(&id)?))
Expand Down
1 change: 1 addition & 0 deletions crates/rune/src/doc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ pub use self::html::write_html;

mod visitor;
pub use self::visitor::Visitor;
pub(crate) use self::visitor::VisitorData;
36 changes: 19 additions & 17 deletions crates/rune/src/doc/context.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
use crate::compile::context::PrivMeta;
use crate::compile::meta;
use crate::compile::{AssociatedFunction, ComponentRef, IntoComponent, Item};
use crate::doc::Visitor;
use crate::doc::{Visitor, VisitorData};
use crate::runtime::ConstValue;
use crate::Hash;

#[derive(Debug, Clone, Copy)]
pub(crate) struct Meta<'a> {
/// Item of the meta.
pub(crate) item: &'a Item,
/// Type hash for the meta item.
pub(crate) hash: Hash,
/// Kind of the meta item.
Expand Down Expand Up @@ -76,25 +78,25 @@ impl<'a> Context<'a> {
/// Get a meta item by its hash.
pub(crate) fn meta_by_hash(&self, hash: Hash) -> Option<Meta<'_>> {
for visitor in self.visitors {
if let Some(m) = visitor.get_by_hash(hash) {
return Some(visitor_meta_to_meta(m, visitor, hash));
if let Some(data) = visitor.get_by_hash(hash) {
return Some(visitor_meta_to_meta(data));
}
}

let meta = self.context.lookup_meta_by_hash(hash)?;
Some(self.context_meta_to_meta(meta)?)
self.context_meta_to_meta(meta)
}

/// Lookup Meta.
pub(crate) fn meta(&self, item: &Item) -> Option<Meta<'_>> {
for visitor in self.visitors {
if let Some((hash, m)) = visitor.get(item) {
return Some(visitor_meta_to_meta(m, visitor, hash));
if let Some(data) = visitor.get(item) {
return Some(visitor_meta_to_meta(data));
}
}

let meta = self.context.lookup_meta(item)?;
Some(self.context_meta_to_meta(meta)?)
self.context_meta_to_meta(meta)
}

fn context_meta_to_meta(&self, meta: &'a PrivMeta) -> Option<Meta<'a>> {
Expand Down Expand Up @@ -132,6 +134,7 @@ impl<'a> Context<'a> {
};

let m = Meta {
item: &meta.item,
hash: meta.hash,
docs: meta.docs.lines(),
kind,
Expand All @@ -145,12 +148,12 @@ impl<'a> Context<'a> {
self.visitors
.iter()
.map(|v| v.base.as_ref())
.chain(self.context.iter_meta().map(|(_, m)| m.module.as_ref()))
.chain(self.context.iter_meta().map(|m| m.module.as_ref()))
}
}

fn visitor_meta_to_meta<'a>(m: &'a meta::Kind, visitor: &'a Visitor, hash: Hash) -> Meta<'a> {
let kind = match m {
fn visitor_meta_to_meta(data: &VisitorData) -> Meta<'_> {
let kind = match &data.kind {
meta::Kind::Unknown { .. } => Kind::Unknown,
meta::Kind::Struct { .. } => Kind::Struct,
meta::Kind::Variant { .. } => Kind::Variant,
Expand All @@ -163,11 +166,10 @@ fn visitor_meta_to_meta<'a>(m: &'a meta::Kind, visitor: &'a Visitor, hash: Hash)
_ => Kind::Unsupported,
};

let docs = visitor
.docs
.get(&hash)
.map(Vec::as_slice)
.unwrap_or_default();

Meta { hash, docs, kind }
Meta {
item: &data.item,
hash: data.hash,
docs: data.docs.as_slice(),
kind,
}
}
43 changes: 33 additions & 10 deletions crates/rune/src/doc/html.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,10 @@ impl Ctxt<'_> {
None => self.syntax_set.find_syntax_plain_text(),
};

self.render_code_by_syntax(lines, syntax)
format!(
"<pre><code class=\"language-rune\">{}</code></pre>",
self.render_code_by_syntax(lines, syntax)
)
}

/// Render documentation.
Expand Down Expand Up @@ -286,23 +289,23 @@ impl Ctxt<'_> {
}

/// Build banklinks for the current item.
fn module_path_html(&self, last: bool) -> String {
fn module_path_html(&self, is_module: bool) -> String {
let mut module = Vec::new();
let mut iter = self.item.iter();
let dir = self.dir();

while iter.next_back().is_some() {
if let Some(name) = iter.as_item().last() {
let url = dir.relative(self.item_path(iter.as_item(), ItemPath::Module));
module.push(format!("<a href=\"{url}\">{name}</a>"));
module.push(format!("<a class=\"module\" href=\"{url}\">{name}</a>"));
}
}

module.reverse();

if last {
if is_module {
if let Some(name) = self.item.last() {
module.push(format!("{name}"));
module.push(format!("<span class=\"module\">{name}</span>"));
}
}

Expand Down Expand Up @@ -407,11 +410,11 @@ pub fn write_html(
match build {
Build::Type(item, hash) => {
cx.set_path(item, ItemPath::Type);
type_(&cx, "Type", hash)?;
type_(&cx, "Type", "type", hash)?;
}
Build::Struct(item, hash) => {
cx.set_path(item, ItemPath::Struct);
type_(&cx, "Struct", hash)?;
type_(&cx, "Struct", "struct", hash)?;
}
Build::Function(item) => {
cx.set_path(item, ItemPath::Function);
Expand Down Expand Up @@ -611,11 +614,12 @@ fn module(
}

/// Build an unknown type.
#[tracing::instrument(skip_all)]
fn type_(cx: &Ctxt<'_>, what: &str, hash: Hash) -> Result<()> {
// #[tracing::instrument(skip_all)]
fn type_(cx: &Ctxt<'_>, what: &str, what_class: &str, hash: Hash) -> Result<()> {
#[derive(Serialize)]
struct Params<'a> {
what: &'a str,
what_class: &'a str,
#[serde(flatten)]
shared: Shared,
module: String,
Expand Down Expand Up @@ -699,7 +703,25 @@ fn type_(cx: &Ctxt<'_>, what: &str, hash: Hash) -> Result<()> {

for hash in &f.name.parameter_types {
if let Some(meta) = cx.context.meta_by_hash(*hash) {
list.push(String::from("META"));
match &meta.kind {
Kind::Unknown => {
let path =
cx.dir().relative(cx.item_path(meta.item, ItemPath::Type));
let name = meta.item.last().context("missing name")?;
list.push(format!("<a class=\"type\" href=\"{path}\">{name}</a>"));
}
Kind::Struct => {
let path =
cx.dir().relative(cx.item_path(meta.item, ItemPath::Struct));
let name = meta.item.last().context("missing name")?;
list.push(format!(
"<a class=\"struct\" href=\"{path}\">{name}</a>"
));
}
_ => {
list.push(String::from("?"));
}
}
} else {
list.push(String::from("?"));
}
Expand Down Expand Up @@ -739,6 +761,7 @@ fn type_(cx: &Ctxt<'_>, what: &str, hash: Hash) -> Result<()> {
cx.write_file(|cx| {
cx.type_template.render(&Params {
what,
what_class,
shared: cx.shared(),
module,
name,
Expand Down
5 changes: 5 additions & 0 deletions crates/rune/src/doc/static/runedoc.css
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
--headings-border-bottom-color: #d2d2d2;
--type-link-color: #2dbfb8;
--fn-link-color: #2bab63;
--mod-link-color: #d2991d;
}

body {
Expand Down Expand Up @@ -74,6 +75,10 @@ a {
color: var(--fn-link-color);
}

.module {
color: var(--mod-link-color);
}

.protocol {
color: var(--fn-link-color);
}
Expand Down
2 changes: 1 addition & 1 deletion crates/rune/src/doc/static/type.html.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
{{#each fonts}}<link rel="preload" as="font" type="font/woff2" crossorigin="" href="{{this}}">{{/each}}
{{#each css}}<link rel="stylesheet" type="text/css" href="{{this}}">{{/each}}
<body>
<h3 class="title">{{what}} <b>{{literal module}}::{{name}}</b></h3>
<h3 class="title">{{what}} {{literal module}}::<span class="{{what_class}}">{{name}}</span></h3>

{{#if methods}}
<h4 class="section-title">Methods</h4>
Expand Down
Loading

0 comments on commit 96c64e8

Please sign in to comment.