diff --git a/mps-interpreter/src/lang/filter.rs b/mps-interpreter/src/lang/filter.rs index 5cab577..1d39329 100644 --- a/mps-interpreter/src/lang/filter.rs +++ b/mps-interpreter/src/lang/filter.rs @@ -323,7 +323,7 @@ impl + 'static> pub fn new(factory: F) -> Self { Self { filter_factory: factory, - idc: PhantomData::default(), + idc: PhantomData::

, } } } diff --git a/mps-interpreter/src/lang/vocabulary/filters/index_filter.rs b/mps-interpreter/src/lang/vocabulary/filters/index_filter.rs index d18a9c4..f2ee9ad 100644 --- a/mps-interpreter/src/lang/vocabulary/filters/index_filter.rs +++ b/mps-interpreter/src/lang/vocabulary/filters/index_filter.rs @@ -4,7 +4,7 @@ use std::fmt::{Debug, Display, Error, Formatter}; use crate::lang::{MpsLanguageDictionary, MpsTypePrimitive}; use crate::lang::{MpsFilterFactory, MpsFilterPredicate, MpsFilterStatementFactory}; use crate::lang::{RuntimeError, SyntaxError}; -use crate::lang::Lookup; +use crate::lang::{Lookup, utility::assert_token_raw}; use crate::processing::{OpGetter, general::MpsType}; use crate::tokens::MpsToken; use crate::MpsContext; @@ -16,6 +16,7 @@ pub struct IndexFilter { // state current: u64, complete: bool, + is_opposite: bool, } impl Display for IndexFilter { @@ -48,10 +49,13 @@ impl MpsFilterPredicate for IndexFilter { msg: format!("Cannot use {} as index", val), }) }; - if self.current == index { + if self.current == index && !self.is_opposite { self.current += 1; self.complete = true; Ok(true) + } else if self.current != index && self.is_opposite { + self.current += 1; + Ok(true) } else { self.current += 1; Ok(false) @@ -73,8 +77,14 @@ pub struct IndexFilterFactory; impl MpsFilterFactory for IndexFilterFactory { fn is_filter(&self, tokens: &VecDeque<&MpsToken>) -> bool { - tokens.len() == 1 - && Lookup::check_is(&tokens[0]) + ( + tokens.len() == 1 + && Lookup::check_is(&tokens[0]) + ) || ( + tokens.len() == 2 + && tokens[0].is_exclamation() + && Lookup::check_is(&tokens[1]) + ) } fn build_filter( @@ -82,11 +92,16 @@ impl MpsFilterFactory for IndexFilterFactory { tokens: &mut VecDeque, _dict: &MpsLanguageDictionary, ) -> Result { + let is_inverted = if tokens[0].is_exclamation() { + assert_token_raw(MpsToken::Exclamation, tokens)?; + true + } else {false}; let lookup = Lookup::parse(tokens)?; Ok(IndexFilter { index: lookup, current: 0, complete: false, + is_opposite: is_inverted, }) } } diff --git a/mps-interpreter/tests/single_line.rs b/mps-interpreter/tests/single_line.rs index 41f4406..030b1cc 100644 --- a/mps-interpreter/tests/single_line.rs +++ b/mps-interpreter/tests/single_line.rs @@ -210,6 +210,11 @@ fn execute_indexfilter_line() -> Result<(), Box> { false, true, )?; + execute_single_line( + "files(`~/Music/MusicFlac/Bruno Mars/24K Magic/`).(!0)", + false, + true, + )?; execute_single_line( "files(`~/Music/MusicFlac/Bruno Mars/24K Magic/`).(200)", true, @@ -252,5 +257,10 @@ fn execute_orfilter_line() -> Result<(), Box> { "files(`~/Music/MusicFlac/Bruno Mars/24K Magic/`).(year != 2020 || 5)", false, true, + )?; + execute_single_line( + "files(`~/Music/MusicFlac/Bruno Mars/24K Magic/`).(year != 2020 || 5 || 4 || 12)", + false, + true, ) }