1#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
12pub struct Position(usize);
13
14impl Position {
15 #[must_use]
17 pub fn value(&self) -> usize {
18 self.0
19 }
20}
21
22impl From<usize> for Position {
23 fn from(value: usize) -> Self {
24 Self(value)
25 }
26}
27
28impl std::fmt::Display for Position {
29 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
30 write!(f, "{}", self.0)
31 }
32}
33
34#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
36pub struct VarName(String);
37
38impl VarName {
39 #[must_use]
41 pub fn as_str(&self) -> &str {
42 &self.0
43 }
44}
45
46impl From<String> for VarName {
47 fn from(value: String) -> Self {
48 Self(value)
49 }
50}
51
52impl From<&str> for VarName {
53 fn from(value: &str) -> Self {
54 Self(value.to_owned())
55 }
56}
57
58impl std::fmt::Display for VarName {
59 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
60 f.write_str(&self.0)
61 }
62}
63
64#[derive(Debug, Clone, PartialEq, Eq)]
66pub enum Expr {
67 Var(VarName),
69 Lam {
71 param: VarName,
73 body: Box<Expr>,
75 },
76 App {
78 func: Box<Expr>,
80 arg: Box<Expr>,
82 },
83 Let {
85 name: VarName,
87 value: Box<Expr>,
89 body: Box<Expr>,
91 },
92 Fix {
94 name: VarName,
96 body: Box<Expr>,
98 },
99 Ref {
101 inner: Box<Expr>,
103 },
104 Deref {
106 inner: Box<Expr>,
110 },
111 Assign {
115 target: Box<Expr>,
117 value: Box<Expr>,
119 },
120 Seq {
123 first: Box<Expr>,
125 second: Box<Expr>,
127 },
128 Object {
131 entries: Vec<(VarName, Expr)>,
134 prototype: Option<Box<Expr>>,
137 },
138 Field {
140 object: Box<Expr>,
142 name: VarName,
144 },
145 Throw {
148 inner: Box<Expr>,
150 },
151 TryCatch {
154 body: Box<Expr>,
156 catch_param: VarName,
158 handler: Box<Expr>,
160 },
161}
162
163impl Expr {
164 #[must_use]
166 pub fn var(name: impl Into<VarName>) -> Self {
167 Self::Var(name.into())
168 }
169
170 #[must_use]
172 pub fn lam(param: impl Into<VarName>, body: Self) -> Self {
173 Self::Lam {
174 param: param.into(),
175 body: Box::new(body),
176 }
177 }
178
179 #[must_use]
181 pub fn app(func: Self, arg: Self) -> Self {
182 Self::App {
183 func: Box::new(func),
184 arg: Box::new(arg),
185 }
186 }
187
188 #[must_use]
190 pub fn bind(name: impl Into<VarName>, value: Self, body: Self) -> Self {
191 Self::Let {
192 name: name.into(),
193 value: Box::new(value),
194 body: Box::new(body),
195 }
196 }
197
198 #[must_use]
200 pub fn fix(name: impl Into<VarName>, body: Self) -> Self {
201 Self::Fix {
202 name: name.into(),
203 body: Box::new(body),
204 }
205 }
206
207 #[must_use]
209 pub fn alloc(inner: Self) -> Self {
210 Self::Ref {
211 inner: Box::new(inner),
212 }
213 }
214
215 #[must_use]
217 pub fn deref(inner: Self) -> Self {
218 Self::Deref {
219 inner: Box::new(inner),
220 }
221 }
222
223 #[must_use]
225 pub fn assign(target: Self, value: Self) -> Self {
226 Self::Assign {
227 target: Box::new(target),
228 value: Box::new(value),
229 }
230 }
231
232 #[must_use]
234 pub fn seq(first: Self, second: Self) -> Self {
235 Self::Seq {
236 first: Box::new(first),
237 second: Box::new(second),
238 }
239 }
240
241 #[must_use]
243 pub fn object(entries: Vec<(VarName, Self)>) -> Self {
244 Self::Object {
245 entries,
246 prototype: None,
247 }
248 }
249
250 #[must_use]
252 pub fn object_with_proto(entries: Vec<(VarName, Self)>, prototype: Self) -> Self {
253 Self::Object {
254 entries,
255 prototype: Some(Box::new(prototype)),
256 }
257 }
258
259 #[must_use]
261 pub fn field(object: Self, name: impl Into<VarName>) -> Self {
262 Self::Field {
263 object: Box::new(object),
264 name: name.into(),
265 }
266 }
267
268 #[must_use]
270 pub fn throw(inner: Self) -> Self {
271 Self::Throw {
272 inner: Box::new(inner),
273 }
274 }
275
276 #[must_use]
278 pub fn try_catch(body: Self, catch_param: impl Into<VarName>, handler: Self) -> Self {
279 Self::TryCatch {
280 body: Box::new(body),
281 catch_param: catch_param.into(),
282 handler: Box::new(handler),
283 }
284 }
285}
286
287impl std::fmt::Display for Expr {
288 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
289 match self {
290 Self::Var(name) => write!(f, "{name}"),
291 Self::Lam { param, body } => write!(f, "(\\{param}. {body})"),
292 Self::App { func, arg } => write!(f, "({func} {arg})"),
293 Self::Let { name, value, body } => {
294 write!(f, "(let {name} = {value} in {body})")
295 }
296 Self::Fix { name, body } => write!(f, "(fix {name}. {body})"),
297 Self::Ref { inner } => write!(f, "(ref {inner})"),
298 Self::Deref { inner } => write!(f, "(!{inner})"),
299 Self::Assign { target, value } => write!(f, "({target} := {value})"),
300 Self::Seq { first, second } => write!(f, "({first} ; {second})"),
301 Self::Object { entries, prototype } => write_object(f, entries, prototype.as_deref()),
302 Self::Field { object, name } => write!(f, "({object}.{name})"),
303 Self::Throw { inner } => write!(f, "(throw {inner})"),
304 Self::TryCatch {
305 body,
306 catch_param,
307 handler,
308 } => write!(f, "(try {body} catch {catch_param}. {handler})"),
309 }
310 }
311}
312
313fn write_object(
314 f: &mut std::fmt::Formatter<'_>,
315 entries: &[(VarName, Expr)],
316 prototype: Option<&Expr>,
317) -> std::fmt::Result {
318 let body = entries
319 .iter()
320 .map(|(k, v)| format!("{k} = {v}"))
321 .collect::<Vec<_>>()
322 .join(", ");
323 let formatted = prototype.map_or_else(
324 || format!("{{{body}}}"),
325 |proto| format!("(extend {proto} {{{body}}})"),
326 );
327 f.write_str(&formatted)
328}