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<T> CloneTo for &T
390where
391 T: for<'a> CloneTo<Data<'a>: Clone + Allocable>,
392 for<'a> <T as CloneTo>::Data<'a>: 'a,
393{
394 type Data<'a> = &'a T::Data<'a>;
395
396 fn clone_to<'to>(data: Self::Data<'_>, dest: &'to AstAlloc) -> Self::Data<'to> {
397 dest.clone_ref_from::<T>(data)
398 }
399}
400
401impl<T: CloneTo> CloneTo for Box<T> {
402 type Data<'a> = Box<T::Data<'a>>;
403
404 fn clone_to<'to>(data: Self::Data<'_>, dest: &'to AstAlloc) -> Self::Data<'to> {
405 Box::new(dest.clone_from::<T>(*data))
406 }
407}
408
409impl<S: CloneTo, T: CloneTo> CloneTo for (S, T) {
410 type Data<'a> = (S::Data<'a>, T::Data<'a>);
411
412 fn clone_to<'to>(data: Self::Data<'_>, dest: &'to AstAlloc) -> Self::Data<'to> {
413 (dest.clone_from::<S>(data.0), dest.clone_from::<T>(data.1))
414 }
415}
416
417impl CloneTo for Ast<'_> {
418 type Data<'a> = Ast<'a>;
419
420 fn clone_to<'to>(data: Ast<'_>, dest: &'to AstAlloc) -> Ast<'to> {
421 Ast {
422 node: Node::clone_to(data.node.clone(), dest),
423 pos: data.pos,
424 }
425 }
426}
427
428impl CloneTo for Node<'_> {
429 type Data<'a> = Node<'a>;
430
431 fn clone_to<'to>(data: Node<'_>, dest: &'to AstAlloc) -> Node<'to> {
432 match data {
433 Node::Null => Node::Null,
434 Node::Bool(b) => Node::Bool(b),
435 Node::Number(rational) => dest.number(rational.clone()),
436 Node::String(s) => Node::String(dest.alloc_str(s)),
437 Node::StringChunks(str_chunks) => Node::StringChunks(
438 dest.alloc_many(
439 str_chunks
440 .iter()
441 .map(|chunk| StringChunk::clone_to(chunk.clone(), dest)),
442 ),
443 ),
444 Node::Fun { args, body } => Node::Fun {
445 args: dest.alloc_many(args.iter().map(|arg| Pattern::clone_to(arg.clone(), dest))),
446 body: dest.clone_ref_from::<Ast>(body),
447 },
448 Node::Let {
449 bindings,
450 body,
451 rec,
452 } => Node::Let {
453 bindings: dest.alloc_many(
454 bindings
455 .iter()
456 .map(|binding| LetBinding::clone_to(binding.clone(), dest)),
457 ),
458 body: dest.clone_ref_from::<Ast>(body),
459 rec,
460 },
461 Node::App { head, args } => Node::App {
462 head: dest.clone_ref_from::<Ast>(head),
463 args: dest.alloc_many(args.iter().map(|arg| Ast::clone_to(arg.clone(), dest))),
464 },
465 Node::Var(loc_ident) => Node::Var(loc_ident),
466 Node::EnumVariant { tag, arg } => Node::EnumVariant {
467 tag,
468 arg: arg.map(|arg| dest.clone_ref_from::<Ast>(arg)),
469 },
470 Node::Record(record) => Node::Record(dest.clone_ref_from::<Record>(record)),
471 Node::IfThenElse {
472 cond,
473 then_branch,
474 else_branch,
475 } => Node::IfThenElse {
476 cond: dest.clone_ref_from::<Ast>(cond),
477 then_branch: dest.clone_ref_from::<Ast>(then_branch),
478 else_branch: dest.clone_ref_from::<Ast>(else_branch),
479 },
480 Node::Match(data) => Node::Match(Match {
481 branches: dest.alloc_many(
482 data.branches
483 .iter()
484 .map(|branch| MatchBranch::clone_to(branch.clone(), dest)),
485 ),
486 }),
487 Node::Array(asts) => Node::Array(
488 dest.alloc_many(asts.iter().map(|ast| Ast::clone_to(ast.clone(), dest))),
489 ),
490 Node::PrimOpApp { op, args } => Node::PrimOpApp {
491 op: dest.alloc(*op),
492 args: dest.alloc_many(args.iter().map(|arg| Ast::clone_to(arg.clone(), dest))),
493 },
494 Node::Annotated { annot, inner } => Node::Annotated {
495 annot: dest.clone_ref_from::<Annotation>(annot),
496 inner: dest.clone_ref_from::<Ast>(inner),
497 },
498 Node::Import(import) => match import {
499 Import::Path { path, format } => dest.import_path(path.to_owned(), format),
500 Import::Package { id } => Node::Import(Import::Package { id }),
501 },
502 Node::Type(ty) => Node::Type(dest.clone_ref_from::<Type>(ty)),
503 Node::ParseError(parse_error) => dest.parse_error(parse_error.clone()),
504 }
505 }
506}
507
508impl CloneTo for LetBinding<'_> {
509 type Data<'ast> = LetBinding<'ast>;
510
511 fn clone_to<'to>(data: Self::Data<'_>, dest: &'to AstAlloc) -> Self::Data<'to> {
512 LetBinding {
513 pattern: Pattern::clone_to(data.pattern, dest),
514 metadata: LetMetadata::clone_to(data.metadata, dest),
515 value: Ast::clone_to(data.value, dest),
516 }
517 }
518}
519
520impl CloneTo for LetMetadata<'_> {
521 type Data<'ast> = LetMetadata<'ast>;
522
523 fn clone_to<'to>(data: Self::Data<'_>, dest: &'to AstAlloc) -> Self::Data<'to> {
524 LetMetadata {
525 doc: data.doc.map(|s| dest.alloc_str(s)),
526 annotation: Annotation::clone_to(data.annotation, dest),
527 }
528 }
529}
530
531impl CloneTo for Include<'_> {
532 type Data<'ast> = Include<'ast>;
533
534 fn clone_to<'to>(data: Self::Data<'_>, dest: &'to AstAlloc) -> Self::Data<'to> {
535 Include {
536 ident: data.ident,
537 metadata: FieldMetadata::clone_to(data.metadata, dest),
538 }
539 }
540}
541
542impl CloneTo for Record<'_> {
543 type Data<'ast> = Record<'ast>;
544
545 fn clone_to<'to>(data: Self::Data<'_>, dest: &'to AstAlloc) -> Self::Data<'to> {
546 Record {
547 includes: dest.alloc_many(
548 data.includes
549 .iter()
550 .cloned()
551 .map(|include| Include::clone_to(include, dest)),
552 ),
553 field_defs: dest.alloc_many(
554 data.field_defs
555 .iter()
556 .cloned()
557 .map(|field_def| FieldDef::clone_to(field_def, dest)),
558 ),
559 open: data.open,
560 }
561 }
562}
563
564impl CloneTo for FieldDef<'_> {
565 type Data<'ast> = FieldDef<'ast>;
566
567 fn clone_to<'to>(data: Self::Data<'_>, dest: &'to AstAlloc) -> Self::Data<'to> {
568 FieldDef {
569 path: dest.alloc_many(
570 data.path
571 .iter()
572 .map(|elem| record::FieldPathElem::clone_to(elem.clone(), dest)),
573 ),
574 metadata: record::FieldMetadata::clone_to(data.metadata, dest),
575 value: data.value.map(|v| Ast::clone_to(v, dest)),
576 pos: data.pos,
577 }
578 }
579}
580
581impl CloneTo for record::FieldPathElem<'_> {
582 type Data<'ast> = record::FieldPathElem<'ast>;
583
584 fn clone_to<'to>(data: Self::Data<'_>, dest: &'to AstAlloc) -> Self::Data<'to> {
585 match data {
586 record::FieldPathElem::Ident(loc_ident) => record::FieldPathElem::Ident(loc_ident),
587 record::FieldPathElem::Expr(ast) => {
588 record::FieldPathElem::Expr(Ast::clone_to(ast, dest))
589 }
590 }
591 }
592}
593
594impl CloneTo for record::FieldMetadata<'_> {
595 type Data<'ast> = record::FieldMetadata<'ast>;
596
597 fn clone_to<'to>(data: Self::Data<'_>, dest: &'to AstAlloc) -> Self::Data<'to> {
598 record::FieldMetadata {
599 doc: data.doc.map(|doc| dest.alloc_str(doc)),
600 annotation: Annotation::clone_to(data.annotation, dest),
601 ..data
602 }
603 }
604}
605
606impl CloneTo for MatchBranch<'_> {
607 type Data<'ast> = MatchBranch<'ast>;
608
609 fn clone_to<'to>(data: Self::Data<'_>, dest: &'to AstAlloc) -> Self::Data<'to> {
610 MatchBranch {
611 pattern: Pattern::clone_to(data.pattern, dest),
612 guard: data.guard.map(|ast| Ast::clone_to(ast, dest)),
613 body: Ast::clone_to(data.body, dest),
614 }
615 }
616}
617
618impl CloneTo for Annotation<'_> {
619 type Data<'ast> = Annotation<'ast>;
620
621 fn clone_to<'to>(data: Self::Data<'_>, dest: &'to AstAlloc) -> Self::Data<'to> {
622 Annotation {
623 typ: data.typ.map(|typ| Type::clone_to(typ, dest)),
624 contracts: dest.alloc_many(
625 data.contracts
626 .iter()
627 .map(|typ| Type::clone_to(typ.clone(), dest)),
628 ),
629 }
630 }
631}
632
633impl CloneTo for Type<'_> {
634 type Data<'ast> = Type<'ast>;
635
636 fn clone_to<'to>(data: Self::Data<'_>, dest: &'to AstAlloc) -> Self::Data<'to> {
637 let typ = match data.typ {
638 TypeF::Dyn => TypeF::Dyn,
639 TypeF::Number => TypeF::Number,
640 TypeF::Bool => TypeF::Bool,
641 TypeF::String => TypeF::String,
642 TypeF::Symbol => TypeF::Symbol,
643 TypeF::ForeignId => TypeF::ForeignId,
644 TypeF::Contract(ast) => TypeF::Contract(dest.clone_ref_from::<Ast>(ast)),
645 TypeF::Arrow(src, tgt) => TypeF::Arrow(
646 dest.clone_ref_from::<Type>(src),
647 dest.clone_ref_from::<Type>(tgt),
648 ),
649 TypeF::Var(id) => TypeF::Var(id),
650 TypeF::Forall {
651 var,
652 var_kind,
653 body,
654 } => TypeF::Forall {
655 var,
656 var_kind,
657 body: dest.clone_ref_from::<Type>(body),
658 },
659 TypeF::Enum(erows) => TypeF::Enum(typ::EnumRows::clone_to(erows, dest)),
660 TypeF::Record(rrows) => TypeF::Record(typ::RecordRows::clone_to(rrows, dest)),
661 TypeF::Dict {
662 type_fields,
663 flavour,
664 } => TypeF::Dict {
665 type_fields: dest.clone_ref_from::<Type>(type_fields),
666 flavour,
667 },
668 TypeF::Array(ty) => TypeF::Array(dest.clone_ref_from::<Type>(ty)),
669 TypeF::Wildcard(wildcard_id) => TypeF::Wildcard(wildcard_id),
670 };
671
672 Type { typ, pos: data.pos }
673 }
674}
675
676impl<Ty: CloneTo, ERows: CloneTo> CloneTo for typ::EnumRowsF<Ty, ERows> {
677 type Data<'ast> = typ::EnumRowsF<Ty::Data<'ast>, ERows::Data<'ast>>;
678
679 fn clone_to<'to>(data: Self::Data<'_>, dest: &'to AstAlloc) -> Self::Data<'to> {
680 use typ::*;
681
682 match data {
683 EnumRowsF::Empty => EnumRowsF::Empty,
684 EnumRowsF::Extend { row, tail } => EnumRowsF::Extend {
685 row: EnumRowF::<Ty>::clone_to(row, dest),
686 tail: dest.clone_from::<ERows>(tail),
687 },
688 EnumRowsF::TailVar(loc_ident) => EnumRowsF::TailVar(loc_ident),
689 }
690 }
691}
692
693impl CloneTo for typ::EnumRows<'_> {
694 type Data<'ast> = typ::EnumRows<'ast>;
695
696 fn clone_to<'to>(data: Self::Data<'_>, dest: &'to AstAlloc) -> Self::Data<'to> {
697 EnumRows(dest.clone_from::<EnumRowsUnr>(data.0))
698 }
699}
700
701impl<Ty: CloneTo> CloneTo for typ::EnumRowF<Ty> {
702 type Data<'ast> = typ::EnumRowF<Ty::Data<'ast>>;
703
704 fn clone_to<'to>(data: Self::Data<'_>, dest: &'to AstAlloc) -> Self::Data<'to> {
705 typ::EnumRowF {
706 id: data.id,
707 typ: data.typ.map(|ty| dest.clone_from::<Ty>(ty)),
708 }
709 }
710}
711
712impl<Ty: CloneTo, RRows: CloneTo> CloneTo for typ::RecordRowsF<Ty, RRows> {
713 type Data<'ast> = typ::RecordRowsF<Ty::Data<'ast>, RRows::Data<'ast>>;
714
715 fn clone_to<'to>(data: Self::Data<'_>, dest: &'to AstAlloc) -> Self::Data<'to> {
716 use typ::*;
717
718 match data {
719 RecordRowsF::Empty => RecordRowsF::Empty,
720 RecordRowsF::Extend { row, tail } => RecordRowsF::Extend {
721 row: RecordRowF::<Ty>::clone_to(row, dest),
722 tail: dest.clone_from::<RRows>(tail),
723 },
724 RecordRowsF::TailVar(loc_ident) => RecordRowsF::TailVar(loc_ident),
725 RecordRowsF::TailDyn => RecordRowsF::TailDyn,
726 }
727 }
728}
729
730impl CloneTo for typ::RecordRows<'_> {
731 type Data<'ast> = typ::RecordRows<'ast>;
732
733 fn clone_to<'to>(data: Self::Data<'_>, dest: &'to AstAlloc) -> Self::Data<'to> {
734 RecordRows(dest.clone_from::<RecordRowsUnr>(data.0))
735 }
736}
737
738impl<Ty: CloneTo> CloneTo for typ::RecordRowF<Ty> {
739 type Data<'ast> = typ::RecordRowF<Ty::Data<'ast>>;
740
741 fn clone_to<'to>(data: Self::Data<'_>, dest: &'to AstAlloc) -> Self::Data<'to> {
742 typ::RecordRowF {
743 id: data.id,
744 typ: dest.clone_from::<Ty>(data.typ),
745 }
746 }
747}
748
749impl CloneTo for StringChunk<Ast<'_>> {
750 type Data<'ast> = StringChunk<Ast<'ast>>;
751
752 fn clone_to<'to>(data: Self::Data<'_>, dest: &'to AstAlloc) -> Self::Data<'to> {
753 match data {
754 StringChunk::Literal(s) => StringChunk::Literal(s),
755 StringChunk::Expr(ast, indent) => StringChunk::Expr(Ast::clone_to(ast, dest), indent),
756 }
757 }
758}
759
760impl CloneTo for Pattern<'_> {
761 type Data<'ast> = Pattern<'ast>;
762
763 fn clone_to<'to>(pat: Pattern<'_>, dest: &'to AstAlloc) -> Pattern<'to> {
764 let data = match pat.data {
765 PatternData::Wildcard => PatternData::Wildcard,
766 PatternData::Any(id) => PatternData::Any(id),
767 PatternData::Record(record_pat) => {
768 PatternData::Record(dest.clone_ref_from::<RecordPattern>(record_pat))
769 }
770 PatternData::Array(array_pat) => {
771 PatternData::Array(dest.clone_ref_from::<ArrayPattern>(array_pat))
772 }
773 PatternData::Enum(enum_pat) => {
774 PatternData::Enum(dest.clone_ref_from::<EnumPattern>(enum_pat))
775 }
776 PatternData::Constant(const_pat) => {
777 PatternData::Constant(dest.clone_ref_from::<ConstantPattern>(const_pat))
778 }
779 PatternData::Or(or_pat) => PatternData::Or(dest.clone_ref_from::<OrPattern>(or_pat)),
780 };
781
782 Pattern { data, ..pat }
783 }
784}
785
786impl CloneTo for EnumPattern<'_> {
787 type Data<'ast> = EnumPattern<'ast>;
788
789 fn clone_to<'to>(data: Self::Data<'_>, dest: &'to AstAlloc) -> Self::Data<'to> {
790 EnumPattern {
791 pattern: data.pattern.map(|pat| Pattern::clone_to(pat, dest)),
792 ..data
793 }
794 }
795}
796
797impl CloneTo for RecordPattern<'_> {
798 type Data<'ast> = RecordPattern<'ast>;
799
800 fn clone_to<'to>(pat: Self::Data<'_>, dest: &'to AstAlloc) -> Self::Data<'to> {
801 RecordPattern {
802 patterns: dest.alloc_many(
803 pat.patterns
804 .iter()
805 .map(|field_pat| FieldPattern::clone_to(field_pat.clone(), dest)),
806 ),
807 ..pat
808 }
809 }
810}
811
812impl CloneTo for FieldPattern<'_> {
813 type Data<'ast> = FieldPattern<'ast>;
814
815 fn clone_to<'to>(pat: Self::Data<'_>, dest: &'to AstAlloc) -> Self::Data<'to> {
816 FieldPattern {
817 annotation: Annotation::clone_to(pat.annotation, dest),
818 default: pat.default.map(|ast| Ast::clone_to(ast, dest)),
819 pattern: Pattern::clone_to(pat.pattern, dest),
820 ..pat
821 }
822 }
823}
824
825impl CloneTo for ArrayPattern<'_> {
826 type Data<'ast> = ArrayPattern<'ast>;
827
828 fn clone_to<'to>(data: Self::Data<'_>, dest: &'to AstAlloc) -> Self::Data<'to> {
829 ArrayPattern {
830 patterns: dest.alloc_many(
831 data.patterns
832 .iter()
833 .map(|pat| Pattern::clone_to(pat.clone(), dest)),
834 ),
835 ..data
836 }
837 }
838}
839
840impl CloneTo for ConstantPattern<'_> {
841 type Data<'ast> = ConstantPattern<'ast>;
842
843 fn clone_to<'to>(pat: Self::Data<'_>, dest: &'to AstAlloc) -> Self::Data<'to> {
844 ConstantPattern {
845 data: ConstantPatternData::clone_to(pat.data, dest),
846 ..pat
847 }
848 }
849}
850
851impl CloneTo for ConstantPatternData<'_> {
852 type Data<'ast> = ConstantPatternData<'ast>;
853
854 fn clone_to<'to>(data: Self::Data<'_>, dest: &'to AstAlloc) -> Self::Data<'to> {
855 match data {
856 ConstantPatternData::Bool(b) => ConstantPatternData::Bool(b),
857 ConstantPatternData::Number(n) => {
858 ConstantPatternData::Number(dest.alloc_number(n.clone()))
859 }
860 ConstantPatternData::String(s) => ConstantPatternData::String(dest.alloc_str(s)),
861 ConstantPatternData::Null => ConstantPatternData::Null,
862 }
863 }
864}
865
866impl CloneTo for OrPattern<'_> {
867 type Data<'ast> = OrPattern<'ast>;
868
869 fn clone_to<'to>(pat: Self::Data<'_>, dest: &'to AstAlloc) -> Self::Data<'to> {
870 OrPattern {
871 patterns: dest.alloc_many(
872 pat.patterns
873 .iter()
874 .map(|pat| Pattern::clone_to(pat.clone(), dest)),
875 ),
876 ..pat
877 }
878 }
879}
880
881impl<Ty, RRows, ERows, Te> CloneTo for TypeF<Ty, RRows, ERows, Te>
882where
883 Ty: CloneTo,
884 RRows: CloneTo,
885 ERows: CloneTo,
886 Te: CloneTo,
887{
888 type Data<'a> = TypeF<Ty::Data<'a>, RRows::Data<'a>, ERows::Data<'a>, Te::Data<'a>>;
889
890 fn clone_to<'to>(data: Self::Data<'_>, dest: &'to AstAlloc) -> Self::Data<'to> {
891 match data {
892 TypeF::Dyn => TypeF::Dyn,
893 TypeF::Number => TypeF::Number,
894 TypeF::Bool => TypeF::Bool,
895 TypeF::String => TypeF::String,
896 TypeF::Symbol => TypeF::Symbol,
897 TypeF::ForeignId => TypeF::ForeignId,
898 TypeF::Contract(te) => TypeF::Contract(dest.clone_from::<Te>(te)),
899 TypeF::Arrow(src, tgt) => {
900 TypeF::Arrow(dest.clone_from::<Ty>(src), dest.clone_from::<Ty>(tgt))
901 }
902 TypeF::Var(id) => TypeF::Var(id),
903 TypeF::Forall {
904 var,
905 var_kind,
906 body,
907 } => TypeF::Forall {
908 var,
909 var_kind,
910 body: dest.clone_from::<Ty>(body),
911 },
912 TypeF::Enum(erows) => TypeF::Enum(dest.clone_from::<ERows>(erows)),
913 TypeF::Record(rrows) => TypeF::Record(dest.clone_from::<RRows>(rrows)),
914 TypeF::Dict {
915 type_fields,
916 flavour,
917 } => TypeF::Dict {
918 type_fields: dest.clone_from::<Ty>(type_fields),
919 flavour,
920 },
921 TypeF::Array(ty) => TypeF::Array(dest.clone_from::<Ty>(ty)),
922 TypeF::Wildcard(wildcard_id) => TypeF::Wildcard(wildcard_id),
923 }
924 }
925}