tamer: asg::graph: *lookup{=>_global}*

Identifier lookups, as done using the graph methods today, look up from a
cache representing the global environment.

Templates must not contribute to this environment until expansion.  Further,
metavariables will not be present in this environment.  To avoid confusion
and help obviate accidental contributions to this environment, the methods
have been renamed.  This will also allow for the creation of more general
methods down the line.

DEV-13708
Mike Gerwitz 2023-03-22 11:28:55 -04:00
parent 7a9cf6bc51
commit 31a39c79d3
13 changed files with 87 additions and 85 deletions

View File

@ -147,7 +147,7 @@ mod base {
bench.iter(|| {
xs.iter()
.map(|sym| sut.lookup(*sym).unwrap())
.map(|sym| sut.lookup_global(*sym).unwrap())
.for_each(drop);
});
}
@ -286,7 +286,7 @@ mod base {
bench.iter(|| {
xs.iter()
.zip(xs.iter().cycle().skip(1))
.map(|(from, to)| sut.add_dep_lookup(*from, *to))
.map(|(from, to)| sut.add_dep_lookup_global(*from, *to))
.for_each(drop);
});
}
@ -303,7 +303,7 @@ mod base {
bench.iter(|| {
xs.iter()
.zip(xs.iter().cycle().skip(1))
.map(|(from, to)| sut.add_dep_lookup(*from, *to))
.map(|(from, to)| sut.add_dep_lookup_global(*from, *to))
.for_each(drop);
});
}

View File

@ -246,7 +246,7 @@ impl ParseState for AirAggregate {
.transition(Empty),
(Empty, AirIdent(IdentDep(sym, dep))) => {
asg.add_dep_lookup(sym, dep);
asg.add_dep_lookup_global(sym, dep);
Transition(Empty).incomplete()
}
@ -255,7 +255,7 @@ impl ParseState for AirAggregate {
}
(Empty, AirIdent(IdentRoot(sym))) => {
let obj = asg.lookup_or_missing(sym);
let obj = asg.lookup_global_or_missing(sym);
asg.add_root(obj);
Transition(Empty).incomplete()

View File

@ -433,9 +433,9 @@ mod root {
fn defines(&self, asg: &mut Asg, id: SPair) -> ObjectIndex<Ident> {
match self {
Self(oi_root) => {
asg.lookup_or_missing(id).add_edge_from(asg, *oi_root, None)
}
Self(oi_root) => asg
.lookup_global_or_missing(id)
.add_edge_from(asg, *oi_root, None),
}
}

View File

@ -899,14 +899,14 @@ fn idents_share_defining_pkg() {
assert!(sut.all(|x| x.is_ok()));
let asg = sut.finalize().unwrap().into_context();
let oi_foo = asg.lookup(id_foo).unwrap();
let oi_bar = asg.lookup(id_bar).unwrap();
let oi_foo = asg.lookup_global(id_foo).unwrap();
let oi_bar = asg.lookup_global(id_bar).unwrap();
assert_eq!(oi_foo.src_pkg(&asg).unwrap(), oi_bar.src_pkg(&asg).unwrap());
// Missing identifiers should not have a source package,
// since we don't know what defined it yet.
let oi_baz = asg.lookup(id_baz).unwrap();
let oi_baz = asg.lookup_global(id_baz).unwrap();
assert_eq!(None, oi_baz.src_pkg(&asg));
// The package span should encompass the entire definition.

View File

@ -46,7 +46,9 @@ fn ident_decl() {
let asg = sut.finalize().unwrap().into_context();
let ident_node = asg.lookup(id).expect("identifier was not added to graph");
let ident_node = asg
.lookup_global(id)
.expect("identifier was not added to graph");
let ident = asg.get(ident_node).unwrap();
assert_eq!(
@ -85,7 +87,9 @@ fn ident_extern_decl() {
let asg = sut.finalize().unwrap().into_context();
let ident_node = asg.lookup(id).expect("identifier was not added to graph");
let ident_node = asg
.lookup_global(id)
.expect("identifier was not added to graph");
let ident = asg.get(ident_node).unwrap();
assert_eq!(
@ -122,8 +126,10 @@ fn ident_dep() {
let asg = sut.finalize().unwrap().into_context();
let ident_node = asg.lookup(id).expect("identifier was not added to graph");
let dep_node = asg.lookup(dep).expect("dep was not added to graph");
let ident_node = asg
.lookup_global(id)
.expect("identifier was not added to graph");
let dep_node = asg.lookup_global(dep).expect("dep was not added to graph");
assert!(asg.has_dep(ident_node, dep_node));
}
@ -153,7 +159,9 @@ fn ident_fragment() {
let asg = sut.finalize().unwrap().into_context();
let ident_node = asg.lookup(id).expect("identifier was not added to graph");
let ident_node = asg
.lookup_global(id)
.expect("identifier was not added to graph");
let ident = asg.get(ident_node).unwrap();
assert_eq!(
@ -189,7 +197,7 @@ fn ident_root_missing() {
let asg = sut.finalize().unwrap().into_context();
let ident_node = asg
.lookup(id)
.lookup_global(id)
.expect("identifier was not added to the graph");
let ident = asg.get(ident_node).unwrap();
@ -228,7 +236,7 @@ fn ident_root_existing() {
let asg = sut.finalize().unwrap().into_context();
let ident_node = asg
.lookup(id)
.lookup_global(id)
.expect("identifier was not added to the graph");
let ident = asg.get(ident_node).unwrap();

View File

@ -191,7 +191,7 @@ impl ParseState for AirTplAggregate {
),
(Toplevel(oi_pkg, tpl, expr), AirBind(BindIdent(id))) => asg
.lookup_or_missing(id)
.lookup_global_or_missing(id)
.bind_definition(asg, id, tpl.oi())
.map(|oi_ident| oi_pkg.defines(asg, oi_ident))
.map(|_| ())

View File

@ -53,7 +53,7 @@ fn tpl_defining_pkg() {
let tpl = asg.expect_ident_obj::<Tpl>(id_tpl);
assert_eq!(S2.merge(S4).unwrap(), tpl.span());
let oi_id_tpl = asg.lookup(id_tpl).unwrap();
let oi_id_tpl = asg.lookup_global(id_tpl).unwrap();
assert_eq!(
S1.merge(S5),
oi_id_tpl.src_pkg(&asg).map(|pkg| pkg.resolve(&asg).span()),
@ -219,18 +219,18 @@ fn tpl_with_reachable_expression() {
// they should be defined by the template...
assert_eq!(
vec![
asg.lookup(id_expr_b).unwrap(),
asg.lookup(id_expr_a).unwrap(),
asg.lookup_global(id_expr_b).unwrap(),
asg.lookup_global(id_expr_a).unwrap(),
],
oi_tpl.edges_filtered::<Ident>(&asg).collect::<Vec<_>>()
);
// ...but not by the package containing the template.
let oi_pkg = asg.lookup(id_tpl).unwrap().src_pkg(&asg).unwrap();
let oi_pkg = asg.lookup_global(id_tpl).unwrap().src_pkg(&asg).unwrap();
assert_eq!(
vec![
// The only identifier on the package should be the template itself.
asg.lookup(id_tpl).unwrap(),
asg.lookup_global(id_tpl).unwrap(),
],
oi_pkg.edges_filtered::<Ident>(&asg).collect::<Vec<_>>()
);

View File

@ -232,11 +232,11 @@ impl Asg {
/// you must resolve the [`Ident`] object and inspect it.
///
/// See [`Ident::declare`] for more information.
pub(super) fn lookup_or_missing(
pub(super) fn lookup_global_or_missing(
&mut self,
ident: SPair,
) -> ObjectIndex<Ident> {
self.lookup(ident).unwrap_or_else(|| {
self.lookup_global(ident).unwrap_or_else(|| {
let index = self.graph.add_node(Ident::declare(ident).into());
self.index_identifier(ident.symbol(), index);
@ -247,13 +247,13 @@ impl Asg {
/// Perform a state transition on an identifier by name.
///
/// Look up `ident` or add a missing identifier if it does not yet exist
/// (see [`Self::lookup_or_missing`]).
/// (see [`Self::lookup_global_or_missing`]).
/// Then invoke `f` with the located identifier and replace the
/// identifier on the graph with the result.
///
/// This will safely restore graph state to the original identifier
/// value on transition failure.
fn with_ident_lookup<F>(
fn with_ident_lookup_global<F>(
&mut self,
name: SPair,
f: F,
@ -261,7 +261,7 @@ impl Asg {
where
F: FnOnce(Ident) -> TransitionResult<Ident>,
{
let identi = self.lookup_or_missing(name);
let identi = self.lookup_global_or_missing(name);
self.with_ident(identi, f)
}
@ -366,11 +366,13 @@ impl Asg {
) -> AsgResult<ObjectIndex<Ident>> {
let is_auto_root = kind.is_auto_root();
self.with_ident_lookup(name, |obj| obj.resolve(name.span(), kind, src))
.map(|node| {
is_auto_root.then(|| self.add_root(node));
node
})
self.with_ident_lookup_global(name, |obj| {
obj.resolve(name.span(), kind, src)
})
.map(|node| {
is_auto_root.then(|| self.add_root(node));
node
})
}
/// Declare an abstract identifier.
@ -399,7 +401,9 @@ impl Asg {
kind: IdentKind,
src: Source,
) -> AsgResult<ObjectIndex<Ident>> {
self.with_ident_lookup(name, |obj| obj.extern_(name.span(), kind, src))
self.with_ident_lookup_global(name, |obj| {
obj.extern_(name.span(), kind, src)
})
}
/// Set the fragment associated with a concrete identifier.
@ -412,7 +416,7 @@ impl Asg {
name: SPair,
text: FragmentText,
) -> AsgResult<ObjectIndex<Ident>> {
self.with_ident_lookup(name, |obj| obj.set_fragment(text))
self.with_ident_lookup_global(name, |obj| obj.set_fragment(text))
}
/// Create a new object on the graph.
@ -610,7 +614,7 @@ impl Asg {
&self,
ident: SPair,
) -> Option<ObjectIndex<O>> {
self.lookup(ident)
self.lookup_global(ident)
.and_then(|identi| {
self.graph
.neighbors_directed(identi.into(), Direction::Outgoing)
@ -722,7 +726,7 @@ impl Asg {
/// graph---for
/// that, see [`Asg::get`].
#[inline]
pub fn lookup(&self, id: SPair) -> Option<ObjectIndex<Ident>> {
pub fn lookup_global(&self, id: SPair) -> Option<ObjectIndex<Ident>> {
let i = id.symbol().as_usize();
self.index
@ -737,7 +741,7 @@ impl Asg {
/// computed before computing the value of `ident`.
/// The [linker][crate::ld] will ensure this ordering.
///
/// See [`add_dep_lookup`][Asg::add_dep_lookup] if identifiers have to
/// See [`Self::add_dep_lookup_global`] if identifiers have to
/// be looked up by [`SymbolId`] or if they may not yet have been
/// declared.
pub fn add_dep<O: ObjectKind>(
@ -777,13 +781,13 @@ impl Asg {
/// See [`Ident::declare`] for more information.
///
/// References to both identifiers are returned in argument order.
pub fn add_dep_lookup(
pub fn add_dep_lookup_global(
&mut self,
ident: SPair,
dep: SPair,
) -> (ObjectIndex<Ident>, ObjectIndex<Ident>) {
let identi = self.lookup_or_missing(ident);
let depi = self.lookup_or_missing(dep);
let identi = self.lookup_global_or_missing(ident);
let depi = self.lookup_global_or_missing(dep);
self.graph.update_edge(
identi.into(),

View File

@ -246,7 +246,7 @@ impl ObjectIndex<Expr> {
/// a missing identifier will take its place to be later resolved once
/// it becomes available.
pub fn ref_expr(self, asg: &mut Asg, ident: SPair) -> Self {
let identi = asg.lookup_or_missing(ident);
let identi = asg.lookup_global_or_missing(ident);
self.add_edge_to(asg, identi, Some(ident.span()))
}

View File

@ -92,7 +92,7 @@ impl ObjectIndex<Tpl> {
/// this application will expand the template in place,
/// re-binding metavariables to the context of `self`.
pub fn apply_named_tpl(self, asg: &mut Asg, id: SPair) -> Self {
let oi_apply = asg.lookup_or_missing(id);
let oi_apply = asg.lookup_global_or_missing(id);
self.add_edge_to(asg, oi_apply, Some(id.span()))
}

View File

@ -142,7 +142,7 @@ fn lookup_by_symbol() -> AsgResult<()> {
},
)?;
assert_eq!(Some(node), sut.lookup(id));
assert_eq!(Some(node), sut.lookup_global(id));
Ok(())
}
@ -311,7 +311,7 @@ fn add_dep_lookup_existing() -> AsgResult<()> {
let _ = sut.declare(sym, IdentKind::Meta, Source::default())?;
let _ = sut.declare(dep, IdentKind::Meta, Source::default())?;
let (symnode, depnode) = sut.add_dep_lookup(sym, dep);
let (symnode, depnode) = sut.add_dep_lookup_global(sym, dep);
assert!(sut.has_dep(symnode, depnode));
Ok(())
@ -325,7 +325,7 @@ fn add_dep_lookup_missing() -> AsgResult<()> {
let dep = SPair("dep".into(), S2);
// both of these are missing
let (symnode, depnode) = sut.add_dep_lookup(sym, dep);
let (symnode, depnode) = sut.add_dep_lookup_global(sym, dep);
assert!(sut.has_dep(symnode, depnode));
assert_eq!(sym, sut.get_ident(symnode).unwrap().name());
@ -342,7 +342,7 @@ fn declare_return_missing_symbol() -> AsgResult<()> {
let dep = SPair("dep".into(), S2);
// both of these are missing, see add_dep_lookup_missing
let (symnode, _) = sut.add_dep_lookup(sym, dep);
let (symnode, _) = sut.add_dep_lookup_global(sym, dep);
let src = Source {
desc: Some("redeclare missing".into()),

View File

@ -56,16 +56,6 @@
//! [asg]: https://en.wikipedia.org/wiki/Abstract_semantic_graph
//! [graph]: https://en.wikipedia.org/wiki/Graph_(discrete_mathematics)
//! [scc]: https://en.wikipedia.org/wiki/Strongly_connected_component
//!
//! Missing Identifiers
//! -------------------
//! Since identifiers in TAME can be defined in any order relative to their
//! dependencies within a source file,
//! it is often the case that a dependency will have to be added to the
//! graph before it is resolved.
//! For example,
//! [`Asg::add_dep_lookup`] will add an [`Ident::Missing`] to the graph
//! if either identifier has not yet been declared.
mod error;
mod graph;

View File

@ -97,7 +97,7 @@ where
let sym = name.into();
depgraph
.lookup(SPair(sym, UNKNOWN_SPAN))
.lookup_global(SPair(sym, UNKNOWN_SPAN))
.and_then(|id| depgraph.get(id))
.unwrap_or_else(|| {
panic!("missing internal identifier: {}", sym.lookup_str())
@ -436,7 +436,7 @@ mod test {
asg.set_fragment(sym, FragmentText::from("foo")).unwrap();
let (_, _) = asg.add_dep_lookup(sym, dep);
let (_, _) = asg.add_dep_lookup_global(sym, dep);
asg.add_root(sym_node);
@ -463,7 +463,7 @@ mod test {
let sym = SPair("sym".into(), S1);
let dep = SPair("dep".into(), S2);
asg_nonempty_no_roots.add_dep_lookup(sym, dep);
asg_nonempty_no_roots.add_dep_lookup_global(sym, dep);
assert_eq!(
sort(&asg_nonempty_no_roots, Sections::new()),
@ -505,8 +505,8 @@ mod test {
asg.set_fragment(sym, FragmentText::from("foo")).unwrap();
asg.set_fragment(dep, FragmentText::from("bar")).unwrap();
let (_, _) = asg.add_dep_lookup(sym, dep);
let (_, _) = asg.add_dep_lookup(dep, sym);
let (_, _) = asg.add_dep_lookup_global(sym, dep);
let (_, _) = asg.add_dep_lookup_global(dep, sym);
asg.add_root(sym_node);
@ -584,10 +584,10 @@ mod test {
asg.set_fragment(dep, FragmentText::from("baz")).unwrap();
asg.set_fragment(dep2, FragmentText::from("huh")).unwrap();
let (_, _) = asg.add_dep_lookup(sym, dep);
let (_, _) = asg.add_dep_lookup(dep, sym);
let (_, _) = asg.add_dep_lookup(sym2, dep2);
let (_, _) = asg.add_dep_lookup(dep2, sym2);
let (_, _) = asg.add_dep_lookup_global(sym, dep);
let (_, _) = asg.add_dep_lookup_global(dep, sym);
let (_, _) = asg.add_dep_lookup_global(sym2, dep2);
let (_, _) = asg.add_dep_lookup_global(dep2, sym2);
asg.add_root(sym_node);
@ -643,8 +643,8 @@ mod test {
asg.set_fragment(sym, FragmentText::from("foo")).unwrap();
asg.set_fragment(dep, FragmentText::from("bar")).unwrap();
let (_, _) = asg.add_dep_lookup(sym, dep);
let (_, _) = asg.add_dep_lookup(sym, dep);
let (_, _) = asg.add_dep_lookup_global(sym, dep);
let (_, _) = asg.add_dep_lookup_global(sym, dep);
asg.add_root(sym_node);
@ -703,9 +703,9 @@ mod test {
asg.set_fragment(sym2, FragmentText::from("bar")).unwrap();
asg.set_fragment(sym3, FragmentText::from("baz")).unwrap();
let (_, _) = asg.add_dep_lookup(sym1, sym2);
let (_, _) = asg.add_dep_lookup(sym2, sym3);
let (_, _) = asg.add_dep_lookup(sym3, sym1);
let (_, _) = asg.add_dep_lookup_global(sym1, sym2);
let (_, _) = asg.add_dep_lookup_global(sym2, sym3);
let (_, _) = asg.add_dep_lookup_global(sym3, sym1);
asg.add_root(sym1_node);
@ -771,9 +771,9 @@ mod test {
asg.set_fragment(sym2, FragmentText::from("bar")).unwrap();
asg.set_fragment(sym3, FragmentText::from("baz")).unwrap();
let (_, _) = asg.add_dep_lookup(sym1, sym2);
let (_, _) = asg.add_dep_lookup(sym2, sym3);
let (_, _) = asg.add_dep_lookup(sym3, sym1);
let (_, _) = asg.add_dep_lookup_global(sym1, sym2);
let (_, _) = asg.add_dep_lookup_global(sym2, sym3);
let (_, _) = asg.add_dep_lookup_global(sym3, sym1);
asg.add_root(sym1_node);
@ -838,9 +838,9 @@ mod test {
asg.set_fragment(sym2, FragmentText::from("bar")).unwrap();
asg.set_fragment(sym3, FragmentText::from("baz")).unwrap();
let (_, _) = asg.add_dep_lookup(sym1, sym2);
let (_, _) = asg.add_dep_lookup(sym2, sym3);
let (_, _) = asg.add_dep_lookup(sym3, sym1);
let (_, _) = asg.add_dep_lookup_global(sym1, sym2);
let (_, _) = asg.add_dep_lookup_global(sym2, sym3);
let (_, _) = asg.add_dep_lookup_global(sym3, sym1);
asg.add_root(sym1_node);
@ -891,8 +891,8 @@ mod test {
asg.set_fragment(sym, FragmentText::from("foo")).unwrap();
asg.set_fragment(dep, FragmentText::from("bar")).unwrap();
let (_, _) = asg.add_dep_lookup(sym, dep);
let (_, _) = asg.add_dep_lookup(dep, sym);
let (_, _) = asg.add_dep_lookup_global(sym, dep);
let (_, _) = asg.add_dep_lookup_global(dep, sym);
asg.add_root(sym_node);
@ -951,9 +951,9 @@ mod test {
asg.set_fragment(sym2, FragmentText::from("bar")).unwrap();
asg.set_fragment(sym3, FragmentText::from("baz")).unwrap();
let (_, _) = asg.add_dep_lookup(sym1, sym2);
let (_, _) = asg.add_dep_lookup(sym2, sym3);
let (_, _) = asg.add_dep_lookup(sym3, sym1);
let (_, _) = asg.add_dep_lookup_global(sym1, sym2);
let (_, _) = asg.add_dep_lookup_global(sym2, sym3);
let (_, _) = asg.add_dep_lookup_global(sym3, sym1);
asg.add_root(sym1_node);
@ -1017,8 +1017,8 @@ mod test {
asg.set_fragment(ignored, FragmentText::from("baz"))
.unwrap();
let (_, _) = asg.add_dep_lookup(sym, dep);
let (_, _) = asg.add_dep_lookup(ignored, sym);
let (_, _) = asg.add_dep_lookup_global(sym, dep);
let (_, _) = asg.add_dep_lookup_global(ignored, sym);
asg.add_root(sym_node);