Skip to content

Commit 309983b

Browse files
committed
Much better API
1 parent 680cfe6 commit 309983b

File tree

2 files changed

+48
-69
lines changed

2 files changed

+48
-69
lines changed

src/ast/printer.rs

+19-69
Original file line numberDiff line numberDiff line change
@@ -141,68 +141,35 @@ impl<'d> ToDisplayTree<'d> for Pattern<'_> {
141141

142142
impl<'d> ToDisplayTree<'d> for Type<'_> {
143143
fn to_display_tree(&self, a: &'d Arenas<'d>) -> DisplayTree<'d> {
144-
/// Remove the refs in front of this type.
145-
fn strip_refs<'a>(ty: &'a Type<'a>, mutabilities: &mut Vec<Mutability>) -> &'a Type<'a> {
146-
match ty {
147-
Type::Ref(mtbl, ty) => {
148-
mutabilities.push(*mtbl);
149-
strip_refs(ty, mutabilities)
150-
}
151-
_ => &ty,
152-
}
153-
}
154-
let mut mutabilities = Vec::new();
155-
let ty = strip_refs(self, &mut mutabilities);
156-
let leaf = match ty {
157-
Type::Tuple(tys) => DisplayTree::sep_by(a, ", ", tys.iter())
144+
match self {
145+
Self::Tuple(tys) => DisplayTree::sep_by(a, ", ", tys.iter())
158146
.surrounded(a, "[", "]")
159147
.tag("ty_list"),
160-
Type::OtherNonRef(name) | Type::AbstractNonRef(name) | Type::Abstract(name) => {
148+
Self::Ref(mutable, ty) => format!("&{mutable}")
149+
.to_display_tree(a)
150+
.prepend_to_tagged_list(a, "ty_refs", "", CompareMode::Suffix, ty),
151+
Self::OtherNonRef(name) | Self::AbstractNonRef(name) | Self::Abstract(name) => {
161152
name.to_display_tree(a)
162153
}
163-
Type::Ref(..) => unreachable!(),
164-
};
165-
// Types tend be the same on the inside; so we want to show that the innermost types are
166-
// the same and the surrounding refs differ. To do this, we extract the list of refs and
167-
// add them to the same list, with `Suffix` compare mode.
168-
DisplayTree::sep_by_compare_mode(
169-
a,
170-
"",
171-
mutabilities
172-
.iter()
173-
.map(|mutable| format!("&{mutable}").to_display_tree(a))
174-
.chain([leaf]),
175-
CompareMode::Suffix,
176-
)
177-
.tag("ty_refs")
154+
}
178155
}
179156
}
180157

181158
impl<'d> ToDisplayTree<'d> for ExprKind<'_> {
182159
fn to_display_tree(&self, a: &'d Arenas<'d>) -> DisplayTree<'d> {
183-
enum Symbol {
184-
Deref,
185-
Ref(Mutability),
186-
}
187-
/// Remove the refs and derefs in front of this expression.
188-
fn strip_symbols<'a>(e: &'a ExprKind<'a>, symbols: &mut Vec<Symbol>) -> &'a ExprKind<'a> {
189-
match e {
190-
ExprKind::Ref(mtbl, e) => {
191-
symbols.push(Symbol::Ref(*mtbl));
192-
strip_symbols(&e.kind, symbols)
193-
}
194-
ExprKind::Deref(e) => {
195-
symbols.push(Symbol::Deref);
196-
strip_symbols(&e.kind, symbols)
197-
}
198-
_ => &e,
199-
}
200-
}
201-
let mut symbols = Vec::new();
202-
let e = strip_symbols(self, &mut symbols);
203-
let leaf = match e {
160+
match self {
204161
ExprKind::Scrutinee => "s".to_display_tree(a),
205162
ExprKind::Abstract { .. } => "e".to_display_tree(a),
163+
ExprKind::Ref(mutable, e) => format!("&{mutable}")
164+
.to_display_tree(a)
165+
.prepend_to_tagged_list(a, "expr_symbols", "", CompareMode::Suffix, e),
166+
ExprKind::Deref(e) => "*".to_display_tree(a).prepend_to_tagged_list(
167+
a,
168+
"expr_symbols",
169+
"",
170+
CompareMode::Suffix,
171+
e,
172+
),
206173
ExprKind::Field(e, n) => {
207174
let needs_parens = matches!(e.kind, ExprKind::Deref(..));
208175
let (before, after) = if needs_parens { ("(", ")") } else { ("", "") };
@@ -218,24 +185,7 @@ impl<'d> ToDisplayTree<'d> for ExprKind<'_> {
218185
],
219186
)
220187
}
221-
ExprKind::Ref(..) | ExprKind::Deref(..) => unreachable!(),
222-
};
223-
// We cleverly diff expressions: expressions tend to start the same then diverge; so we
224-
// want to show that the innermost expressions are the same and the surrounding `&`/`*`
225-
// differ. To do this, we extract the list of `&`/`*` and add them to the same list, with
226-
// `Suffix` compare mode.
227-
DisplayTree::sep_by_compare_mode(
228-
a,
229-
"",
230-
symbols
231-
.iter()
232-
.map(|s| match s {
233-
Symbol::Deref => "*".to_display_tree(a),
234-
Symbol::Ref(mutable) => format!("&{mutable}").to_display_tree(a),
235-
})
236-
.chain([leaf]),
237-
CompareMode::Suffix,
238-
)
188+
}
239189
}
240190
}
241191

src/ast/printer/display_tree.rs

+29
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,35 @@ impl<'a> DisplayTree<'a> {
200200
self
201201
}
202202

203+
/// Incrementally build a list by prepending new elements to it. This will only prepend to a
204+
/// subtree if the tags match.
205+
pub fn prepend_to_tagged_list(
206+
&self,
207+
a: &'a Arenas<'a>,
208+
tag: &'static str,
209+
sep: &str,
210+
compare_mode: CompareMode,
211+
x: impl ToDisplayTree<'a>,
212+
) -> Self {
213+
let this = self.to_display_tree(a);
214+
let mut inner = x.to_display_tree(a);
215+
match &mut inner.kind {
216+
Separated { children, .. } if inner.tag == tag => {
217+
let new_children = [this]
218+
.into_iter()
219+
.chain(children.iter().copied())
220+
.collect_vec();
221+
*children = a.bump.alloc_slice_copy(&new_children);
222+
inner
223+
}
224+
_ => {
225+
// Base case: create a new list.
226+
let children = [this, inner];
227+
Self::sep_by_compare_mode(a, sep, children, compare_mode).tag(tag)
228+
}
229+
}
230+
}
231+
203232
/// Display `self` and `other`, highlighting differences.
204233
pub fn diff_display(&self, other: &Self) -> (String, String) {
205234
let (left, right, _) = self.diff_display_has_diff(other);

0 commit comments

Comments
 (0)