]> Witch of Git - ess/blob - src/sexp.rs
Change List to use Cow<[Sexp]> instead of Vec<Sexp>
[ess] / src / sexp.rs
1 //! The `Sexp` type, the representation of s-expressions.
2
3 use std::borrow::{Cow, ToOwned};
4
5 use span::{ByteSpan, Span};
6
7 /// A type representing arbitrary s-expressions.
8 ///
9 /// `Sexp` carries the source code location it came from along with it for later
10 /// diagnostic purposes.
11 #[derive(Clone, Debug, PartialEq, PartialOrd)]
12 pub enum Sexp<'a, Loc = ByteSpan>
13 where
14 Loc: Span + Clone,
15 {
16 /// A value representing a symbol.
17 Sym(Cow<'a, str>, Loc),
18 /// A value representing a string literal.
19 Str(Cow<'a, str>, Loc),
20 /// A value representing a single character.
21 Char(char, Loc),
22 /// A value representing an integer. Any number containing no decimal point
23 /// will be parsed as an `Int`.
24 Int(i64, Loc),
25 /// A value representing a floating point number. Any number containing a
26 /// decimal point will be parsed as a `Float`.
27 Float(f64, Loc),
28 /// A list of subexpressions.
29 List(Cow<'a, [Sexp<'a, Loc>]>, Loc),
30 }
31
32 impl<'a, Loc> Sexp<'a, Loc>
33 where
34 Loc: Span + Clone,
35 {
36 /// Gives a reference to the source location contained in the `Sexp`.
37 pub fn get_loc(&self) -> &Loc {
38 match *self {
39 Sexp::Sym(.., ref l)
40 | Sexp::Str(.., ref l)
41 | Sexp::Char(.., ref l)
42 | Sexp::Int(.., ref l)
43 | Sexp::Float(.., ref l)
44 | Sexp::List(.., ref l) => l,
45 }
46 }
47
48 /// Gives a mutable reference to the `Sexp`'s source location.
49 pub fn get_loc_mut(&mut self) -> &mut Loc {
50 match *self {
51 Sexp::Sym(.., ref mut l)
52 | Sexp::Str(.., ref mut l)
53 | Sexp::Char(.., ref mut l)
54 | Sexp::Int(.., ref mut l)
55 | Sexp::Float(.., ref mut l)
56 | Sexp::List(.., ref mut l) => l,
57 }
58 }
59 }
60
61 fn extend_cow<'a, T: ?Sized>(cow: &Cow<'a, T>) -> Cow<'static, T>
62 where
63 T: ToOwned,
64 {
65 Cow::Owned(cow.clone().into_owned())
66 }
67
68 impl<'a, Loc> Sexp<'a, Loc>
69 where
70 Loc: Span + ToOwned + Clone,
71 Loc::Owned: Span + Clone,
72 {
73 /// Take ownership of an s-expression's contents.
74 pub fn to_owned(&self) -> Sexp<'static, Loc::Owned> {
75 match self {
76 Sexp::Sym(s, l) => Sexp::Sym(extend_cow(s), l.to_owned()),
77 Sexp::Str(s, l) => Sexp::Str(extend_cow(s), l.to_owned()),
78 Sexp::Char(c, l) => Sexp::Char(*c, l.to_owned()),
79 Sexp::Int(i, l) => Sexp::Int(*i, l.to_owned()),
80 Sexp::Float(f, l) => Sexp::Float(*f, l.to_owned()),
81 Sexp::List(xs, l) => Sexp::List(
82 xs.iter().map(Sexp::to_owned).collect(),
83 l.to_owned(),
84 ),
85 }
86 }
87 }