Skip to content

Commit c37ce99

Browse files
authored
Merge pull request #386 from brendanzab/cleanups-to-arrow-distillation
Cleanups to arrow distillation
2 parents 9536407 + 3ec1b51 commit c37ce99

File tree

2 files changed

+53
-43
lines changed

2 files changed

+53
-43
lines changed

fathom/src/core.rs

Lines changed: 47 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,53 @@ impl<'arena> Term<'arena> {
215215
| Term::ConstMatch(span, _, _, _) => *span,
216216
}
217217
}
218+
219+
/// Returns `true` if the term contains an occurrence of the rigid variable.
220+
pub fn binds_rigid_var(&self, mut var: LocalVar) -> bool {
221+
match self {
222+
Term::RigidVar(_, v) => *v == var,
223+
Term::ItemVar(_, _)
224+
| Term::FlexibleVar(_, _)
225+
| Term::FlexibleInsertion(_, _, _)
226+
| Term::Universe(_)
227+
| Term::Prim(_, _)
228+
| Term::ConstLit(_, _) => false,
229+
230+
Term::Ann(_, expr, r#type) => expr.binds_rigid_var(var) || r#type.binds_rigid_var(var),
231+
Term::Let(_, _, def_type, def_expr, output_expr) => {
232+
def_type.binds_rigid_var(var)
233+
|| def_expr.binds_rigid_var(var)
234+
|| output_expr.binds_rigid_var(var.prev())
235+
}
236+
Term::FunType(_, _, input_type, output_type) => {
237+
input_type.binds_rigid_var(var) || output_type.binds_rigid_var(var.prev())
238+
}
239+
Term::FunLit(_, _, output_expr) => output_expr.binds_rigid_var(var.prev()),
240+
Term::FunApp(_, head_expr, input_expr) => {
241+
head_expr.binds_rigid_var(var) || input_expr.binds_rigid_var(var)
242+
}
243+
Term::RecordType(_, _, terms)
244+
| Term::RecordLit(_, _, terms)
245+
| Term::FormatRecord(_, _, terms)
246+
| Term::FormatOverlap(_, _, terms) => terms.iter().any(|term| {
247+
let result = term.binds_rigid_var(var);
248+
var = var.prev();
249+
result
250+
}),
251+
Term::RecordProj(_, head_expr, _) => head_expr.binds_rigid_var(var),
252+
Term::ArrayLit(_, elem_exprs) => {
253+
elem_exprs.iter().any(|term| term.binds_rigid_var(var))
254+
}
255+
Term::FormatCond(_, _, format, pred) => {
256+
format.binds_rigid_var(var) || pred.binds_rigid_var(var.prev())
257+
}
258+
Term::ConstMatch(_, scrut, branches, default_expr) => {
259+
scrut.binds_rigid_var(var)
260+
|| branches.iter().any(|(_, term)| term.binds_rigid_var(var))
261+
|| default_expr.map_or(false, |term| term.binds_rigid_var(var.prev()))
262+
}
263+
}
264+
}
218265
}
219266

220267
macro_rules! def_prims {
@@ -623,45 +670,3 @@ mod tests {
623670
assert!(!std::mem::needs_drop::<Term<'_>>());
624671
}
625672
}
626-
627-
impl<'arena> Term<'arena> {
628-
pub fn contains_free(&self, mut var: LocalVar) -> bool {
629-
match self {
630-
Term::RigidVar(_, v) => *v == var,
631-
Term::ItemVar(_, _)
632-
| Term::FlexibleVar(_, _)
633-
| Term::FlexibleInsertion(_, _, _)
634-
| Term::Universe(_)
635-
| Term::Prim(_, _)
636-
| Term::ConstLit(_, _) => false,
637-
638-
Term::Ann(_, term, r#type) => term.contains_free(var) || r#type.contains_free(var),
639-
Term::Let(_, _, r#type, def, body) => {
640-
r#type.contains_free(var)
641-
|| def.contains_free(var)
642-
|| body.contains_free(var.prev())
643-
}
644-
Term::FunType(_, _, input_type, output_type) => {
645-
input_type.contains_free(var) || output_type.contains_free(var.prev())
646-
}
647-
Term::FunLit(_, _, body) => body.contains_free(var.prev()),
648-
Term::FunApp(_, head, arg) => head.contains_free(var) || arg.contains_free(var),
649-
Term::RecordType(_, _, terms)
650-
| Term::RecordLit(_, _, terms)
651-
| Term::FormatRecord(_, _, terms)
652-
| Term::FormatOverlap(_, _, terms) => terms.iter().any(|term| {
653-
let result = term.contains_free(var);
654-
var = var.prev();
655-
result
656-
}),
657-
Term::RecordProj(_, term, _) => term.contains_free(var),
658-
Term::ArrayLit(_, terms) => terms.iter().any(|term| term.contains_free(var)),
659-
Term::FormatCond(_, _, t1, t2) => t1.contains_free(var) || t2.contains_free(var.prev()),
660-
Term::ConstMatch(_, scrut, branches, default) => {
661-
scrut.contains_free(var)
662-
|| branches.iter().any(|(_, term)| term.contains_free(var))
663-
|| default.map_or(false, |term| term.contains_free(var.prev()))
664-
}
665-
}
666-
}
667-
}

fathom/src/surface/distillation.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -369,8 +369,11 @@ impl<'interner, 'arena, 'env> Context<'interner, 'arena, 'env> {
369369
)
370370
}
371371
core::Term::Universe(_span) => Term::Universe(()),
372+
373+
// Use arrow sugar if the the input binding is not referenced in the
374+
// output type.
372375
core::Term::FunType(_span, _, input_type, output_type)
373-
if !output_type.contains_free(LocalVar::last()) =>
376+
if !output_type.binds_rigid_var(LocalVar::last()) =>
374377
{
375378
let input_type = self.check(input_type);
376379

@@ -384,6 +387,7 @@ impl<'interner, 'arena, 'env> Context<'interner, 'arena, 'env> {
384387
self.scope.to_scope(output_type),
385388
)
386389
}
390+
// Otherwise distill to a function type with an explicit parameter.
387391
core::Term::FunType(_span, input_name, input_type, output_type) => {
388392
let input_type = self.check(input_type);
389393

@@ -398,6 +402,7 @@ impl<'interner, 'arena, 'env> Context<'interner, 'arena, 'env> {
398402
self.scope.to_scope(output_type),
399403
)
400404
}
405+
401406
core::Term::FunLit(_span, input_name, output_expr) => {
402407
let input_name = self.push_rigid(*input_name);
403408
let output_expr = self.synth(output_expr);

0 commit comments

Comments
 (0)