diff options
| author | Greg Brown <gmb60@cam.ac.uk> | 2020-11-23 14:34:36 +0000 | 
|---|---|---|
| committer | Greg Brown <gmb60@cam.ac.uk> | 2020-11-23 14:34:36 +0000 | 
| commit | fce22234591b4e3bdd2cd4227459d7779e4859c9 (patch) | |
| tree | f0ed7e087c939cc3eaa1377da31a2bec538e5af4 /src/ast/typed.rs | |
| parent | 1183a0996d560fda9d992a9bb8ca1328465a2b33 (diff) | |
Introduce guarded variables
Diffstat (limited to 'src/ast/typed.rs')
| -rw-r--r-- | src/ast/typed.rs | 224 | 
1 files changed, 126 insertions, 98 deletions
| diff --git a/src/ast/typed.rs b/src/ast/typed.rs index a0b8d1b..6ccd0ac 100644 --- a/src/ast/typed.rs +++ b/src/ast/typed.rs @@ -1,3 +1,5 @@ +use proc_macro2::Span; +  use super::Typed;  use super::VariableError;  use std::collections::BTreeSet; @@ -36,8 +38,14 @@ impl FirstSet {              inner: self.inner.intersection(&other.inner).copied().collect(),          }      } +} + +impl IntoIterator for FirstSet { +    type Item = char; -    pub fn into_iter(self) -> impl Iterator<Item = char> { +    type IntoIter = <BTreeSet<char> as IntoIterator>::IntoIter; + +    fn into_iter(self) -> Self::IntoIter {          self.inner.into_iter()      }  } @@ -81,163 +89,183 @@ impl FlastSet {      }  } -pub trait NullContext { -    type PushNull: NullContext; - -    fn get_depth(&self) -> usize; - -    fn get_nullable(&self, index: usize) -> Option<bool>; - -    fn push_nullable<F: FnOnce(&mut Self::PushNull) -> R, R>(&mut self, nullable: bool, f: F) -> R; +#[derive(Debug)] +pub struct NullContext<'a> { +    inner: &'a mut FlastContext  } -impl NullContext for Vec<bool> { -    type PushNull = Self; - -    fn get_depth(&self) -> usize { -        self.len() +impl NullContext<'_> { +    pub fn depth(&self) -> usize { +        self.inner.depth()      } -    fn get_nullable(&self, index: usize) -> Option<bool> { -        self.get(self.len() - index - 1).copied() +    pub fn is_guarded(&self, index: usize) -> Option<bool> { +        self.inner.is_guarded(index)      } -    fn push_nullable<F: FnOnce(&mut Self::PushNull) -> R, R>(&mut self, nullable: bool, f: F) -> R { -        self.push(nullable); -        let res = f(self); -        self.pop(); -        res -    } -} - -impl NullContext for Vec<(bool, FirstSet)> { -    type PushNull = Self; - -    fn get_depth(&self) -> usize { -        self.len() +    pub fn unguard<F: FnOnce(&mut NullContext<'_>) -> R, R>(&mut self, f: F) -> R { +        self.inner.unguard(|ctx| f(&mut NullContext {inner: ctx}))      } -    fn get_nullable(&self, index: usize) -> Option<bool> { -        self.get(self.len() - index - 1).map(|(null, _)| null).copied() +    pub fn is_nullable(&self, index: usize) -> Option<bool> { +        self.inner.is_nullable(index)      } -    fn push_nullable<F: FnOnce(&mut Self::PushNull) -> R, R>(&mut self, nullable: bool, f: F) -> R { -        self.push((nullable, FirstSet::new())); -        let res = f(self); -        self.pop(); -        res +    pub fn push_nullable<F: FnOnce(&mut NullContext<'_>) -> R, R>( +        &mut self, +        nullable: bool, +        f: F, +    ) -> R { +        self.inner.push_nullable(nullable, f)      }  } -impl NullContext for Vec<(bool, FirstSet, FlastSet)> { -    type PushNull = Self; +#[derive(Debug)] +pub struct FirstContext<'a> { +    inner: &'a mut FlastContext, +} -    fn get_depth(&self) -> usize { -        self.len() +impl FirstContext<'_> { +    pub fn depth(&self) -> usize { +        self.inner.depth()      } -    fn get_nullable(&self, index: usize) -> Option<bool> { -        self.get(self.len() - index - 1).map(|(null, _, _)| null).copied() +    pub fn is_guarded(&self, index: usize) -> Option<bool> { +        self.inner.is_guarded(index)      } -    fn push_nullable<F: FnOnce(&mut Self::PushNull) -> R, R>(&mut self, nullable: bool, f: F) -> R { -        self.push((nullable, FirstSet::new(), FlastSet::new())); -        let res = f(self); -        self.pop(); -        res +    pub fn unguard<F: FnOnce(&mut FirstContext<'_>) -> R, R>(&mut self, f: F) -> R { +        self.inner.unguard(|ctx| { +            f(&mut FirstContext{inner: ctx}) +        })      } -} -pub trait FirstSetContext: NullContext { -    type PushFirstSet: FirstSetContext; - -    fn get_first_set(&self, index: usize) -> Option<&FirstSet>; +    pub fn is_nullable(&self, index: usize) -> Option<bool> { +        self.inner.is_nullable(index) +    } -    fn push_first_set<F: FnOnce(&mut Self::PushFirstSet) -> R, R>( +    pub fn push_nullable<F: FnOnce(&mut NullContext<'_>) -> R, R>(          &mut self,          nullable: bool, -        first_set: FirstSet,          f: F, -    ) -> R; -} - -impl FirstSetContext for Vec<(bool, FirstSet)> { -    type PushFirstSet = Self; +    ) -> R { +        self.inner.push_nullable(nullable, f) +    } -    fn get_first_set(&self, index: usize) -> Option<&FirstSet> { -        self.get(self.len() - index - 1).map(|(_, first_set)| first_set) +    pub fn first_set(&self, index: usize) -> Option<&FirstSet> { +        self.inner.first_set(index)      } -    fn push_first_set<F: FnOnce(&mut Self::PushFirstSet) -> R, R>( +    pub fn push_first_set<F: FnOnce(&mut FirstContext<'_>) -> R, R>(          &mut self,          nullable: bool,          first_set: FirstSet,          f: F,      ) -> R { -        self.push((nullable, first_set)); -        let res = f(self); -        self.pop(); -        res +        self.inner.push_first_set(nullable, first_set, f) +    } + +    pub fn as_null(&mut self) -> NullContext<'_> { +        NullContext { +           inner: self.inner +        }      }  } -impl FirstSetContext for Vec<(bool, FirstSet, FlastSet)> { -    type PushFirstSet = Self; +#[derive(Debug)] +pub struct FlastContext { +    data: Vec<(bool, FirstSet, FlastSet)>, +    guard: Vec<usize>, +} + +impl FlastContext { +    pub fn new() -> Self { +        Self { +            data: Vec::new(), +            guard: Vec::new(), +        } +    } + +    pub fn depth(&self) -> usize { +        self.data.len() +    } + +    pub fn is_guarded(&self, index: usize) -> Option<bool> { +        if self.data.len() <= index { +            None +        } else if self.guard.is_empty() { +            Some(false) +        } else { +            Some(self.guard[self.guard.len() - 1] + index >= self.data.len()) +        } +    } + +    pub fn unguard<F: FnOnce(&mut Self) -> R, R>(&mut self, f: F) -> R { +        self.guard.push(self.data.len()); +        let res = f(self); +        self.guard.pop(); +        res +    } -    fn get_first_set(&self, index: usize) -> Option<&FirstSet> { -        self.get(self.len() - index - 1).map(|(_, first_set, _)| first_set) +    pub fn is_nullable(&self, index: usize) -> Option<bool> { +        self.data.get(index).map(|(null, _, _)| *null)      } -    fn push_first_set<F: FnOnce(&mut Self::PushFirstSet) -> R, R>( +    pub fn push_nullable<F: FnOnce(&mut NullContext<'_>) -> R, R>(          &mut self,          nullable: bool, -        first_set: FirstSet,          f: F,      ) -> R { -        self.push((nullable, first_set, FlastSet::new())); -        let res = f(self); -        self.pop(); -        res +        self.push_first_set(nullable, FirstSet::new(), |ctx| { +            f(&mut ctx.as_null()) +        })      } -} - -pub trait FlastSetContext: FirstSetContext { -    type PushFlastSet: FlastSetContext; -    fn get_flast_set(&self, index: usize) -> Option<&FlastSet>; +    pub fn first_set(&self, index: usize) -> Option<&FirstSet> { +        self.data.get(index).map(|(_, first, _)| first) +    } -    fn push_flast_set<F: FnOnce(&mut Self::PushFlastSet) -> R, R>( +    pub fn push_first_set<F: FnOnce(&mut FirstContext<'_>) -> R, R>(          &mut self,          nullable: bool,          first_set: FirstSet, -        flast_set: FlastSet,          f: F, -    ) -> R; -} - -impl FlastSetContext for Vec<(bool, FirstSet, FlastSet)> { -    type PushFlastSet = Self; +    ) -> R { +        self.push_flast_set(nullable, first_set, FlastSet::new(), |ctx| f(&mut ctx.as_first())) +    } -    fn get_flast_set(&self, index: usize) -> Option<&FlastSet> { -        self.get(self.len() - index - 1).map(|(_, _, flast_set)| flast_set) +    pub fn flast_set(&self, index: usize) -> Option<&FlastSet> { +        self.data.get(index).map(|(_, _, flast)| flast)      } -    fn push_flast_set<F: FnOnce(&mut Self::PushFlastSet) -> R, R>( +    pub fn push_flast_set<F: FnOnce(&mut Self) -> R, R>(          &mut self,          nullable: bool,          first_set: FirstSet,          flast_set: FlastSet,          f: F,      ) -> R { -        self.push((nullable, first_set, flast_set)); +        self.data.push((nullable, first_set, flast_set));          let res = f(self); -        self.pop(); +        self.data.pop();          res      } + +    pub fn as_first(&mut self) -> FirstContext<'_> { +        FirstContext { +            inner: self +        } +    } + +    pub fn as_null(&mut self) -> NullContext<'_> { +        NullContext{ +            inner: self +        } +    }  }  pub trait Type { -    type Err: Display; +    type Err: Into<syn::Error>;      /// # Errors      /// Returns [`Err`] if there is a variable with an index greater than or equal @@ -247,19 +275,19 @@ pub trait Type {      /// # Errors      /// Returns [`None`] only if `self.closed(context.get_depth())` returns an      /// [`Err`]. -    fn is_nullable<C: NullContext>(&self, context: &mut C) -> Option<bool>; +    fn is_nullable(&self, context: &mut NullContext<'_>) -> Option<bool>;      /// # Errors      /// Returns [`None`] only if `self.closed(context.get_depth())` returns an      /// [`Err`]. -    fn first_set<C: FirstSetContext>(&self, context: &mut C) -> Option<FirstSet>; +    fn first_set(&self, context: &mut FirstContext<'_>) -> Option<FirstSet>;      /// # Errors      /// Returns [`None`] only if `self.closed(context.get_depth())` returns an      /// [`Err`]. -    fn flast_set<C: FlastSetContext>(&self, context: &mut C) -> Option<FlastSet>; +    fn flast_set(&self, context: &mut FlastContext) -> Option<FlastSet>;      /// # Errors      /// Returns an [`Err`] if this term is not well typed. -    fn well_typed<C: FlastSetContext>(self, context: &mut C) -> Result<Typed, Self::Err>; +    fn well_typed(self, context: &mut FlastContext) -> Result<(Typed, Span), Self::Err>;  } | 
