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}