Skip to content

Commit

Permalink
Implement Binding::list_items()
Browse files Browse the repository at this point in the history
  • Loading branch information
arendjr committed Mar 27, 2024
1 parent 04d768d commit a557361
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 71 deletions.
39 changes: 39 additions & 0 deletions crates/core/src/binding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use marzano_util::analysis_logs::{AnalysisLogBuilder, AnalysisLogs};
use marzano_util::node_with_source::NodeWithSource;
use marzano_util::position::{Position, Range};
use marzano_util::tree_sitter_util::children_by_field_id_count;
use std::iter;
use std::ops::Range as StdRange;
use std::path::Path;
use std::{borrow::Cow, collections::HashMap, fmt::Display};
Expand Down Expand Up @@ -522,6 +523,44 @@ impl<'a> Binding<'a> {
matches!(self, Self::List(..))
}

/// Returns an iterator over the items in a list.
///
/// Returns `None` if the binding is not bound to a list.
pub(crate) fn list_items(&self) -> Option<impl Iterator<Item = NodeWithSource<'a>>> {
match self {
Self::List(src, node, field_id) => {
let field_id = *field_id;
let mut cursor = node.walk();
cursor.goto_first_child();
let mut done = false;
Some(
iter::from_fn(move || {
while !done {
while cursor.field_id() != Some(field_id) {
if !cursor.goto_next_sibling() {
return None;
}
}
let result = cursor.node();
if !cursor.goto_next_sibling() {
done = true;
}
return Some(result);
}
None
})
.filter(|child| child.is_named())
.map(|named_child| NodeWithSource::new(named_child, src)),
)
}
Self::Empty(..)
| Self::Node(..)
| Self::String(..)
| Self::ConstantRef(..)
| Self::FileName(..) => None,
}
}

/// Returns the parent node of this binding.
///
/// Returns `None` if the binding has no relation to a node.
Expand Down
37 changes: 13 additions & 24 deletions crates/core/src/pattern/every.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use super::{
variable::VariableSourceLocations,
State,
};
use crate::{binding::Binding, context::Context, resolve};
use crate::{context::Context, resolve};
use anyhow::{anyhow, Result};
use im::vector;
use marzano_util::analysis_logs::AnalysisLogs;
Expand Down Expand Up @@ -67,32 +67,21 @@ impl Matcher for Every {
match binding {
ResolvedPattern::Binding(bindings) => {
let binding = resolve!(bindings.last());
let pattern = &self.pattern;
let Some(list_items) = binding.list_items() else {
return Ok(false);
};

match binding {
Binding::Empty(_, _, _) => Ok(false),
Binding::Node(_, _node) => Ok(false),
Binding::String(_, _) => Ok(false),
Binding::List(src, node, field_id) => {
let mut cursor = node.walk();
let children = node
.children_by_field_id(*field_id, &mut cursor)
.filter(|c| c.is_named());
for child in children {
if !pattern.execute(
&ResolvedPattern::from_node(src, child),
init_state,
context,
logs,
)? {
return Ok(false);
}
}
Ok(true)
for item in list_items {
if !self.pattern.execute(
&ResolvedPattern::from_node(item.source, item.node),
init_state,
context,
logs,
)? {
return Ok(false);
}
Binding::ConstantRef(_) => Ok(false),
Binding::FileName(_) => Ok(false),
}
Ok(true)
}
ResolvedPattern::List(elements) => {
let pattern = &self.pattern;
Expand Down
22 changes: 8 additions & 14 deletions crates/core/src/pattern/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use super::{
state::State,
variable::VariableSourceLocations,
};
use crate::{binding::Binding, context::Context};
use crate::context::Context;
use anyhow::{anyhow, bail, Result};
use core::fmt::Debug;
use marzano_language::language::Field;
Expand Down Expand Up @@ -121,21 +121,15 @@ impl Matcher for List {
) -> Result<bool> {
match binding {
ResolvedPattern::Binding(v) => {
if let Some(Binding::List(src, node, field_id)) = v.last() {
let mut cursor = node.walk();
let Some(list_items) = v.last().and_then(|b| b.list_items()) else {
return Ok(false);
};

let children_vec: Vec<Cow<ResolvedPattern>> = node
.children_by_field_id(*field_id, &mut cursor)
.filter(|n| n.is_named())
.map(|node| Cow::Owned(ResolvedPattern::from_node(src, node)))
.collect();
let children: Vec<Cow<ResolvedPattern>> = list_items
.map(|node| Cow::Owned(ResolvedPattern::from_node(node.source, node.node)))
.collect();

let children: &[Cow<ResolvedPattern>] = &children_vec;
let patterns: &[Pattern] = &self.patterns;
execute_assoc(patterns, children, state, context, logs)
} else {
Ok(false)
}
execute_assoc(&self.patterns, &children, state, context, logs)
}
ResolvedPattern::List(patterns) => {
let patterns: Vec<Cow<ResolvedPattern<'_>>> =
Expand Down
54 changes: 21 additions & 33 deletions crates/core/src/pattern/some.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
use anyhow::{anyhow, Result};
use im::vector;

use crate::{binding::Binding, context::Context, resolve};

use super::{
compiler::CompilationContext,
patterns::{Matcher, Name, Pattern},
resolved_pattern::ResolvedPattern,
variable::VariableSourceLocations,
State,
};
use crate::{context::Context, resolve};
use anyhow::{anyhow, Result};
use im::vector;
use marzano_util::analysis_logs::AnalysisLogs;
use std::collections::BTreeMap;
use tree_sitter::Node;
Expand Down Expand Up @@ -67,37 +65,27 @@ impl Matcher for Some {
match binding {
ResolvedPattern::Binding(bindings) => {
let binding = resolve!(bindings.last());
let Some(list_items) = binding.list_items() else {
return Ok(false);
};

let mut did_match = false;
let pattern = &self.pattern;
match binding {
Binding::Empty(_, _, _) => Ok(false),
Binding::Node(_, _node) => Ok(false),
Binding::String(_, _) => Ok(false),
Binding::List(src, node, field_id) => {
let mut cur_state = init_state.clone();
let mut cursor = node.walk();
let children = node
.children_by_field_id(*field_id, &mut cursor)
.filter(|c| c.is_named());
for child in children {
let state = cur_state.clone();
if pattern.execute(
&ResolvedPattern::from_node(src, child),
&mut cur_state,
context,
logs,
)? {
did_match = true;
} else {
cur_state = state;
}
}
*init_state = cur_state;
Ok(did_match)
let mut cur_state = init_state.clone();
for item in list_items {
let state = cur_state.clone();
if self.pattern.execute(
&ResolvedPattern::from_node(item.source, item.node),
&mut cur_state,
context,
logs,
)? {
did_match = true;
} else {
cur_state = state;
}
Binding::ConstantRef(_) => Ok(false),
Binding::FileName(_) => Ok(false),
}
*init_state = cur_state;
Ok(did_match)
}
ResolvedPattern::List(elements) => {
let pattern = &self.pattern;
Expand Down

0 comments on commit a557361

Please sign in to comment.