Skip to main content

cljrs_reader/
form.rs

1use cljrs_types::span::Span;
2
3/// A parsed Clojure form with its source location.
4///
5/// `PartialEq` ignores spans so test assertions can compare forms without
6/// constructing exact span values.
7#[derive(Debug, Clone)]
8pub struct Form {
9    pub kind: FormKind,
10    pub span: Span,
11}
12
13impl Form {
14    pub fn new(kind: FormKind, span: Span) -> Self {
15        Self { kind, span }
16    }
17}
18
19impl PartialEq for Form {
20    fn eq(&self, other: &Self) -> bool {
21        self.kind == other.kind
22    }
23}
24
25/// The payload of a `Form` node.
26#[derive(Debug, Clone, PartialEq)]
27pub enum FormKind {
28    // ── Atoms ─────────────────────────────────────────────────────────────────
29    Nil,
30    Bool(bool),
31    Int(i64),
32    BigInt(String),
33    Float(f64), // NaN != NaN per IEEE 754 — acceptable for AST equality
34    BigDecimal(String),
35    Ratio(String),
36    Char(char),
37    Str(String),
38    Regex(String),
39    /// `##Inf` → `INFINITY`, `##-Inf` → `NEG_INFINITY`, `##NaN` → `NAN`
40    Symbolic(f64),
41
42    // ── Identifiers ───────────────────────────────────────────────────────────
43    Symbol(String),
44    Keyword(String),
45    AutoKeyword(String),
46
47    // ── Collections ───────────────────────────────────────────────────────────
48    List(Vec<Form>),
49    Vector(Vec<Form>),
50    /// Flat key/value pairs; length is always even.
51    Map(Vec<Form>),
52    Set(Vec<Form>),
53
54    // ── Wrapping reader macros ────────────────────────────────────────────────
55    Quote(Box<Form>),
56    SyntaxQuote(Box<Form>),
57    Unquote(Box<Form>),
58    UnquoteSplice(Box<Form>),
59    Deref(Box<Form>),
60    /// `#'symbol`
61    Var(Box<Form>),
62    /// `^meta-form annotated-form` — raw meta form kept as-is; evaluator
63    /// expands shorthand (`:kw` → `{:kw true}`, `Sym` → `{:tag Sym}`).
64    Meta(Box<Form>, Box<Form>),
65
66    // ── Dispatch forms ────────────────────────────────────────────────────────
67    /// `#(…)` anonymous function literal
68    AnonFn(Vec<Form>),
69    /// `#tag form` tagged literal
70    TaggedLiteral(String, Box<Form>),
71
72    // ── Reader conditionals ───────────────────────────────────────────────────
73    /// All branches are kept; the evaluator filters by `:rust`.
74    /// `clauses` is flat: `[keyword, form, keyword, form, …]`.
75    ReaderCond {
76        splicing: bool,
77        clauses: Vec<Form>,
78    },
79}