1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
|
use super::func::FuncHeader;
use super::expr::{Expr, Tuple, Object};
use super::*;
function! {
/// Most functions in the tests are parsed into the debug function for easy
/// inspection of arguments and body.
#[derive(Debug, Clone, PartialEq)]
pub struct DebugFn {
pub header: FuncHeader,
pub body: Option<SyntaxModel>,
}
parse(header, body, ctx, errors, decos) {
let cloned = header.clone();
header.args.pos.items.clear();
header.args.key.pairs.clear();
DebugFn {
header: cloned,
body: body!(opt: body, ctx, errors, decos),
}
}
layout(self, ctx, errors) { vec![] }
}
/// Compares elements by only looking at values and ignoring spans.
pub trait SpanlessEq<Rhs=Self> {
fn spanless_eq(&self, other: &Rhs) -> bool;
}
impl SpanlessEq for Vec<Spanned<Token<'_>>> {
fn spanless_eq(&self, other: &Vec<Spanned<Token>>) -> bool {
self.len() == other.len()
&& self.iter().zip(other).all(|(x, y)| x.v == y.v)
}
}
impl SpanlessEq for SyntaxModel {
fn spanless_eq(&self, other: &SyntaxModel) -> bool {
fn downcast<'a>(func: &'a (dyn Model + 'static)) -> &'a DebugFn {
func.downcast::<DebugFn>().expect("not a debug fn")
}
self.nodes.len() == other.nodes.len()
&& self.nodes.iter().zip(&other.nodes).all(|(x, y)| match (&x.v, &y.v) {
(Node::Model(a), Node::Model(b)) => {
downcast(a.as_ref()).spanless_eq(downcast(b.as_ref()))
}
(a, b) => a == b,
})
}
}
impl SpanlessEq for DebugFn {
fn spanless_eq(&self, other: &DebugFn) -> bool {
self.header.name.v == other.header.name.v
&& self.header.args.pos.spanless_eq(&other.header.args.pos)
&& self.header.args.key.spanless_eq(&other.header.args.key)
}
}
impl SpanlessEq for Expr {
fn spanless_eq(&self, other: &Expr) -> bool {
match (self, other) {
(Expr::Tuple(a), Expr::Tuple(b)) => a.spanless_eq(b),
(Expr::Object(a), Expr::Object(b)) => a.spanless_eq(b),
(a, b) => a == b,
}
}
}
impl SpanlessEq for Tuple {
fn spanless_eq(&self, other: &Tuple) -> bool {
self.items.len() == other.items.len()
&& self.items.iter().zip(&other.items)
.all(|(x, y)| x.v.spanless_eq(&y.v))
}
}
impl SpanlessEq for Object {
fn spanless_eq(&self, other: &Object) -> bool {
self.pairs.len() == other.pairs.len()
&& self.pairs.iter().zip(&other.pairs)
.all(|(x, y)| x.key.v == y.key.v && x.value.v.spanless_eq(&y.value.v))
}
}
|