1use crate::{
4 defs::Def,
5 dll::*,
6 literal::{
7 LitType,
8 Literal,
9 },
10 name::Name,
11 position::Pos,
12 prim::Op,
13 term::Term,
14 uses::Uses,
15};
16
17use core::ptr::NonNull;
18
19use sp_std::{
20 boxed::Box,
21 collections::{
22 btree_map::BTreeMap,
23 btree_set::BTreeSet,
24 },
25 fmt,
26 mem,
27};
28
29use alloc::string::String;
30use sp_cid::Cid;
31
32pub struct DAG {
35 pub head: DAGPtr,
36}
37
38#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
42pub enum DAGPtr {
43 Var(NonNull<Var>),
44 Lam(NonNull<Lam>),
45 App(NonNull<App>),
46 All(NonNull<All>),
47 Slf(NonNull<Slf>),
48 Fix(NonNull<Fix>),
49 Dat(NonNull<Dat>),
50 Cse(NonNull<Cse>),
51 Ref(NonNull<Ref>),
52 Let(NonNull<Let>),
53 Typ(NonNull<Typ>),
54 Ann(NonNull<Ann>),
55 Lit(NonNull<Lit>),
56 LTy(NonNull<LTy>),
57 Opr(NonNull<Opr>),
58}
59
60pub type Parents = DLL<ParentPtr>;
62
63#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
66pub enum ParentPtr {
67 Root,
68 LamBod(NonNull<Lam>),
69 SlfBod(NonNull<Slf>),
70 FixBod(NonNull<Fix>),
71 DatBod(NonNull<Dat>),
72 CseBod(NonNull<Cse>),
73 AppFun(NonNull<App>),
74 AppArg(NonNull<App>),
75 AllDom(NonNull<All>),
76 AllImg(NonNull<All>),
77 AnnTyp(NonNull<Ann>),
78 AnnExp(NonNull<Ann>),
79 LetTyp(NonNull<Let>),
80 LetExp(NonNull<Let>),
81 LetBod(NonNull<Let>),
82}
83
84#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
85pub enum BinderPtr {
86 Free,
87 Lam(NonNull<Lam>),
88 Slf(NonNull<Slf>),
89 Fix(NonNull<Fix>),
90}
91
92#[derive(Clone, Debug)]
94#[repr(C)]
95pub struct Var {
96 pub nam: Name,
97 pub rec: bool,
100 pub dep: u64,
103 pub binder: BinderPtr,
104 pub parents: Option<NonNull<Parents>>,
105}
106
107#[repr(C)]
108pub struct Lam {
109 pub bod: DAGPtr,
110 pub bod_ref: Parents,
111 pub var: Var,
112 pub parents: Option<NonNull<Parents>>,
113}
114
115#[repr(C)]
116pub struct App {
117 pub fun: DAGPtr,
118 pub arg: DAGPtr,
119 pub fun_ref: Parents,
120 pub arg_ref: Parents,
121 pub copy: Option<NonNull<App>>,
123 pub parents: Option<NonNull<Parents>>,
124}
125
126#[repr(C)]
127pub struct All {
128 pub uses: Uses,
129 pub dom: DAGPtr,
130 pub img: NonNull<Lam>,
131 pub dom_ref: Parents,
132 pub img_ref: Parents,
133 pub copy: Option<NonNull<All>>,
134 pub parents: Option<NonNull<Parents>>,
135}
136
137#[repr(C)]
138pub struct Slf {
139 pub bod: DAGPtr,
140 pub bod_ref: Parents,
141 pub var: Var,
142 pub parents: Option<NonNull<Parents>>,
143}
144
145#[repr(C)]
146pub struct Fix {
147 pub bod: DAGPtr,
148 pub bod_ref: Parents,
149 pub var: Var,
150 pub parents: Option<NonNull<Parents>>,
151}
152
153#[repr(C)]
154pub struct Dat {
155 pub bod: DAGPtr,
156 pub bod_ref: Parents,
157 pub parents: Option<NonNull<Parents>>,
158}
159
160#[repr(C)]
161pub struct Cse {
162 pub bod: DAGPtr,
163 pub bod_ref: Parents,
164 pub parents: Option<NonNull<Parents>>,
165}
166
167#[repr(C)]
168pub struct Ann {
169 pub typ: DAGPtr,
170 pub exp: DAGPtr,
171 pub typ_ref: Parents,
172 pub exp_ref: Parents,
173 pub copy: Option<NonNull<Ann>>,
174 pub parents: Option<NonNull<Parents>>,
175}
176
177#[repr(C)]
178pub struct Let {
179 pub uses: Uses,
180 pub typ: DAGPtr,
181 pub exp: DAGPtr,
182 pub bod: NonNull<Lam>,
183 pub typ_ref: Parents,
184 pub exp_ref: Parents,
185 pub bod_ref: Parents,
186 pub copy: Option<NonNull<Let>>,
187 pub parents: Option<NonNull<Parents>>,
188}
189
190#[repr(C)]
191pub struct Ref {
192 pub nam: Name,
193 pub rec: bool,
194 pub exp: Cid,
195 pub ast: Cid,
196 pub parents: Option<NonNull<Parents>>,
197}
198
199#[repr(C)]
200pub struct Typ {
201 pub parents: Option<NonNull<Parents>>,
202}
203
204#[repr(C)]
205pub struct Lit {
206 pub lit: Literal,
207 pub parents: Option<NonNull<Parents>>,
208}
209
210#[repr(C)]
211pub struct LTy {
212 pub lty: LitType,
213 pub parents: Option<NonNull<Parents>>,
214}
215
216#[repr(C)]
217pub struct Opr {
218 pub opr: Op,
219 pub parents: Option<NonNull<Parents>>,
220}
221
222#[inline]
224pub fn alloc_val<T>(val: T) -> NonNull<T> {
225 NonNull::new(Box::leak(Box::new(val))).unwrap()
226}
227
228#[inline]
229pub fn alloc_lam(
230 var_nam: Name,
231 var_dep: u64,
232 bod: DAGPtr,
233 parents: Option<NonNull<Parents>>,
234) -> NonNull<Lam> {
235 unsafe {
236 let lam = alloc_val(Lam {
237 var: Var {
238 nam: var_nam,
239 rec: false,
240 dep: var_dep,
241 binder: mem::zeroed(),
242 parents: None,
243 },
244 bod,
245 bod_ref: mem::zeroed(),
246 parents,
247 });
248 (*lam.as_ptr()).var.binder = BinderPtr::Lam(lam);
249 (*lam.as_ptr()).bod_ref = DLL::singleton(ParentPtr::LamBod(lam));
250 lam
251 }
252}
253
254#[inline]
255pub fn alloc_slf(
256 var_nam: Name,
257 var_dep: u64,
258 bod: DAGPtr,
259 parents: Option<NonNull<Parents>>,
260) -> NonNull<Slf> {
261 unsafe {
262 let slf = alloc_val(Slf {
263 var: Var {
264 nam: var_nam,
265 rec: false,
266 dep: var_dep,
267 binder: mem::zeroed(),
268 parents: None,
269 },
270 bod,
271 bod_ref: mem::zeroed(),
272 parents,
273 });
274 (*slf.as_ptr()).var.binder = BinderPtr::Slf(slf);
275 (*slf.as_ptr()).bod_ref = DLL::singleton(ParentPtr::SlfBod(slf));
276 slf
277 }
278}
279
280#[inline]
281pub fn alloc_fix(
282 var_nam: Name,
283 var_dep: u64,
284 bod: DAGPtr,
285 parents: Option<NonNull<Parents>>,
286) -> NonNull<Fix> {
287 unsafe {
288 let fix = alloc_val(Fix {
289 var: Var {
290 nam: var_nam,
291 rec: false,
292 dep: var_dep,
293 binder: mem::zeroed(),
294 parents: None,
295 },
296 bod,
297 bod_ref: mem::zeroed(),
298 parents,
299 });
300 (*fix.as_ptr()).var.binder = BinderPtr::Fix(fix);
301 (*fix.as_ptr()).bod_ref = DLL::singleton(ParentPtr::FixBod(fix));
302 fix
303 }
304}
305
306#[inline]
307pub fn alloc_dat(
308 bod: DAGPtr,
309 parents: Option<NonNull<Parents>>,
310) -> NonNull<Dat> {
311 unsafe {
312 let dat = alloc_val(Dat { bod, bod_ref: mem::zeroed(), parents });
313 (*dat.as_ptr()).bod_ref = DLL::singleton(ParentPtr::DatBod(dat));
314 dat
315 }
316}
317
318#[inline]
319pub fn alloc_cse(
320 bod: DAGPtr,
321 parents: Option<NonNull<Parents>>,
322) -> NonNull<Cse> {
323 unsafe {
324 let cse = alloc_val(Cse { bod, bod_ref: mem::zeroed(), parents });
325 (*cse.as_ptr()).bod_ref = DLL::singleton(ParentPtr::CseBod(cse));
326 cse
327 }
328}
329
330#[inline]
331pub fn alloc_all(
332 uses: Uses,
333 dom: DAGPtr,
334 img: NonNull<Lam>,
335 parents: Option<NonNull<Parents>>,
336) -> NonNull<All> {
337 unsafe {
338 let all = alloc_val(All {
339 uses,
340 dom,
341 img,
342 copy: None,
343 dom_ref: mem::zeroed(),
344 img_ref: mem::zeroed(),
345 parents,
346 });
347 (*all.as_ptr()).dom_ref = DLL::singleton(ParentPtr::AllDom(all));
348 (*all.as_ptr()).img_ref = DLL::singleton(ParentPtr::AllImg(all));
349 all
350 }
351}
352
353#[inline]
354pub fn alloc_app(
355 fun: DAGPtr,
356 arg: DAGPtr,
357 parents: Option<NonNull<Parents>>,
358) -> NonNull<App> {
359 unsafe {
360 let app = alloc_val(App {
361 fun,
362 arg,
363 copy: None,
364 fun_ref: mem::zeroed(),
365 arg_ref: mem::zeroed(),
366 parents,
367 });
368 (*app.as_ptr()).fun_ref = DLL::singleton(ParentPtr::AppFun(app));
369 (*app.as_ptr()).arg_ref = DLL::singleton(ParentPtr::AppArg(app));
370 app
371 }
372}
373
374#[inline]
375pub fn alloc_ann(
376 typ: DAGPtr,
377 exp: DAGPtr,
378 parents: Option<NonNull<Parents>>,
379) -> NonNull<Ann> {
380 unsafe {
381 let ann = alloc_val(Ann {
382 typ,
383 exp,
384 copy: None,
385 typ_ref: mem::zeroed(),
386 exp_ref: mem::zeroed(),
387 parents,
388 });
389 (*ann.as_ptr()).typ_ref = DLL::singleton(ParentPtr::AnnTyp(ann));
390 (*ann.as_ptr()).exp_ref = DLL::singleton(ParentPtr::AnnExp(ann));
391 ann
392 }
393}
394
395#[inline]
396#[allow(clippy::too_many_arguments)]
397pub fn alloc_let(
398 uses: Uses,
399 typ: DAGPtr,
400 exp: DAGPtr,
401 bod: NonNull<Lam>,
402 parents: Option<NonNull<Parents>>,
403) -> NonNull<Let> {
404 unsafe {
405 let let_ = alloc_val(Let {
406 uses,
407 typ,
408 exp,
409 bod,
410 copy: None,
411 typ_ref: mem::zeroed(),
412 exp_ref: mem::zeroed(),
413 bod_ref: mem::zeroed(),
414 parents,
415 });
416 (*let_.as_ptr()).typ_ref = DLL::singleton(ParentPtr::LetTyp(let_));
417 (*let_.as_ptr()).exp_ref = DLL::singleton(ParentPtr::LetExp(let_));
418 (*let_.as_ptr()).bod_ref = DLL::singleton(ParentPtr::LetBod(let_));
419 let_
420 }
421}
422
423#[inline]
425pub fn get_parents(term: DAGPtr) -> Option<NonNull<Parents>> {
426 unsafe {
427 match term {
428 DAGPtr::Var(link) => (*link.as_ptr()).parents,
429 DAGPtr::Lam(link) => (*link.as_ptr()).parents,
430 DAGPtr::App(link) => (*link.as_ptr()).parents,
431 DAGPtr::All(link) => (*link.as_ptr()).parents,
432 DAGPtr::Slf(link) => (*link.as_ptr()).parents,
433 DAGPtr::Fix(link) => (*link.as_ptr()).parents,
434 DAGPtr::Dat(link) => (*link.as_ptr()).parents,
435 DAGPtr::Cse(link) => (*link.as_ptr()).parents,
436 DAGPtr::Ref(link) => (*link.as_ptr()).parents,
437 DAGPtr::Let(link) => (*link.as_ptr()).parents,
438 DAGPtr::Typ(link) => (*link.as_ptr()).parents,
439 DAGPtr::Ann(link) => (*link.as_ptr()).parents,
440 DAGPtr::Lit(link) => (*link.as_ptr()).parents,
441 DAGPtr::LTy(link) => (*link.as_ptr()).parents,
442 DAGPtr::Opr(link) => (*link.as_ptr()).parents,
443 }
444 }
445}
446
447#[inline]
448pub fn set_parents(term: DAGPtr, pref: Option<NonNull<Parents>>) {
449 unsafe {
450 match term {
451 DAGPtr::Var(link) => (*link.as_ptr()).parents = pref,
452 DAGPtr::Lam(link) => (*link.as_ptr()).parents = pref,
453 DAGPtr::App(link) => (*link.as_ptr()).parents = pref,
454 DAGPtr::All(link) => (*link.as_ptr()).parents = pref,
455 DAGPtr::Slf(link) => (*link.as_ptr()).parents = pref,
456 DAGPtr::Fix(link) => (*link.as_ptr()).parents = pref,
457 DAGPtr::Dat(link) => (*link.as_ptr()).parents = pref,
458 DAGPtr::Cse(link) => (*link.as_ptr()).parents = pref,
459 DAGPtr::Ref(link) => (*link.as_ptr()).parents = pref,
460 DAGPtr::Let(link) => (*link.as_ptr()).parents = pref,
461 DAGPtr::Typ(link) => (*link.as_ptr()).parents = pref,
462 DAGPtr::Ann(link) => (*link.as_ptr()).parents = pref,
463 DAGPtr::Lit(link) => (*link.as_ptr()).parents = pref,
464 DAGPtr::LTy(link) => (*link.as_ptr()).parents = pref,
465 DAGPtr::Opr(link) => (*link.as_ptr()).parents = pref,
466 }
467 }
468}
469
470#[inline]
472pub fn install_child(parent: &mut ParentPtr, newchild: DAGPtr) {
473 unsafe {
474 match parent {
475 ParentPtr::LamBod(parent) => (*parent.as_ptr()).bod = newchild,
476 ParentPtr::SlfBod(parent) => (*parent.as_ptr()).bod = newchild,
477 ParentPtr::FixBod(parent) => (*parent.as_ptr()).bod = newchild,
478 ParentPtr::DatBod(parent) => (*parent.as_ptr()).bod = newchild,
479 ParentPtr::CseBod(parent) => (*parent.as_ptr()).bod = newchild,
480 ParentPtr::AppFun(parent) => (*parent.as_ptr()).fun = newchild,
481 ParentPtr::AppArg(parent) => (*parent.as_ptr()).arg = newchild,
482 ParentPtr::AllDom(parent) => (*parent.as_ptr()).dom = newchild,
483 ParentPtr::AllImg(parent) => match newchild {
484 DAGPtr::Lam(link) => (*parent.as_ptr()).img = link,
485 _ => panic!("Cannot install a non-lambda node as image"),
486 },
487 ParentPtr::AnnExp(parent) => (*parent.as_ptr()).exp = newchild,
488 ParentPtr::AnnTyp(parent) => (*parent.as_ptr()).typ = newchild,
489 ParentPtr::LetTyp(parent) => (*parent.as_ptr()).typ = newchild,
490 ParentPtr::LetExp(parent) => (*parent.as_ptr()).exp = newchild,
491 ParentPtr::LetBod(parent) => match newchild {
492 DAGPtr::Lam(link) => (*parent.as_ptr()).bod = link,
493 _ => panic!("Cannot install a non-lambda node as let body"),
494 },
495 ParentPtr::Root => (),
496 }
497 }
498}
499
500pub fn replace_child(oldchild: DAGPtr, newchild: DAGPtr) {
502 unsafe {
503 let oldpref = get_parents(oldchild);
504 if let Some(old_parents) = oldpref {
505 let mut iter = (*old_parents.as_ptr()).iter();
506 let newpref = get_parents(newchild);
507 let mut last_old = None;
508 let first_new = newpref.map(DLL::first);
509 while let Some(parent) = iter.next() {
510 if iter.is_last() {
511 last_old = iter.this();
512 last_old.map_or((), |last_old| (*last_old.as_ptr()).next = first_new);
513 }
514 install_child(parent, newchild);
515 }
516 first_new.map_or((), |first_new| (*first_new.as_ptr()).prev = last_old);
517 set_parents(newchild, oldpref);
518 }
519 set_parents(oldchild, None);
520 }
521}
522
523#[inline]
525pub fn add_to_parents(node: DAGPtr, plink: NonNull<Parents>) {
526 let parents = get_parents(node);
527 match parents {
528 Some(parents) => unsafe { (*parents.as_ptr()).merge(plink) },
529 None => set_parents(node, Some(plink)),
530 }
531}
532
533pub fn free_dead_node(node: DAGPtr) {
535 unsafe {
536 match node {
537 DAGPtr::Lam(link) => {
538 let Lam { bod, bod_ref, .. } = &link.as_ref();
539 let new_bod_parents = bod_ref.unlink_node();
540 set_parents(*bod, new_bod_parents);
541 if new_bod_parents.is_none() {
542 free_dead_node(*bod)
543 }
544 Box::from_raw(link.as_ptr());
545 }
546 DAGPtr::Slf(mut link) => {
547 let Slf { bod, bod_ref, .. } = &link.as_mut();
548 let new_bod_parents = bod_ref.unlink_node();
549 set_parents(*bod, new_bod_parents);
550 if new_bod_parents.is_none() {
551 free_dead_node(*bod)
552 }
553 Box::from_raw(link.as_ptr());
554 }
555 DAGPtr::Fix(mut link) => {
556 let Fix { bod, bod_ref, .. } = &link.as_mut();
557 let new_bod_parents = bod_ref.unlink_node();
558 set_parents(*bod, new_bod_parents);
559 if new_bod_parents.is_none() {
560 free_dead_node(*bod)
561 }
562 Box::from_raw(link.as_ptr());
563 }
564 DAGPtr::Cse(link) => {
565 let Cse { bod, bod_ref, .. } = link.as_ref();
566 let new_bod_parents = bod_ref.unlink_node();
567 set_parents(*bod, new_bod_parents);
568 if new_bod_parents.is_none() {
569 free_dead_node(*bod)
570 }
571 Box::from_raw(link.as_ptr());
572 }
573 DAGPtr::Dat(link) => {
574 let Dat { bod, bod_ref, .. } = &link.as_ref();
575 let new_bod_parents = bod_ref.unlink_node();
576 set_parents(*bod, new_bod_parents);
577 if new_bod_parents.is_none() {
578 free_dead_node(*bod)
579 }
580 Box::from_raw(link.as_ptr());
581 }
582 DAGPtr::All(link) => {
583 let All { dom, img, dom_ref, img_ref, .. } = link.as_ref();
584 let img = DAGPtr::Lam(*img);
585 let new_dom_parents = dom_ref.unlink_node();
586 set_parents(*dom, new_dom_parents);
587 if new_dom_parents.is_none() {
588 free_dead_node(*dom)
589 }
590 let new_img_parents = img_ref.unlink_node();
591 set_parents(img, new_img_parents);
592 if new_img_parents.is_none() {
593 free_dead_node(img)
594 }
595 Box::from_raw(link.as_ptr());
596 }
597 DAGPtr::App(link) => {
598 let App { fun, arg, fun_ref, arg_ref, .. } = link.as_ref();
599 let new_fun_parents = fun_ref.unlink_node();
600 set_parents(*fun, new_fun_parents);
601 if new_fun_parents.is_none() {
602 free_dead_node(*fun)
603 }
604 let new_arg_parents = arg_ref.unlink_node();
605 set_parents(*arg, new_arg_parents);
606 if new_arg_parents.is_none() {
607 free_dead_node(*arg)
608 }
609 Box::from_raw(link.as_ptr());
610 }
611 DAGPtr::Ann(link) => {
612 let Ann { exp, typ, exp_ref, typ_ref, .. } = link.as_ref();
613 let new_exp_parents = exp_ref.unlink_node();
614 set_parents(*exp, new_exp_parents);
615 if new_exp_parents.is_none() {
616 free_dead_node(*exp)
617 }
618 let new_typ_parents = typ_ref.unlink_node();
619 set_parents(*typ, new_typ_parents);
620 if new_typ_parents.is_none() {
621 free_dead_node(*typ)
622 }
623 Box::from_raw(link.as_ptr());
624 }
625 DAGPtr::Let(link) => {
626 let Let { exp, typ, exp_ref, typ_ref, bod, bod_ref, .. } =
627 link.as_ref();
628 let bod = DAGPtr::Lam(*bod);
629 let new_exp_parents = exp_ref.unlink_node();
630 set_parents(*exp, new_exp_parents);
631 if new_exp_parents.is_none() {
632 free_dead_node(*exp)
633 }
634 let new_typ_parents = typ_ref.unlink_node();
635 set_parents(*typ, new_typ_parents);
636 if new_typ_parents.is_none() {
637 free_dead_node(*typ)
638 }
639 let new_bod_parents = bod_ref.unlink_node();
640 set_parents(bod, new_bod_parents);
641 if new_bod_parents.is_none() {
642 free_dead_node(bod)
643 }
644 Box::from_raw(link.as_ptr());
645 }
646 DAGPtr::Var(link) => {
647 let Var { binder, .. } = link.as_ref();
648 if let BinderPtr::Free = binder {
650 Box::from_raw(link.as_ptr());
651 }
652 }
653 DAGPtr::Ref(link) => {
654 Box::from_raw(link.as_ptr());
655 }
656 DAGPtr::Typ(link) => {
657 Box::from_raw(link.as_ptr());
658 }
659 DAGPtr::Lit(link) => {
660 Box::from_raw(link.as_ptr());
661 }
662 DAGPtr::LTy(link) => {
663 Box::from_raw(link.as_ptr());
664 }
665 DAGPtr::Opr(link) => {
666 Box::from_raw(link.as_ptr());
667 }
668 }
669 }
670}
671
672impl DAG {
673 pub fn new(head: DAGPtr) -> DAG { DAG { head } }
675
676 pub fn free(self) {
678 match get_parents(self.head) {
679 None => (),
680 Some(pref) => unsafe {
681 Box::from_raw(pref.as_ptr());
682 set_parents(self.head, None);
683 },
684 }
685 free_dead_node(self.head)
686 }
687
688 pub fn dag_ptr_to_term(
690 node: &DAGPtr,
691 map: &mut BTreeMap<*mut Var, u64>,
692 depth: u64,
693 re_rec: bool,
694 ) -> Term {
695 match node {
696 DAGPtr::Var(link) => {
697 let Var { nam, dep: var_depth, rec, .. } = unsafe { link.as_ref() };
698 if *rec && re_rec {
699 Term::Rec(Pos::None)
700 }
701 else if let Some(level) = map.get(&link.as_ptr()) {
702 Term::Var(Pos::None, nam.clone(), depth - level - 1)
703 }
704 else {
705 Term::Var(Pos::None, nam.clone(), *var_depth)
706 }
707 }
708 DAGPtr::Typ(_) => Term::Typ(Pos::None),
709 DAGPtr::LTy(link) => {
710 let LTy { lty, .. } = unsafe { link.as_ref() };
711 Term::LTy(Pos::None, *lty)
712 }
713 DAGPtr::Lit(link) => {
714 let Lit { lit, .. } = unsafe { link.as_ref() };
715 Term::Lit(Pos::None, lit.clone())
716 }
717 DAGPtr::Opr(link) => {
718 let Opr { opr, .. } = unsafe { link.as_ref() };
719 Term::Opr(Pos::None, opr.clone())
720 }
721 DAGPtr::Ref(link) => {
722 let Ref { nam, exp, ast, rec, .. } = unsafe { link.as_ref() };
723 if *rec && re_rec {
724 Term::Rec(Pos::None)
725 }
726 else {
727 Term::Ref(Pos::None, nam.clone(), *exp, *ast)
728 }
729 }
730 DAGPtr::Lam(link) => {
731 let Lam { var, bod, .. } = unsafe { &mut *link.as_ptr() };
732 let nam = var.nam.clone();
733 map.insert(var, depth);
734 let body = DAG::dag_ptr_to_term(bod, map, depth + 1, re_rec);
735 Term::Lam(Pos::None, nam, Box::new(body))
736 }
737 DAGPtr::Slf(link) => {
738 let Slf { var, bod, .. } = unsafe { &mut *link.as_ptr() };
739 let nam = var.nam.clone();
740 map.insert(var, depth);
741 let body = DAG::dag_ptr_to_term(bod, map, depth + 1, re_rec);
742 Term::Slf(Pos::None, nam, Box::new(body))
743 }
744 DAGPtr::Fix(_) => {
745 panic!("Fix conversion TODO")
746 }
747 DAGPtr::Cse(link) => {
748 let Cse { bod, .. } = unsafe { link.as_ref() };
749 Term::Cse(
750 Pos::None,
751 Box::new(DAG::dag_ptr_to_term(bod, map, depth, re_rec)),
752 )
753 }
754 DAGPtr::Dat(link) => {
755 let Dat { bod, .. } = unsafe { link.as_ref() };
756 Term::Dat(
757 Pos::None,
758 Box::new(DAG::dag_ptr_to_term(bod, map, depth, re_rec)),
759 )
760 }
761 DAGPtr::App(link) => {
762 let App { fun, arg, .. } = unsafe { link.as_ref() };
763 let fun_map = &mut map.clone();
764 Term::App(
765 Pos::None,
766 Box::new((
767 DAG::dag_ptr_to_term(fun, fun_map, depth, re_rec),
768 DAG::dag_ptr_to_term(arg, map, depth, re_rec),
769 )),
770 )
771 }
772 DAGPtr::Ann(link) => {
773 let Ann { typ, exp, .. } = unsafe { link.as_ref() };
774 let typ_map = &mut map.clone();
775 Term::Ann(
776 Pos::None,
777 Box::new((
778 DAG::dag_ptr_to_term(typ, typ_map, depth, re_rec),
779 DAG::dag_ptr_to_term(exp, map, depth, re_rec),
780 )),
781 )
782 }
783 DAGPtr::All(link) => {
784 let All { uses, dom, img: lam_link, .. } =
785 unsafe { &mut *link.as_ptr() };
786 let Lam { var, bod: img, .. } = unsafe { &mut *lam_link.as_ptr() };
787 let nam = var.nam.clone();
788 let dom_map = &mut map.clone();
789 map.insert(var, depth);
790 Term::All(
791 Pos::None,
792 *uses,
793 nam,
794 Box::new((
795 DAG::dag_ptr_to_term(dom, dom_map, depth, re_rec),
796 DAG::dag_ptr_to_term(img, map, depth + 1, re_rec),
797 )),
798 )
799 }
800 DAGPtr::Let(link) => {
801 let Let { uses, typ, exp, bod: lam_link, .. } =
802 unsafe { &mut *link.as_ptr() };
803 let Lam { var, bod, .. } = unsafe { &mut *lam_link.as_ptr() };
804 let nam = var.nam.clone();
805 let typ_map = &mut map.clone();
806 let exp_map = &mut map.clone();
807 let mut exp_depth = depth;
808 let (rec, exp) = match exp {
809 DAGPtr::Fix(link) => unsafe {
810 let Fix { var, bod, .. } = &mut *link.as_ptr();
811 exp_map.insert(var, depth);
812 exp_depth += 1;
813 (true, bod)
814 },
815 _ => (false, exp),
816 };
817 map.insert(var, depth);
818 Term::Let(
819 Pos::None,
820 rec,
821 *uses,
822 nam,
823 Box::new((
824 DAG::dag_ptr_to_term(typ, typ_map, depth, re_rec),
825 DAG::dag_ptr_to_term(exp, exp_map, exp_depth, re_rec),
826 DAG::dag_ptr_to_term(bod, map, depth + 1, re_rec),
827 )),
828 )
829 }
830 }
831 }
832
833 pub fn to_term(&self, re_rec: bool) -> Term {
835 let mut map = BTreeMap::new();
836 DAG::dag_ptr_to_term(&self.head, &mut map, 0, re_rec)
837 }
838
839 pub fn from_term(tree: &Term) -> Self {
841 let root = alloc_val(DLL::singleton(ParentPtr::Root));
842 DAG::new(DAG::from_term_inner(tree, 0, BTreeMap::new(), Some(root), None))
843 }
844
845 pub fn from_def(def: &Def, name: Name) -> Self {
847 let root = alloc_val(DLL::singleton(ParentPtr::Root));
848 let (d, _, a) = def.embed();
849 let def_cid = d.cid();
850 let ast_cid = a.cid();
851 DAG::new(DAG::from_term_inner(
852 &def.term,
853 0,
854 BTreeMap::new(),
855 Some(root),
856 Some((name, def_cid, ast_cid)),
857 ))
858 }
859
860 pub fn from_ref(
861 def: &Def,
862 name: Name,
863 def_cid: Cid,
864 ast_cid: Cid,
865 parents: Option<NonNull<Parents>>,
866 ) -> DAGPtr {
867 DAG::from_term_inner(
868 &def.term,
869 0,
870 BTreeMap::new(),
871 parents,
872 Some((name, def_cid, ast_cid)),
873 )
874 }
875
876 pub fn from_term_inner(
878 tree: &Term,
879 depth: u64,
880 mut ctx: BTreeMap<usize, DAGPtr>,
881 parents: Option<NonNull<Parents>>,
882 rec_ref: Option<(Name, Cid, Cid)>,
883 ) -> DAGPtr {
884 match tree {
885 Term::Rec(_) => match rec_ref {
886 Some((nam, exp, ast)) => {
887 let ref_ = alloc_val(Ref { nam, rec: true, exp, ast, parents });
888 DAGPtr::Ref(ref_)
889 }
890 None => {
891 let var = alloc_val(Var {
892 nam: Name::from("#^"),
893 rec: true,
894 dep: depth,
895 binder: BinderPtr::Free,
896 parents,
897 });
898 DAGPtr::Var(var)
899 }
900 },
901 Term::Var(_, name, idx) => {
902 let dep = (depth - 1 - *idx) as usize;
903 match ctx.get(&dep) {
904 Some(val) => {
905 if let Some(parents) = parents {
906 DLL::concat(parents, get_parents(*val));
907 set_parents(*val, Some(parents));
908 }
909 *val
910 }
911 None => {
912 if depth < 1 + idx {
913 panic!("Negative index found.")
914 }
915 let var = alloc_val(Var {
916 nam: name.clone(),
917 rec: false,
918 dep: depth - 1 - idx,
919 binder: BinderPtr::Free,
920 parents,
921 });
922 DAGPtr::Var(var)
923 }
924 }
925 }
926 Term::Typ(_) => DAGPtr::Typ(alloc_val(Typ { parents })),
927 Term::LTy(_, lty) => DAGPtr::LTy(alloc_val(LTy { lty: *lty, parents })),
928 Term::Lit(_, lit) => {
929 DAGPtr::Lit(alloc_val(Lit { lit: lit.clone(), parents }))
930 }
931 Term::Opr(_, opr) => DAGPtr::Opr(alloc_val(Opr { opr: opr.clone(), parents })),
932 Term::Ref(_, nam, exp, ast) => DAGPtr::Ref(alloc_val(Ref {
933 nam: nam.clone(),
934 rec: false,
935 exp: *exp,
936 ast: *ast,
937 parents,
938 })),
939 Term::Lam(_, nam, bod) => unsafe {
940 let lam = alloc_lam(nam.clone(), 0, mem::zeroed(), parents);
941 let Lam { var, bod_ref, .. } = &mut *lam.as_ptr();
942 ctx.insert(depth as usize, DAGPtr::Var(NonNull::new(var).unwrap()));
943 let bod = DAG::from_term_inner(
944 &**bod,
945 depth + 1,
946 ctx,
947 NonNull::new(bod_ref),
948 rec_ref.clone(),
949 );
950 (*lam.as_ptr()).bod = bod;
951 DAGPtr::Lam(lam)
952 },
953 Term::Slf(_, nam, bod) => unsafe {
954 let slf = alloc_slf(nam.clone(), 0, mem::zeroed(), parents);
955 let Slf { var, bod_ref, .. } = &mut *slf.as_ptr();
956 ctx.insert(depth as usize, DAGPtr::Var(NonNull::new(var).unwrap()));
957 let bod = DAG::from_term_inner(
958 &**bod,
959 depth + 1,
960 ctx,
961 NonNull::new(bod_ref),
962 rec_ref.clone(),
963 );
964 (*slf.as_ptr()).bod = bod;
965 DAGPtr::Slf(slf)
966 },
967 Term::Dat(_, bod) => unsafe {
968 let dat = alloc_dat(mem::zeroed(), parents);
969 let Dat { bod_ref, .. } = &mut *dat.as_ptr();
970 let bod = DAG::from_term_inner(
971 &**bod,
972 depth,
973 ctx,
974 NonNull::new(bod_ref),
975 rec_ref.clone(),
976 );
977 (*dat.as_ptr()).bod = bod;
978 DAGPtr::Dat(dat)
979 },
980 Term::Cse(_, bod) => unsafe {
981 let cse = alloc_cse(mem::zeroed(), parents);
982 let Cse { bod_ref, .. } = &mut *cse.as_ptr();
983 let bod = DAG::from_term_inner(
984 &**bod,
985 depth,
986 ctx,
987 NonNull::new(bod_ref),
988 rec_ref.clone(),
989 );
990 (*cse.as_ptr()).bod = bod;
991 DAGPtr::Cse(cse)
992 },
993 Term::All(_, uses, nam, dom_img) => unsafe {
994 let (dom, img) = &**dom_img;
995 let all = alloc_all(*uses, mem::zeroed(), NonNull::dangling(), parents);
996 let All { dom_ref, img_ref, .. } = &mut *all.as_ptr();
997 let lam =
998 alloc_lam(nam.clone(), 0, mem::zeroed(), NonNull::new(img_ref));
999 let Lam { var, bod_ref, .. } = &mut *lam.as_ptr();
1000 let mut img_ctx = ctx.clone();
1001 let dom = DAG::from_term_inner(
1002 dom,
1003 depth,
1004 ctx,
1005 NonNull::new(dom_ref),
1006 rec_ref.clone(),
1007 );
1008 img_ctx.insert(depth as usize, DAGPtr::Var(NonNull::new(var).unwrap()));
1009 let img = DAG::from_term_inner(
1010 img,
1011 depth + 1,
1012 img_ctx,
1013 NonNull::new(bod_ref),
1014 rec_ref.clone(),
1015 );
1016 (*all.as_ptr()).dom = dom;
1017 (*all.as_ptr()).img = lam;
1018 (*lam.as_ptr()).bod = img;
1019 DAGPtr::All(all)
1020 },
1021 Term::App(_, fun_arg) => unsafe {
1022 let (fun, arg) = &**fun_arg;
1023 let app = alloc_app(mem::zeroed(), mem::zeroed(), parents);
1024 let App { fun_ref, arg_ref, .. } = &mut *app.as_ptr();
1025 let fun = DAG::from_term_inner(
1026 fun,
1027 depth,
1028 ctx.clone(),
1029 NonNull::new(fun_ref),
1030 rec_ref.clone(),
1031 );
1032 let arg = DAG::from_term_inner(
1033 arg,
1034 depth,
1035 ctx,
1036 NonNull::new(arg_ref),
1037 rec_ref.clone(),
1038 );
1039 (*app.as_ptr()).fun = fun;
1040 (*app.as_ptr()).arg = arg;
1041 DAGPtr::App(app)
1042 },
1043 Term::Ann(_, typ_exp) => unsafe {
1044 let (typ, exp) = &**typ_exp;
1045 let ann = alloc_ann(mem::zeroed(), mem::zeroed(), parents);
1046 let Ann { typ_ref, exp_ref, .. } = &mut *ann.as_ptr();
1047 let typ = DAG::from_term_inner(
1048 typ,
1049 depth,
1050 ctx.clone(),
1051 NonNull::new(typ_ref),
1052 rec_ref.clone(),
1053 );
1054 let exp = DAG::from_term_inner(
1055 exp,
1056 depth,
1057 ctx,
1058 NonNull::new(exp_ref),
1059 rec_ref.clone(),
1060 );
1061 (*ann.as_ptr()).typ = typ;
1062 (*ann.as_ptr()).exp = exp;
1063 DAGPtr::Ann(ann)
1064 },
1065 Term::Let(_, rec, uses, nam, typ_exp_bod) => unsafe {
1066 let (typ, exp, bod) = &**typ_exp_bod;
1067 let let_ = alloc_let(
1069 *uses,
1070 mem::zeroed(),
1071 mem::zeroed(),
1072 NonNull::dangling(),
1073 parents,
1074 );
1075 let Let { typ_ref, exp_ref, bod_ref, .. } = &mut *let_.as_ptr();
1076 let lam =
1077 alloc_lam(nam.clone(), 0, mem::zeroed(), NonNull::new(bod_ref));
1078 let Lam { var: lam_var, bod_ref: lam_bod_ref, .. } = &mut *lam.as_ptr();
1079 let typ_ctx = ctx.clone();
1081 let mut bod_ctx = ctx.clone();
1082 bod_ctx
1083 .insert(depth as usize, DAGPtr::Var(NonNull::new(lam_var).unwrap()));
1084 let typ = DAG::from_term_inner(
1087 typ,
1088 depth,
1089 typ_ctx,
1090 NonNull::new(typ_ref),
1091 rec_ref.clone(),
1092 );
1093 let bod = DAG::from_term_inner(
1094 bod,
1095 depth + 1,
1096 bod_ctx,
1097 NonNull::new(lam_bod_ref),
1098 rec_ref.clone(),
1099 );
1100 (*let_.as_ptr()).typ = typ;
1101 (*let_.as_ptr()).bod = lam;
1102 (*lam.as_ptr()).bod = bod;
1103 if *rec {
1106 let fix =
1107 alloc_fix(nam.clone(), 0, mem::zeroed(), NonNull::new(exp_ref));
1108 let Fix { var: fix_var, bod_ref: fix_bod_ref, .. } =
1109 &mut *fix.as_ptr();
1110 ctx.insert(
1111 depth as usize,
1112 DAGPtr::Var(NonNull::new(fix_var).unwrap()),
1113 );
1114 let exp = DAG::from_term_inner(
1115 exp,
1116 depth + 1,
1117 ctx,
1118 NonNull::new(fix_bod_ref),
1119 rec_ref.clone(),
1120 );
1121 (*let_.as_ptr()).exp = DAGPtr::Fix(fix);
1122 (*fix.as_ptr()).bod = exp;
1123 }
1124 else {
1125 let exp = DAG::from_term_inner(
1126 exp,
1127 depth,
1128 ctx,
1129 NonNull::new(exp_ref),
1130 rec_ref.clone(),
1131 );
1132 (*let_.as_ptr()).exp = exp;
1133 }
1134 DAGPtr::Let(let_)
1135 },
1136 }
1137 }
1138
1139 pub fn from_subdag(
1141 node: DAGPtr,
1142 map: &mut BTreeMap<DAGPtr, DAGPtr>,
1143 parents: Option<NonNull<Parents>>,
1144 ) -> DAGPtr {
1145 if let Some(copy) = (*map).get(&node) {
1148 if let Some(parents) = parents {
1149 DLL::concat(parents, get_parents(*copy));
1150 set_parents(*copy, Some(parents));
1151 }
1152 return *copy;
1153 }
1154 let new_node = match node {
1156 DAGPtr::Var(link) => unsafe {
1157 let Var { nam, dep, rec, .. } = &*link.as_ptr();
1158 let var = alloc_val(Var {
1159 nam: nam.clone(),
1160 rec: *rec,
1161 dep: *dep,
1162 binder: BinderPtr::Free,
1163 parents,
1164 });
1165 DAGPtr::Var(var)
1166 },
1167 DAGPtr::Ref(link) => unsafe {
1168 let Ref { nam, exp, ast, rec, .. } = &*link.as_ptr();
1169 let node = alloc_val(Ref {
1170 nam: nam.clone(),
1171 rec: *rec,
1172 exp: *exp,
1173 ast: *ast,
1174 parents,
1175 });
1176 DAGPtr::Ref(node)
1177 },
1178 DAGPtr::Lam(link) => unsafe {
1179 let Lam { var, bod, .. } = &mut *link.as_ptr();
1180 let lam = alloc_lam(var.nam.clone(), var.dep, mem::zeroed(), parents);
1181 let Lam { var: new_var, bod: new_bod, bod_ref, .. } =
1182 &mut *lam.as_ptr();
1183 map.insert(
1184 DAGPtr::Var(NonNull::new(var).unwrap()),
1185 DAGPtr::Var(NonNull::new(new_var).unwrap()),
1186 );
1187 *new_bod = DAG::from_subdag(*bod, map, NonNull::new(bod_ref));
1188 DAGPtr::Lam(lam)
1189 },
1190 DAGPtr::Slf(link) => unsafe {
1191 let Slf { var, bod, .. } = &mut *link.as_ptr();
1192 let slf = alloc_slf(var.nam.clone(), var.dep, mem::zeroed(), parents);
1193 let Slf { var: new_var, bod: new_bod, bod_ref, .. } =
1194 &mut *slf.as_ptr();
1195 map.insert(
1196 DAGPtr::Var(NonNull::new(var).unwrap()),
1197 DAGPtr::Var(NonNull::new(new_var).unwrap()),
1198 );
1199 *new_bod = DAG::from_subdag(*bod, map, NonNull::new(bod_ref));
1200 DAGPtr::Slf(slf)
1201 },
1202 DAGPtr::Fix(link) => unsafe {
1203 let Fix { var, bod, .. } = &mut *link.as_ptr();
1204 let fix = alloc_fix(var.nam.clone(), var.dep, mem::zeroed(), parents);
1205 let Fix { var: new_var, bod: new_bod, bod_ref, .. } =
1206 &mut *fix.as_ptr();
1207 map.insert(
1208 DAGPtr::Var(NonNull::new(var).unwrap()),
1209 DAGPtr::Var(NonNull::new(new_var).unwrap()),
1210 );
1211 *new_bod = DAG::from_subdag(*bod, map, NonNull::new(bod_ref));
1212 DAGPtr::Fix(fix)
1213 },
1214 DAGPtr::Cse(link) => unsafe {
1215 let Cse { bod, .. } = &mut *link.as_ptr();
1216 let cse = alloc_cse(mem::zeroed(), parents);
1217 let Cse { bod: new_bod, bod_ref, .. } = &mut *cse.as_ptr();
1218 *new_bod = DAG::from_subdag(*bod, map, NonNull::new(bod_ref));
1219 DAGPtr::Cse(cse)
1220 },
1221 DAGPtr::Dat(link) => unsafe {
1222 let Dat { bod, .. } = &mut *link.as_ptr();
1223 let dat = alloc_dat(mem::zeroed(), parents);
1224 let Dat { bod: new_bod, bod_ref, .. } = &mut *dat.as_ptr();
1225 *new_bod = DAG::from_subdag(*bod, map, NonNull::new(bod_ref));
1226 DAGPtr::Dat(dat)
1227 },
1228 DAGPtr::App(link) => unsafe {
1229 let App { fun, arg, .. } = &mut *link.as_ptr();
1230 let app = alloc_app(mem::zeroed(), mem::zeroed(), parents);
1231 let App { fun: new_fun, fun_ref, arg: new_arg, arg_ref, .. } =
1232 &mut *app.as_ptr();
1233 *new_fun = DAG::from_subdag(*fun, map, NonNull::new(fun_ref));
1234 *new_arg = DAG::from_subdag(*arg, map, NonNull::new(arg_ref));
1235 DAGPtr::App(app)
1236 },
1237 DAGPtr::All(link) => unsafe {
1238 let All { uses, dom, img, .. } = &mut *link.as_ptr();
1239 let all = alloc_all(*uses, mem::zeroed(), NonNull::dangling(), parents);
1240 let All { dom: new_dom, dom_ref, img: new_img, img_ref, .. } =
1241 &mut *all.as_ptr();
1242 *new_dom = DAG::from_subdag(*dom, map, NonNull::new(dom_ref));
1243 *new_img =
1244 match DAG::from_subdag(DAGPtr::Lam(*img), map, NonNull::new(img_ref))
1245 {
1246 DAGPtr::Lam(link) => link,
1247 _ => panic!("Clone implementation incorrect"),
1248 };
1249 DAGPtr::All(all)
1250 },
1251 DAGPtr::Let(link) => unsafe {
1252 let Let { uses, typ, exp, bod, .. } = &mut *link.as_ptr();
1253 let let_ = alloc_let(
1254 *uses,
1255 mem::zeroed(),
1256 mem::zeroed(),
1257 NonNull::dangling(),
1258 parents,
1259 );
1260 let Let {
1261 typ: new_typ,
1262 typ_ref,
1263 exp: new_exp,
1264 exp_ref,
1265 bod: new_bod,
1266 bod_ref,
1267 ..
1268 } = &mut *let_.as_ptr();
1269 *new_exp = DAG::from_subdag(*exp, map, NonNull::new(exp_ref));
1270 *new_typ = DAG::from_subdag(*typ, map, NonNull::new(typ_ref));
1271 *new_bod =
1272 match DAG::from_subdag(DAGPtr::Lam(*bod), map, NonNull::new(bod_ref))
1273 {
1274 DAGPtr::Lam(link) => link,
1275 _ => panic!("Clone implementation incorrect"),
1276 };
1277 DAGPtr::Let(let_)
1278 },
1279 DAGPtr::Ann(link) => unsafe {
1280 let Ann { typ, exp, .. } = &mut *link.as_ptr();
1281 let ann = alloc_ann(mem::zeroed(), mem::zeroed(), parents);
1282 let Ann { typ: new_typ, typ_ref, exp: new_exp, exp_ref, .. } =
1283 &mut *ann.as_ptr();
1284 *new_typ = DAG::from_subdag(*typ, map, NonNull::new(typ_ref));
1285 *new_exp = DAG::from_subdag(*exp, map, NonNull::new(exp_ref));
1286 DAGPtr::Ann(ann)
1287 },
1288 DAGPtr::Lit(link) => unsafe {
1289 let Lit { lit, .. } = &*link.as_ptr();
1290 let node = alloc_val(Lit { lit: lit.clone(), parents });
1291 DAGPtr::Lit(node)
1292 },
1293 DAGPtr::LTy(link) => unsafe {
1294 let LTy { lty, .. } = *link.as_ptr();
1295 let node = alloc_val(LTy { lty, parents });
1296 DAGPtr::LTy(node)
1297 },
1298 DAGPtr::Opr(link) => unsafe {
1299 let Opr { opr, .. } = &*link.as_ptr();
1300 let node = alloc_val(Opr { opr: opr.clone(), parents });
1301 DAGPtr::Opr(node)
1302 },
1303 DAGPtr::Typ(_) => {
1304 let node = alloc_val(Typ { parents });
1305 DAGPtr::Typ(node)
1306 } };
1308 map.insert(node, new_node);
1310 new_node
1311 }
1312
1313 pub fn subst(&mut self, idx: u64, val: DAGPtr) {
1315 pub fn go(node: DAGPtr, idx: u64, val: DAGPtr) {
1316 match node {
1317 DAGPtr::Var(link) => {
1318 let Var { dep, binder, .. } = unsafe { &*link.as_ptr() };
1319 if *dep == idx {
1320 match binder {
1321 BinderPtr::Free => (),
1322 _ => panic!("Variable not free"),
1323 }
1324 replace_child(node, val);
1325 free_dead_node(node);
1326 }
1327 }
1328 DAGPtr::Lam(link) => {
1329 let Lam { bod, .. } = unsafe { &*link.as_ptr() };
1330 go(*bod, idx, val)
1331 }
1332 DAGPtr::Slf(link) => {
1333 let Slf { bod, .. } = unsafe { &*link.as_ptr() };
1334 go(*bod, idx, val)
1335 }
1336 DAGPtr::Fix(link) => {
1337 let Fix { bod, .. } = unsafe { &*link.as_ptr() };
1338 go(*bod, idx, val)
1339 }
1340 DAGPtr::Cse(link) => {
1341 let Cse { bod, .. } = unsafe { &*link.as_ptr() };
1342 go(*bod, idx, val)
1343 }
1344 DAGPtr::Dat(link) => {
1345 let Dat { bod, .. } = unsafe { &*link.as_ptr() };
1346 go(*bod, idx, val)
1347 }
1348 DAGPtr::App(link) => {
1349 let App { fun, arg, .. } = unsafe { &*link.as_ptr() };
1350 go(*fun, idx, val);
1351 go(*arg, idx, val)
1352 }
1353 DAGPtr::All(link) => {
1354 let All { dom, img, .. } = unsafe { &*link.as_ptr() };
1355 go(*dom, idx, val);
1356 go(DAGPtr::Lam(*img), idx, val)
1357 }
1358 DAGPtr::Let(link) => {
1359 let Let { typ, exp, bod, .. } = unsafe { &*link.as_ptr() };
1360 go(*typ, idx, val);
1361 go(*exp, idx, val);
1362 go(DAGPtr::Lam(*bod), idx, val)
1363 }
1364 DAGPtr::Ann(link) => {
1365 let Ann { typ, exp, .. } = unsafe { &*link.as_ptr() };
1366 go(*typ, idx, val);
1367 go(*exp, idx, val)
1368 }
1369 _ => (),
1370 }
1371 }
1372 go(self.head, idx, val)
1373 }
1374}
1375
1376impl Clone for DAG {
1377 fn clone(&self) -> Self {
1378 let mut map: BTreeMap<DAGPtr, DAGPtr> = BTreeMap::new();
1379 let root = alloc_val(DLL::singleton(ParentPtr::Root));
1380 DAG::new(DAG::from_subdag(self.head, &mut map, Some(root)))
1381 }
1382}
1383
1384impl fmt::Debug for DAG {
1385 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1386 #[inline]
1387 fn format_uplink(p: ParentPtr) -> String {
1388 match p {
1389 ParentPtr::Root => String::from("ROOT"),
1390 ParentPtr::LamBod(link) => format!("LamBod<{:?}>", link.as_ptr()),
1391 ParentPtr::SlfBod(link) => format!("SlfBod<{:?}>", link.as_ptr()),
1392 ParentPtr::FixBod(link) => format!("FixBod<{:?}>", link.as_ptr()),
1393 ParentPtr::DatBod(link) => format!("DatBod<{:?}>", link.as_ptr()),
1394 ParentPtr::CseBod(link) => format!("CseBod<{:?}>", link.as_ptr()),
1395 ParentPtr::AppFun(link) => format!("AppFun<{:?}>", link.as_ptr()),
1396 ParentPtr::AppArg(link) => format!("AppArg<{:?}>", link.as_ptr()),
1397 ParentPtr::AllDom(link) => format!("AllDom<{:?}>", link.as_ptr()),
1398 ParentPtr::AllImg(link) => format!("AllImg<{:?}>", link.as_ptr()),
1399 ParentPtr::AnnExp(link) => format!("AnnExp<{:?}>", link.as_ptr()),
1400 ParentPtr::AnnTyp(link) => format!("AnnTyp<{:?}>", link.as_ptr()),
1401 ParentPtr::LetTyp(link) => format!("LetTyp<{:?}>", link.as_ptr()),
1402 ParentPtr::LetExp(link) => format!("LetExp<{:?}>", link.as_ptr()),
1403 ParentPtr::LetBod(link) => format!("LetBod<{:?}>", link.as_ptr()),
1404 }
1405 }
1406 #[inline]
1407 fn format_parents(dll: Option<NonNull<Parents>>) -> String {
1408 match dll {
1409 Some(dll) => unsafe {
1410 let mut iter = (*dll.as_ptr()).iter();
1411 let head =
1412 &iter.next().map_or(String::from(""), |head| format_uplink(*head));
1413 let mut msg = String::from("[ ") + head;
1414 for val in iter {
1415 msg = msg + " <-> " + &format_uplink(*val);
1416 }
1417 msg + " ]"
1418 },
1419 _ => String::from("[]"),
1420 }
1421 }
1422 fn go(term: DAGPtr, set: &mut BTreeSet<usize>) -> String {
1423 match term {
1424 DAGPtr::Var(link) => {
1425 let Var { nam, parents, binder, dep, .. } = unsafe { link.as_ref() };
1426 let binder = match binder {
1427 BinderPtr::Free => format!("Free<{}>", *dep),
1428 BinderPtr::Lam(link) => format!("Lam<{:?}>", link.as_ptr()),
1429 BinderPtr::Slf(link) => format!("Slf<{:?}>", link.as_ptr()),
1430 BinderPtr::Fix(link) => format!("Fix<{:?}>", link.as_ptr()),
1431 };
1432 if set.get(&(link.as_ptr() as usize)).is_none() {
1433 set.insert(link.as_ptr() as usize);
1434 format!(
1435 "\nVar<{:?}> {} bound at {} parents: {}",
1436 link.as_ptr(),
1437 binder,
1438 nam,
1439 format_parents(*parents)
1440 )
1441 }
1442 else {
1443 format!("\nSHARE<{:?}>", link.as_ptr())
1444 }
1445 }
1446 DAGPtr::Typ(link) => {
1447 let Typ { parents, .. } = unsafe { link.as_ref() };
1448 format!(
1449 "\nTyp<{:?}> parents: {}",
1450 (link.as_ptr()),
1451 format_parents(*parents)
1452 )
1453 }
1454 DAGPtr::LTy(link) => {
1455 let LTy { parents, .. } = unsafe { link.as_ref() };
1456 format!(
1457 "\nLTy<{:?}> parents: {}",
1458 (link.as_ptr()),
1459 format_parents(*parents)
1460 )
1461 }
1462 DAGPtr::Lit(link) => {
1463 let Lit { parents, .. } = unsafe { link.as_ref() };
1464 format!(
1465 "\nLit<{:?}> parents: {}",
1466 (link.as_ptr()),
1467 format_parents(*parents)
1468 )
1469 }
1470 DAGPtr::Opr(link) => {
1471 let Opr { parents, .. } = unsafe { link.as_ref() };
1472 format!(
1473 "\nOpr<{:?}> parents: {}",
1474 (link.as_ptr()),
1475 format_parents(*parents)
1476 )
1477 }
1478 DAGPtr::Ref(link) => {
1479 let Ref { nam, parents, .. } = unsafe { link.as_ref() };
1480 format!(
1481 "\nRef<{:?}> {} parents: {}",
1482 (link.as_ptr()),
1483 nam,
1484 format_parents(*parents)
1485 )
1486 }
1487 DAGPtr::Lam(link) => {
1488 if set.get(&(link.as_ptr() as usize)).is_none() {
1489 let Lam { var, parents, bod, .. } = unsafe { link.as_ref() };
1490 let name = var.nam.clone();
1491 set.insert(link.as_ptr() as usize);
1492 format!(
1493 "\nLam<{:?}> {} parents: {}{}",
1494 link.as_ptr(),
1495 name,
1496 format_parents(*parents),
1497 go(*bod, set)
1498 )
1499 }
1500 else {
1501 format!("\nSHARE<{:?}>", link.as_ptr())
1502 }
1503 }
1504 DAGPtr::Slf(link) => {
1505 if set.get(&(link.as_ptr() as usize)).is_none() {
1506 let Slf { var, parents, bod, .. } = unsafe { link.as_ref() };
1507 let name = var.nam.clone();
1508 set.insert(link.as_ptr() as usize);
1509 format!(
1510 "\nSlf<{:?}> {} parents: {}{}",
1511 link.as_ptr(),
1512 name,
1513 format_parents(*parents),
1514 go(*bod, set)
1515 )
1516 }
1517 else {
1518 format!("\nSHARE<{:?}>", link.as_ptr())
1519 }
1520 }
1521 DAGPtr::Fix(link) => {
1522 if set.get(&(link.as_ptr() as usize)).is_none() {
1523 let Fix { var, parents, bod, .. } = unsafe { link.as_ref() };
1524 let name = var.nam.clone();
1525 set.insert(link.as_ptr() as usize);
1526 format!(
1527 "\nFix<{:?}> {} parents: {}{}",
1528 link.as_ptr(),
1529 name,
1530 format_parents(*parents),
1531 go(*bod, set)
1532 )
1533 }
1534 else {
1535 format!("\nSHARE<{:?}>", link.as_ptr())
1536 }
1537 }
1538 DAGPtr::Dat(link) => {
1539 if set.get(&(link.as_ptr() as usize)).is_none() {
1540 let Dat { parents, bod, .. } = unsafe { link.as_ref() };
1541 set.insert(link.as_ptr() as usize);
1542 format!(
1543 "\nDat<{:?}> parents: {}{}",
1544 link.as_ptr(),
1545 format_parents(*parents),
1546 go(*bod, set)
1547 )
1548 }
1549 else {
1550 format!("\nSHARE<{:?}>", link.as_ptr())
1551 }
1552 }
1553 DAGPtr::Cse(link) => {
1554 if set.get(&(link.as_ptr() as usize)).is_none() {
1555 let Cse { parents, bod, .. } = unsafe { link.as_ref() };
1556 set.insert(link.as_ptr() as usize);
1557 format!(
1558 "\nCse<{:?}> parents: {}{}",
1559 link.as_ptr(),
1560 format_parents(*parents),
1561 go(*bod, set)
1562 )
1563 }
1564 else {
1565 format!("\nSHARE<{:?}>", link.as_ptr())
1566 }
1567 }
1568 DAGPtr::App(link) => {
1569 if set.get(&(link.as_ptr() as usize)).is_none() {
1570 set.insert(link.as_ptr() as usize);
1571 let App { fun, arg, parents, copy, .. } = unsafe { link.as_ref() };
1572 let copy = copy.map(|link| link.as_ptr() as usize);
1573 format!(
1574 "\nApp<{:?}> parents: {} copy: {:?}{}{}",
1575 link.as_ptr(),
1576 format_parents(*parents),
1577 copy,
1578 go(*fun, set),
1579 go(*arg, set)
1580 )
1581 }
1582 else {
1583 format!("\nSHARE<{}>", link.as_ptr() as usize)
1584 }
1585 }
1586 DAGPtr::Ann(link) => {
1587 if set.get(&(link.as_ptr() as usize)).is_none() {
1588 set.insert(link.as_ptr() as usize);
1589 let Ann { typ, exp, parents, copy, .. } = unsafe { link.as_ref() };
1590 let copy = copy.map(|link| link.as_ptr() as usize);
1591 format!(
1592 "\nAnn<{:?}> parents: {} copy: {:?}{}{}",
1593 link.as_ptr(),
1594 format_parents(*parents),
1595 copy,
1596 go(*typ, set),
1597 go(*exp, set),
1598 )
1599 }
1600 else {
1601 format!("\nSHARE<{:?}>", link.as_ptr())
1602 }
1603 }
1604 DAGPtr::All(link) => {
1605 if set.get(&(link.as_ptr() as usize)).is_none() {
1606 set.insert(link.as_ptr() as usize);
1607 let All { dom, img, parents, copy, .. } = unsafe { link.as_ref() };
1608 let copy = copy.map(|link| link.as_ptr() as usize);
1609 format!(
1610 "\nAll<{:?}> parents: {} copy: {:?}{}{}",
1611 link.as_ptr(),
1612 format_parents(*parents),
1613 copy,
1614 go(*dom, set),
1615 go(DAGPtr::Lam(*img), set),
1616 )
1617 }
1618 else {
1619 format!("\nSHARE<{:?}>", link.as_ptr())
1620 }
1621 }
1622 DAGPtr::Let(link) => {
1623 if set.get(&(link.as_ptr() as usize)).is_none() {
1624 set.insert(link.as_ptr() as usize);
1625 let Let { exp, typ, bod, parents, copy, .. } =
1626 unsafe { link.as_ref() };
1627 let copy = copy.map(|link| link.as_ptr() as usize);
1628 format!(
1629 "\nLet<{:?}> parents: {} copy: {:?}{}{}{}",
1630 link.as_ptr(),
1631 format_parents(*parents),
1632 copy,
1633 go(*typ, set),
1634 go(*exp, set),
1635 go(DAGPtr::Lam(*bod), set),
1636 )
1637 }
1638 else {
1639 format!("\nSHARE<{:?}>", link.as_ptr())
1640 }
1641 }
1642 }
1643 }
1644 write!(f, "{}", go(self.head, &mut BTreeSet::new()))
1645 }
1646}
1647
1648impl fmt::Display for DAG {
1649 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1650 write!(f, "{}", self.to_term(false))
1651 }
1652}
1653
1654impl fmt::Display for DAGPtr {
1655 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1656 write!(f, "{}", DAG::new(*self).to_term(false))
1657 }
1658}
1659
1660#[cfg(test)]
1661pub mod test {
1662 use super::*;
1663 #[quickcheck]
1677 fn dag_term_iso(x: Term) -> bool {
1678 let y = DAG::to_term(&DAG::from_term(&x), true);
1681 x == y
1684 }
1685
1686 #[quickcheck]
1687 fn dag_def_iso(x: Def) -> bool {
1688 let y = DAG::to_term(&DAG::from_def(&x, Name::from("test")), true);
1689 x.term == y
1690 }
1691}