Skip to content

Commit 5d4d535

Browse files
authored
Merge pull request #418 from brendanzab/tuple-distillation-tweaks
Some tweaks to tuple distillation
2 parents 2893469 + f9e0d65 commit 5d4d535

File tree

14 files changed

+107
-89
lines changed

14 files changed

+107
-89
lines changed

fathom/src/core.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
//! Core language.
22
33
use crate::env::{Index, Level};
4-
use crate::source::Span;
5-
use crate::StringId;
4+
use crate::source::{Span, StringId};
65

76
pub mod binary;
87
pub mod prim;

fathom/src/core/prim.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,7 @@ use std::sync::Arc;
66
use crate::core::semantics::{ArcValue, Elim, ElimEnv, Value};
77
use crate::core::{self, Const, Prim, UIntStyle};
88
use crate::env::{self, SharedEnv, UniqueEnv};
9-
use crate::source::Span;
10-
use crate::source::Spanned;
11-
use crate::{StringId, StringInterner};
9+
use crate::source::{Span, Spanned, StringId, StringInterner};
1210

1311
/// Environment of primitives
1412
pub struct Env<'arena> {

fathom/src/core/semantics.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@ use std::sync::Arc;
88
use crate::alloc::SliceVec;
99
use crate::core::{prim, Const, LocalInfo, Prim, Term};
1010
use crate::env::{EnvLen, Index, Level, SharedEnv, SliceEnv};
11-
use crate::source::{Span, Spanned};
12-
use crate::StringId;
11+
use crate::source::{Span, Spanned, StringId};
1312

1413
/// Atomically reference counted values. We use reference counting to increase
1514
/// the amount of sharing we can achieve during evaluation.

fathom/src/driver.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ use std::path::Path;
77

88
use crate::core::binary;
99
use crate::core::binary::{BufferError, ReadError};
10-
use crate::source::{ByteRange, FileId, Span};
10+
use crate::source::{ByteRange, FileId, Span, StringInterner};
1111
use crate::surface::{self, elaboration};
12-
use crate::{StringInterner, BUG_REPORT_URL};
12+
use crate::BUG_REPORT_URL;
1313

1414
#[derive(Debug, Copy, Clone)]
1515
pub enum Status {

fathom/src/lib.rs

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,3 @@ pub const BUG_REPORT_URL: &str = concat!(env!("CARGO_PKG_REPOSITORY"), "/issues/
1919

2020
// Public exports
2121
pub use driver::{Driver, Status};
22-
23-
/// Interned strings.
24-
pub type StringId = string_interner::symbol::SymbolU16;
25-
26-
/// String interner.
27-
pub type StringInterner = string_interner::StringInterner<
28-
string_interner::backend::BucketBackend<StringId>,
29-
std::hash::BuildHasherDefault<fxhash::FxHasher32>,
30-
>;

fathom/src/source.rs

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,61 @@
1+
//! Types related to source files.
2+
13
use std::ops::{Deref, DerefMut};
24

3-
///! Types related to source files.
5+
// Interned strings.
6+
pub type StringId = string_interner::symbol::SymbolU16;
7+
8+
/// String interner.
9+
pub struct StringInterner {
10+
tuple_labels: Vec<StringId>,
11+
strings: string_interner::StringInterner<
12+
string_interner::backend::BucketBackend<StringId>,
13+
std::hash::BuildHasherDefault<fxhash::FxHasher32>,
14+
>,
15+
}
16+
17+
impl Deref for StringInterner {
18+
type Target = string_interner::StringInterner<
19+
string_interner::backend::BucketBackend<StringId>,
20+
std::hash::BuildHasherDefault<fxhash::FxHasher32>,
21+
>;
22+
23+
fn deref(&self) -> &Self::Target {
24+
&self.strings
25+
}
26+
}
27+
28+
impl DerefMut for StringInterner {
29+
fn deref_mut(&mut self) -> &mut Self::Target {
30+
&mut self.strings
31+
}
32+
}
33+
34+
impl StringInterner {
35+
/// Construct an empty string interner.
36+
pub fn new() -> StringInterner {
37+
StringInterner {
38+
tuple_labels: Vec::new(),
39+
strings: string_interner::StringInterner::new(),
40+
}
41+
}
42+
43+
/// Get or intern a string in the form `_{index}`.
44+
pub fn get_tuple_label(&mut self, index: usize) -> StringId {
45+
(self.tuple_labels.get(index).copied())
46+
.unwrap_or_else(|| self.get_or_intern(format!("_{}", index)))
47+
}
48+
49+
/// Returns true if `label` refers to a string in the form `_{index}`.
50+
pub fn is_tuple_label(&mut self, index: usize, label: StringId) -> bool {
51+
label == self.get_tuple_label(index)
52+
}
53+
54+
/// Returns true if `labels` is a sequence of tuple labels: `_0`, `_1`, ...
55+
pub fn is_tuple_labels(&mut self, labels: &[StringId]) -> bool {
56+
(labels.iter().enumerate()).all(|(index, label)| self.is_tuple_label(index, *label))
57+
}
58+
}
459

560
/// File id.
661
pub type FileId = usize; // TODO: use wrapper struct

fathom/src/surface.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@ use codespan_reporting::diagnostic::{Diagnostic, Label};
77
use lalrpop_util::lalrpop_mod;
88
use scoped_arena::Scope;
99

10-
use crate::source::{ByteRange, FileId};
11-
use crate::{StringId, StringInterner};
10+
use crate::source::{ByteRange, FileId, StringId, StringInterner};
1211

1312
lalrpop_mod!(
1413
#[allow(clippy::all)]

fathom/src/surface/distillation.rs

Lines changed: 30 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@ use scoped_arena::Scope;
44
use std::cell::RefCell;
55

66
use crate::alloc::SliceVec;
7+
use crate::core;
78
use crate::core::{Const, UIntStyle};
89
use crate::env::{self, EnvLen, Index, Level, UniqueEnv};
9-
use crate::source::Span;
10+
use crate::source::{Span, StringId, StringInterner};
1011
use crate::surface::elaboration::MetaSource;
1112
use crate::surface::{
1213
BinOp, ExprField, FormatField, Item, ItemDef, Module, Pattern, Term, TypeField,
1314
};
14-
use crate::{core, StringId, StringInterner};
1515

1616
/// Distillation context.
1717
pub struct Context<'interner, 'arena, 'env> {
@@ -244,21 +244,21 @@ impl<'interner, 'arena, 'env> Context<'interner, 'arena, 'env> {
244244
self.scope.to_scope(body_expr),
245245
)
246246
}
247-
core::Term::RecordType(_span, labels, exprs)
248-
if is_tuple_type(labels, exprs, &self.interner.borrow()) =>
247+
core::Term::RecordType(_, labels, types)
248+
if is_tuple_type(&mut self.interner.borrow_mut(), labels, types) =>
249249
{
250250
let scope = self.scope;
251-
let exprs = exprs.iter().map(|expr| self.check(expr));
252-
Term::Tuple((), scope.to_scope_from_iter(exprs))
251+
let types = types.iter().map(|expr| self.check(expr));
252+
Term::Tuple((), scope.to_scope_from_iter(types))
253253
}
254-
core::Term::RecordLit(_span, labels, exprs)
255-
if is_tuple_expr(labels, &self.interner.borrow()) =>
254+
core::Term::RecordLit(_, labels, exprs)
255+
if self.interner.borrow_mut().is_tuple_labels(labels) =>
256256
{
257257
let scope = self.scope;
258258
let exprs = exprs.iter().map(|expr| self.check(expr));
259259
Term::Tuple((), scope.to_scope_from_iter(exprs))
260260
}
261-
core::Term::RecordLit(_span, labels, exprs) => {
261+
core::Term::RecordLit(_, labels, exprs) => {
262262
let scope = self.scope;
263263
let expr_fields =
264264
Iterator::zip(labels.iter(), exprs.iter()).map(|(label, expr)| ExprField {
@@ -274,8 +274,8 @@ impl<'interner, 'arena, 'env> Context<'interner, 'arena, 'env> {
274274

275275
Term::ArrayLiteral((), scope.to_scope_from_iter(elem_exprs))
276276
}
277-
core::Term::FormatRecord(_span, labels, formats)
278-
if is_tuple_type(labels, formats, &self.interner.borrow()) =>
277+
core::Term::FormatRecord(_, labels, formats)
278+
if is_tuple_type(&mut self.interner.borrow_mut(), labels, formats) =>
279279
{
280280
let scope = self.scope;
281281
let formats = formats.iter().map(|format| self.check(format));
@@ -517,12 +517,12 @@ impl<'interner, 'arena, 'env> Context<'interner, 'arena, 'env> {
517517
)
518518
}
519519
},
520-
core::Term::RecordType(_span, labels, exprs)
521-
if is_tuple_type(labels, exprs, &self.interner.borrow()) =>
520+
core::Term::RecordType(_, labels, types)
521+
if is_tuple_type(&mut self.interner.borrow_mut(), labels, types) =>
522522
{
523523
let initial_local_len = self.local_len();
524524
let types = (self.scope).to_scope_from_iter(
525-
Iterator::zip(labels.iter(), exprs.iter()).map(|(label, r#type)| {
525+
Iterator::zip(labels.iter(), types.iter()).map(|(label, r#type)| {
526526
let r#type = self.check(r#type);
527527
self.push_local(Some(*label));
528528
r#type
@@ -551,8 +551,8 @@ impl<'interner, 'arena, 'env> Context<'interner, 'arena, 'env> {
551551

552552
Term::RecordType((), type_fields)
553553
}
554-
core::Term::RecordLit(_span, labels, exprs)
555-
if is_tuple_expr(labels, &self.interner.borrow()) =>
554+
core::Term::RecordLit(_, labels, exprs)
555+
if self.interner.borrow_mut().is_tuple_labels(labels) =>
556556
{
557557
let scope = self.scope;
558558
let exprs = exprs.iter().map(|expr| self.synth(expr));
@@ -592,7 +592,7 @@ impl<'interner, 'arena, 'env> Context<'interner, 'arena, 'env> {
592592
Term::ArrayLiteral((), scope.to_scope_from_iter(elem_exprs))
593593
}
594594
core::Term::FormatRecord(_span, labels, formats)
595-
if is_tuple_type(labels, formats, &self.interner.borrow()) =>
595+
if is_tuple_type(&mut self.interner.borrow_mut(), labels, formats) =>
596596
{
597597
let scope = self.scope;
598598
let formats = formats.iter().map(|format| self.synth(format));
@@ -782,27 +782,19 @@ fn match_if_then_else<'arena>(
782782
}
783783
}
784784

785-
// Return true if `labels` are all tuple labels
786-
fn is_tuple_expr(labels: &[StringId], interner: &StringInterner) -> bool {
787-
labels
788-
.iter()
789-
.enumerate()
790-
.all(|(idx, label)| interner.resolve(*label) == Some(&format!("_{}", idx)))
791-
}
792-
793-
// Return true if `labels` are all tuple labels, and `exprs` do not depend on any of the expressions bound by `labels`
794-
fn is_tuple_type(labels: &[StringId], exprs: &[core::Term<'_>], interner: &StringInterner) -> bool {
795-
let suffixes = (1..=exprs.len()).rev().map(move |idx| &exprs[idx..]);
796-
labels
797-
.iter()
798-
.zip(suffixes)
799-
.enumerate()
800-
.all(|(idx, (label, suffix))| {
801-
interner.resolve(*label) == Some(&format!("_{}", idx))
802-
&& suffix
803-
.iter()
804-
.zip(env::indices())
805-
.all(|(expr, idx)| !expr.binds_local(idx))
785+
/// Returns true if `labels` is a sequence of tuple labels (`_0`, `_1`, ...),
786+
/// and a telescope of `types` contains independent entries.
787+
fn is_tuple_type(
788+
interner: &mut StringInterner,
789+
labels: &[StringId],
790+
types: &[core::Term<'_>],
791+
) -> bool {
792+
interner.is_tuple_labels(labels)
793+
// For each type in the telescope, ensure that the subsequent types in
794+
// the telescope do not depend on the current field.
795+
&& (1..=types.len()).all(|index| {
796+
Iterator::zip(types[index..].iter(), env::indices())
797+
.all(|(expr, var)| !expr.binds_local(var))
806798
})
807799
}
808800

fathom/src/surface/elaboration.rs

Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,9 @@ use crate::alloc::SliceVec;
2929
use crate::core::semantics::{self, ArcValue, Head, Telescope, Value};
3030
use crate::core::{self, prim, Const, Prim, UIntStyle};
3131
use crate::env::{self, EnvLen, Level, SharedEnv, UniqueEnv};
32-
use crate::source::{ByteRange, Span, Spanned};
32+
use crate::source::{ByteRange, Span, Spanned, StringId, StringInterner};
3333
use crate::surface::elaboration::reporting::Message;
3434
use crate::surface::{distillation, pretty, BinOp, FormatField, Item, Module, Pattern, Term};
35-
use crate::{StringId, StringInterner};
3635

3736
mod order;
3837
mod reporting;
@@ -982,11 +981,8 @@ impl<'interner, 'arena> Context<'interner, 'arena> {
982981
core::Term::RecordLit(range.into(), labels, exprs.into())
983982
}
984983
(Term::Tuple(range, elem_exprs), Value::Universe) => {
985-
let labels = (0..elem_exprs.len()).map(|idx| {
986-
self.interner
987-
.borrow_mut()
988-
.get_or_intern(format!("_{}", idx))
989-
});
984+
let labels = (0..elem_exprs.len())
985+
.map(|index| self.interner.borrow_mut().get_tuple_label(index));
990986
let labels = self.scope.to_scope_from_iter(labels);
991987

992988
let initial_local_len = self.local_env.len();
@@ -1019,12 +1015,10 @@ impl<'interner, 'arena> Context<'interner, 'arena> {
10191015
}
10201016

10211017
// use numeric labels for excess elems
1022-
for (idx, elem_expr) in elem_exprs {
1018+
for (index, elem_expr) in elem_exprs {
10231019
expr_labels.push((
10241020
elem_expr.range(),
1025-
self.interner
1026-
.borrow_mut()
1027-
.get_or_intern(format!("_{}", idx)),
1021+
self.interner.borrow_mut().get_tuple_label(index),
10281022
));
10291023
}
10301024

@@ -1056,11 +1050,8 @@ impl<'interner, 'arena> Context<'interner, 'arena> {
10561050
let initial_local_len = self.local_env.len();
10571051
let format_type = self.format_type.clone();
10581052

1059-
let labels = (0..elem_exprs.len()).map(|idx| {
1060-
self.interner
1061-
.borrow_mut()
1062-
.get_or_intern(format!("_{}", idx))
1063-
});
1053+
let labels = (0..elem_exprs.len())
1054+
.map(|index| self.interner.borrow_mut().get_tuple_label(index));
10641055
let labels = self.scope.to_scope_from_iter(labels);
10651056

10661057
let mut formats = SliceVec::new(self.scope, elem_exprs.len());
@@ -1432,11 +1423,8 @@ impl<'interner, 'arena> Context<'interner, 'arena> {
14321423
)
14331424
}
14341425
Term::Tuple(range, elem_exprs) => {
1435-
let labels = (0..elem_exprs.len()).map(|idx| {
1436-
self.interner
1437-
.borrow_mut()
1438-
.get_or_intern(format!("_{}", idx))
1439-
});
1426+
let labels = (0..elem_exprs.len())
1427+
.map(|index| self.interner.borrow_mut().get_tuple_label(index));
14401428
let labels = self.scope.to_scope_from_iter(labels);
14411429

14421430
let mut exprs = SliceVec::new(self.scope, labels.len());

fathom/src/surface/elaboration/order.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,9 @@
2020
2121
use fxhash::{FxHashMap, FxHashSet};
2222

23-
use crate::source::ByteRange;
23+
use crate::source::{ByteRange, StringId};
2424
use crate::surface::elaboration::reporting::Message;
2525
use crate::surface::{elaboration, FormatField, Item, Module, Pattern, Term};
26-
use crate::StringId;
2726

2827
enum Error {
2928
CycleDetected,

0 commit comments

Comments
 (0)