1use std::fmt::Debug;
2
3use num::{complex::Complex64, BigRational};
4
5use crate::{lexer::scanner::Position, Fixnum};
6
7pub enum Expr<I: Interner> {
58 Symbol(I::Sym),
59 Syntax(Position, Box<Self>),
60 Bool(bool),
61 Fixnum(Fixnum),
62 BigInt(num::BigInt),
63 Rational(crate::Rational),
64 BigRational(BigRational),
65 Float(f64),
66 Complex(Complex64),
67 Char(char),
68 Str(String),
69 Pair(Box<Expr<I>>, Box<Expr<I>>),
70 ImmutableVector(Box<[Box<Expr<I>>]>),
71 GrowableVector(Box<[Box<Expr<I>>]>),
72 ByteVector(Box<[u8]>),
73 Null,
74}
75
76impl<I: Interner> Expr<I> {
77 pub fn datum(self: Box<Self>) -> Box<Self> {
78 match *self {
79 Self::Pair(car, cdr) => Box::new(Self::Pair(car.datum(), cdr.datum())),
80 Self::Syntax(_, expr) => expr,
81 _ => self,
82 }
83 }
84
85 pub fn from_slice(mut exprs: Vec<Box<Expr<I>>>, append: Box<Expr<I>>) -> Box<Self> {
86 exprs.reverse();
87 Self::make_list_unchecked(exprs, append)
88 }
89
90 pub fn make_list_unchecked(from_stack: Vec<Box<Expr<I>>>, append: Box<Expr<I>>) -> Box<Self> {
91 let mut res = append;
92 for expr in from_stack {
93 res = Box::new(Expr::Pair(expr, res));
94 }
95
96 res
97 }
98
99 pub fn to_string(&self, interner: &I, escape: bool) -> String {
100 fn double_string(f: f64) -> String {
101 if f.is_infinite() {
102 if f.is_sign_negative() {
103 "-inf.0".to_string()
104 } else {
105 "+inf.0".to_string()
106 }
107 } else if f.is_nan() {
108 if f.is_sign_negative() {
109 "-nan.0".to_string()
110 } else {
111 "+nan.0".to_string()
112 }
113 } else {
114 f.to_string()
115 }
116 }
117
118 match self {
119 Self::Null => "null".to_string(),
120 Self::Symbol(sym) => interner.description(sym).to_string(),
121 Self::Bool(x) => {
122 if *x {
123 "#t".to_string()
124 } else {
125 "#f".to_string()
126 }
127 }
128 Self::Syntax(_, expr) => expr.to_string(interner, escape),
129 Self::Float(x) => double_string(*x),
130 Self::Pair(head, tail) => {
131 let mut s = String::new();
132 s.push('(');
133 s.push_str(&head.to_string(interner, escape));
134 let mut expr = tail;
135
136 while let Expr::Pair(car, cdr) = &**expr {
137
138 s.push(' ');
139 s.push_str(&car.to_string(interner, escape));
140
141 expr = cdr;
142 }
143
144 if let Expr::Null = &**expr {
145 s.push(')');
146 s
147 } else {
148 s.push_str(" . ");
149 s.push_str(&tail.to_string(interner, escape));
150 s.push(')');
151 s
152 }
153 }
154 Self::BigInt(x) => x.to_string(),
155 Self::Fixnum(x) => x.to_string(),
156 Self::BigRational(x) => x.to_string(),
157 Self::Rational(x) => format!("{}/{}", x.numer(), x.denom()),
158 Self::Complex(x) => {
159 let mut res = double_string(x.re);
160
161 if x.im.is_nan() || x.im.is_infinite() || x.im < 0.0 {
162 res = format!("{}{}", res, double_string(x.im));
163 } else {
164 res = format!("{}+{}", res, double_string(x.im));
165 }
166
167 res.push('i');
168 res
169 }
170
171 Self::Char(c) => {
172 if !escape {
173 return c.to_string();
174 } else {
175 todo!()
176 }
177 }
178 Self::Str(s) => {
179 if !escape {
180 return s.to_string();
181 } else {
182 todo!()
183 }
184 }
185
186 Self::ByteVector(bytes) => {
187 let mut s = String::new();
188
189 s.push_str("#u8(");
190
191 for (i, b) in bytes.iter().enumerate() {
192 if i != bytes.len() - 1 {
193 s.push(' ');
194 }
195
196 s.push_str(&b.to_string());
197 }
198
199 s.push(')');
200
201 s
202 }
203
204 Self::ImmutableVector(vector) => {
205 let mut s = String::new();
206
207 s.push_str("#(");
208
209 for (i, b) in vector.iter().enumerate() {
210 if i != vector.len() - 1 {
211 s.push(' ');
212 }
213
214 s.push_str(&b.to_string(interner, escape));
215 }
216
217 s.push(')');
218
219 s
220 }
221
222 Self::GrowableVector(vector) => {
223 let mut s = String::new();
224
225 s.push_str("#g(");
226
227 for (i, b) in vector.iter().enumerate() {
228 if i != vector.len() - 1 {
229 s.push(' ');
230 }
231
232 s.push_str(&b.to_string(interner, escape));
233 }
234
235 s.push(')');
236
237 s
238 }
239 }
240 }
241}
242pub trait Sym: PartialEq + Eq {}
243
244pub trait Interner {
245 type Sym: PartialEq + Eq + Debug;
246 fn intern(&mut self, s: &str) -> Self::Sym;
247 fn description(&self, s: &Self::Sym) -> String;
248}
249
250impl Sym for &'static str {}
251impl Sym for String {}
252
253pub struct NoIntern;
254
255impl Interner for NoIntern {
256 type Sym = String;
257 fn intern(&mut self, s: &str) -> Self::Sym {
258 s.to_string()
259 }
260
261 fn description(&self, s: &Self::Sym) -> String {
262 s.to_string()
263 }
264}