Skip to content

Commit

Permalink
fix: add a new assignment kind instead of using a boolean
Browse files Browse the repository at this point in the history
  • Loading branch information
rvcas committed Jun 25, 2024
1 parent f1cfc84 commit 5bdea11
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 12 deletions.
12 changes: 12 additions & 0 deletions crates/aiken-lang/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1679,13 +1679,15 @@ pub type TypedAssignmentKind = AssignmentKind<()>;

#[derive(Debug, Clone, PartialEq, Eq, Copy, serde::Serialize, serde::Deserialize)]
pub enum AssignmentKind<T> {
Is,
Let { backpassing: T },
Expect { backpassing: T },
}

impl From<UntypedAssignmentKind> for TypedAssignmentKind {
fn from(kind: UntypedAssignmentKind) -> TypedAssignmentKind {
match kind {
AssignmentKind::Is => AssignmentKind::Is,
AssignmentKind::Let { .. } => AssignmentKind::Let { backpassing: () },
AssignmentKind::Expect { .. } => AssignmentKind::Expect { backpassing: () },
}
Expand All @@ -1701,8 +1703,13 @@ impl<T> AssignmentKind<T> {
matches!(self, AssignmentKind::Expect { .. })
}

pub fn if_is(&self) -> bool {
matches!(self, AssignmentKind::Is)
}

pub fn location_offset(&self) -> usize {
match self {
AssignmentKind::Is => 2,
AssignmentKind::Let { .. } => 3,
AssignmentKind::Expect { .. } => 6,
}
Expand All @@ -1712,6 +1719,7 @@ impl<T> AssignmentKind<T> {
impl AssignmentKind<bool> {
pub fn is_backpassing(&self) -> bool {
match self {
Self::Is => unreachable!(),
Self::Let { backpassing } | Self::Expect { backpassing } => *backpassing,
}
}
Expand All @@ -1724,6 +1732,10 @@ impl<T: Default> AssignmentKind<T> {
}
}

pub fn is() -> Self {
AssignmentKind::Is
}

pub fn expect() -> Self {
AssignmentKind::Expect {
backpassing: Default::default(),
Expand Down
1 change: 1 addition & 0 deletions crates/aiken-lang/src/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -703,6 +703,7 @@ impl<'comments> Formatter<'comments> {
kind: UntypedAssignmentKind,
) -> Document<'a> {
let keyword = match kind {
AssignmentKind::Is => unreachable!(),
AssignmentKind::Let { .. } => "let",
AssignmentKind::Expect { .. } => "expect",
};
Expand Down
4 changes: 2 additions & 2 deletions crates/aiken-lang/src/tests/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2691,7 +2691,7 @@ fn if_soft_cast_unused_pattern() {
}
"#;

let (warnings, _ast) = dbg!(check(parse(source_code))).unwrap();
let (warnings, _ast) = check(parse(source_code)).unwrap();

assert!(matches!(
warnings[0],
Expand All @@ -2716,7 +2716,7 @@ fn if_soft_cast_not_data() {
}
"#;

let (warnings, _ast) = dbg!(check(parse(source_code))).unwrap();
let (warnings, _ast) = check(parse(source_code)).unwrap();

assert!(matches!(warnings[0], Warning::UseWhenInstead { .. }))
}
20 changes: 10 additions & 10 deletions crates/aiken-lang/src/tipo/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -510,7 +510,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
location: _,
} = patterns.into_vec().swap_remove(0);

self.infer_assignment(pattern, *value, kind, &annotation, location, true)
self.infer_assignment(pattern, *value, kind, &annotation, location)
}

UntypedExpr::Trace {
Expand Down Expand Up @@ -1182,7 +1182,6 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
kind: UntypedAssignmentKind,
annotation: &Option<Annotation>,
location: Span,
check_exhaustiveness: bool,
) -> Result<TypedExpr, Error> {
let typed_value = self.infer(untyped_value.clone())?;
let mut value_typ = typed_value.tipo();
Expand All @@ -1199,7 +1198,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
ann_typ.clone(),
value_typ.clone(),
typed_value.type_defining_location(),
(kind.is_let() && ann_typ.is_data()) || kind.is_expect(),
(kind.is_let() && ann_typ.is_data()) || kind.is_expect() || kind.if_is(),
)?;

value_typ = ann_typ.clone();
Expand Down Expand Up @@ -1240,11 +1239,13 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
// If `expect` is explicitly used, we still check exhaustiveness but instead of returning an
// error we emit a warning which explains that using `expect` is unnecessary.
match kind {
AssignmentKind::Let { .. } if check_exhaustiveness => self
.environment
.check_exhaustiveness(&[&pattern], location, true)?,
AssignmentKind::Is => (),
AssignmentKind::Let { .. } => {
self.environment
.check_exhaustiveness(&[&pattern], location, true)?
}

AssignmentKind::Expect { .. } if check_exhaustiveness => {
AssignmentKind::Expect { .. } => {
let is_exaustive_pattern = self
.environment
.check_exhaustiveness(&[&pattern], location, false)
Expand Down Expand Up @@ -1292,7 +1293,6 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
});
}
}
_ => (),
}

Ok(TypedExpr::Assignment {
Expand Down Expand Up @@ -1749,10 +1749,9 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
let TypedExpr::Assignment { value, pattern, .. } = typer.infer_assignment(
pattern,
branch.condition.clone(),
AssignmentKind::expect(),
AssignmentKind::is(),
&annotation,
location,
false,
)?
else {
unreachable!()
Expand Down Expand Up @@ -2104,6 +2103,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
.into(),
// erase backpassing while preserving assignment kind.
kind: match kind {
AssignmentKind::Is => unreachable!(),
AssignmentKind::Let { .. } => AssignmentKind::let_(),
AssignmentKind::Expect { .. }
if pattern_is_var && annotation.is_none() =>
Expand Down

0 comments on commit 5bdea11

Please sign in to comment.