1use std::{ffi::OsString, fmt, iter};
4
5use bumpalo::Bump;
6
7use super::*;
8
9pub trait Allocable {}
14
15impl Allocable for Ast<'_> {}
16impl Allocable for Node<'_> {}
17impl<T: Allocable> Allocable for StringChunk<T> {}
18impl Allocable for LetBinding<'_> {}
19impl Allocable for LetMetadata<'_> {}
20impl Allocable for PrimOp {}
21impl Allocable for Annotation<'_> {}
22impl Allocable for MatchBranch<'_> {}
23
24impl Allocable for Record<'_> {}
25impl Allocable for record::FieldPathElem<'_> {}
26impl Allocable for record::FieldDef<'_> {}
27impl Allocable for record::FieldMetadata<'_> {}
28impl Allocable for record::Include<'_> {}
29
30impl Allocable for Pattern<'_> {}
31impl Allocable for EnumPattern<'_> {}
32impl Allocable for FieldPattern<'_> {}
33impl Allocable for RecordPattern<'_> {}
34impl Allocable for ArrayPattern<'_> {}
35impl Allocable for OrPattern<'_> {}
36impl Allocable for ConstantPattern<'_> {}
37impl Allocable for ConstantPatternData<'_> {}
38
39impl Allocable for Type<'_> {}
40impl Allocable for typ::RecordRows<'_> {}
41impl Allocable for typ::EnumRows<'_> {}
42impl Allocable for typ::EnumRow<'_> {}
43impl Allocable for typ::RecordRow<'_> {}
44
45impl Allocable for Ident {}
46impl Allocable for LocIdent {}
47
48pub struct AstAlloc {
67 generic_arena: Bump,
68 number_arena: typed_arena::Arena<Number>,
69 error_arena: typed_arena::Arena<ParseError>,
70}
71
72impl AstAlloc {
73 pub fn new() -> Self {
75 Self {
76 generic_arena: Bump::new(),
77 number_arena: typed_arena::Arena::new(),
78 error_arena: typed_arena::Arena::new(),
79 }
80 }
81
82 pub fn allocated_bytes(&self) -> usize {
84 self.generic_arena.allocated_bytes() + self.number_arena.len() + self.error_arena.len()
85 }
86
87 pub fn alloc<T: Allocable>(&self, value: T) -> &T {
95 self.generic_arena.alloc(value)
96 }
97
98 pub fn alloc_many<T: Allocable, I>(&self, iter: I) -> &[T]
102 where
103 I: IntoIterator<Item = T>,
104 I::IntoIter: ExactSizeIterator,
105 {
106 self.generic_arena.alloc_slice_fill_iter(iter)
107 }
108
109 pub fn alloc_singleton<T: Allocable>(&self, value: T) -> &[T] {
111 self.generic_arena.alloc_slice_fill_iter(iter::once(value))
112 }
113
114 pub fn alloc_str<'ast>(&'ast self, s: &str) -> &'ast str {
116 self.generic_arena.alloc_str(s)
117 }
118
119 pub fn clone_from<'to, T: CloneTo>(&'to self, data: T::Data<'_>) -> T::Data<'to> {
121 T::clone_to(data, self)
122 }
123
124 pub fn clone_ref_from<'from, 'to, T>(
126 &'to self,
127 data: &'from T::Data<'from>,
128 ) -> &'to T::Data<'to>
129 where
130 T: for<'a> CloneTo<Data<'a>: Clone + Allocable>,
131 {
132 self.alloc(T::clone_to(data.clone(), self))
133 }
134
135 pub fn number(&self, number: Number) -> Node<'_> {
136 Node::Number(self.number_arena.alloc(number))
137 }
138
139 pub fn alloc_number(&self, number: Number) -> &'_ Number {
140 self.number_arena.alloc(number)
141 }
142
143 pub fn string<'ast>(&'ast self, s: &str) -> Node<'ast> {
144 Node::String(self.generic_arena.alloc_str(s))
145 }
146
147 pub fn string_chunks<'ast, I>(&'ast self, chunks: I) -> Node<'ast>
148 where
149 I: IntoIterator<Item = StringChunk<Ast<'ast>>>,
150 I::IntoIter: ExactSizeIterator,
151 {
152 Node::StringChunks(self.alloc_many(chunks))
153 }
154
155 pub fn fun<'ast, I>(&'ast self, args: I, body: Ast<'ast>) -> Node<'ast>
156 where
157 I: IntoIterator<Item = Pattern<'ast>>,
158 I::IntoIter: ExactSizeIterator,
159 {
160 Node::Fun {
161 args: self.generic_arena.alloc_slice_fill_iter(args),
162 body: self.generic_arena.alloc(body),
163 }
164 }
165
166 pub fn unary_fun<'ast>(&'ast self, arg: Pattern<'ast>, body: Ast<'ast>) -> Node<'ast> {
167 Node::Fun {
168 args: self.alloc_singleton(arg),
169 body: self.generic_arena.alloc(body),
170 }
171 }
172
173 pub fn let_block<'ast, I>(&'ast self, bindings: I, body: Ast<'ast>, rec: bool) -> Node<'ast>
174 where
175 I: IntoIterator<Item = LetBinding<'ast>>,
176 I::IntoIter: ExactSizeIterator,
177 {
178 let bindings = self.generic_arena.alloc_slice_fill_iter(bindings);
179 let body = self.generic_arena.alloc(body);
180
181 Node::Let {
182 bindings,
183 body,
184 rec,
185 }
186 }
187
188 pub fn app<'ast, I>(&'ast self, head: Ast<'ast>, args: I) -> Node<'ast>
189 where
190 I: IntoIterator<Item = Ast<'ast>>,
191 I::IntoIter: ExactSizeIterator,
192 {
193 Node::App {
194 head: self.generic_arena.alloc(head),
195 args: self.generic_arena.alloc_slice_fill_iter(args),
196 }
197 }
198
199 pub fn enum_variant<'ast>(&'ast self, tag: LocIdent, arg: Option<Ast<'ast>>) -> Node<'ast> {
200 Node::EnumVariant {
201 tag,
202 arg: arg.map(|arg| &*self.generic_arena.alloc(arg)),
203 }
204 }
205
206 pub fn record<'ast>(&'ast self, record: Record<'ast>) -> Node<'ast> {
207 let record = self.generic_arena.alloc(record);
208 Node::Record(record)
209 }
210
211 pub fn record_data<'ast, Is, Ds>(
212 &'ast self,
213 includes: Is,
214 field_defs: Ds,
215 open: bool,
216 ) -> &'ast Record<'ast>
217 where
218 Ds: IntoIterator<Item = FieldDef<'ast>>,
219 Is: IntoIterator<Item = Include<'ast>>,
220 Ds::IntoIter: ExactSizeIterator,
221 Is::IntoIter: ExactSizeIterator,
222 {
223 self.generic_arena.alloc(Record {
224 includes: self.generic_arena.alloc_slice_fill_iter(includes),
225 field_defs: self.generic_arena.alloc_slice_fill_iter(field_defs),
226 open,
227 })
228 }
229
230 pub fn if_then_else<'ast>(
231 &'ast self,
232 cond: Ast<'ast>,
233 then_branch: Ast<'ast>,
234 else_branch: Ast<'ast>,
235 ) -> Node<'ast> {
236 Node::IfThenElse {
237 cond: self.generic_arena.alloc(cond),
238 then_branch: self.generic_arena.alloc(then_branch),
239 else_branch: self.generic_arena.alloc(else_branch),
240 }
241 }
242
243 pub fn match_expr<'ast, I>(&'ast self, branches: I) -> Node<'ast>
244 where
245 I: IntoIterator<Item = MatchBranch<'ast>>,
246 I::IntoIter: ExactSizeIterator,
247 {
248 Node::Match(Match {
249 branches: self.generic_arena.alloc_slice_fill_iter(branches),
250 })
251 }
252
253 pub fn array<'ast, I>(&'ast self, elts: I) -> Node<'ast>
254 where
255 I: IntoIterator<Item = Ast<'ast>>,
256 I::IntoIter: ExactSizeIterator,
257 {
258 Node::Array(self.generic_arena.alloc_slice_fill_iter(elts))
259 }
260
261 pub fn prim_op<'ast, I>(&'ast self, op: PrimOp, args: I) -> Node<'ast>
262 where
263 I: IntoIterator<Item = Ast<'ast>>,
264 I::IntoIter: ExactSizeIterator,
265 {
266 let op = self.generic_arena.alloc(op);
267 let args = self.generic_arena.alloc_slice_fill_iter(args);
268 Node::PrimOpApp { op, args }
269 }
270
271 pub fn annotated<'ast>(&'ast self, annot: Annotation<'ast>, inner: Ast<'ast>) -> Node<'ast> {
272 Node::Annotated {
273 annot: self.generic_arena.alloc(annot),
274 inner: self.generic_arena.alloc(inner),
275 }
276 }
277
278 pub fn annotation<'ast, I>(
279 &'ast self,
280 typ: Option<Type<'ast>>,
281 contracts: I,
282 ) -> Annotation<'ast>
283 where
284 I: IntoIterator<Item = Type<'ast>>,
285 I::IntoIter: ExactSizeIterator,
286 {
287 Annotation {
288 typ,
289 contracts: self.generic_arena.alloc_slice_fill_iter(contracts),
290 }
291 }
292
293 pub fn import_path(&self, path: OsString, format: InputFormat) -> Node<'_> {
294 Node::Import(Import::Path {
295 path: self.generic_arena.alloc(path),
296 format,
297 })
298 }
299
300 pub fn import_package(&self, id: Ident) -> Node<'_> {
301 Node::Import(Import::Package { id })
302 }
303
304 pub fn typ<'ast>(&'ast self, typ: Type<'ast>) -> Node<'ast> {
305 Node::Type(self.generic_arena.alloc(typ))
306 }
307
308 pub fn type_data<'ast>(&'ast self, typ: TypeUnr<'ast>, pos: TermPos) -> &'ast Type<'ast> {
309 self.generic_arena.alloc(Type { typ, pos })
310 }
311
312 pub fn enum_rows<'ast>(&'ast self, erows: EnumRowsUnr<'ast>) -> &'ast EnumRows<'ast> {
313 self.generic_arena.alloc(EnumRows(erows))
314 }
315
316 pub fn record_rows<'ast>(&'ast self, rrows: RecordRowsUnr<'ast>) -> &'ast RecordRows<'ast> {
317 self.generic_arena.alloc(RecordRows(rrows))
318 }
319
320 pub fn parse_error(&self, error: ParseError) -> Node<'_> {
321 Node::ParseError(self.error_arena.alloc(error))
322 }
323
324 pub fn record_pattern<'ast, I>(
325 &'ast self,
326 patterns: I,
327 tail: TailPattern,
328 pos: TermPos,
329 ) -> &'ast RecordPattern<'ast>
330 where
331 I: IntoIterator<Item = FieldPattern<'ast>>,
332 I::IntoIter: ExactSizeIterator,
333 {
334 self.generic_arena.alloc(RecordPattern {
335 patterns: self.generic_arena.alloc_slice_fill_iter(patterns),
336 tail,
337 pos,
338 })
339 }
340
341 pub fn array_pattern<'ast, I>(
342 &'ast self,
343 patterns: I,
344 tail: TailPattern,
345 pos: TermPos,
346 ) -> &'ast ArrayPattern<'ast>
347 where
348 I: IntoIterator<Item = Pattern<'ast>>,
349 I::IntoIter: ExactSizeIterator,
350 {
351 self.generic_arena.alloc(ArrayPattern {
352 patterns: self.generic_arena.alloc_slice_fill_iter(patterns),
353 tail,
354 pos,
355 })
356 }
357
358 pub fn or_pattern<'ast, I>(&'ast self, patterns: I, pos: TermPos) -> &'ast OrPattern<'ast>
359 where
360 I: IntoIterator<Item = Pattern<'ast>>,
361 I::IntoIter: ExactSizeIterator,
362 {
363 self.generic_arena.alloc(OrPattern {
364 patterns: self.generic_arena.alloc_slice_fill_iter(patterns),
365 pos,
366 })
367 }
368}
369
370impl fmt::Debug for AstAlloc {
373 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> fmt::Result {
374 write!(f, "AstAlloc")
375 }
376}
377
378pub trait CloneTo {
380 type Data<'a>;
384
385 fn clone_to<'to>(data: Self::Data<'_>, dest: &'to AstAlloc) -> Self::Data<'to>;
387}
388
389impl CloneTo for Ast<'_> {
390 type Data<'a> = Ast<'a>;
391
392 fn clone_to<'to>(data: Ast<'_>, dest: &'to AstAlloc) -> Ast<'to> {
393 Ast {
394 node: Node::clone_to(data.node.clone(), dest),
395 pos: data.pos,
396 }
397 }
398}
399
400impl CloneTo for Node<'_> {
401 type Data<'a> = Node<'a>;
402
403 fn clone_to<'to>(data: Node<'_>, dest: &'to AstAlloc) -> Node<'to> {
404 match data {
405 Node::Null => Node::Null,
406 Node::Bool(b) => Node::Bool(b),
407 Node::Number(rational) => dest.number(rational.clone()),
408 Node::String(s) => Node::String(dest.alloc_str(s)),
409 Node::StringChunks(str_chunks) => Node::StringChunks(
410 dest.alloc_many(
411 str_chunks
412 .iter()
413 .map(|chunk| StringChunk::clone_to(chunk.clone(), dest)),
414 ),
415 ),
416 Node::Fun { args, body } => Node::Fun {
417 args: dest.alloc_many(args.iter().map(|arg| Pattern::clone_to(arg.clone(), dest))),
418 body: dest.clone_ref_from::<Ast>(body),
419 },
420 Node::Let {
421 bindings,
422 body,
423 rec,
424 } => Node::Let {
425 bindings: dest.alloc_many(
426 bindings
427 .iter()
428 .map(|binding| LetBinding::clone_to(binding.clone(), dest)),
429 ),
430 body: dest.clone_ref_from::<Ast>(body),
431 rec,
432 },
433 Node::App { head, args } => Node::App {
434 head: dest.clone_ref_from::<Ast>(head),
435 args: dest.alloc_many(args.iter().map(|arg| Ast::clone_to(arg.clone(), dest))),
436 },
437 Node::Var(loc_ident) => Node::Var(loc_ident),
438 Node::EnumVariant { tag, arg } => Node::EnumVariant {
439 tag,
440 arg: arg.map(|arg| dest.clone_ref_from::<Ast>(arg)),
441 },
442 Node::Record(record) => Node::Record(dest.clone_ref_from::<Record>(record)),
443 Node::IfThenElse {
444 cond,
445 then_branch,
446 else_branch,
447 } => Node::IfThenElse {
448 cond: dest.clone_ref_from::<Ast>(cond),
449 then_branch: dest.clone_ref_from::<Ast>(then_branch),
450 else_branch: dest.clone_ref_from::<Ast>(else_branch),
451 },
452 Node::Match(data) => Node::Match(Match {
453 branches: dest.alloc_many(
454 data.branches
455 .iter()
456 .map(|branch| MatchBranch::clone_to(branch.clone(), dest)),
457 ),
458 }),
459 Node::Array(asts) => Node::Array(
460 dest.alloc_many(asts.iter().map(|ast| Ast::clone_to(ast.clone(), dest))),
461 ),
462 Node::PrimOpApp { op, args } => Node::PrimOpApp {
463 op: dest.alloc(*op),
464 args: dest.alloc_many(args.iter().map(|arg| Ast::clone_to(arg.clone(), dest))),
465 },
466 Node::Annotated { annot, inner } => Node::Annotated {
467 annot: dest.clone_ref_from::<Annotation>(annot),
468 inner: dest.clone_ref_from::<Ast>(inner),
469 },
470 Node::Import(import) => match import {
471 Import::Path { path, format } => dest.import_path(path.to_owned(), format),
472 Import::Package { id } => Node::Import(Import::Package { id }),
473 },
474 Node::Type(ty) => Node::Type(dest.clone_ref_from::<Type>(ty)),
475 Node::ParseError(parse_error) => dest.parse_error(parse_error.clone()),
476 }
477 }
478}
479
480impl CloneTo for LetBinding<'_> {
481 type Data<'ast> = LetBinding<'ast>;
482
483 fn clone_to<'to>(data: Self::Data<'_>, dest: &'to AstAlloc) -> Self::Data<'to> {
484 LetBinding {
485 pattern: Pattern::clone_to(data.pattern, dest),
486 metadata: LetMetadata::clone_to(data.metadata, dest),
487 value: Ast::clone_to(data.value, dest),
488 }
489 }
490}
491
492impl CloneTo for LetMetadata<'_> {
493 type Data<'ast> = LetMetadata<'ast>;
494
495 fn clone_to<'to>(data: Self::Data<'_>, dest: &'to AstAlloc) -> Self::Data<'to> {
496 LetMetadata {
497 doc: data.doc.map(|s| dest.alloc_str(s)),
498 annotation: Annotation::clone_to(data.annotation, dest),
499 }
500 }
501}
502
503impl CloneTo for Include<'_> {
504 type Data<'ast> = Include<'ast>;
505
506 fn clone_to<'to>(data: Self::Data<'_>, dest: &'to AstAlloc) -> Self::Data<'to> {
507 Include {
508 ident: data.ident,
509 metadata: FieldMetadata::clone_to(data.metadata, dest),
510 }
511 }
512}
513
514impl CloneTo for Record<'_> {
515 type Data<'ast> = Record<'ast>;
516
517 fn clone_to<'to>(data: Self::Data<'_>, dest: &'to AstAlloc) -> Self::Data<'to> {
518 Record {
519 includes: dest.alloc_many(
520 data.includes
521 .iter()
522 .cloned()
523 .map(|include| Include::clone_to(include, dest)),
524 ),
525 field_defs: dest.alloc_many(
526 data.field_defs
527 .iter()
528 .cloned()
529 .map(|field_def| FieldDef::clone_to(field_def, dest)),
530 ),
531 open: data.open,
532 }
533 }
534}
535
536impl CloneTo for FieldDef<'_> {
537 type Data<'ast> = FieldDef<'ast>;
538
539 fn clone_to<'to>(data: Self::Data<'_>, dest: &'to AstAlloc) -> Self::Data<'to> {
540 FieldDef {
541 path: dest.alloc_many(
542 data.path
543 .iter()
544 .map(|elem| record::FieldPathElem::clone_to(elem.clone(), dest)),
545 ),
546 metadata: record::FieldMetadata::clone_to(data.metadata, dest),
547 value: data.value.map(|v| Ast::clone_to(v, dest)),
548 pos: data.pos,
549 }
550 }
551}
552
553impl CloneTo for record::FieldPathElem<'_> {
554 type Data<'ast> = record::FieldPathElem<'ast>;
555
556 fn clone_to<'to>(data: Self::Data<'_>, dest: &'to AstAlloc) -> Self::Data<'to> {
557 match data {
558 record::FieldPathElem::Ident(loc_ident) => record::FieldPathElem::Ident(loc_ident),
559 record::FieldPathElem::Expr(ast) => {
560 record::FieldPathElem::Expr(Ast::clone_to(ast, dest))
561 }
562 }
563 }
564}
565
566impl CloneTo for record::FieldMetadata<'_> {
567 type Data<'ast> = record::FieldMetadata<'ast>;
568
569 fn clone_to<'to>(data: Self::Data<'_>, dest: &'to AstAlloc) -> Self::Data<'to> {
570 record::FieldMetadata {
571 doc: data.doc.map(|doc| dest.alloc_str(doc)),
572 annotation: Annotation::clone_to(data.annotation, dest),
573 ..data
574 }
575 }
576}
577
578impl CloneTo for MatchBranch<'_> {
579 type Data<'ast> = MatchBranch<'ast>;
580
581 fn clone_to<'to>(data: Self::Data<'_>, dest: &'to AstAlloc) -> Self::Data<'to> {
582 MatchBranch {
583 pattern: Pattern::clone_to(data.pattern, dest),
584 guard: data.guard.map(|ast| Ast::clone_to(ast, dest)),
585 body: Ast::clone_to(data.body, dest),
586 }
587 }
588}
589
590impl CloneTo for Annotation<'_> {
591 type Data<'ast> = Annotation<'ast>;
592
593 fn clone_to<'to>(data: Self::Data<'_>, dest: &'to AstAlloc) -> Self::Data<'to> {
594 Annotation {
595 typ: data.typ.map(|typ| Type::clone_to(typ, dest)),
596 contracts: dest.alloc_many(
597 data.contracts
598 .iter()
599 .map(|typ| Type::clone_to(typ.clone(), dest)),
600 ),
601 }
602 }
603}
604
605impl CloneTo for Type<'_> {
606 type Data<'ast> = Type<'ast>;
607
608 fn clone_to<'to>(data: Self::Data<'_>, dest: &'to AstAlloc) -> Self::Data<'to> {
609 let typ = match data.typ {
610 TypeF::Dyn => TypeF::Dyn,
611 TypeF::Number => TypeF::Number,
612 TypeF::Bool => TypeF::Bool,
613 TypeF::String => TypeF::String,
614 TypeF::Symbol => TypeF::Symbol,
615 TypeF::ForeignId => TypeF::ForeignId,
616 TypeF::Contract(ast) => TypeF::Contract(dest.clone_ref_from::<Ast>(ast)),
617 TypeF::Arrow(src, tgt) => TypeF::Arrow(
618 dest.clone_ref_from::<Type>(src),
619 dest.clone_ref_from::<Type>(tgt),
620 ),
621 TypeF::Var(id) => TypeF::Var(id),
622 TypeF::Forall {
623 var,
624 var_kind,
625 body,
626 } => TypeF::Forall {
627 var,
628 var_kind,
629 body: dest.clone_ref_from::<Type>(body),
630 },
631 TypeF::Enum(erows) => TypeF::Enum(typ::EnumRows::clone_to(erows, dest)),
632 TypeF::Record(rrows) => TypeF::Record(typ::RecordRows::clone_to(rrows, dest)),
633 TypeF::Dict {
634 type_fields,
635 flavour,
636 } => TypeF::Dict {
637 type_fields: dest.clone_ref_from::<Type>(type_fields),
638 flavour,
639 },
640 TypeF::Array(ty) => TypeF::Array(dest.clone_ref_from::<Type>(ty)),
641 TypeF::Wildcard(wildcard_id) => TypeF::Wildcard(wildcard_id),
642 };
643
644 Type { typ, pos: data.pos }
645 }
646}
647
648impl CloneTo for typ::EnumRows<'_> {
649 type Data<'ast> = typ::EnumRows<'ast>;
650
651 fn clone_to<'to>(data: Self::Data<'_>, dest: &'to AstAlloc) -> Self::Data<'to> {
652 use typ::*;
653
654 let inner = match data.0 {
655 EnumRowsF::Empty => EnumRowsF::Empty,
656 EnumRowsF::Extend { row, tail } => EnumRowsF::Extend {
657 row: EnumRow::clone_to(row, dest),
658 tail: dest.clone_ref_from::<EnumRows>(tail),
659 },
660 EnumRowsF::TailVar(loc_ident) => EnumRowsF::TailVar(loc_ident),
661 };
662
663 EnumRows(inner)
664 }
665}
666
667impl CloneTo for typ::EnumRow<'_> {
668 type Data<'ast> = typ::EnumRow<'ast>;
669
670 fn clone_to<'to>(data: Self::Data<'_>, dest: &'to AstAlloc) -> Self::Data<'to> {
671 typ::EnumRow {
672 id: data.id,
673 typ: data.typ.map(|ty| dest.clone_ref_from::<Type>(ty)),
674 }
675 }
676}
677
678impl CloneTo for typ::RecordRows<'_> {
679 type Data<'ast> = typ::RecordRows<'ast>;
680
681 fn clone_to<'to>(data: Self::Data<'_>, dest: &'to AstAlloc) -> Self::Data<'to> {
682 use typ::*;
683
684 let inner = match data.0 {
685 RecordRowsF::Empty => RecordRowsF::Empty,
686 RecordRowsF::Extend { row, tail } => RecordRowsF::Extend {
687 row: RecordRow::clone_to(row, dest),
688 tail: dest.clone_ref_from::<RecordRows>(tail),
689 },
690 RecordRowsF::TailVar(loc_ident) => RecordRowsF::TailVar(loc_ident),
691 RecordRowsF::TailDyn => RecordRowsF::TailDyn,
692 };
693
694 RecordRows(inner)
695 }
696}
697
698impl CloneTo for typ::RecordRow<'_> {
699 type Data<'ast> = typ::RecordRow<'ast>;
700
701 fn clone_to<'to>(data: Self::Data<'_>, dest: &'to AstAlloc) -> Self::Data<'to> {
702 typ::RecordRow {
703 id: data.id,
704 typ: dest.clone_ref_from::<Type>(data.typ),
705 }
706 }
707}
708
709impl CloneTo for StringChunk<Ast<'_>> {
710 type Data<'ast> = StringChunk<Ast<'ast>>;
711
712 fn clone_to<'to>(data: Self::Data<'_>, dest: &'to AstAlloc) -> Self::Data<'to> {
713 match data {
714 StringChunk::Literal(s) => StringChunk::Literal(s),
715 StringChunk::Expr(ast, indent) => StringChunk::Expr(Ast::clone_to(ast, dest), indent),
716 }
717 }
718}
719
720impl CloneTo for Pattern<'_> {
721 type Data<'ast> = Pattern<'ast>;
722
723 fn clone_to<'to>(pat: Pattern<'_>, dest: &'to AstAlloc) -> Pattern<'to> {
724 let data = match pat.data {
725 PatternData::Wildcard => PatternData::Wildcard,
726 PatternData::Any(id) => PatternData::Any(id),
727 PatternData::Record(record_pat) => {
728 PatternData::Record(dest.clone_ref_from::<RecordPattern>(record_pat))
729 }
730 PatternData::Array(array_pat) => {
731 PatternData::Array(dest.clone_ref_from::<ArrayPattern>(array_pat))
732 }
733 PatternData::Enum(enum_pat) => {
734 PatternData::Enum(dest.clone_ref_from::<EnumPattern>(enum_pat))
735 }
736 PatternData::Constant(const_pat) => {
737 PatternData::Constant(dest.clone_ref_from::<ConstantPattern>(const_pat))
738 }
739 PatternData::Or(or_pat) => PatternData::Or(dest.clone_ref_from::<OrPattern>(or_pat)),
740 };
741
742 Pattern { data, ..pat }
743 }
744}
745
746impl CloneTo for EnumPattern<'_> {
747 type Data<'ast> = EnumPattern<'ast>;
748
749 fn clone_to<'to>(data: Self::Data<'_>, dest: &'to AstAlloc) -> Self::Data<'to> {
750 EnumPattern {
751 pattern: data.pattern.map(|pat| Pattern::clone_to(pat, dest)),
752 ..data
753 }
754 }
755}
756
757impl CloneTo for RecordPattern<'_> {
758 type Data<'ast> = RecordPattern<'ast>;
759
760 fn clone_to<'to>(pat: Self::Data<'_>, dest: &'to AstAlloc) -> Self::Data<'to> {
761 RecordPattern {
762 patterns: dest.alloc_many(
763 pat.patterns
764 .iter()
765 .map(|field_pat| FieldPattern::clone_to(field_pat.clone(), dest)),
766 ),
767 ..pat
768 }
769 }
770}
771
772impl CloneTo for FieldPattern<'_> {
773 type Data<'ast> = FieldPattern<'ast>;
774
775 fn clone_to<'to>(pat: Self::Data<'_>, dest: &'to AstAlloc) -> Self::Data<'to> {
776 FieldPattern {
777 annotation: Annotation::clone_to(pat.annotation, dest),
778 default: pat.default.map(|ast| Ast::clone_to(ast, dest)),
779 pattern: Pattern::clone_to(pat.pattern, dest),
780 ..pat
781 }
782 }
783}
784
785impl CloneTo for ArrayPattern<'_> {
786 type Data<'ast> = ArrayPattern<'ast>;
787
788 fn clone_to<'to>(data: Self::Data<'_>, dest: &'to AstAlloc) -> Self::Data<'to> {
789 ArrayPattern {
790 patterns: dest.alloc_many(
791 data.patterns
792 .iter()
793 .map(|pat| Pattern::clone_to(pat.clone(), dest)),
794 ),
795 ..data
796 }
797 }
798}
799
800impl CloneTo for ConstantPattern<'_> {
801 type Data<'ast> = ConstantPattern<'ast>;
802
803 fn clone_to<'to>(pat: Self::Data<'_>, dest: &'to AstAlloc) -> Self::Data<'to> {
804 ConstantPattern {
805 data: ConstantPatternData::clone_to(pat.data, dest),
806 ..pat
807 }
808 }
809}
810
811impl CloneTo for ConstantPatternData<'_> {
812 type Data<'ast> = ConstantPatternData<'ast>;
813
814 fn clone_to<'to>(data: Self::Data<'_>, dest: &'to AstAlloc) -> Self::Data<'to> {
815 match data {
816 ConstantPatternData::Bool(b) => ConstantPatternData::Bool(b),
817 ConstantPatternData::Number(n) => {
818 ConstantPatternData::Number(dest.alloc_number(n.clone()))
819 }
820 ConstantPatternData::String(s) => ConstantPatternData::String(dest.alloc_str(s)),
821 ConstantPatternData::Null => ConstantPatternData::Null,
822 }
823 }
824}
825
826impl CloneTo for OrPattern<'_> {
827 type Data<'ast> = OrPattern<'ast>;
828
829 fn clone_to<'to>(pat: Self::Data<'_>, dest: &'to AstAlloc) -> Self::Data<'to> {
830 OrPattern {
831 patterns: dest.alloc_many(
832 pat.patterns
833 .iter()
834 .map(|pat| Pattern::clone_to(pat.clone(), dest)),
835 ),
836 ..pat
837 }
838 }
839}