From 6939cc3556999092c6f0a1f551d2173c28f11ffd Mon Sep 17 00:00:00 2001 From: Yuya Nishihara Date: Thu, 9 May 2024 16:59:55 +0900 Subject: [PATCH] revset: move alias types to separate module Alias expansion is purely substitution of parsed tree, which should belong to the first parsing stage. --- lib/src/revset.rs | 100 +------------------------------------ lib/src/revset_parser.rs | 103 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 103 insertions(+), 100 deletions(-) diff --git a/lib/src/revset.rs b/lib/src/revset.rs index db21c32ae7..85a6c5e797 100644 --- a/lib/src/revset.rs +++ b/lib/src/revset.rs @@ -42,9 +42,9 @@ use crate::object_id::{HexPrefix, PrefixResolution}; use crate::op_store::WorkspaceId; use crate::repo::Repo; use crate::revset_graph::RevsetGraphEdge; +use crate::revset_parser::{RevsetAliasId, RevsetParser, STRING_LITERAL_PARSER}; // TODO: introduce AST types and remove Rule from the re-exports -pub use crate::revset_parser::{RevsetParseError, RevsetParseErrorKind, Rule}; -use crate::revset_parser::{RevsetParser, STRING_LITERAL_PARSER}; +pub use crate::revset_parser::{RevsetAliasesMap, RevsetParseError, RevsetParseErrorKind, Rule}; use crate::store::Store; use crate::str_util::StringPattern; @@ -525,102 +525,6 @@ impl ResolvedExpression { } } -#[derive(Clone, Debug, Default)] -pub struct RevsetAliasesMap { - symbol_aliases: HashMap, - function_aliases: HashMap, String)>, -} - -impl RevsetAliasesMap { - pub fn new() -> Self { - Self::default() - } - - /// Adds new substitution rule `decl = defn`. - /// - /// 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, - defn: impl Into, - ) -> Result<(), RevsetParseError> { - match RevsetAliasDeclaration::parse(decl.as_ref())? { - RevsetAliasDeclaration::Symbol(name) => { - self.symbol_aliases.insert(name, defn.into()); - } - RevsetAliasDeclaration::Function(name, params) => { - self.function_aliases.insert(name, (params, defn.into())); - } - } - Ok(()) - } - - pub fn get_symbol(&self, name: &str) -> Option<&str> { - self.symbol_aliases.get(name).map(|defn| defn.as_ref()) - } - - pub fn get_function(&self, name: &str) -> Option<(&[String], &str)> { - self.function_aliases - .get(name) - .map(|(params, defn)| (params.as_ref(), defn.as_ref())) - } -} - -/// Parsed declaration part of alias rule. -#[derive(Clone, Debug)] -enum RevsetAliasDeclaration { - Symbol(String), - Function(String, Vec), -} - -impl RevsetAliasDeclaration { - fn parse(source: &str) -> Result { - let mut pairs = RevsetParser::parse(Rule::alias_declaration, source)?; - let first = pairs.next().unwrap(); - match first.as_rule() { - Rule::identifier => Ok(RevsetAliasDeclaration::Symbol(first.as_str().to_owned())), - Rule::function_name => { - let name = first.as_str().to_owned(); - let params_pair = pairs.next().unwrap(); - let params_span = params_pair.as_span(); - let params = params_pair - .into_inner() - .map(|pair| match pair.as_rule() { - Rule::identifier => pair.as_str().to_owned(), - r => panic!("unexpected formal parameter rule {r:?}"), - }) - .collect_vec(); - if params.iter().all_unique() { - Ok(RevsetAliasDeclaration::Function(name, params)) - } else { - Err(RevsetParseError::with_span( - RevsetParseErrorKind::RedefinedFunctionParameter, - params_span, - )) - } - } - r => panic!("unexpected alias declaration rule {r:?}"), - } - } -} - -/// Borrowed reference to identify alias expression. -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -enum RevsetAliasId<'a> { - Symbol(&'a str), - Function(&'a str), -} - -impl fmt::Display for RevsetAliasId<'_> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - RevsetAliasId::Symbol(name) => write!(f, "{name}"), - RevsetAliasId::Function(name) => write!(f, "{name}()"), - } - } -} - #[derive(Clone, Copy, Debug)] pub struct ParseState<'a> { function_map: &'a HashMap<&'static str, RevsetFunction>, diff --git a/lib/src/revset_parser.rs b/lib/src/revset_parser.rs index 6e35fe1d6a..3de981a41f 100644 --- a/lib/src/revset_parser.rs +++ b/lib/src/revset_parser.rs @@ -14,9 +14,11 @@ #![allow(missing_docs)] -use std::collections::HashSet; -use std::error; +use std::collections::{HashMap, HashSet}; +use std::{error, fmt}; +use itertools::Itertools as _; +use pest::Parser; use pest_derive::Parser; use thiserror::Error; @@ -236,3 +238,100 @@ fn rename_rules_in_pest_error(mut err: pest::error::Error) -> pest::error: .unwrap_or_else(|| format!("<{rule:?}>")) }) } + +#[derive(Clone, Debug, Default)] +pub struct RevsetAliasesMap { + symbol_aliases: HashMap, + // TODO: remove pub(super) + pub(super) function_aliases: HashMap, String)>, +} + +impl RevsetAliasesMap { + pub fn new() -> Self { + Self::default() + } + + /// Adds new substitution rule `decl = defn`. + /// + /// 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, + defn: impl Into, + ) -> Result<(), RevsetParseError> { + match RevsetAliasDeclaration::parse(decl.as_ref())? { + RevsetAliasDeclaration::Symbol(name) => { + self.symbol_aliases.insert(name, defn.into()); + } + RevsetAliasDeclaration::Function(name, params) => { + self.function_aliases.insert(name, (params, defn.into())); + } + } + Ok(()) + } + + pub fn get_symbol(&self, name: &str) -> Option<&str> { + self.symbol_aliases.get(name).map(|defn| defn.as_ref()) + } + + pub fn get_function(&self, name: &str) -> Option<(&[String], &str)> { + self.function_aliases + .get(name) + .map(|(params, defn)| (params.as_ref(), defn.as_ref())) + } +} + +/// Parsed declaration part of alias rule. +#[derive(Clone, Debug)] +enum RevsetAliasDeclaration { + Symbol(String), + Function(String, Vec), +} + +impl RevsetAliasDeclaration { + fn parse(source: &str) -> Result { + let mut pairs = RevsetParser::parse(Rule::alias_declaration, source)?; + let first = pairs.next().unwrap(); + match first.as_rule() { + Rule::identifier => Ok(RevsetAliasDeclaration::Symbol(first.as_str().to_owned())), + Rule::function_name => { + let name = first.as_str().to_owned(); + let params_pair = pairs.next().unwrap(); + let params_span = params_pair.as_span(); + let params = params_pair + .into_inner() + .map(|pair| match pair.as_rule() { + Rule::identifier => pair.as_str().to_owned(), + r => panic!("unexpected formal parameter rule {r:?}"), + }) + .collect_vec(); + if params.iter().all_unique() { + Ok(RevsetAliasDeclaration::Function(name, params)) + } else { + Err(RevsetParseError::with_span( + RevsetParseErrorKind::RedefinedFunctionParameter, + params_span, + )) + } + } + r => panic!("unexpected alias declaration rule {r:?}"), + } + } +} + +/// Borrowed reference to identify alias expression. +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub(super) enum RevsetAliasId<'a> { + Symbol(&'a str), + Function(&'a str), +} + +impl fmt::Display for RevsetAliasId<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + RevsetAliasId::Symbol(name) => write!(f, "{name}"), + RevsetAliasId::Function(name) => write!(f, "{name}()"), + } + } +}