Skip to content

Commit 597bd3f

Browse files
authored
Merge pull request #453 from brendanzab/implicit-function-cleanups
Implicit function cleanups
2 parents 378855a + 941aa50 commit 597bd3f

File tree

9 files changed

+198
-227
lines changed

9 files changed

+198
-227
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ jobs:
4242
uses: cachix/install-nix-action@v17
4343

4444
- name: Run cargo fmt
45-
run: nix develop .#${{ matrix.rust-toolchain }} --command cargo fmt
45+
run: nix develop .#${{ matrix.rust-toolchain }} --command cargo fmt --check
4646

4747
cargo-clippy:
4848
runs-on: ubuntu-latest

doc/reference.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -729,20 +729,21 @@ id Type S32
729729

730730
### Implicit parameters
731731

732-
Function parameters can be made *implicit* by prefixing them with `@`:
732+
Function parameters can be made _implicit_ by prefixing them with `@`:
733733

734734
```fathom
735735
fun (@A : Type) => A
736736
```
737737

738-
Implicit parameters will be filled in automatically when they can be inferred by the types of other terms:
738+
Implicit parameters will be filled in automatically when they can be inferred by
739+
the types of other terms:
739740

740741
```fathom
741742
let id = fun (@A : Type) (a : A) => a;
742743
id false
743744
```
744745

745-
Implicit parameters can be passed explictly by prefixing the argument with `@`:
746+
Implicit arguments can be passed explicitly by prefixing the argument with `@`:
746747

747748
```fathom
748749
id @Bool false

fathom/src/core/pretty.rs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -180,10 +180,9 @@ impl<'interner, 'arena> Context<'interner> {
180180
RcDoc::concat([
181181
RcDoc::concat([
182182
self.plicity(*plicity),
183-
if let Some(name) = param_name {
184-
self.string_id(*name)
185-
} else {
186-
RcDoc::nil()
183+
match param_name {
184+
Some(name) => self.string_id(*name),
185+
None => RcDoc::text("_"),
187186
},
188187
RcDoc::space(),
189188
RcDoc::text(":"),
@@ -208,10 +207,9 @@ impl<'interner, 'arena> Context<'interner> {
208207
RcDoc::text("fun"),
209208
RcDoc::space(),
210209
self.plicity(*plicity),
211-
if let Some(name) = param_name {
212-
self.string_id(*name)
213-
} else {
214-
RcDoc::nil()
210+
match param_name {
211+
Some(name) => self.string_id(*name),
212+
None => RcDoc::text("_"),
215213
},
216214
RcDoc::space(),
217215
RcDoc::text("=>"),

fathom/src/surface.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ pub struct ItemDef<'arena, Range> {
6868
/// The label that identifies this definition
6969
label: (Range, StringId),
7070
/// Parameter patterns
71-
params: &'arena [FunParam<'arena, Range>],
71+
params: &'arena [Param<'arena, Range>],
7272
/// An optional type annotation for the defined expression
7373
r#type: Option<&'arena Term<'arena, Range>>,
7474
/// The defined expression
@@ -212,20 +212,20 @@ pub enum Term<'arena, Range> {
212212
/// Dependent function types.
213213
FunType(
214214
Range,
215-
&'arena [FunParam<'arena, Range>],
215+
&'arena [Param<'arena, Range>],
216216
&'arena Term<'arena, Range>,
217217
),
218218
/// Function literals.
219219
FunLiteral(
220220
Range,
221-
&'arena [FunParam<'arena, Range>],
221+
&'arena [Param<'arena, Range>],
222222
&'arena Term<'arena, Range>,
223223
),
224224
/// Applications.
225225
App(
226226
Range,
227227
&'arena Term<'arena, Range>,
228-
&'arena [AppArg<'arena, Range>],
228+
&'arena [Arg<'arena, Range>],
229229
),
230230
/// Dependent record types.
231231
RecordType(Range, &'arena [TypeField<'arena, Range>]),
@@ -333,15 +333,14 @@ impl<'arena> Term<'arena, ByteRange> {
333333
}
334334

335335
#[derive(Debug, Clone)]
336-
pub struct FunParam<'arena, Range> {
336+
pub struct Param<'arena, Range> {
337337
pub plicity: Plicity,
338338
pub pattern: Pattern<Range>,
339339
pub r#type: Option<Term<'arena, Range>>,
340340
}
341341

342342
#[derive(Debug, Clone)]
343-
344-
pub struct AppArg<'arena, Range> {
343+
pub struct Arg<'arena, Range> {
345344
pub plicity: Plicity,
346345
pub term: Term<'arena, Range>,
347346
}

fathom/src/surface/distillation.rs

Lines changed: 30 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,12 @@ use scoped_arena::Scope;
66

77
use crate::alloc::SliceVec;
88
use crate::core;
9-
use crate::core::{Const, UIntStyle};
9+
use crate::core::{Const, Plicity, UIntStyle};
1010
use crate::env::{self, EnvLen, Index, Level, UniqueEnv};
1111
use crate::source::{Span, StringId, StringInterner};
1212
use crate::surface::elaboration::MetaSource;
1313
use crate::surface::{
14-
AppArg, BinOp, ExprField, FormatField, FunParam, Item, ItemDef, Module, Pattern, Plicity, Term,
15-
TypeField,
14+
Arg, BinOp, ExprField, FormatField, Item, ItemDef, Module, Param, Pattern, Term, TypeField,
1615
};
1716

1817
/// Distillation context.
@@ -59,10 +58,10 @@ impl<'interner, 'arena, 'env> Context<'interner, 'arena, 'env> {
5958
}
6059

6160
fn push_local(&mut self, name: Option<StringId>) -> StringId {
62-
let name =
63-
name.unwrap_or_else(|| {
64-
self.interner.borrow_mut().get_or_intern_static("_") // TODO: choose a better name?
65-
});
61+
let name = name.unwrap_or_else(|| {
62+
// TODO: choose a better name?
63+
self.interner.borrow_mut().get_or_intern_static("_")
64+
});
6665

6766
// TODO: avoid globals
6867
// TODO: ensure we chose a correctly bound name
@@ -275,7 +274,7 @@ impl<'interner, 'arena, 'env> Context<'interner, 'arena, 'env> {
275274
let body_expr = self.check(body_expr);
276275
self.truncate_local(initial_local_len);
277276

278-
let params = params.into_iter().map(|(plicity, name)| FunParam {
277+
let params = params.into_iter().map(|(plicity, name)| Param {
279278
plicity,
280279
pattern: Pattern::Name((), name),
281280
r#type: None,
@@ -427,7 +426,7 @@ impl<'interner, 'arena, 'env> Context<'interner, 'arena, 'env> {
427426
core::LocalInfo::Def => {}
428427
core::LocalInfo::Param => {
429428
let var = self.local_len().level_to_index(var).unwrap();
430-
args.push(AppArg {
429+
args.push(Arg {
431430
plicity: Plicity::Explicit,
432431
term: self.check(&core::Term::LocalVar(Span::Empty, var)),
433432
});
@@ -478,7 +477,7 @@ impl<'interner, 'arena, 'env> Context<'interner, 'arena, 'env> {
478477
let param_type = self.check(param_type);
479478
let param_name = self.freshen_name(*param_name, next_body_type);
480479
let param_name = self.push_local(param_name);
481-
params.push(FunParam {
480+
params.push(Param {
482481
plicity: *plicity,
483482
pattern: Pattern::Name((), param_name),
484483
r#type: Some(param_type),
@@ -516,7 +515,6 @@ impl<'interner, 'arena, 'env> Context<'interner, 'arena, 'env> {
516515
)
517516
}
518517
}
519-
520518
core::Term::FunLit(..) => {
521519
let initial_local_len = self.local_len();
522520
let mut params = Vec::new();
@@ -531,7 +529,7 @@ impl<'interner, 'arena, 'env> Context<'interner, 'arena, 'env> {
531529
let body_expr = self.synth(body_expr);
532530
self.truncate_local(initial_local_len);
533531

534-
let params = params.into_iter().map(|(plicity, name)| FunParam {
532+
let params = params.into_iter().map(|(plicity, name)| Param {
535533
plicity,
536534
pattern: Pattern::Name((), name),
537535
r#type: None,
@@ -543,34 +541,38 @@ impl<'interner, 'arena, 'env> Context<'interner, 'arena, 'env> {
543541
self.scope.to_scope(body_expr),
544542
)
545543
}
546-
core::Term::FunApp(
547-
..,
548-
core::Term::FunApp(.., core::Term::Prim(_, prim), lhs),
549-
arg_expr,
550-
) if prim_to_bin_op(prim).is_some() => {
551-
self.synth_bin_op(lhs, arg_expr, prim_to_bin_op(prim).unwrap())
552-
}
553-
554544
core::Term::FunApp(..) => {
555545
let mut head_expr = core_term;
556546
let mut args = Vec::new();
557547

558-
while let core::Term::FunApp(_, plicity, next_head_expr, arg_expr) = head_expr {
548+
// Collect a spine of arguments in reverse order
549+
while let core::Term::FunApp(_, plicity, next_head_expr, arg_expr) = *head_expr {
559550
head_expr = next_head_expr;
560-
args.push(AppArg {
561-
plicity: *plicity,
562-
term: self.check(arg_expr),
563-
});
551+
args.push((plicity, arg_expr));
564552
}
565553

566-
let head_expr = self.synth(head_expr);
554+
// Distill appropriate primitives to binary operator expressions
555+
if let (core::Term::Prim(_, prim), [(_, rhs), (_, lhs)]) = (head_expr, &args[..]) {
556+
if let Some(binop) = prim_to_bin_op(prim) {
557+
let lhs = self.scope.to_scope(self.synth(lhs));
558+
let rhs = self.scope.to_scope(self.synth(rhs));
559+
return Term::BinOp((), lhs, binop, rhs);
560+
}
561+
}
567562

563+
// Otherwise distill to a function application
568564
Term::App(
569565
(),
570-
self.scope.to_scope(head_expr),
571-
self.scope.to_scope_from_iter(args.into_iter().rev()),
566+
self.scope.to_scope(self.synth(head_expr)),
567+
self.scope.to_scope_from_iter(args.into_iter().rev().map(
568+
|(plicity, arg_expr)| Arg {
569+
plicity,
570+
term: self.check(arg_expr),
571+
},
572+
)),
572573
)
573574
}
575+
574576
core::Term::RecordType(_, labels, types)
575577
if is_tuple_type(&mut self.interner.borrow_mut(), labels, types) =>
576578
{
@@ -738,22 +740,6 @@ impl<'interner, 'arena, 'env> Context<'interner, 'arena, 'env> {
738740
}
739741
}
740742

741-
fn synth_bin_op(
742-
&mut self,
743-
lhs: &core::Term<'_>,
744-
rhs: &core::Term<'_>,
745-
op: BinOp<()>,
746-
) -> Term<'arena, ()> {
747-
let lhs = self.synth(lhs);
748-
let rhs = self.synth(rhs);
749-
Term::BinOp(
750-
(),
751-
self.scope.to_scope(lhs),
752-
op,
753-
self.scope.to_scope(self.scope.to_scope(rhs)),
754-
)
755-
}
756-
757743
fn synth_format_fields(
758744
&mut self,
759745
labels: &[StringId],

0 commit comments

Comments
 (0)