Skip to content

Commit

Permalink
refactor: Allow the aliases map to map to arbitrary types.
Browse files Browse the repository at this point in the history
For #3673, we will have aliases such as:
```toml
'upload(revision)' = [
  ["fix", "-r", "$revision"],
  ["lint", "-r", "$revision"],
  ["git", "push", "-r", "$revision"],
]
```

Which will require aliases to map to `Vec<Vec<String>>`
  • Loading branch information
matts1 committed Jul 3, 2024
1 parent ca4eb60 commit ec0e734
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 21 deletions.
2 changes: 1 addition & 1 deletion cli/src/template_parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -552,7 +552,7 @@ pub fn parse_template(template_text: &str) -> TemplateParseResult<ExpressionNode
}
}

pub type TemplateAliasesMap = AliasesMap<TemplateAliasParser>;
pub type TemplateAliasesMap = AliasesMap<TemplateAliasParser, String>;

#[derive(Clone, Debug, Default)]
pub struct TemplateAliasParser;
Expand Down
58 changes: 39 additions & 19 deletions lib/src/dsl_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
//! Domain-specific language helpers.
use std::collections::HashMap;
use std::ops::Deref;
use std::{array, fmt};

use itertools::Itertools as _;
Expand Down Expand Up @@ -360,16 +361,28 @@ impl<R: RuleType> StringLiteralParser<R> {
}

/// Map of symbol and function aliases.
#[derive(Clone, Debug, Default)]
pub struct AliasesMap<P> {
symbol_aliases: HashMap<String, String>,
#[derive(Clone, Debug)]
pub struct AliasesMap<P, V: Deref> {
symbol_aliases: HashMap<String, V>,
// name: [(params, defn)] (sorted by arity)
function_aliases: HashMap<String, Vec<(Vec<String>, String)>>,
function_aliases: HashMap<String, Vec<(Vec<String>, V)>>,
// Parser type P helps prevent misuse of AliasesMap of different language.
parser: P,
}

impl<P> AliasesMap<P> {
// Unfortunately, #[derive(Default)] doesn't work correctly since V isn't
// Default. https://stackoverflow.com/questions/59538071/the-trait-bound-t-stddefaultdefault-is-not-satisfied-when-using-phantomda
impl<P: Default, V: Deref> Default for AliasesMap<P, V> {
fn default() -> Self {
Self {
symbol_aliases: Default::default(),
function_aliases: Default::default(),
parser: Default::default(),
}
}
}

impl<P, V: Deref> AliasesMap<P, V> {
/// Creates an empty aliases map with default-constructed parser.
pub fn new() -> Self
where
Expand All @@ -382,7 +395,7 @@ impl<P> AliasesMap<P> {
///
/// Returns error if `decl` is invalid. The `defn` part isn't checked. A bad
/// `defn` will be reported when the alias is substituted.
pub fn insert(&mut self, decl: impl AsRef<str>, defn: impl Into<String>) -> Result<(), P::Error>
pub fn insert(&mut self, decl: impl AsRef<str>, defn: impl Into<V>) -> Result<(), P::Error>
where
P: AliasDeclarationParser,
{
Expand Down Expand Up @@ -412,46 +425,53 @@ impl<P> AliasesMap<P> {
}

/// Looks up symbol alias by name. Returns identifier and definition text.
pub fn get_symbol(&self, name: &str) -> Option<(AliasId<'_>, &str)> {
pub fn get_symbol(&self, name: &str) -> Option<(AliasId<'_>, &<V as Deref>::Target)> {
self.symbol_aliases
.get_key_value(name)
.map(|(name, defn)| (AliasId::Symbol(name), defn.as_ref()))
.map(|(name, defn)| (AliasId::Symbol(name), defn.deref()))
}

/// Looks up function alias by name and arity. Returns identifier, list of
/// parameter names, and definition text.
pub fn get_function(&self, name: &str, arity: usize) -> Option<(AliasId<'_>, &[String], &str)> {
pub fn get_function(
&self,
name: &str,
arity: usize,
) -> Option<(AliasId<'_>, &[String], &<V as Deref>::Target)> {
let overloads = self.get_function_overloads(name)?;
overloads.find_by_arity(arity)
}

/// Looks up function aliases by name.
fn get_function_overloads(&self, name: &str) -> Option<AliasFunctionOverloads<'_>> {
fn get_function_overloads(&self, name: &str) -> Option<AliasFunctionOverloads<'_, V>> {
let (name, overloads) = self.function_aliases.get_key_value(name)?;
Some(AliasFunctionOverloads { name, overloads })
}
}

#[derive(Clone, Copy, Debug)]
struct AliasFunctionOverloads<'a> {
struct AliasFunctionOverloads<'a, V: Deref> {
name: &'a String,
overloads: &'a Vec<(Vec<String>, String)>,
overloads: &'a Vec<(Vec<String>, V)>,
}

impl<'a> AliasFunctionOverloads<'a> {
fn arities(self) -> impl DoubleEndedIterator<Item = usize> + ExactSizeIterator + 'a {
impl<'a, V: Deref> AliasFunctionOverloads<'a, V> {
fn arities(&self) -> impl DoubleEndedIterator<Item = usize> + ExactSizeIterator + 'a {
self.overloads.iter().map(|(params, _)| params.len())
}

fn min_arity(self) -> usize {
fn min_arity(&self) -> usize {
self.arities().next().unwrap()
}

fn max_arity(self) -> usize {
fn max_arity(&self) -> usize {
self.arities().next_back().unwrap()
}

fn find_by_arity(self, arity: usize) -> Option<(AliasId<'a>, &'a [String], &'a str)> {
fn find_by_arity(
&self,
arity: usize,
) -> Option<(AliasId<'a>, &'a [String], &'a <V as Deref>::Target)> {
let index = self
.overloads
.binary_search_by_key(&arity, |(params, _)| params.len())
Expand Down Expand Up @@ -546,7 +566,7 @@ pub trait AliasExpandError: Sized {
#[derive(Debug)]
struct AliasExpander<'i, T, P> {
/// Alias symbols and functions that are globally available.
aliases_map: &'i AliasesMap<P>,
aliases_map: &'i AliasesMap<P, String>,
/// Stack of aliases and local parameters currently expanding.
states: Vec<AliasExpandingState<'i, T>>,
}
Expand Down Expand Up @@ -645,7 +665,7 @@ where
/// Expands aliases recursively.
pub fn expand_aliases<'i, T, P>(
node: ExpressionNode<'i, T>,
aliases_map: &'i AliasesMap<P>,
aliases_map: &'i AliasesMap<P, String>,
) -> Result<ExpressionNode<'i, T>, P::Error>
where
T: AliasExpandableExpression<'i> + Clone,
Expand Down
2 changes: 1 addition & 1 deletion lib/src/revset_parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -682,7 +682,7 @@ fn parse_function_call_node(pair: Pair<Rule>) -> Result<FunctionCallNode, Revset
})
}

pub type RevsetAliasesMap = AliasesMap<RevsetAliasParser>;
pub type RevsetAliasesMap = AliasesMap<RevsetAliasParser, String>;

#[derive(Clone, Debug, Default)]
pub struct RevsetAliasParser;
Expand Down

0 comments on commit ec0e734

Please sign in to comment.