From bf19918e3c70a51558e6d975bace0666f780c736 Mon Sep 17 00:00:00 2001 From: JT Date: Mon, 9 Aug 2021 12:19:07 +1200 Subject: [PATCH] begin aliases --- src/eval.rs | 2 ++ src/main.rs | 2 +- src/parser.rs | 51 ++++++++++++++++++++++++++++++++++++++++++--- src/parser_state.rs | 28 +++++++++++++++++++++++++ 4 files changed, 79 insertions(+), 4 deletions(-) diff --git a/src/eval.rs b/src/eval.rs index 958256653..20c2b71f9 100644 --- a/src/eval.rs +++ b/src/eval.rs @@ -359,6 +359,8 @@ fn eval_call(state: &State, stack: Stack, call: &Call) -> Result std::io::Result<()> { working_set.add_decl(sig.into()); let sig = Signature::build("alias") - .required("var_name", SyntaxShape::Variable, "variable name") + .required("name", SyntaxShape::String, "name of the alias") .required( "initial_value", SyntaxShape::Keyword(b"=".to_vec(), Box::new(SyntaxShape::Expression)), diff --git a/src/parser.rs b/src/parser.rs index 12e4821af..e8786248c 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -782,13 +782,17 @@ impl<'a> ParserWorkingSet<'a> { (Box::new(call), span(spans), error) } - pub fn parse_call(&mut self, spans: &[Span]) -> (Expression, Option) { + pub fn parse_call( + &mut self, + spans: &[Span], + expand_aliases: bool, + ) -> (Expression, Option) { // assume spans.len() > 0? let mut pos = 0; let mut shorthand = vec![]; while pos < spans.len() { - // First, check if there is any environment shorthand + // Check if there is any environment shorthand let name = self.get_span_contents(spans[pos]); let split: Vec<_> = name.splitn(2, |x| *x == b'=').collect(); if split.len() == 2 { @@ -807,6 +811,21 @@ impl<'a> ParserWorkingSet<'a> { } let name = self.get_span_contents(spans[pos]); + + if expand_aliases { + if let Some(expansion) = self.find_alias(name) { + //let mut spans = spans.to_vec(); + let mut new_spans: Vec = vec![]; + new_spans.extend(&spans[0..pos]); + new_spans.extend(expansion); + if spans.len() > pos { + new_spans.extend(&spans[(pos + 1)..]); + } + + return self.parse_call(&new_spans, false); + } + } + pos += 1; if let Some(mut decl_id) = self.find_decl(name) { @@ -2115,7 +2134,7 @@ impl<'a> ParserWorkingSet<'a> { match bytes[0] { b'0' | b'1' | b'2' | b'3' | b'4' | b'5' | b'6' | b'7' | b'8' | b'9' | b'(' | b'{' | b'[' | b'$' | b'"' | b'\'' => self.parse_math_expression(spans), - _ => self.parse_call(spans), + _ => self.parse_call(spans, true), } } @@ -2234,6 +2253,30 @@ impl<'a> ParserWorkingSet<'a> { } } + pub fn parse_alias(&mut self, spans: &[Span]) -> (Statement, Option) { + let name = self.get_span_contents(spans[0]); + + if name == b"alias" && spans.len() >= 4 { + let alias_name = self.get_span_contents(spans[1]).to_vec(); + let _equals = self.get_span_contents(spans[2]); + + let replacement = spans[3..].to_vec(); + + self.add_alias(alias_name, replacement); + } + ( + Statement::Expression(Expression { + expr: Expr::Garbage, + span: span(spans), + ty: Type::Unknown, + }), + Some(ParseError::UnknownState( + "internal error: let statement unparseable".into(), + span(spans), + )), + ) + } + pub fn parse_let(&mut self, spans: &[Span]) -> (Statement, Option) { let name = self.get_span_contents(spans[0]); @@ -2271,6 +2314,8 @@ impl<'a> ParserWorkingSet<'a> { (decl, None) } else if let (stmt, None) = self.parse_let(spans) { (stmt, None) + } else if let (stmt, None) = self.parse_alias(spans) { + (stmt, None) } else { let (expr, err) = self.parse_expression(spans); (Statement::Expression(expr), err) diff --git a/src/parser_state.rs b/src/parser_state.rs index c53c8f350..db5d721e5 100644 --- a/src/parser_state.rs +++ b/src/parser_state.rs @@ -36,6 +36,7 @@ pub type BlockId = usize; struct ScopeFrame { vars: HashMap, VarId>, decls: HashMap, DeclId>, + aliases: HashMap, Vec>, } impl ScopeFrame { @@ -43,6 +44,7 @@ impl ScopeFrame { Self { vars: HashMap::new(), decls: HashMap::new(), + aliases: HashMap::new(), } } } @@ -352,6 +354,22 @@ impl<'a> ParserWorkingSet<'a> { None } + pub fn find_alias(&self, name: &[u8]) -> Option<&[Span]> { + for scope in self.delta.scope.iter().rev() { + if let Some(spans) = scope.aliases.get(name) { + return Some(spans); + } + } + + for scope in self.permanent_state.scope.iter().rev() { + if let Some(spans) = scope.aliases.get(name) { + return Some(spans); + } + } + + None + } + pub fn add_variable(&mut self, mut name: Vec, ty: Type) -> VarId { let next_id = self.next_var_id(); @@ -373,6 +391,16 @@ impl<'a> ParserWorkingSet<'a> { next_id } + pub fn add_alias(&mut self, name: Vec, replacement: Vec) { + let last = self + .delta + .scope + .last_mut() + .expect("internal error: missing stack frame"); + + last.aliases.insert(name, replacement); + } + pub fn set_variable_type(&mut self, var_id: VarId, ty: Type) { let num_permanent_vars = self.permanent_state.num_vars(); if var_id < num_permanent_vars {