summaryrefslogtreecommitdiff
path: root/src/chomp/typed
diff options
context:
space:
mode:
authorGreg Brown <gmb60@cam.ac.uk>2021-01-21 09:42:02 +0000
committerGreg Brown <gmb60@cam.ac.uk>2021-01-21 17:45:02 +0000
commit1a93b1f82bc8c21d24e67031c5eca96830e928c7 (patch)
tree4c3fbfac9f0fbbc31defee03cd460e0400278d30 /src/chomp/typed
parentfaa3f30deb32d0a1fd7cb196559762635b22ecfd (diff)
Fix many warnings.
Diffstat (limited to 'src/chomp/typed')
-rw-r--r--src/chomp/typed/context.rs35
-rw-r--r--src/chomp/typed/error.rs96
-rw-r--r--src/chomp/typed/infer.rs37
-rw-r--r--src/chomp/typed/mod.rs30
4 files changed, 109 insertions, 89 deletions
diff --git a/src/chomp/typed/context.rs b/src/chomp/typed/context.rs
index 5c8d398..f3263ce 100644
--- a/src/chomp/typed/context.rs
+++ b/src/chomp/typed/context.rs
@@ -17,16 +17,6 @@ impl Context {
self.vars.len()
}
- pub fn is_unguarded(&self, var: &Variable) -> Option<bool> {
- if self.vars.len() <= var.index {
- None
- } else if self.unguard_points.is_empty() {
- Some(false)
- } else {
- Some(self.unguard_points[self.unguard_points.len() - 1] + var.index >= self.vars.len())
- }
- }
-
pub fn with_unguard<F: FnOnce(&mut Self) -> R, R>(&mut self, f: F) -> R {
self.unguard_points.push(self.vars.len());
let res = f(self);
@@ -34,12 +24,23 @@ impl Context {
res
}
- pub fn get_variable_type(&self, var: &Variable) -> Result<&Type, GetVariableError> {
- match self.is_unguarded(var) {
- None => Err(GetVariableError::FreeVariable),
- Some(false) => Err(GetVariableError::GuardedVariable),
- Some(true) => Ok(&self.vars[self.vars.len() - var.index - 1]),
- }
+ pub fn get_variable_type(&self, var: Variable) -> Result<&Type, GetVariableError> {
+ self.vars
+ .iter()
+ .nth_back(var.index)
+ .ok_or(GetVariableError::FreeVariable)
+ .and_then(|ty| {
+ self.unguard_points
+ .last()
+ .and_then(|point| {
+ if point + var.index >= self.vars.len() {
+ Some(ty)
+ } else {
+ None
+ }
+ })
+ .ok_or(GetVariableError::GuardedVariable)
+ })
}
pub fn with_variable_type<F: FnOnce(&mut Self) -> R, R>(&mut self, ty: Type, f: F) -> R {
@@ -50,7 +51,7 @@ impl Context {
}
}
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum GetVariableError {
FreeVariable,
GuardedVariable,
diff --git a/src/chomp/typed/error.rs b/src/chomp/typed/error.rs
index bb807fc..5c1e21e 100644
--- a/src/chomp/typed/error.rs
+++ b/src/chomp/typed/error.rs
@@ -18,91 +18,105 @@ pub struct VariableError {
pub name: Option<Name>,
}
-impl PartialEq for VariableError {
- fn eq(&self, other: &Self) -> bool {
- todo!()
- }
-}
-
-impl Eq for VariableError {}
-
impl From<VariableError> for syn::Error {
fn from(other: VariableError) -> Self {
- todo!()
+ let msg = other.to_string();
+ let span = other.span;
+ Self::new(span.unwrap_or_else(Span::call_site), msg)
}
}
impl Display for VariableError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- todo!()
+ match &self.inner {
+ GetVariableError::FreeVariable => write!(f, "unbound variable: "),
+ GetVariableError::GuardedVariable => write!(f, "usage of guarded variable: "),
+ }?;
+
+ if let Some(name) = &self.name {
+ write!(f, "`{}`", name)
+ } else {
+ write!(f, "'{}", self.var.index)
+ }
}
}
impl Error for VariableError {}
-/// A type error when concatenating two terms.
#[derive(Debug)]
pub enum CatError {
- /// The first term was unexpectedly nullable.
- FirstNullable(TypedExpression, Option<Span>),
- /// The flast set of the first term intersects the first set of the second.
- FirstFlastOverlap(Vec<TypedExpression>, Option<Span>, TypedExpression),
+ FirstNullable {
+ expr: TypedExpression,
+ punct: Option<Span>,
+ },
+ FirstFlastOverlap {
+ first: Vec<TypedExpression>,
+ punct: Option<Span>,
+ next: TypedExpression,
+ },
}
-impl PartialEq for CatError {
- fn eq(&self, other: &Self) -> bool {
- todo!()
- }
-}
-
-impl Eq for CatError {}
-
impl From<CatError> for syn::Error {
fn from(other: CatError) -> Self {
- todo!()
+ let msg = other.to_string();
+ let span = match other {
+ CatError::FirstNullable { punct, .. } | CatError::FirstFlastOverlap { punct, .. } => {
+ punct
+ }
+ };
+ Self::new(span.unwrap_or_else(Span::call_site), msg)
}
}
impl Display for CatError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- todo!()
+ match self {
+ Self::FirstNullable { .. } => write!(f, "first part of concatenation is nullable"),
+ Self::FirstFlastOverlap { .. } => {
+ write!(f, "first set overlaps with preceding flast set")
+ }
+ }
}
}
impl Error for CatError {}
-/// A type error when alternating two terms.
#[derive(Debug)]
pub enum AltError {
- /// Both terms are nullable.
- BothNullable(Vec<TypedExpression>, Option<Span>, TypedExpression),
- /// The first sets of the two terms intersect.
- FirstOverlap(Vec<TypedExpression>, Option<Span>, TypedExpression),
-}
-
-impl PartialEq for AltError {
- fn eq(&self, other: &Self) -> bool {
- todo!()
- }
+ BothNullable {
+ left: Vec<TypedExpression>,
+ punct: Option<Span>,
+ right: TypedExpression,
+ },
+ FirstOverlap {
+ left: Vec<TypedExpression>,
+ punct: Option<Span>,
+ right: TypedExpression,
+ },
}
-impl Eq for AltError {}
-
impl From<AltError> for syn::Error {
fn from(other: AltError) -> Self {
- todo!()
+ let msg = other.to_string();
+ let span = match other {
+ AltError::BothNullable { punct, .. } | AltError::FirstOverlap { punct, .. } => punct,
+ };
+ Self::new(span.unwrap_or_else(Span::call_site), msg)
}
}
impl Display for AltError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- todo!()
+ match self {
+ Self::BothNullable { .. } => write!(f, "both branches are nullable"),
+ Self::FirstOverlap { .. } => write!(f, "first sets of both branches overlap"),
+ }
}
}
impl Error for AltError {}
-#[derive(Debug, Eq, PartialEq)]
+#[derive(Debug)]
pub enum TypeError {
Cat(CatError),
Alt(AltError),
diff --git a/src/chomp/typed/infer.rs b/src/chomp/typed/infer.rs
index 8095103..44ea654 100644
--- a/src/chomp/typed/infer.rs
+++ b/src/chomp/typed/infer.rs
@@ -61,25 +61,18 @@ impl Folder for TypeInfer<'_> {
fn fold_alt(&mut self, name: Option<Name>, span: Option<Span>, alt: Alt) -> Self::Out {
let first = alt.first.fold(self)?;
- let second = alt.second;
- let rest = alt.rest;
+ let second = alt.second.fold(self)?;
+ let rest = alt
+ .rest
+ .into_iter()
+ .map(|(punct, term)| -> Result<_, TypeError> { Ok((punct, term.fold(self)?)) })
+ .collect::<Result<Vec<_>, _>>()?;
let punct = alt.punct;
- self.context
- .with_unguard(|context| -> Result<TypedExpression, TypeError> {
- let mut infer = TypeInfer { context };
- let second = second.fold(&mut infer)?;
- let rest = rest
- .into_iter()
- .map(|(punct, term)| -> Result<_, TypeError> {
- Ok((punct, term.fold(&mut infer)?))
- })
- .collect::<Result<Vec<_>, _>>()?;
- Ok(TypedExpression {
- inner: super::Alt::new(first, punct, second, rest)?.into(),
- name,
- span,
- })
- })
+ Ok(TypedExpression {
+ inner: super::Alt::new(first, punct, second, rest)?.into(),
+ name,
+ span,
+ })
}
fn fold_fix(&mut self, name: Option<Name>, span: Option<Span>, fix: Fix) -> Self::Out {
@@ -111,7 +104,7 @@ impl Folder for TypeInfer<'_> {
span: Option<Span>,
var: Variable,
) -> Self::Out {
- let ty = match self.context.get_variable_type(&var) {
+ let ty = match self.context.get_variable_type(var) {
Ok(ty) => ty.clone(),
Err(inner) => {
return Err(VariableError {
@@ -136,10 +129,10 @@ impl Folder for TypeInfer<'_> {
_span: Option<Span>,
_param: Parameter,
) -> Self::Out {
- todo!()
+ unimplemented!()
}
- fn fold_call(&mut self, _name: Option<Name>,_span: Option<Span>, _call: Call) -> Self::Out {
- todo!()
+ fn fold_call(&mut self, _name: Option<Name>, _span: Option<Span>, _call: Call) -> Self::Out {
+ unimplemented!()
}
}
diff --git a/src/chomp/typed/mod.rs b/src/chomp/typed/mod.rs
index e9aed79..2a9e365 100644
--- a/src/chomp/typed/mod.rs
+++ b/src/chomp/typed/mod.rs
@@ -14,8 +14,8 @@ pub mod lower;
mod infer;
-pub use self::infer::TypeInfer;
use self::error::{AltError, CatError};
+pub use self::infer::TypeInfer;
#[derive(Debug, Default, Clone, Eq, Hash, PartialEq)]
pub struct Type {
@@ -130,7 +130,7 @@ impl Cat {
rest: I,
) -> Result<Self, CatError> {
if first.get_type().nullable() {
- return Err(CatError::FirstNullable(first, punct));
+ return Err(CatError::FirstNullable { expr: first, punct });
}
iter::once((punct, second))
@@ -138,16 +138,20 @@ impl Cat {
.try_fold(
(first.get_type().clone(), vec![first]),
|(ty, mut terms), (punct, right)| {
- if !ty
+ if ty
.flast_set()
.intersect_first(right.get_type().first_set())
.is_empty()
{
- Err(CatError::FirstFlastOverlap(terms, punct, right))
- } else {
let ty = ty.cat(right.get_type().clone());
terms.push(right);
Ok((ty, terms))
+ } else {
+ Err(CatError::FirstFlastOverlap {
+ first: terms,
+ punct,
+ next: right,
+ })
}
},
)
@@ -184,17 +188,25 @@ impl Alt {
(first.get_type().clone(), vec![first]),
|(ty, mut terms), (punct, right)| {
if ty.nullable() && right.get_type().nullable() {
- Err(AltError::BothNullable(terms, punct, right))
- } else if !ty
+ Err(AltError::BothNullable {
+ left: terms,
+ punct,
+ right,
+ })
+ } else if ty
.first_set()
.intersect(right.get_type().first_set())
.is_empty()
{
- Err(AltError::FirstOverlap(terms, punct, right))
- } else {
let ty = ty.alt(right.get_type().clone());
terms.push(right);
Ok((ty, terms))
+ } else {
+ Err(AltError::FirstOverlap {
+ left: terms,
+ punct,
+ right,
+ })
}
},
)