1use std::rc::Rc;
2
3use super::{BindingId, Keyword, ReferenceKind, TypeExpr};
4use crate::reader::{Form, Number};
5use crate::source::Span;
6
7#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
8pub struct Expr {
9 kind: ExprKind,
10 span: Span,
11}
12
13#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
14pub enum ExprKind {
15 Leaf(Leaf),
16 Fn(Rc<Lambda>),
17 Call(Box<Expr>, Vec<Expr>),
18 Recur(Vec<Expr>),
19 Try(Box<Expr>),
20 Infer(Box<Expr>),
21 Borrow(ReferenceKind, Box<Expr>),
22 Deref(Box<Expr>),
23 Control(Control),
24 Struct(StructExpr),
25 Variant(BindingId, Vec<Expr>),
26 LabeledVariant(BindingId, Vec<(FieldLabel, Expr)>),
27 Assoc(Box<Expr>, Vec<Expr>, Box<Expr>),
28 MapAt(MapOperation, Box<Expr>, Vec<Expr>),
29 SetAt(Box<Expr>, Vec<Expr>, Box<Expr>),
30}
31
32#[derive(Clone, Copy, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
33pub enum MapOperation {
34 Get,
35 Keys,
36 Vals,
37 Iter,
38 Update,
39 Push,
40}
41
42impl MapOperation {
43 const KEYWORDS: [(Self, &'static str); 6] = [
44 (Self::Get, "get"),
45 (Self::Keys, "keys"),
46 (Self::Vals, "vals"),
47 (Self::Iter, "iter"),
48 (Self::Update, "update"),
49 (Self::Push, "push"),
50 ];
51
52 pub fn of(name: &str) -> Option<Self> {
53 Self::KEYWORDS
54 .iter()
55 .find(|(_, keyword)| *keyword == name)
56 .map(|(operation, _)| *operation)
57 }
58
59 pub fn keyword(self) -> &'static str {
60 Self::KEYWORDS
61 .iter()
62 .find(|(operation, _)| *operation == self)
63 .map(|(_, keyword)| *keyword)
64 .expect("every map operation has a keyword")
65 }
66}
67
68#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
69pub enum Leaf {
70 Literal(Literal),
71 Var(BindingId),
72 Quote(Form),
73 Rust(Rc<RustTemplate>),
74}
75
76#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
77pub enum Control {
78 Block(Block),
79 If(Box<Expr>, Box<Expr>, Box<Expr>),
80 Match(Box<Expr>, Vec<Arm>),
81}
82
83#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
84pub struct Arm {
85 pub pattern: Pattern,
86 pub body: Block,
87 pub span: Span,
88}
89
90#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
91pub struct Pattern {
92 pub kind: PatternKind,
93 pub span: Span,
94}
95
96#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
97pub enum PatternKind {
98 Wildcard,
99 Bind(BindingId),
100 BareName {
101 name: Rc<str>,
102 binding: BindingId,
103 candidates: Vec<BindingId>,
104 outer: Option<BindingId>,
105 },
106 Variant(BindingId, PatternArguments),
107 Struct(BindingId, PatternArguments),
108 ShortVariant {
109 name: Rc<str>,
110 candidates: Vec<BindingId>,
111 arguments: PatternArguments,
112 },
113 Literal(Literal),
114}
115
116#[derive(Clone, Debug, Default, serde::Serialize, serde::Deserialize)]
117pub struct PatternArguments {
118 pub parts: Vec<PatternPart>,
119}
120
121#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
122pub enum PatternPart {
123 Positional(Pattern),
124 Labeled(FieldLabel, Option<Pattern>),
125}
126
127impl PatternArguments {
128 pub fn patterns(&self) -> impl Iterator<Item = &Pattern> {
129 self.parts.iter().filter_map(|part| match part {
130 PatternPart::Positional(pattern) => Some(pattern),
131 PatternPart::Labeled(_, pattern) => pattern.as_ref(),
132 })
133 }
134
135 pub fn positional(&self) -> impl Iterator<Item = &Pattern> {
136 self.parts.iter().filter_map(|part| match part {
137 PatternPart::Positional(pattern) => Some(pattern),
138 PatternPart::Labeled(..) => None,
139 })
140 }
141
142 pub fn labeled(&self) -> impl Iterator<Item = (&FieldLabel, Option<&Pattern>)> {
143 self.parts.iter().filter_map(|part| match part {
144 PatternPart::Positional(_) => None,
145 PatternPart::Labeled(label, pattern) => Some((label, pattern.as_ref())),
146 })
147 }
148}
149
150impl Pattern {
151 pub fn new(kind: PatternKind, span: Span) -> Self {
152 Self { kind, span }
153 }
154
155 pub fn arm_outer(&self) -> Option<(BindingId, BindingId)> {
156 match &self.kind {
157 PatternKind::BareName {
158 binding,
159 outer: Some(outer),
160 ..
161 } => Some((*binding, *outer)),
162 _ => None,
163 }
164 }
165
166 pub fn nested(&self) -> impl Iterator<Item = &Pattern> {
167 self.arguments()
168 .into_iter()
169 .flat_map(PatternArguments::patterns)
170 }
171
172 fn arguments(&self) -> Option<&PatternArguments> {
173 match &self.kind {
174 PatternKind::Variant(_, arguments)
175 | PatternKind::Struct(_, arguments)
176 | PatternKind::ShortVariant { arguments, .. } => Some(arguments),
177 _ => None,
178 }
179 }
180}
181
182#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
183pub enum StructExpr {
184 New(BindingId, Vec<(FieldLabel, Expr)>),
185 Update(Box<Expr>, Vec<(FieldLabel, Expr)>),
186 Field(Box<Expr>, FieldLabel),
187}
188
189#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
190pub enum Literal {
191 Number(Number),
192 String(Rc<str>),
193 Bool(bool),
194}
195
196#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
197pub struct FieldLabel {
198 pub name: Rc<str>,
199 pub span: Span,
200 pub spelling: FieldSpelling,
201}
202
203impl FieldLabel {
204 pub fn spelled(&self, field_name: &str) -> String {
205 match self.spelling {
206 FieldSpelling::Bare => field_name.to_string(),
207 FieldSpelling::Keyword => format!("{}{field_name}", Keyword::MARKER),
208 }
209 }
210}
211
212#[derive(Clone, Copy, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
213pub enum FieldSpelling {
214 Bare,
215 Keyword,
216}
217
218#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
219pub struct Binder {
220 pub binding: BindingId,
221 pub annotation: Option<TypeExpr>,
222 pub span: Span,
223}
224
225#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
226pub struct Lambda {
227 pub params: Vec<Binder>,
228 pub body: Block,
229}
230
231#[derive(Clone, Debug, Default, serde::Serialize, serde::Deserialize)]
232pub struct Block {
233 pub items: Vec<BodyItem>,
234}
235
236#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
237pub enum BodyItem {
238 Let(Binder, Expr),
239 Expr(Expr),
240}
241
242#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
243pub struct RustTemplate {
244 pub template: Rc<str>,
245 pub type_expr: TypeExpr,
246 pub clauses: Vec<RustClause>,
247}
248
249#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
250pub struct RustClause {
251 pub target: TypeExpr,
252 pub template: Rc<str>,
253}
254
255impl Expr {
256 pub fn new(kind: ExprKind, span: Span) -> Self {
257 Self { kind, span }
258 }
259
260 pub fn kind(&self) -> &ExprKind {
261 &self.kind
262 }
263
264 pub fn span(&self) -> Span {
265 self.span
266 }
267
268 pub fn children(&self) -> Vec<&Expr> {
269 match &self.kind {
270 ExprKind::Leaf(_) => Vec::new(),
271 ExprKind::Fn(lambda) => lambda.body.expressions().collect(),
272 ExprKind::Call(callee, arguments) => {
273 std::iter::once(callee.as_ref()).chain(arguments).collect()
274 }
275 ExprKind::Control(control) => control.children(),
276 other => other.nested_children(),
277 }
278 }
279}
280
281impl ExprKind {
282 fn nested_children(&self) -> Vec<&Expr> {
283 match self {
284 ExprKind::Recur(arguments) => arguments.iter().collect(),
285 ExprKind::Try(value)
286 | ExprKind::Infer(value)
287 | ExprKind::Borrow(_, value)
288 | ExprKind::Deref(value) => {
289 vec![value]
290 }
291 ExprKind::Struct(structure) => structure.children(),
292 ExprKind::Variant(_, arguments) => arguments.iter().collect(),
293 ExprKind::LabeledVariant(_, fields) => fields.iter().map(|(_, value)| value).collect(),
294 other => other.collection_children(),
295 }
296 }
297
298 fn collection_children(&self) -> Vec<&Expr> {
299 match self {
300 ExprKind::Assoc(value, keys, item) | ExprKind::SetAt(value, keys, item) => {
301 std::iter::once(value.as_ref())
302 .chain(keys)
303 .chain(std::iter::once(item.as_ref()))
304 .collect()
305 }
306 ExprKind::MapAt(_, value, arguments) => {
307 std::iter::once(value.as_ref()).chain(arguments).collect()
308 }
309 _ => Vec::new(),
310 }
311 }
312}
313
314impl Control {
315 fn children(&self) -> Vec<&Expr> {
316 match self {
317 Control::Block(block) => block.expressions().collect(),
318 Control::If(test, then, otherwise) => vec![test, then, otherwise],
319 Control::Match(value, arms) => std::iter::once(value.as_ref())
320 .chain(arms.iter().flat_map(|arm| arm.body.expressions()))
321 .collect(),
322 }
323 }
324}
325
326impl StructExpr {
327 fn children(&self) -> Vec<&Expr> {
328 match self {
329 StructExpr::New(_, fields) => fields.iter().map(|(_, value)| value).collect(),
330 StructExpr::Update(base, fields) => std::iter::once(base.as_ref())
331 .chain(fields.iter().map(|(_, value)| value))
332 .collect(),
333 StructExpr::Field(value, _) => vec![value],
334 }
335 }
336}
337
338impl Block {
339 pub fn expressions(&self) -> impl Iterator<Item = &Expr> {
340 self.items.iter().map(BodyItem::expr)
341 }
342}
343
344impl BodyItem {
345 pub fn expr(&self) -> &Expr {
346 match self {
347 BodyItem::Let(_, value) | BodyItem::Expr(value) => value,
348 }
349 }
350}
351
352#[cfg(test)]
353mod tests {
354 use super::{
355 FieldLabel, FieldSpelling, MapOperation, Pattern, PatternArguments, PatternKind,
356 PatternPart,
357 };
358 use crate::core::{BindingArena, BindingId, BindingInfo, BindingKind};
359 use crate::source::{SourceId, Span};
360
361 struct PatternFixture {
362 bindings: BindingArena,
363 }
364
365 impl PatternFixture {
366 fn new() -> Self {
367 Self {
368 bindings: BindingArena::default(),
369 }
370 }
371
372 fn binding(&mut self) -> BindingId {
373 self.bindings
374 .add(BindingInfo::new("name".into(), BindingKind::Local, None))
375 }
376
377 fn pattern(kind: PatternKind) -> Pattern {
378 Pattern::new(kind, Span::new(SourceId::new(0), 0..0))
379 }
380
381 fn bare_name(&mut self, outer: Option<BindingId>) -> Pattern {
382 let binding = self.binding();
383 Self::pattern(PatternKind::BareName {
384 name: "name".into(),
385 binding,
386 candidates: Vec::new(),
387 outer,
388 })
389 }
390
391 fn held(&mut self) -> PatternArguments {
392 PatternArguments {
393 parts: vec![PatternPart::Positional(self.bare_name(None))],
394 }
395 }
396
397 fn label() -> FieldLabel {
398 FieldLabel {
399 name: "name".into(),
400 spelling: FieldSpelling::Keyword,
401 span: Span::new(SourceId::new(0), 0..0),
402 }
403 }
404 }
405
406 #[test]
407 fn a_bare_name_pairs_its_binding_with_its_outer_binding() {
408 let mut fixture = PatternFixture::new();
409 let outer = fixture.binding();
410 let pattern = fixture.bare_name(Some(outer));
411 let (_, found) = pattern.arm_outer().expect("the name has an outer binding");
412 assert_eq!(found, outer);
413 }
414
415 #[test]
416 fn a_bare_name_without_an_outer_binding_has_no_arm_outer() {
417 assert_eq!(PatternFixture::new().bare_name(None).arm_outer(), None);
418 }
419
420 #[test]
421 fn a_wildcard_has_no_arm_outer() {
422 let pattern = PatternFixture::pattern(PatternKind::Wildcard);
423 assert_eq!(pattern.arm_outer(), None);
424 }
425
426 #[test]
427 fn a_variant_pattern_holds_its_nested_patterns() {
428 let mut fixture = PatternFixture::new();
429 let variant = fixture.binding();
430 let held = fixture.held();
431 let pattern = PatternFixture::pattern(PatternKind::Variant(variant, held));
432 assert_eq!(pattern.nested().count(), 1);
433 }
434
435 #[test]
436 fn a_struct_pattern_holds_its_nested_patterns() {
437 let mut fixture = PatternFixture::new();
438 let shape = fixture.binding();
439 let held = fixture.held();
440 let pattern = PatternFixture::pattern(PatternKind::Struct(shape, held));
441 assert_eq!(pattern.nested().count(), 1);
442 }
443
444 #[test]
445 fn a_short_variant_pattern_holds_its_nested_patterns() {
446 let mut fixture = PatternFixture::new();
447 let arguments = fixture.held();
448 let pattern = PatternFixture::pattern(PatternKind::ShortVariant {
449 name: "name".into(),
450 candidates: Vec::new(),
451 arguments,
452 });
453 assert_eq!(pattern.nested().count(), 1);
454 }
455
456 #[test]
457 fn a_labeled_part_holds_its_pattern() {
458 let mut fixture = PatternFixture::new();
459 let shape = fixture.binding();
460 let inner = fixture.bare_name(None);
461 let label = PatternFixture::label();
462 let parts = vec![PatternPart::Labeled(label, Some(inner))];
463 let pattern =
464 PatternFixture::pattern(PatternKind::Struct(shape, PatternArguments { parts }));
465 assert_eq!(pattern.nested().count(), 1);
466 }
467
468 #[test]
469 fn a_label_without_a_pattern_holds_nothing() {
470 let parts = vec![PatternPart::Labeled(PatternFixture::label(), None)];
471 assert_eq!(PatternArguments { parts }.patterns().count(), 0);
472 }
473
474 #[test]
475 fn a_wildcard_holds_no_nested_patterns() {
476 let wildcard = PatternFixture::pattern(PatternKind::Wildcard);
477 assert_eq!(wildcard.nested().count(), 0);
478 }
479
480 #[test]
481 fn every_operation_name_round_trips() {
482 assert_eq!(MapOperation::of("iter"), Some(MapOperation::Iter));
483 assert_eq!(MapOperation::Iter.keyword(), "iter");
484 assert_eq!(MapOperation::of("unknown"), None);
485 }
486}