diff --git a/crates/core/src/binding.rs b/crates/core/src/binding.rs index 77c91e45a..41ccc5e52 100644 --- a/crates/core/src/binding.rs +++ b/crates/core/src/binding.rs @@ -80,16 +80,16 @@ pub enum Binding<'a> { impl PartialEq for Binding<'_> { fn eq(&self, other: &Self) -> bool { match (self, other) { - (Self::Empty(_, _, _), Self::Empty(_, _, _)) => true, - (Self::Node(src1, n1), Self::Node(src2, n2)) => { + (Binding::Empty(_, _, _), Binding::Empty(_, _, _)) => true, + (Binding::Node(src1, n1), Binding::Node(src2, n2)) => { n1.utf8_text(src1.as_bytes()) == n2.utf8_text(src2.as_bytes()) } - (Self::String(src1, r1), Self::String(src2, r2)) => { + (Binding::String(src1, r1), Binding::String(src2, r2)) => { src1[r1.start_byte as usize..r1.end_byte as usize] == src2[r2.start_byte as usize..r2.end_byte as usize] } - (Self::List(_, n1, f1), Self::List(_, n2, f2)) => n1 == n2 && f1 == f2, - (Self::ConstantRef(c1), Self::ConstantRef(c2)) => c1 == c2, + (Binding::List(_, n1, f1), Binding::List(_, n2, f2)) => n1 == n2 && f1 == f2, + (Binding::ConstantRef(c1), Binding::ConstantRef(c2)) => c1 == c2, _ => false, } } @@ -307,22 +307,10 @@ pub(crate) fn linearize_binding<'a>( } impl<'a> Binding<'a> { - pub(crate) fn from_constant(constant: &'a Constant) -> Self { - Self::ConstantRef(constant) - } - pub(crate) fn from_node(node: NodeWithSource<'a>) -> Self { Self::Node(node.source, node.node) } - pub(crate) fn from_path(path: &'a Path) -> Self { - Self::FileName(path) - } - - pub(crate) fn from_range(range: Range, source: &'a str) -> Self { - Self::String(source, range) - } - /// Returns the only node bound by this binding. /// /// This includes list bindings that only match a single child. @@ -351,8 +339,8 @@ impl<'a> Binding<'a> { pub fn get_sexp(&self) -> Option { match self { - Self::Node(_, node) => Some(node.to_sexp().to_string()), - Self::List(_, parent_node, field_id) => { + Binding::Node(_, node) => Some(node.to_sexp().to_string()), + Binding::List(_, parent_node, field_id) => { let mut cursor = parent_node.walk(); let mut children = parent_node.children_by_field_id(*field_id, &mut cursor); let mut result = String::new(); @@ -365,17 +353,20 @@ impl<'a> Binding<'a> { } Some(result) } - Self::String(..) | Self::FileName(_) | Self::Empty(..) | Self::ConstantRef(_) => None, + Binding::String(..) + | Binding::FileName(_) + | Binding::Empty(..) + | Binding::ConstantRef(_) => None, } } // todo implement for empty and empty list pub fn position(&self) -> Option { match self { - Self::Empty(_, _, _) => None, - Self::Node(_, node) => Some(Range::from(node.range())), - Self::String(_, range) => Some(range.to_owned()), - Self::List(_, parent_node, field_id) => { + Binding::Empty(_, _, _) => None, + Binding::Node(_, node) => Some(Range::from(node.range())), + Binding::String(_, range) => Some(range.to_owned()), + Binding::List(_, parent_node, field_id) => { let mut cursor = parent_node.walk(); let mut children = parent_node.children_by_field_id(*field_id, &mut cursor); @@ -417,8 +408,8 @@ impl<'a> Binding<'a> { } } } - Self::FileName(_) => None, - Self::ConstantRef(_) => None, + Binding::FileName(_) => None, + Binding::ConstantRef(_) => None, } } @@ -432,8 +423,8 @@ impl<'a> Binding<'a> { logs: &mut AnalysisLogs, ) -> Result> { let res: Result> = match self { - Self::Empty(_, _, _) => Ok(Cow::Borrowed("")), - Self::Node(source, node) => { + Binding::Empty(_, _, _) => Ok(Cow::Borrowed("")), + Binding::Node(source, node) => { let range = CodeRange::from_node(source, node); linearize_binding( language, @@ -449,11 +440,11 @@ impl<'a> Binding<'a> { } // can't linearize until we update source to point to the entire file // otherwise file file pointers won't match - Self::String(s, r) => Ok(Cow::Owned( + Binding::String(s, r) => Ok(Cow::Owned( s[r.start_byte as usize..r.end_byte as usize].into(), )), - Self::FileName(s) => Ok(Cow::Owned(s.to_string_lossy().into())), - Self::List(source, _parent_node, _field_id) => { + Binding::FileName(s) => Ok(Cow::Owned(s.to_string_lossy().into())), + Binding::List(source, _parent_node, _field_id) => { if let Some(pos) = self.position() { let range = CodeRange::new(pos.start_byte, pos.end_byte, source); linearize_binding( @@ -471,37 +462,37 @@ impl<'a> Binding<'a> { Ok("".into()) } } - Self::ConstantRef(c) => Ok(Cow::Owned(c.to_string())), + Binding::ConstantRef(c) => Ok(Cow::Owned(c.to_string())), }; res } pub fn text(&self) -> String { match self { - Self::Empty(_, _, _) => "".to_string(), - Self::Node(source, node) => { + Binding::Empty(_, _, _) => "".to_string(), + Binding::Node(source, node) => { NodeWithSource::new(node.clone(), source).text().to_string() } - Self::String(s, r) => s[r.start_byte as usize..r.end_byte as usize].into(), - Self::FileName(s) => s.to_string_lossy().into(), - Self::List(source, _, _) => { + Binding::String(s, r) => s[r.start_byte as usize..r.end_byte as usize].into(), + Binding::FileName(s) => s.to_string_lossy().into(), + Binding::List(source, _, _) => { if let Some(pos) = self.position() { source[pos.start_byte as usize..pos.end_byte as usize].to_string() } else { "".to_string() } } - Self::ConstantRef(c) => c.to_string(), + Binding::ConstantRef(c) => c.to_string(), } } pub fn source(&self) -> Option<&'a str> { match self { - Self::Empty(source, _, _) => Some(source), - Self::Node(source, _) => Some(source), - Self::String(source, _) => Some(source), - Self::List(source, _, _) => Some(source), - Self::FileName(..) | Self::ConstantRef(..) => None, + Binding::Empty(source, _, _) => Some(source), + Binding::Node(source, _) => Some(source), + Binding::String(source, _) => Some(source), + Binding::List(source, _, _) => Some(source), + Binding::FileName(..) | Binding::ConstantRef(..) => None, } } diff --git a/crates/core/src/pattern/after.rs b/crates/core/src/pattern/after.rs index 77bb4c9ee..698826ef6 100644 --- a/crates/core/src/pattern/after.rs +++ b/crates/core/src/pattern/after.rs @@ -5,11 +5,12 @@ use super::{ variable::VariableSourceLocations, Node, State, }; +use crate::{binding::Binding, context::Context, resolve}; use crate::{binding::Constant, errors::debug}; -use crate::{context::Context, resolve}; use anyhow::{anyhow, bail, Result}; use core::fmt::Debug; use grit_util::AstNode; +use im::vector; use marzano_util::analysis_logs::AnalysisLogs; use std::collections::BTreeMap; @@ -60,7 +61,7 @@ impl After { }; if let Some(next) = node.next_non_trivia_node() { - Ok(ResolvedPattern::from_node(next)) + Ok(ResolvedPattern::Binding(vector![Binding::from_node(next)])) } else { debug( logs, diff --git a/crates/core/src/pattern/ast_node.rs b/crates/core/src/pattern/ast_node.rs index b1f073585..c0804e913 100644 --- a/crates/core/src/pattern/ast_node.rs +++ b/crates/core/src/pattern/ast_node.rs @@ -7,7 +7,7 @@ use super::{ variable::VariableSourceLocations, State, }; -use crate::{context::Context, resolve}; +use crate::{binding::Binding, context::Context, resolve}; use anyhow::{anyhow, Result}; use itertools::Itertools; use marzano_language::language::{FieldId, Language, SortId}; @@ -163,7 +163,12 @@ impl Matcher for ASTNode { return Ok(false); }; if binding.is_list() { - return self.execute(&ResolvedPattern::from_node(node), init_state, context, logs); + return self.execute( + &ResolvedPattern::from_binding(Binding::from_node(node)), + init_state, + context, + logs, + ); } let NodeWithSource { node, source } = node; @@ -176,9 +181,10 @@ impl Matcher for ASTNode { if context.language().is_comment(self.sort) { let content = context.language().comment_text(&node, source); let content = resolve!(content); + let content = Binding::String(source, content.1); return self.args[0].2.execute( - &ResolvedPattern::from_range(content.1, source), + &ResolvedPattern::from_binding(content), init_state, context, logs, diff --git a/crates/core/src/pattern/before.rs b/crates/core/src/pattern/before.rs index 65231249b..0b5c682e1 100644 --- a/crates/core/src/pattern/before.rs +++ b/crates/core/src/pattern/before.rs @@ -5,11 +5,12 @@ use super::{ variable::VariableSourceLocations, Node, State, }; +use crate::{binding::Binding, context::Context, resolve}; use crate::{binding::Constant, errors::debug}; -use crate::{context::Context, resolve}; use anyhow::{anyhow, bail, Result}; use core::fmt::Debug; use grit_util::AstNode; +use im::vector; use marzano_util::analysis_logs::AnalysisLogs; use std::collections::BTreeMap; @@ -60,7 +61,7 @@ impl Before { }; if let Some(prev) = node.previous_non_trivia_node() { - Ok(ResolvedPattern::from_node(prev)) + Ok(ResolvedPattern::Binding(vector![Binding::from_node(prev)])) } else { debug( logs, diff --git a/crates/core/src/pattern/list_index.rs b/crates/core/src/pattern/list_index.rs index 634dc7d90..29dfc2047 100644 --- a/crates/core/src/pattern/list_index.rs +++ b/crates/core/src/pattern/list_index.rs @@ -168,9 +168,9 @@ impl ListIndex { let len = list_items.clone().count(); let index = resolve_opt!(to_unsigned(index, len)); - Ok(list_items + return Ok(list_items .nth(index) - .map(|_| PatternOrResolvedMut::_ResolvedBinding)) + .map(|_| PatternOrResolvedMut::_ResolvedBinding)); } Some(PatternOrResolvedMut::Resolved(ResolvedPattern::List(l))) => { let index = resolve_opt!(to_unsigned(index, l.len())); diff --git a/crates/core/src/pattern/or.rs b/crates/core/src/pattern/or.rs index 637a608f1..d7a43a4ba 100644 --- a/crates/core/src/pattern/or.rs +++ b/crates/core/src/pattern/or.rs @@ -74,10 +74,10 @@ impl Matcher for Or { if let ResolvedPattern::Binding(binding_vector) = &binding { for p in self.patterns.iter() { // filter out pattern which cannot match because of a mismatched node type - if let (Some(binding_node), Pattern::ASTNode(node_pattern)) = - (binding_vector.last().and_then(Binding::as_node), p) + if let (Binding::Node(_src, binding_node), Pattern::ASTNode(node_pattern)) = + (binding_vector.last().unwrap(), p) { - if node_pattern.sort != binding_node.node.kind_id() { + if node_pattern.sort != binding_node.kind_id() { continue; } } diff --git a/crates/core/src/pattern/regex.rs b/crates/core/src/pattern/regex.rs index 9c905a1f4..9d15fee43 100644 --- a/crates/core/src/pattern/regex.rs +++ b/crates/core/src/pattern/regex.rs @@ -6,9 +6,10 @@ use super::{ variable::{Variable, VariableSourceLocations}, State, }; -use crate::context::Context; +use crate::{binding::Binding, context::Context}; use anyhow::{anyhow, bail, Result}; use core::fmt::Debug; +use im::vector; use marzano_language::{language::Language, target_language::TargetLanguage}; use marzano_util::analysis_logs::{AnalysisLogBuilder, AnalysisLogs}; use marzano_util::position::Range; @@ -200,7 +201,7 @@ impl RegexPattern { // have a Range for String bindings? position.end_byte = position.start_byte + range.end as u32; position.start_byte += range.start as u32; - ResolvedPattern::from_range(position, source) + ResolvedPattern::Binding(vector![Binding::String(source, position)]) } else { ResolvedPattern::from_string(value.to_string()) } diff --git a/crates/core/src/pattern/resolved_pattern.rs b/crates/core/src/pattern/resolved_pattern.rs index 25d178db3..7917bf188 100644 --- a/crates/core/src/pattern/resolved_pattern.rs +++ b/crates/core/src/pattern/resolved_pattern.rs @@ -23,7 +23,6 @@ use marzano_util::{ use std::{ borrow::Cow, collections::{BTreeMap, HashMap}, - path::Path, }; use tree_sitter::Node; @@ -57,7 +56,9 @@ impl<'a> File<'a> { pub(crate) fn name(&self, files: &FileRegistry<'a>) -> ResolvedPattern<'a> { match self { File::Resolved(resolved) => resolved.name.clone(), - File::Ptr(ptr) => ResolvedPattern::from_path(&files.get_file(*ptr).name), + File::Ptr(ptr) => { + ResolvedPattern::Binding(vector![Binding::FileName(&files.get_file(*ptr).name)]) + } } } @@ -68,9 +69,9 @@ impl<'a> File<'a> { let absolute_path = absolutize(name.as_ref())?; Ok(ResolvedPattern::Constant(Constant::String(absolute_path))) } - File::Ptr(ptr) => Ok(ResolvedPattern::from_path( - &files.get_file(*ptr).absolute_path, - )), + File::Ptr(ptr) => Ok(ResolvedPattern::Binding(vector![Binding::FileName( + &files.get_file(*ptr).absolute_path + )])), } } @@ -80,7 +81,7 @@ impl<'a> File<'a> { File::Ptr(ptr) => { let file = &files.get_file(*ptr); let range = file.tree.root_node().range().into(); - ResolvedPattern::from_range(range, &file.source) + ResolvedPattern::Binding(vector![Binding::String(&file.source, range)]) } } } @@ -91,7 +92,7 @@ impl<'a> File<'a> { File::Ptr(ptr) => { let file = &files.get_file(*ptr); let node = file.tree.root_node(); - ResolvedPattern::from_node(NodeWithSource::new(node, &file.source)) + ResolvedPattern::Binding(vector![Binding::Node(&file.source, node)]) } } } @@ -417,27 +418,19 @@ impl<'a> ResolvedPattern<'a> { } pub fn from_constant(constant: &'a Constant) -> Self { - Self::from_binding(Binding::from_constant(constant)) + Self::Binding(vector![Binding::ConstantRef(constant)]) } pub(crate) fn from_node(node: NodeWithSource<'a>) -> Self { - Self::from_binding(Binding::from_node(node)) + Self::Binding(vector![Binding::Node(node.source, node.node)]) } pub(crate) fn from_list(src: &'a str, node: Node<'a>, field_id: FieldId) -> Self { - Self::from_binding(Binding::List(src, node, field_id)) + Self::Binding(vector![Binding::List(src, node, field_id)]) } pub(crate) fn empty_field(src: &'a str, node: Node<'a>, field_id: FieldId) -> Self { - Self::from_binding(Binding::Empty(src, node, field_id)) - } - - pub(crate) fn from_path(path: &'a Path) -> Self { - Self::from_binding(Binding::from_path(path)) - } - - pub(crate) fn from_range(range: Range, src: &'a str) -> Self { - Self::from_binding(Binding::from_range(range, src)) + Self::Binding(vector![Binding::Empty(src, node, field_id)]) } pub fn from_string(string: String) -> Self { @@ -878,10 +871,9 @@ impl<'a> ResolvedPattern<'a> { pub(crate) fn matches_undefined(&self) -> bool { match self { - ResolvedPattern::Binding(b) => b - .last() - .and_then(Binding::as_constant) - .map_or(false, |c| c == &Constant::Undefined), + ResolvedPattern::Binding(b) => { + matches!(b.last(), Some(Binding::ConstantRef(Constant::Undefined))) + } ResolvedPattern::Constant(Constant::Undefined) => true, ResolvedPattern::Constant(_) | ResolvedPattern::Snippets(_) diff --git a/crates/core/src/text_unparser.rs b/crates/core/src/text_unparser.rs index c1b99b5e3..89b54d8b2 100644 --- a/crates/core/src/text_unparser.rs +++ b/crates/core/src/text_unparser.rs @@ -1,4 +1,4 @@ -use crate::binding::linearize_binding; +use crate::binding::{linearize_binding, Binding}; use crate::pattern::resolved_pattern::CodeRange; use crate::pattern::state::FileRegistry; use crate::pattern::Effect; @@ -46,8 +46,8 @@ pub(crate) fn apply_effects<'a>( logs, )?; for effect in effects.iter() { - if let Some(filename) = effect.binding.as_filename() { - if std::ptr::eq(filename, the_filename) { + if let Binding::FileName(c) = effect.binding { + if std::ptr::eq(c, the_filename) { let snippet = effect .pattern .linearized_text(language, &effects, files, &mut memo, false, logs)?;