tamer: asg::air: Use new parse::util::spair function to reduce test ceremony

This makes `SPair` construction more concise, getting rid of the `into`
invocations.  For now I have only made this change in AIR's tests, since
that's what I'm working on and I want to observe how this convention
evolves.  This may also encourage other changes, e.g. placing spans within
the `toks` array, rather than having to jump around the test for them.

The comment for `spair` mentions why this is a test-only function.  But it
also shows how dangerous `impl Into<SymbolId> for &str` can be, since it
seems so innocuous---it uses a global interner.  I'll be interested to see a
year from now if I decided to forego that impl in favor of explicit
internment, since I'm not sure it's worth the convenience anymore.

DEV-13163
main
Mike Gerwitz 2023-07-11 10:33:19 -04:00
parent 8a10f8bbbe
commit b4bbc0d8f0
5 changed files with 183 additions and 158 deletions

View File

@ -18,19 +18,23 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
use super::*;
use crate::asg::{
air::{
test::{
air_ctx_from_pkg_body_toks, air_ctx_from_toks, parse_as_pkg_body,
pkg_expect_ident_obj, pkg_expect_ident_oi, pkg_lookup,
},
Air::*,
AirAggregate,
},
graph::object::{expr::ExprRel, Doc, ObjectRel},
ExprOp, Ident,
};
use crate::span::dummy::*;
use crate::{
asg::{
air::{
test::{
air_ctx_from_pkg_body_toks, air_ctx_from_toks,
parse_as_pkg_body, pkg_expect_ident_obj, pkg_expect_ident_oi,
pkg_lookup,
},
Air::*,
AirAggregate,
},
graph::object::{expr::ExprRel, Doc, ObjectRel},
ExprOp, Ident,
},
parse::util::spair,
};
use std::assert_matches::assert_matches;
type Sut = AirAggregate;
@ -47,7 +51,7 @@ pub fn collect_subexprs(
#[test]
fn expr_empty_ident() {
let id = SPair("foo".into(), S2);
let id = spair("foo", S2);
#[rustfmt::skip]
let toks = [
@ -71,7 +75,7 @@ fn expr_without_pkg() {
// (because we're not parsing with `parse_as_pkg_body` below)
ExprStart(ExprOp::Sum, S1),
// RECOVERY
PkgStart(S2, SPair("/pkg".into(), S2)),
PkgStart(S2, spair("/pkg", S2)),
PkgEnd(S3),
];
@ -89,11 +93,11 @@ fn expr_without_pkg() {
// Note that this can't happen in e.g. NIR / TAME's source XML.
#[test]
fn close_pkg_mid_expr() {
let id = SPair("foo".into(), S4);
let id = spair("foo", S4);
#[rustfmt::skip]
let toks = [
PkgStart(S1, SPair("/pkg".into(), S1)),
PkgStart(S1, spair("/pkg", S1)),
ExprStart(ExprOp::Sum, S2),
PkgEnd(S3),
// RECOVERY: Let's finish the expression first...
@ -124,9 +128,9 @@ fn close_pkg_mid_expr() {
#[test]
fn open_pkg_mid_expr() {
let pkg_a = SPair("/pkg".into(), S1);
let pkg_nested = SPair("/pkg-nested".into(), S3);
let id = SPair("foo".into(), S4);
let pkg_a = spair("/pkg", S1);
let pkg_nested = spair("/pkg-nested", S3);
let id = spair("foo", S4);
#[rustfmt::skip]
let toks = [
@ -164,8 +168,8 @@ fn open_pkg_mid_expr() {
#[test]
fn expr_non_empty_ident_root() {
let id_a = SPair("foo".into(), S2);
let id_b = SPair("bar".into(), S2);
let id_a = spair("foo", S2);
let id_b = spair("bar", S2);
#[rustfmt::skip]
let toks = [
@ -198,7 +202,7 @@ fn expr_non_empty_ident_root() {
// which only becomes reachable at the end.
#[test]
fn expr_non_empty_bind_only_after() {
let id = SPair("foo".into(), S2);
let id = spair("foo", S2);
#[rustfmt::skip]
let toks = [
@ -281,7 +285,7 @@ fn expr_dangling_with_subexpr() {
#[test]
fn expr_dangling_with_subexpr_ident() {
let id = SPair("foo".into(), S3);
let id = spair("foo", S3);
#[rustfmt::skip]
let toks = [
@ -324,7 +328,7 @@ fn expr_dangling_with_subexpr_ident() {
// but this also protects against potential future breakages.
#[test]
fn expr_reachable_subsequent_dangling() {
let id = SPair("foo".into(), S2);
let id = spair("foo", S2);
#[rustfmt::skip]
let toks = [
@ -363,7 +367,7 @@ fn expr_reachable_subsequent_dangling() {
// Recovery from dangling expression.
#[test]
fn recovery_expr_reachable_after_dangling() {
let id = SPair("foo".into(), S4);
let id = spair("foo", S4);
#[rustfmt::skip]
let toks = [
@ -416,7 +420,7 @@ fn recovery_expr_reachable_after_dangling() {
#[test]
fn expr_close_unbalanced() {
let id = SPair("foo".into(), S3);
let id = spair("foo", S3);
#[rustfmt::skip]
let toks = [
@ -468,7 +472,7 @@ fn expr_close_unbalanced() {
// for non-associative expressions.
#[test]
fn sibling_subexprs_have_ordered_edges_to_parent() {
let id_root = SPair("root".into(), S1);
let id_root = spair("root", S1);
#[rustfmt::skip]
let toks = [
@ -517,8 +521,8 @@ fn sibling_subexprs_have_ordered_edges_to_parent() {
#[test]
fn nested_subexprs_related_to_relative_parent() {
let id_root = SPair("root".into(), S1);
let id_suba = SPair("suba".into(), S2);
let id_root = spair("root", S1);
let id_suba = spair("suba", S2);
#[rustfmt::skip]
let toks = [
@ -557,8 +561,8 @@ fn nested_subexprs_related_to_relative_parent() {
fn expr_redefine_ident() {
// Same identifier but with different spans
// (which would be the case in the real world).
let id_first = SPair("foo".into(), S2);
let id_dup = SPair("foo".into(), S3);
let id_first = spair("foo", S2);
let id_dup = spair("foo", S3);
#[rustfmt::skip]
let toks = [
@ -607,10 +611,10 @@ fn expr_redefine_ident() {
fn expr_still_dangling_on_redefine() {
// Same identifier but with different spans
// (which would be the case in the real world).
let id_first = SPair("foo".into(), S2);
let id_dup = SPair("foo".into(), S5);
let id_dup2 = SPair("foo".into(), S8);
let id_second = SPair("bar".into(), S9);
let id_first = spair("foo", S2);
let id_dup = spair("foo", S5);
let id_dup2 = spair("foo", S8);
let id_second = spair("bar", S9);
#[rustfmt::skip]
let toks = [
@ -692,8 +696,8 @@ fn expr_still_dangling_on_redefine() {
#[test]
fn expr_ref_to_ident() {
let id_foo = SPair("foo".into(), S2);
let id_bar = SPair("bar".into(), S6);
let id_foo = spair("foo", S2);
let id_bar = spair("bar", S6);
#[rustfmt::skip]
let toks = [
@ -702,7 +706,7 @@ fn expr_ref_to_ident() {
// Reference to an as-of-yet-undefined id (okay),
// with a different span than `id_bar`.
RefIdent(SPair("bar".into(), S3)),
RefIdent(spair("bar", S3)),
ExprEnd(S4),
//
@ -749,14 +753,14 @@ fn expr_ref_to_ident() {
#[test]
fn idents_share_defining_pkg() {
let id_foo = SPair("foo".into(), S3);
let id_bar = SPair("bar".into(), S5);
let id_baz = SPair("baz".into(), S6);
let id_foo = spair("foo", S3);
let id_bar = spair("bar", S5);
let id_baz = spair("baz", S6);
// An expression nested within another.
#[rustfmt::skip]
let toks = [
PkgStart(S1, SPair("/pkg".into(), S1)),
PkgStart(S1, spair("/pkg", S1)),
ExprStart(ExprOp::Sum, S2),
BindIdent(id_foo),
@ -790,8 +794,8 @@ fn idents_share_defining_pkg() {
#[test]
fn expr_doc_short_desc() {
let id_expr = SPair("foo".into(), S2);
let clause = SPair("short desc".into(), S3);
let id_expr = spair("foo", S2);
let clause = spair("short desc", S3);
#[rustfmt::skip]
let toks = [
@ -823,8 +827,8 @@ fn expr_doc_short_desc() {
// like a template.
#[test]
fn abstract_bind_without_dangling_container() {
let id_meta = SPair("@foo@".into(), S2);
let id_ok = SPair("concrete".into(), S5);
let id_meta = spair("@foo@", S2);
let id_ok = spair("concrete", S5);
#[rustfmt::skip]
let toks = [

View File

@ -26,7 +26,7 @@ use crate::{
graph::object::{ObjectRel, ObjectRelFrom, ObjectRelatable},
IdentKind, ObjectIndexRelTo, Source, TransitionError,
},
parse::{ParseError, Parsed, Parser},
parse::{util::spair, ParseError, Parsed, Parser},
span::dummy::*,
};
@ -39,7 +39,7 @@ mod scope;
#[test]
fn ident_decl() {
let id = SPair("foo".into(), S2);
let id = spair("foo", S2);
let kind = IdentKind::Tpl;
let src = Source {
src: Some("test/decl".into()),
@ -48,7 +48,7 @@ fn ident_decl() {
#[rustfmt::skip]
let toks = [
PkgStart(S1, SPair("/pkg".into(), S1)),
PkgStart(S1, spair("/pkg", S1)),
IdentDecl(id, kind.clone(), src.clone()),
// Attempt re-declaration.
IdentDecl(id, kind.clone(), src.clone()),
@ -88,8 +88,8 @@ fn ident_decl() {
#[test]
fn ident_extern_decl() {
let id = SPair("foo".into(), S2);
let re_id = SPair("foo".into(), S3);
let id = spair("foo", S2);
let re_id = spair("foo", S3);
let kind = IdentKind::Tpl;
let different_kind = IdentKind::Meta;
let src = Source {
@ -99,7 +99,7 @@ fn ident_extern_decl() {
#[rustfmt::skip]
let toks = [
PkgStart(S1, SPair("/pkg".into(), S1)),
PkgStart(S1, spair("/pkg", S1)),
IdentExternDecl(id, kind.clone(), src.clone()),
// Redeclare with a different kind
IdentExternDecl(re_id, different_kind.clone(), src.clone()),
@ -141,12 +141,12 @@ fn ident_extern_decl() {
#[test]
fn ident_dep() {
let id = SPair("foo".into(), S2);
let dep = SPair("dep".into(), S3);
let id = spair("foo", S2);
let dep = spair("dep", S3);
#[rustfmt::skip]
let toks = [
PkgStart(S1, SPair("/pkg".into(), S1)),
PkgStart(S1, spair("/pkg", S1)),
IdentDep(id, dep),
PkgEnd(S4),
].into_iter();
@ -174,7 +174,7 @@ fn ident_dep() {
#[test]
fn ident_fragment() {
let id = SPair("frag".into(), S2);
let id = spair("frag", S2);
let kind = IdentKind::Tpl;
let src = Source {
src: Some("test/frag".into()),
@ -184,7 +184,7 @@ fn ident_fragment() {
#[rustfmt::skip]
let toks = [
PkgStart(S1, SPair("/pkg".into(), S1)),
PkgStart(S1, spair("/pkg", S1)),
// Identifier must be declared before it can be given a
// fragment.
IdentDecl(id, kind.clone(), src.clone()),
@ -232,11 +232,11 @@ fn ident_fragment() {
// `Ident::Missing`.
#[test]
fn ident_root_missing() {
let id = SPair("toroot".into(), S2);
let id = spair("toroot", S2);
#[rustfmt::skip]
let toks = [
PkgStart(S1, SPair("/pkg".into(), S1)),
PkgStart(S1, spair("/pkg", S1)),
IdentRoot(id),
PkgEnd(S3),
].into_iter();
@ -269,7 +269,7 @@ fn ident_root_missing() {
#[test]
fn ident_root_existing() {
let id = SPair("toroot".into(), S2);
let id = spair("toroot", S2);
let kind = IdentKind::Tpl;
let src = Source {
src: Some("test/root-existing".into()),
@ -282,9 +282,9 @@ fn ident_root_existing() {
#[rustfmt::skip]
let toks = [
PkgStart(S1, SPair("/pkg".into(), S1)),
PkgStart(S1, spair("/pkg", S1)),
IdentDecl(id, kind.clone(), src.clone()),
IdentRoot(SPair(id.symbol(), S3)),
IdentRoot(spair(id, S3)),
PkgEnd(S3),
]
.into_iter();
@ -329,8 +329,8 @@ fn declare_kind_auto_root() {
assert!(auto_kind.is_auto_root());
assert!(!no_auto_kind.is_auto_root());
let id_auto = SPair("auto_root".into(), S2);
let id_no_auto = SPair("no_auto_root".into(), S3);
let id_auto = spair("auto_root", S2);
let id_no_auto = spair("no_auto_root", S3);
let src = Source {
src: Some("src/pkg".into()),
@ -339,7 +339,7 @@ fn declare_kind_auto_root() {
#[rustfmt::skip]
let toks = [
PkgStart(S1, SPair("/pkg".into(), S1)),
PkgStart(S1, spair("/pkg", S1)),
// auto-rooting
IdentDecl(id_auto, auto_kind, src.clone()),
// non-auto-rooting
@ -373,7 +373,7 @@ fn declare_kind_auto_root() {
fn pkg_is_rooted() {
#[rustfmt::skip]
let toks = [
PkgStart(S1, SPair("/pkg".into(), S1)),
PkgStart(S1, spair("/pkg", S1)),
PkgEnd(S2),
];
@ -397,7 +397,7 @@ fn close_pkg_without_open() {
let toks = [
PkgEnd(S1),
// RECOVERY: Try again.
PkgStart(S2, SPair("/pkg".into(), S2)),
PkgStart(S2, spair("/pkg", S2)),
PkgEnd(S3),
];
@ -414,8 +414,8 @@ fn close_pkg_without_open() {
#[test]
fn nested_open_pkg() {
let name_a = SPair("/pkg-a".into(), S2);
let name_b = SPair("/pkg-b".into(), S4);
let name_a = spair("/pkg-a", S2);
let name_b = spair("/pkg-b", S4);
#[rustfmt::skip]
let toks = [
@ -442,7 +442,7 @@ fn nested_open_pkg() {
#[test]
fn pkg_canonical_name() {
let name = SPair("/foo/bar".into(), S2);
let name = spair("/foo/bar", S2);
#[rustfmt::skip]
let toks = [
@ -477,9 +477,9 @@ fn pkg_canonical_name() {
// filenames.
#[test]
fn pkg_cannot_redeclare() {
let name = SPair("/foo/bar".into(), S2);
let name2 = SPair("/foo/bar".into(), S5);
let namefix = SPair("/foo/fix".into(), S7);
let name = spair("/foo/bar", S2);
let name2 = spair("/foo/bar", S5);
let namefix = spair("/foo/fix", S7);
#[rustfmt::skip]
let toks = [
@ -527,8 +527,8 @@ fn pkg_cannot_redeclare() {
#[test]
fn pkg_import_canonicalized_against_current_pkg() {
let pkg_name = SPair("/foo/bar".into(), S2);
let pkg_rel = SPair("baz/quux".into(), S3);
let pkg_name = spair("/foo/bar", S2);
let pkg_rel = spair("baz/quux", S3);
#[rustfmt::skip]
let toks = [
@ -553,15 +553,15 @@ fn pkg_import_canonicalized_against_current_pkg() {
.resolve(&asg);
// TODO
assert_eq!(SPair("/foo/baz/quux".into(), S3), import.canonical_name());
assert_eq!(spair("/foo/baz/quux", S3), import.canonical_name());
}
// Documentation can be mixed in with objects in a literate style.
#[test]
fn pkg_doc() {
let doc_a = SPair("first".into(), S2);
let id_import = SPair("import".into(), S3);
let doc_b = SPair("first".into(), S4);
let doc_a = spair("first", S2);
let id_import = spair("import", S3);
let doc_b = spair("first", S4);
#[rustfmt::skip]
let toks = [
@ -597,9 +597,9 @@ fn pkg_doc() {
// index.
#[test]
fn resume_previous_parsing_context() {
let name_foo = SPair("foo".into(), S2);
let name_bar = SPair("bar".into(), S5);
let name_baz = SPair("baz".into(), S6);
let name_foo = spair("foo", S2);
let name_bar = spair("bar", S5);
let name_baz = spair("baz", S6);
let kind = IdentKind::Tpl;
let src = Source::default();
@ -609,7 +609,7 @@ fn resume_previous_parsing_context() {
let toks = [
// The first package will reference an identifier from another
// package.
PkgStart(S1, SPair("/pkg-a".into(), S1)),
PkgStart(S1, spair("/pkg-a", S1)),
IdentDep(name_foo, name_bar),
PkgEnd(S3),
];
@ -624,7 +624,7 @@ fn resume_previous_parsing_context() {
// This package will define that identifier,
// which should also find the identifier having been placed into
// the global environment.
PkgStart(S4, SPair("/pkg-b".into(), S4)),
PkgStart(S4, spair("/pkg-b", S4)),
IdentDecl(name_bar, kind.clone(), src.clone()),
// This is a third identifier that is unique to this package.
@ -692,7 +692,7 @@ where
use std::iter;
Sut::parse(
iter::once(PkgStart(S1, SPair("/pkg".into(), S1)))
iter::once(PkgStart(S1, spair("/pkg", S1)))
.chain(toks.into_iter())
.chain(iter::once(PkgEnd(S1))),
)

View File

@ -51,6 +51,7 @@ use crate::{
visit::{tree_reconstruction, TreeWalkRel},
ExprOp,
},
parse::util::spair,
span::UNKNOWN_SPAN,
};
use std::iter::once;
@ -120,9 +121,9 @@ macro_rules! test_scopes {
test_scopes! {
setup {
let pkg_name = SPair("/pkg".into(), S1);
let outer = SPair("outer".into(), S3);
let inner = SPair("inner".into(), S5);
let pkg_name = spair("/pkg", S1);
let outer = spair("outer", S3);
let inner = spair("inner", S5);
}
air {
@ -166,15 +167,15 @@ test_scopes! {
test_scopes! {
setup {
let pkg_name = SPair("/pkg".into(), S1);
let pkg_name = spair("/pkg", S1);
let tpl_outer = SPair("_tpl-outer_".into(), S3);
let meta_outer = SPair("@param_outer@".into(), S5);
let expr_outer = SPair("exprOuter".into(), S8);
let tpl_outer = spair("_tpl-outer_", S3);
let meta_outer = spair("@param_outer@", S5);
let expr_outer = spair("exprOuter", S8);
let tpl_inner = SPair("_tpl-inner_".into(), S11);
let meta_inner = SPair("@param_inner@".into(), S13);
let expr_inner = SPair("exprInner".into(), S16);
let tpl_inner = spair("_tpl-inner_", S11);
let meta_inner = spair("@param_inner@", S13);
let expr_inner = spair("exprInner", S16);
}
air {
@ -329,18 +330,18 @@ test_scopes! {
test_scopes! {
setup {
let pkg_name = SPair("/pkg".into(), S1);
let pkg_name = spair("/pkg", S1);
let tpl_outer = SPair("_tpl-outer_".into(), S3);
let tpl_inner = SPair("_tpl-inner_".into(), S9);
let tpl_outer = spair("_tpl-outer_", S3);
let tpl_inner = spair("_tpl-inner_", S9);
// Note how these have the _same name_.
let meta_name = "@param@".into();
let meta_same_a = SPair(meta_name, S5);
let meta_same_b = SPair(meta_name, S11);
let meta_name = "@param@";
let meta_same_a = spair(meta_name, S5);
let meta_same_b = spair(meta_name, S11);
// This one will be used for asserting.
let meta_same = SPair(meta_name, S11);
let meta_same = spair(meta_name, S11);
}
air {
@ -433,11 +434,11 @@ test_scopes! {
// From the perspective of the linker (tameld):
test_scopes! {
setup {
let pkg_a = SPair("/pkg/a".into(), S1);
let opaque_a = SPair("opaque_a".into(), S2);
let pkg_a = spair("/pkg/a", S1);
let opaque_a = spair("opaque_a", S2);
let pkg_b = SPair("/pkg/b".into(), S4);
let opaque_b = SPair("opaque_b".into(), S5);
let pkg_b = spair("/pkg/b", S4);
let opaque_b = spair("opaque_b", S5);
}
air {

View File

@ -18,29 +18,33 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
use super::*;
use crate::asg::{
air::{
expr::test::collect_subexprs,
test::{
air_ctx_from_pkg_body_toks, air_ctx_from_toks, parse_as_pkg_body,
pkg_expect_ident_obj, pkg_expect_ident_oi, pkg_lookup,
},
Air::*,
},
graph::object::{Doc, Meta, ObjectRel},
Expr, ExprOp, Ident,
};
use crate::span::dummy::*;
use crate::{
asg::{
air::{
expr::test::collect_subexprs,
test::{
air_ctx_from_pkg_body_toks, air_ctx_from_toks,
parse_as_pkg_body, pkg_expect_ident_obj, pkg_expect_ident_oi,
pkg_lookup,
},
Air::*,
},
graph::object::{Doc, Meta, ObjectRel},
Expr, ExprOp, Ident,
},
parse::util::spair,
};
// A template is defined by the package containing it,
// like an expression.
#[test]
fn tpl_defining_pkg() {
let id_tpl = SPair("_tpl_".into(), S3);
let id_tpl = spair("_tpl_", S3);
#[rustfmt::skip]
let toks = [
PkgStart(S1, SPair("/pkg".into(), S1)),
PkgStart(S1, spair("/pkg", S1)),
// This also tests tpl as a transition away from the package header.
TplStart(S2),
BindIdent(id_tpl),
@ -63,12 +67,12 @@ fn tpl_defining_pkg() {
#[test]
fn tpl_after_expr() {
let id_expr = SPair("expr".into(), S3);
let id_tpl = SPair("_tpl_".into(), S6);
let id_expr = spair("expr", S3);
let id_tpl = spair("_tpl_", S6);
#[rustfmt::skip]
let toks = [
PkgStart(S1, SPair("/pkg".into(), S1)),
PkgStart(S1, spair("/pkg", S1)),
// This expression is incidental to this test;
// it need only parse.
ExprStart(ExprOp::Sum, S2),
@ -100,12 +104,12 @@ fn tpl_after_expr() {
// This context includes the entire active expression stack.
#[test]
fn tpl_within_expr() {
let id_expr = SPair("expr".into(), S3);
let id_tpl = SPair("_tpl_".into(), S7);
let id_expr = spair("expr", S3);
let id_tpl = spair("_tpl_", S7);
#[rustfmt::skip]
let toks = [
PkgStart(S1, SPair("/pkg".into(), S1)),
PkgStart(S1, spair("/pkg", S1)),
ExprStart(ExprOp::Sum, S2),
BindIdent(id_expr),
@ -159,9 +163,9 @@ fn tpl_within_expr() {
// but now we're _applying_ a template.
#[test]
fn tpl_apply_within_expr() {
let id_expr = SPair("expr".into(), S3);
let id_tpl = SPair("_tpl_".into(), S5);
let ref_tpl = SPair("_tpl_".into(), S8);
let id_expr = spair("expr", S3);
let id_tpl = spair("_tpl_", S5);
let ref_tpl = spair("_tpl_", S8);
#[rustfmt::skip]
let toks = [
@ -208,7 +212,7 @@ fn tpl_apply_within_expr() {
#[test]
fn close_tpl_without_open() {
let id_tpl = SPair("_tpl_".into(), S3);
let id_tpl = spair("_tpl_", S3);
#[rustfmt::skip]
let toks = [
@ -236,9 +240,9 @@ fn close_tpl_without_open() {
#[test]
fn tpl_with_reachable_expression() {
let id_tpl = SPair("_tpl_".into(), S2);
let id_expr_a = SPair("expra".into(), S4);
let id_expr_b = SPair("exprb".into(), S7);
let id_tpl = spair("_tpl_", S2);
let id_expr_a = spair("expra", S4);
let id_expr_b = spair("exprb", S7);
#[rustfmt::skip]
let toks = [
@ -311,7 +315,7 @@ fn tpl_with_reachable_expression() {
// will become reachable in its expansion context.
#[test]
fn tpl_holds_dangling_expressions() {
let id_tpl = SPair("_tpl_".into(), S2);
let id_tpl = spair("_tpl_", S2);
#[rustfmt::skip]
let toks = [
@ -345,8 +349,8 @@ fn tpl_holds_dangling_expressions() {
#[test]
fn close_tpl_mid_open() {
let id_tpl = SPair("_tpl_".into(), S2);
let id_expr = SPair("expr".into(), S4);
let id_tpl = spair("_tpl_", S2);
let id_expr = spair("expr", S4);
#[rustfmt::skip]
let toks = [
@ -393,7 +397,7 @@ fn close_tpl_mid_open() {
// but may not be true in the future.
#[test]
fn unreachable_anonymous_tpl() {
let id_ok = SPair("_tpl_".into(), S4);
let id_ok = spair("_tpl_", S4);
#[rustfmt::skip]
let toks = [
@ -457,12 +461,12 @@ fn anonymous_tpl_immediate_ref() {
#[test]
fn tpl_with_param() {
let id_tpl = SPair("_tpl_".into(), S2);
let id_tpl = spair("_tpl_", S2);
let id_param1 = SPair("@param1@".into(), S4);
let pval1 = SPair("value1".into(), S5);
let id_param2 = SPair("@param2@".into(), S8);
let param_desc = SPair("param desc".into(), S9);
let id_param1 = spair("@param1@", S4);
let pval1 = spair("value1", S5);
let id_param2 = spair("@param2@", S8);
let param_desc = spair("param desc", S9);
#[rustfmt::skip]
let toks = [
@ -527,8 +531,8 @@ fn tpl_with_param() {
// definition in the context of the expansion site.
#[test]
fn tpl_nested() {
let id_tpl_outer = SPair("_tpl-outer_".into(), S2);
let id_tpl_inner = SPair("_tpl-inner_".into(), S4);
let id_tpl_outer = spair("_tpl-outer_", S2);
let id_tpl_inner = spair("_tpl-inner_", S4);
#[rustfmt::skip]
let toks = vec![
@ -573,7 +577,7 @@ fn tpl_nested() {
// it all starts the same.
#[test]
fn tpl_apply_nested() {
let id_tpl_outer = SPair("_tpl-outer_".into(), S2);
let id_tpl_outer = spair("_tpl-outer_", S2);
#[rustfmt::skip]
let toks = [
@ -606,12 +610,12 @@ fn tpl_apply_nested() {
// ref/def.
#[test]
fn tpl_apply_nested_missing() {
let id_tpl_outer = SPair("_tpl-outer_".into(), S2);
let tpl_inner = "_tpl-inner_".into();
let id_tpl_inner = SPair(tpl_inner, S7);
let id_tpl_outer = spair("_tpl-outer_", S2);
let ref_tpl_inner_pre = SPair(tpl_inner, S4);
let ref_tpl_inner_post = SPair(tpl_inner, S10);
let tpl_inner = "_tpl-inner_";
let id_tpl_inner = spair(tpl_inner, S7);
let ref_tpl_inner_pre = spair(tpl_inner, S4);
let ref_tpl_inner_post = spair(tpl_inner, S10);
#[rustfmt::skip]
let toks = [
@ -678,8 +682,8 @@ fn tpl_apply_nested_missing() {
#[test]
fn tpl_doc_short_desc() {
let id_tpl = SPair("foo".into(), S2);
let clause = SPair("short desc".into(), S3);
let id_tpl = spair("foo", S2);
let clause = spair("short desc", S3);
#[rustfmt::skip]
let toks = [
@ -718,11 +722,11 @@ fn tpl_doc_short_desc() {
// generators.
#[test]
fn metavars_within_exprs_hoisted_to_parent_tpl() {
let id_tpl_outer = SPair("_tpl-outer_".into(), S2);
let id_tpl_inner = SPair("_tpl-inner_".into(), S9);
let id_tpl_outer = spair("_tpl-outer_", S2);
let id_tpl_inner = spair("_tpl-inner_", S9);
let id_param_outer = SPair("@param_outer@".into(), S5);
let id_param_inner = SPair("@param_inner@".into(), S12);
let id_param_outer = spair("@param_outer@", S5);
let id_param_inner = spair("@param_inner@", S12);
#[rustfmt::skip]
let toks = [
@ -788,8 +792,8 @@ fn metavars_within_exprs_hoisted_to_parent_tpl() {
#[test]
fn expr_abstract_bind_produces_cross_edge_from_ident_to_meta() {
let id_tpl = SPair("_tpl_".into(), S2);
let id_meta = SPair("@foo@".into(), S4);
let id_tpl = spair("_tpl_", S2);
let id_meta = spair("@foo@", S4);
#[rustfmt::skip]
let toks = [

View File

@ -56,6 +56,22 @@ use std::fmt::Display;
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub struct SPair(pub SymbolId, pub Span);
/// More concisely construct an [`SPair`] from [`SymbolId`]- and
/// [`Span`]-like things.
///
/// This is restricted to `cfg(test)` because it can cause unexpected
/// internment if you're not careful.
/// For example,
/// if a [`str`] is assigned to a variable and then that variable is
/// supplied to multiple calls to this function,
/// each call will invoke the internment system.
/// This isn't much of a concern for short-running tests,
/// but is not acceptable elsewhere.
#[cfg(test)]
pub fn spair(sym: impl Into<SymbolId>, span: impl Into<Span>) -> SPair {
SPair(sym.into(), span.into())
}
impl SPair {
/// Retrieve the [`SymbolId`] of this pair.
///