properly fix Expr equality (which ignores SourceSpans)
This commit is contained in:
parent
f49ebe6a09
commit
52c4891c5b
3 changed files with 81 additions and 55 deletions
|
@ -15,22 +15,58 @@ pub use pat::{FullPattern, Pattern};
|
|||
|
||||
pub mod typeck;
|
||||
|
||||
use core::cmp;
|
||||
use miette::SourceSpan;
|
||||
use std::collections::VecDeque;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Record<V> {
|
||||
pub span: SourceSpan,
|
||||
pub fields: Vec<(Option<Box<str>>, V)>,
|
||||
/// A SourceSpan which is always equal to all other SourceSpans
|
||||
/// (to be used to ignore span differences in expression comparisons)
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct EvEqSourceSpan(pub SourceSpan);
|
||||
|
||||
impl cmp::PartialEq for EvEqSourceSpan {
|
||||
#[inline(always)]
|
||||
fn eq(&self, _: &Self) -> bool {
|
||||
true
|
||||
}
|
||||
#[inline(always)]
|
||||
fn ne(&self, _: &Self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: core::cmp::PartialEq> core::cmp::PartialEq for Record<V> {
|
||||
fn eq(&self, rhs: &Self) -> bool {
|
||||
self.fields == rhs.fields
|
||||
impl From<(usize, usize)> for EvEqSourceSpan {
|
||||
#[inline]
|
||||
fn from(x: (usize, usize)) -> Self {
|
||||
Self(x.into())
|
||||
}
|
||||
fn ne(&self, rhs: &Self) -> bool {
|
||||
self.fields != rhs.fields
|
||||
}
|
||||
|
||||
impl From<core::ops::Range<usize>> for EvEqSourceSpan {
|
||||
#[inline]
|
||||
fn from(x: core::ops::Range<usize>) -> Self {
|
||||
Self(x.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<EvEqSourceSpan> for SourceSpan {
|
||||
#[inline(always)]
|
||||
fn from(x: EvEqSourceSpan) -> SourceSpan {
|
||||
x.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a EvEqSourceSpan> for SourceSpan {
|
||||
#[inline(always)]
|
||||
fn from(x: &'a EvEqSourceSpan) -> SourceSpan {
|
||||
x.0
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct Record<V> {
|
||||
pub span: EvEqSourceSpan,
|
||||
pub fields: Vec<(Option<Box<str>>, V)>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
|
@ -47,13 +83,13 @@ pub enum Expr {
|
|||
|
||||
TyLambda {
|
||||
pat: FullPattern,
|
||||
body_span: SourceSpan,
|
||||
body_span: EvEqSourceSpan,
|
||||
exp: Box<Expr>,
|
||||
},
|
||||
|
||||
SelfRecur {
|
||||
pat: FullPattern,
|
||||
inner_span: SourceSpan,
|
||||
inner_span: EvEqSourceSpan,
|
||||
inner: Box<Expr>,
|
||||
},
|
||||
|
||||
|
@ -64,7 +100,7 @@ pub enum Expr {
|
|||
|
||||
Apply {
|
||||
lam: Box<Expr>,
|
||||
args: Vec<(SourceSpan, Expr)>,
|
||||
args: Vec<(EvEqSourceSpan, Expr)>,
|
||||
},
|
||||
|
||||
Ref(usize),
|
||||
|
@ -73,9 +109,9 @@ pub enum Expr {
|
|||
TyRecord(Record<Expr>),
|
||||
|
||||
Select {
|
||||
prim_span: SourceSpan,
|
||||
prim_span: EvEqSourceSpan,
|
||||
prim: Box<Expr>,
|
||||
then: VecDeque<(SourceSpan, Box<str>)>,
|
||||
then: VecDeque<(EvEqSourceSpan, Box<str>)>,
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -269,7 +305,7 @@ fn parse_minexpr(env: &mut ParseEnv<'_>) -> Result<Expr, Perr> {
|
|||
match kind {
|
||||
Tok::DotIdent(i) => {
|
||||
let ioffset_end = env.lxr.offset();
|
||||
let span: SourceSpan = (usize::try_from(offset).unwrap()..ioffset_end).into();
|
||||
let span: EvEqSourceSpan = (usize::try_from(offset).unwrap()..ioffset_end).into();
|
||||
if let Expr::Select { then, .. } = &mut ret {
|
||||
then.push_back((span, i));
|
||||
} else {
|
||||
|
|
|
@ -4,13 +4,12 @@
|
|||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
use super::{Expr, Record};
|
||||
use crate::parser::{
|
||||
unexpected_token, Env as ParseEnv, Error as Perr, ErrorKind as Pek, MaybeParse, Offset, Parse,
|
||||
Token, TokenKind as Tok,
|
||||
};
|
||||
use crate::typeck::{BinderState, TyContext};
|
||||
use miette::SourceSpan;
|
||||
use crate::{EvEqSourceSpan, Expr, Record};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum Pattern {
|
||||
|
@ -42,33 +41,10 @@ impl core::cmp::PartialEq for Pattern {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct FullPattern {
|
||||
pub pat: Pattern,
|
||||
pub pty: Option<Box<(SourceSpan, Expr)>>,
|
||||
}
|
||||
|
||||
impl core::cmp::PartialEq for FullPattern {
|
||||
fn eq(&self, rhs: &Self) -> bool {
|
||||
if self.pat != rhs.pat {
|
||||
return false;
|
||||
}
|
||||
match (&self.pty, &rhs.pty) {
|
||||
(None, None) => true,
|
||||
(Some(_), None) | (None, Some(_)) => false,
|
||||
(Some(lt), Some(rt)) => lt.1 == rt.1,
|
||||
}
|
||||
}
|
||||
fn ne(&self, rhs: &Self) -> bool {
|
||||
if self.pat == rhs.pat {
|
||||
return false;
|
||||
}
|
||||
match (&self.pty, &rhs.pty) {
|
||||
(None, None) => false,
|
||||
(Some(_), None) | (None, Some(_)) => true,
|
||||
(Some(lt), Some(rt)) => lt.1 != rt.1,
|
||||
}
|
||||
}
|
||||
pub pty: Option<Box<(EvEqSourceSpan, Expr)>>,
|
||||
}
|
||||
|
||||
impl Pattern {
|
||||
|
|
|
@ -122,13 +122,19 @@ impl FullPattern {
|
|||
) -> Result<(), Error> {
|
||||
if pr.fields.len() != tr.fields.len() {
|
||||
return Err(Error::RecordLengthMismatch {
|
||||
lengths: vec![(pr.span, pr.fields.len()), (tr.span, tr.fields.len())],
|
||||
lengths: vec![
|
||||
(pr.span.into(), pr.fields.len()),
|
||||
(tr.span.into(), tr.fields.len()),
|
||||
],
|
||||
});
|
||||
}
|
||||
for (pv, tv) in pr.fields.iter().zip(tr.fields.iter()) {
|
||||
if pv.0 != tv.0 {
|
||||
return Err(Error::RecordFieldNameMismatch {
|
||||
names: vec![(pr.span, pv.0.clone()), (tr.span, tv.0.clone())],
|
||||
names: vec![
|
||||
(pr.span.into(), pv.0.clone()),
|
||||
(tr.span.into(), tv.0.clone()),
|
||||
],
|
||||
});
|
||||
}
|
||||
intern(&pv.1, &tv.1, &tr.span, ctx)?;
|
||||
|
@ -139,11 +145,11 @@ impl FullPattern {
|
|||
fn intern(
|
||||
pat: &Pattern,
|
||||
ty: &Expr,
|
||||
tspan: &SourceSpan,
|
||||
tspan: &EvEqSourceSpan,
|
||||
ctx: &mut TyContext,
|
||||
) -> Result<(), Error> {
|
||||
if ty.weak_is_type() == Some(false) {
|
||||
return Err(Error::ExprNotaType(*tspan, ty.clone()));
|
||||
return Err(Error::ExprNotaType(tspan.into(), ty.clone()));
|
||||
}
|
||||
match (pat, ty) {
|
||||
// catch-all
|
||||
|
@ -161,7 +167,7 @@ impl FullPattern {
|
|||
|
||||
// recursion
|
||||
(Pattern::Record(pr), Expr::TyRecord(tr)) => intern_record(pr, tr, ctx),
|
||||
(Pattern::Record(_), _) => Err(Error::ExprNotaType(*tspan, ty.clone())),
|
||||
(Pattern::Record(_), _) => Err(Error::ExprNotaType(tspan.into(), ty.clone())),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -177,10 +183,10 @@ impl FullPattern {
|
|||
impl Expr {
|
||||
fn type_check(
|
||||
&mut self,
|
||||
self_span: SourceSpan,
|
||||
self_span: EvEqSourceSpan,
|
||||
ctx: &mut TyContext,
|
||||
expect: &Expr,
|
||||
expect_span: SourceSpan,
|
||||
expect_span: EvEqSourceSpan,
|
||||
) -> Result<(), Error> {
|
||||
// TODO: implement this properly
|
||||
if let Some(got) = self.type_infer(ctx)? {
|
||||
|
@ -188,7 +194,10 @@ impl Expr {
|
|||
Ok(())
|
||||
} else {
|
||||
Err(Error::TypesMismatch {
|
||||
cases: vec![(self_span, got), (expect_span, expect.clone())],
|
||||
cases: vec![
|
||||
(self_span.into(), got),
|
||||
(expect_span.into(), expect.clone()),
|
||||
],
|
||||
})
|
||||
}
|
||||
} else {
|
||||
|
@ -224,7 +233,7 @@ impl Expr {
|
|||
match rcd.lookup(RecordEntry::Name(&i)) {
|
||||
None => {
|
||||
return Err(Error::SelectNotFound {
|
||||
span,
|
||||
span: span.into(),
|
||||
name: i,
|
||||
val: Expr::Record(rcd.clone()),
|
||||
})
|
||||
|
@ -280,7 +289,7 @@ impl Expr {
|
|||
if let (Some((loc, x)), Some(y)) = (pat.pty.as_ref().map(|x| &**x), &tmp) {
|
||||
if x != y {
|
||||
return Err(Error::TypesMismatch {
|
||||
cases: vec![(*loc, x.clone()), (*inner_span, y.clone())],
|
||||
cases: vec![(loc.into(), x.clone()), ((*inner_span).into(), y.clone())],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -321,7 +330,12 @@ impl Expr {
|
|||
let span = *span;
|
||||
let pat = match &mut lam_t {
|
||||
Expr::TyLambda { pat, .. } => pat,
|
||||
_ => return Err(Error::InvalidInvoke { span, ty: lam_t }),
|
||||
_ => {
|
||||
return Err(Error::InvalidInvoke {
|
||||
span: span.into(),
|
||||
ty: lam_t,
|
||||
})
|
||||
}
|
||||
};
|
||||
// TODO: figure out subtpying
|
||||
if let Some(y) = &mut pat.pty {
|
||||
|
@ -377,7 +391,7 @@ impl Expr {
|
|||
};
|
||||
assert!(!then.is_empty());
|
||||
for (ispan, i) in &*then {
|
||||
let span = *ispan;
|
||||
let span = ispan.into();
|
||||
match pt {
|
||||
pt @ (Expr::TyTy
|
||||
| Expr::Tbool
|
||||
|
|
Loading…
Reference in a new issue