1use std::fmt;
2use std::str::FromStr;
3use std::sync::Arc;
4
5use miniscript::iter::{Tree, TreeLike};
6use simplicity::types::{CompleteBound, Final};
7
8use crate::array::{BTreeSlice, Partition};
9use crate::num::{NonZeroPow2Usize, Pow2Usize};
10use crate::str::AliasName;
11
12#[derive(Debug, PartialEq, Eq, Hash, Clone)]
14#[non_exhaustive]
15pub enum TypeInner<A> {
16 Either(A, A),
18 Option(A),
20 Boolean,
22 UInt(UIntType),
24 Tuple(Arc<[A]>),
26 Array(A, usize),
28 List(A, NonZeroPow2Usize),
30}
31
32impl<A> TypeInner<A> {
33 fn display(&self, f: &mut fmt::Formatter<'_>, n_children_yielded: usize) -> fmt::Result {
37 match self {
38 TypeInner::Either(_, _) => match n_children_yielded {
39 0 => f.write_str("Either<"),
40 1 => f.write_str(","),
41 n => {
42 debug_assert_eq!(n, 2);
43 f.write_str(">")
44 }
45 },
46 TypeInner::Option(_) => match n_children_yielded {
47 0 => f.write_str("Option<"),
48 n => {
49 debug_assert_eq!(n, 1);
50 f.write_str(">")
51 }
52 },
53 TypeInner::Boolean => f.write_str("bool"),
54 TypeInner::UInt(ty) => write!(f, "{ty}"),
55 TypeInner::Tuple(elements) => match n_children_yielded {
56 0 => {
57 f.write_str("(")?;
58 if 0 == elements.len() {
59 f.write_str(")")?;
60 }
61 Ok(())
62 }
63 n if n == elements.len() => {
64 if n == 1 {
65 f.write_str(",")?;
66 }
67 f.write_str(")")
68 }
69 n => {
70 debug_assert!(n < elements.len());
71 f.write_str(", ")
72 }
73 },
74 TypeInner::Array(_, size) => match n_children_yielded {
75 0 => f.write_str("["),
76 n => {
77 debug_assert_eq!(n, 1);
78 write!(f, "; {size}]")
79 }
80 },
81 TypeInner::List(_, bound) => match n_children_yielded {
82 0 => f.write_str("List<"),
83 n => {
84 debug_assert_eq!(n, 1);
85 write!(f, ", {bound}>")
86 }
87 },
88 }
89 }
90}
91
92#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
94#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
95pub enum UIntType {
96 U1,
98 U2,
100 U4,
102 U8,
104 U16,
106 U32,
108 U64,
110 U128,
112 U256,
114}
115
116impl UIntType {
117 pub const fn two_n(n: u32) -> Option<Self> {
119 match n {
120 0 => Some(UIntType::U1),
121 1 => Some(UIntType::U2),
122 2 => Some(UIntType::U4),
123 3 => Some(UIntType::U8),
124 4 => Some(UIntType::U16),
125 5 => Some(UIntType::U32),
126 6 => Some(UIntType::U64),
127 7 => Some(UIntType::U128),
128 8 => Some(UIntType::U256),
129 _ => None,
130 }
131 }
132
133 pub const fn bit_width(self) -> Pow2Usize {
135 let bit_width: usize = match self {
136 UIntType::U1 => 1,
137 UIntType::U2 => 2,
138 UIntType::U4 => 4,
139 UIntType::U8 => 8,
140 UIntType::U16 => 16,
141 UIntType::U32 => 32,
142 UIntType::U64 => 64,
143 UIntType::U128 => 128,
144 UIntType::U256 => 256,
145 };
146 debug_assert!(bit_width.is_power_of_two());
147 Pow2Usize::new_unchecked(bit_width)
148 }
149
150 pub const fn from_bit_width(bit_width: Pow2Usize) -> Option<Self> {
152 match bit_width.get() {
153 1 => Some(UIntType::U1),
154 2 => Some(UIntType::U2),
155 4 => Some(UIntType::U4),
156 8 => Some(UIntType::U8),
157 16 => Some(UIntType::U16),
158 32 => Some(UIntType::U32),
159 64 => Some(UIntType::U64),
160 128 => Some(UIntType::U128),
161 256 => Some(UIntType::U256),
162 _ => None,
163 }
164 }
165
166 pub const fn byte_width(self) -> usize {
170 self.bit_width().get() / 8
171 }
172}
173
174impl fmt::Debug for UIntType {
175 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
176 write!(f, "{}", self)
177 }
178}
179
180impl fmt::Display for UIntType {
181 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
182 match self {
183 UIntType::U1 => f.write_str("u1"),
184 UIntType::U2 => f.write_str("u2"),
185 UIntType::U4 => f.write_str("u4"),
186 UIntType::U8 => f.write_str("u8"),
187 UIntType::U16 => f.write_str("u16"),
188 UIntType::U32 => f.write_str("u32"),
189 UIntType::U64 => f.write_str("u64"),
190 UIntType::U128 => f.write_str("u128"),
191 UIntType::U256 => f.write_str("u256"),
192 }
193 }
194}
195
196impl TryFrom<&StructuralType> for UIntType {
197 type Error = ();
198
199 fn try_from(value: &StructuralType) -> Result<Self, Self::Error> {
200 let mut current = value.as_ref();
201 let mut n = 0;
202 while let Some((left, right)) = current.as_product() {
203 if left.tmr() != right.tmr() {
204 return Err(());
205 }
206 current = left;
207 n += 1;
208 }
209 if let Some((left, right)) = current.as_sum() {
210 if left.is_unit() && right.is_unit() {
211 return UIntType::two_n(n).ok_or(());
212 }
213 }
214 Err(())
215 }
216}
217
218impl TryFrom<&ResolvedType> for UIntType {
219 type Error = ();
220
221 fn try_from(value: &ResolvedType) -> Result<Self, Self::Error> {
222 UIntType::try_from(&StructuralType::from(value))
223 }
224}
225
226macro_rules! construct_int {
227 ($name: ident, $ty: ident, $text: expr) => {
228 #[doc = "Create the type of"]
229 #[doc = $text]
230 #[doc = "integers."]
231 fn $name() -> Self {
232 Self::from(UIntType::$ty)
233 }
234 };
235}
236
237pub trait TypeConstructible: Sized + From<UIntType> {
239 fn either(left: Self, right: Self) -> Self;
241
242 fn option(inner: Self) -> Self;
244
245 fn boolean() -> Self;
247
248 fn tuple<I: IntoIterator<Item = Self>>(elements: I) -> Self;
253
254 fn unit() -> Self {
256 Self::tuple([])
257 }
258
259 fn product(left: Self, right: Self) -> Self {
261 Self::tuple([left, right])
262 }
263
264 fn array(element: Self, size: usize) -> Self;
266
267 fn byte_array(size: usize) -> Self {
269 Self::array(Self::u8(), size)
270 }
271
272 fn list(element: Self, bound: NonZeroPow2Usize) -> Self;
274
275 construct_int!(u1, U1, "1-bit");
276 construct_int!(u2, U2, "2-bit");
277 construct_int!(u4, U4, "4-bit");
278 construct_int!(u8, U8, "8-bit");
279 construct_int!(u16, U16, "16-bit");
280 construct_int!(u32, U32, "32-bit");
281 construct_int!(u64, U64, "64-bit");
282 construct_int!(u128, U128, "128-bit");
283 construct_int!(u256, U256, "256-bit");
284}
285
286pub trait TypeDeconstructible: Sized {
291 fn as_either(&self) -> Option<(&Self, &Self)>;
293
294 fn as_option(&self) -> Option<&Self>;
296
297 fn is_boolean(&self) -> bool;
299
300 fn as_integer(&self) -> Option<UIntType>;
302
303 fn as_tuple(&self) -> Option<&[Arc<Self>]>;
305
306 fn is_unit(&self) -> bool {
308 matches!(self.as_tuple(), Some(components) if components.is_empty())
309 }
310
311 fn as_array(&self) -> Option<(&Self, usize)>;
313
314 fn as_list(&self) -> Option<(&Self, NonZeroPow2Usize)>;
316}
317
318#[derive(PartialEq, Eq, Hash, Clone)]
320pub struct ResolvedType(TypeInner<Arc<Self>>);
321
322impl ResolvedType {
323 pub fn as_inner(&self) -> &TypeInner<Arc<Self>> {
325 &self.0
326 }
327}
328
329impl TypeConstructible for ResolvedType {
330 fn either(left: Self, right: Self) -> Self {
331 Self(TypeInner::Either(Arc::new(left), Arc::new(right)))
332 }
333
334 fn option(inner: Self) -> Self {
335 Self(TypeInner::Option(Arc::new(inner)))
336 }
337
338 fn boolean() -> Self {
339 Self(TypeInner::Boolean)
340 }
341
342 fn tuple<I: IntoIterator<Item = Self>>(elements: I) -> Self {
343 Self(TypeInner::Tuple(
344 elements.into_iter().map(Arc::new).collect(),
345 ))
346 }
347
348 fn array(element: Self, size: usize) -> Self {
349 Self(TypeInner::Array(Arc::new(element), size))
350 }
351
352 fn list(element: Self, bound: NonZeroPow2Usize) -> Self {
353 Self(TypeInner::List(Arc::new(element), bound))
354 }
355}
356
357impl TypeDeconstructible for ResolvedType {
358 fn as_either(&self) -> Option<(&Self, &Self)> {
359 match self.as_inner() {
360 TypeInner::Either(ty_l, ty_r) => Some((ty_l, ty_r)),
361 _ => None,
362 }
363 }
364
365 fn as_option(&self) -> Option<&Self> {
366 match self.as_inner() {
367 TypeInner::Option(ty) => Some(ty),
368 _ => None,
369 }
370 }
371
372 fn is_boolean(&self) -> bool {
373 matches!(self.as_inner(), TypeInner::Boolean)
374 }
375
376 fn as_integer(&self) -> Option<UIntType> {
377 match self.as_inner() {
378 TypeInner::UInt(ty) => Some(*ty),
379 _ => None,
380 }
381 }
382
383 fn as_tuple(&self) -> Option<&[Arc<Self>]> {
384 match self.as_inner() {
385 TypeInner::Tuple(components) => Some(components),
386 _ => None,
387 }
388 }
389
390 fn as_array(&self) -> Option<(&Self, usize)> {
391 match self.as_inner() {
392 TypeInner::Array(ty, size) => Some((ty, *size)),
393 _ => None,
394 }
395 }
396
397 fn as_list(&self) -> Option<(&Self, NonZeroPow2Usize)> {
398 match self.as_inner() {
399 TypeInner::List(ty, bound) => Some((ty, *bound)),
400 _ => None,
401 }
402 }
403}
404
405impl TreeLike for &ResolvedType {
406 fn as_node(&self) -> Tree<Self> {
407 match &self.0 {
408 TypeInner::Boolean | TypeInner::UInt(..) => Tree::Nullary,
409 TypeInner::Option(l) | TypeInner::Array(l, _) | TypeInner::List(l, _) => Tree::Unary(l),
410 TypeInner::Either(l, r) => Tree::Binary(l, r),
411 TypeInner::Tuple(elements) => Tree::Nary(elements.iter().map(Arc::as_ref).collect()),
412 }
413 }
414}
415
416impl fmt::Debug for ResolvedType {
417 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
418 write!(f, "{}", self)
419 }
420}
421
422impl fmt::Display for ResolvedType {
423 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
424 for data in self.verbose_pre_order_iter() {
425 data.node.0.display(f, data.n_children_yielded)?;
426 }
427 Ok(())
428 }
429}
430
431impl From<UIntType> for ResolvedType {
432 fn from(value: UIntType) -> Self {
433 Self(TypeInner::UInt(value))
434 }
435}
436
437#[cfg(feature = "arbitrary")]
438impl crate::ArbitraryRec for ResolvedType {
439 fn arbitrary_rec(u: &mut arbitrary::Unstructured, budget: usize) -> arbitrary::Result<Self> {
440 use arbitrary::Arbitrary;
441
442 match budget.checked_sub(1) {
443 None => match u.int_in_range(0..=1)? {
444 0 => Ok(Self::boolean()),
445 1 => UIntType::arbitrary(u).map(Self::from),
446 _ => unreachable!(),
447 },
448 Some(new_budget) => match u.int_in_range(0..=6)? {
449 0 => Ok(Self::boolean()),
450 1 => UIntType::arbitrary(u).map(Self::from),
451 2 => Self::arbitrary_rec(u, new_budget).map(Self::option),
452 3 => {
453 let left = Self::arbitrary_rec(u, new_budget)?;
454 let right = Self::arbitrary_rec(u, new_budget)?;
455 Ok(Self::either(left, right))
456 }
457 4 => {
458 let len = u.int_in_range(0..=3)?;
459 (0..len)
460 .map(|_| Self::arbitrary_rec(u, new_budget))
461 .collect::<arbitrary::Result<Vec<Self>>>()
462 .map(Self::tuple)
463 }
464 5 => {
465 let element = Self::arbitrary_rec(u, new_budget)?;
466 let size = u.int_in_range(0..=3)?;
467 Ok(Self::array(element, size))
468 }
469 6 => {
470 let element = Self::arbitrary_rec(u, new_budget)?;
471 let bound = NonZeroPow2Usize::arbitrary(u)?;
472 Ok(Self::list(element, bound))
473 }
474 _ => unreachable!(),
475 },
476 }
477 }
478}
479
480#[cfg(feature = "arbitrary")]
481impl<'a> arbitrary::Arbitrary<'a> for ResolvedType {
482 fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
483 <Self as crate::ArbitraryRec>::arbitrary_rec(u, 3)
484 }
485}
486
487#[derive(PartialEq, Eq, Hash, Clone)]
489pub struct AliasedType(AliasedInner);
490
491#[derive(Debug, PartialEq, Eq, Hash, Clone)]
495enum AliasedInner {
496 Alias(AliasName),
498 Builtin(BuiltinAlias),
500 Inner(TypeInner<Arc<AliasedType>>),
502}
503
504#[derive(Copy, Clone, PartialEq, Eq, Hash)]
506#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
507pub enum BuiltinAlias {
508 Ctx8,
509 Pubkey,
510 Message,
511 Message64,
512 Signature,
513 Scalar,
514 Fe,
515 Ge,
516 Gej,
517 Point,
518 Height,
519 Time,
520 Distance,
521 Duration,
522 Lock,
523 Outpoint,
524 Confidential1,
525 ExplicitAsset,
526 Asset1,
527 ExplicitAmount,
528 Amount1,
529 ExplicitNonce,
530 Nonce,
531 TokenAmount1,
532}
533
534impl AliasedType {
535 pub const fn as_alias(&self) -> Option<&AliasName> {
537 match &self.0 {
538 AliasedInner::Alias(name) => Some(name),
539 _ => None,
540 }
541 }
542
543 pub const fn as_builtin(&self) -> Option<&BuiltinAlias> {
545 match &self.0 {
546 AliasedInner::Builtin(builtin) => Some(builtin),
547 _ => None,
548 }
549 }
550
551 pub const fn alias(name: AliasName) -> Self {
553 Self(AliasedInner::Alias(name))
554 }
555
556 pub const fn builtin(builtin: BuiltinAlias) -> Self {
558 Self(AliasedInner::Builtin(builtin))
559 }
560
561 pub fn resolve<F>(&self, mut get_alias: F) -> Result<ResolvedType, AliasName>
563 where
564 F: FnMut(&AliasName) -> Option<ResolvedType>,
565 {
566 let mut output = vec![];
567 for data in self.post_order_iter() {
568 match &data.node.0 {
569 AliasedInner::Alias(name) => {
570 let resolved = get_alias(name).ok_or(name.clone())?;
571 output.push(resolved);
572 }
573 AliasedInner::Builtin(builtin) => {
574 let resolved = builtin.resolve();
575 output.push(resolved);
576 }
577 AliasedInner::Inner(inner) => match inner {
578 TypeInner::Either(_, _) => {
579 let right = output.pop().unwrap();
580 let left = output.pop().unwrap();
581 output.push(ResolvedType::either(left, right));
582 }
583 TypeInner::Option(_) => {
584 let inner = output.pop().unwrap();
585 output.push(ResolvedType::option(inner));
586 }
587 TypeInner::Boolean => output.push(ResolvedType::boolean()),
588 TypeInner::UInt(integer) => output.push(ResolvedType::from(*integer)),
589 TypeInner::Tuple(_) => {
590 let size = data.node.n_children();
591 let elements = output.split_off(output.len() - size);
592 debug_assert_eq!(elements.len(), size);
593 output.push(ResolvedType::tuple(elements));
594 }
595 TypeInner::Array(_, size) => {
596 let element = output.pop().unwrap();
597 output.push(ResolvedType::array(element, *size));
598 }
599 TypeInner::List(_, bound) => {
600 let element = output.pop().unwrap();
601 output.push(ResolvedType::list(element, *bound));
602 }
603 },
604 }
605 }
606 debug_assert_eq!(output.len(), 1);
607 Ok(output.pop().unwrap())
608 }
609
610 pub fn resolve_builtin(&self) -> Result<ResolvedType, AliasName> {
612 self.resolve(|_| None)
613 }
614}
615
616impl TypeConstructible for AliasedType {
617 fn either(left: Self, right: Self) -> Self {
618 Self(AliasedInner::Inner(TypeInner::Either(
619 Arc::new(left),
620 Arc::new(right),
621 )))
622 }
623
624 fn option(inner: Self) -> Self {
625 Self(AliasedInner::Inner(TypeInner::Option(Arc::new(inner))))
626 }
627
628 fn boolean() -> Self {
629 Self(AliasedInner::Inner(TypeInner::Boolean))
630 }
631
632 fn tuple<I: IntoIterator<Item = Self>>(elements: I) -> Self {
633 Self(AliasedInner::Inner(TypeInner::Tuple(
634 elements.into_iter().map(Arc::new).collect(),
635 )))
636 }
637
638 fn array(element: Self, size: usize) -> Self {
639 Self(AliasedInner::Inner(TypeInner::Array(
640 Arc::new(element),
641 size,
642 )))
643 }
644
645 fn list(element: Self, bound: NonZeroPow2Usize) -> Self {
646 Self(AliasedInner::Inner(TypeInner::List(
647 Arc::new(element),
648 bound,
649 )))
650 }
651}
652
653impl TypeDeconstructible for AliasedType {
654 fn as_either(&self) -> Option<(&Self, &Self)> {
655 match &self.0 {
656 AliasedInner::Inner(TypeInner::Either(ty_l, ty_r)) => Some((ty_l, ty_r)),
657 _ => None,
658 }
659 }
660
661 fn as_option(&self) -> Option<&Self> {
662 match &self.0 {
663 AliasedInner::Inner(TypeInner::Option(ty)) => Some(ty),
664 _ => None,
665 }
666 }
667
668 fn is_boolean(&self) -> bool {
669 matches!(&self.0, AliasedInner::Inner(TypeInner::Boolean))
670 }
671
672 fn as_integer(&self) -> Option<UIntType> {
673 match &self.0 {
674 AliasedInner::Inner(TypeInner::UInt(ty)) => Some(*ty),
675 _ => None,
676 }
677 }
678
679 fn as_tuple(&self) -> Option<&[Arc<Self>]> {
680 match &self.0 {
681 AliasedInner::Inner(TypeInner::Tuple(components)) => Some(components),
682 _ => None,
683 }
684 }
685
686 fn as_array(&self) -> Option<(&Self, usize)> {
687 match &self.0 {
688 AliasedInner::Inner(TypeInner::Array(ty, size)) => Some((ty, *size)),
689 _ => None,
690 }
691 }
692
693 fn as_list(&self) -> Option<(&Self, NonZeroPow2Usize)> {
694 match &self.0 {
695 AliasedInner::Inner(TypeInner::List(ty, bound)) => Some((ty, *bound)),
696 _ => None,
697 }
698 }
699}
700
701impl TreeLike for &AliasedType {
702 fn as_node(&self) -> Tree<Self> {
703 match &self.0 {
704 AliasedInner::Alias(_) | AliasedInner::Builtin(_) => Tree::Nullary,
705 AliasedInner::Inner(inner) => match inner {
706 TypeInner::Boolean | TypeInner::UInt(..) => Tree::Nullary,
707 TypeInner::Option(l) | TypeInner::Array(l, _) | TypeInner::List(l, _) => {
708 Tree::Unary(l)
709 }
710 TypeInner::Either(l, r) => Tree::Binary(l, r),
711 TypeInner::Tuple(elements) => {
712 Tree::Nary(elements.iter().map(Arc::as_ref).collect())
713 }
714 },
715 }
716 }
717}
718
719impl fmt::Debug for AliasedType {
720 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
721 write!(f, "{}", self)
722 }
723}
724
725impl fmt::Display for AliasedType {
726 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
727 for data in self.verbose_pre_order_iter() {
728 match &data.node.0 {
729 AliasedInner::Alias(alias) => write!(f, "{alias}")?,
730 AliasedInner::Builtin(builtin) => write!(f, "{builtin}")?,
731 AliasedInner::Inner(inner) => inner.display(f, data.n_children_yielded)?,
732 }
733 }
734 Ok(())
735 }
736}
737
738impl From<UIntType> for AliasedType {
739 fn from(value: UIntType) -> Self {
740 Self(AliasedInner::Inner(TypeInner::UInt(value)))
741 }
742}
743
744impl From<AliasName> for AliasedType {
745 fn from(value: AliasName) -> Self {
746 Self::alias(value)
747 }
748}
749
750impl From<BuiltinAlias> for AliasedType {
751 fn from(value: BuiltinAlias) -> Self {
752 Self::builtin(value)
753 }
754}
755
756#[cfg(feature = "arbitrary")]
757impl crate::ArbitraryRec for AliasedType {
758 fn arbitrary_rec(u: &mut arbitrary::Unstructured, budget: usize) -> arbitrary::Result<Self> {
759 use arbitrary::Arbitrary;
760
761 match budget.checked_sub(1) {
762 None => match u.int_in_range(0..=3)? {
763 0 => AliasName::arbitrary(u).map(Self::alias),
764 1 => BuiltinAlias::arbitrary(u).map(Self::builtin),
765 2 => Ok(Self::boolean()),
766 3 => UIntType::arbitrary(u).map(Self::from),
767 _ => unreachable!(),
768 },
769 Some(new_budget) => match u.int_in_range(0..=8)? {
770 0 => AliasName::arbitrary(u).map(Self::alias),
771 1 => BuiltinAlias::arbitrary(u).map(Self::builtin),
772 2 => Ok(Self::boolean()),
773 3 => UIntType::arbitrary(u).map(Self::from),
774 4 => Self::arbitrary_rec(u, new_budget).map(Self::option),
775 5 => {
776 let left = Self::arbitrary_rec(u, new_budget)?;
777 let right = Self::arbitrary_rec(u, new_budget)?;
778 Ok(Self::either(left, right))
779 }
780 6 => {
781 let len = u.int_in_range(0..=3)?;
782 (0..len)
783 .map(|_| Self::arbitrary_rec(u, new_budget))
784 .collect::<arbitrary::Result<Vec<Self>>>()
785 .map(Self::tuple)
786 }
787 7 => {
788 let element = Self::arbitrary_rec(u, new_budget)?;
789 let size = u.int_in_range(0..=3)?;
790 Ok(Self::array(element, size))
791 }
792 8 => {
793 let element = Self::arbitrary_rec(u, new_budget)?;
794 let bound = NonZeroPow2Usize::arbitrary(u)?;
795 Ok(Self::list(element, bound))
796 }
797 _ => unreachable!(),
798 },
799 }
800 }
801}
802
803#[cfg(feature = "arbitrary")]
804impl<'a> arbitrary::Arbitrary<'a> for AliasedType {
805 fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
806 <Self as crate::ArbitraryRec>::arbitrary_rec(u, 3)
807 }
808}
809
810impl BuiltinAlias {
811 pub fn resolve(self) -> ResolvedType {
812 use BuiltinAlias as B;
813 use UIntType::*;
814
815 match self {
816 B::Ctx8 => ResolvedType::tuple([
817 ResolvedType::list(U8.into(), NonZeroPow2Usize::new(64).unwrap()),
818 ResolvedType::tuple([U64.into(), U256.into()]),
819 ]),
820 B::Pubkey | B::Message | B::Scalar | B::Fe | B::ExplicitAsset | B::ExplicitNonce => {
821 U256.into()
822 }
823 B::Message64 | B::Signature => ResolvedType::array(U8.into(), 64),
824 B::Ge => ResolvedType::tuple([U256.into(), U256.into()]),
825 B::Gej => {
826 ResolvedType::tuple([ResolvedType::tuple([U256.into(), U256.into()]), U256.into()])
827 }
828 B::Point | B::Confidential1 => ResolvedType::tuple([U1.into(), U256.into()]),
829 B::Height | B::Time | B::Lock => U32.into(),
830 B::Distance | B::Duration => U16.into(),
831 B::Outpoint => ResolvedType::tuple([U256.into(), U32.into()]),
832 B::Asset1 | B::Nonce => {
833 ResolvedType::either(ResolvedType::tuple([U1.into(), U256.into()]), U256.into())
834 }
835 B::ExplicitAmount => U64.into(),
836 B::Amount1 | B::TokenAmount1 => {
837 ResolvedType::either(ResolvedType::tuple([U1.into(), U256.into()]), U64.into())
838 }
839 }
840 }
841}
842
843impl fmt::Debug for BuiltinAlias {
844 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
845 write!(f, "{}", self)
846 }
847}
848
849impl fmt::Display for BuiltinAlias {
850 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
851 match self {
852 BuiltinAlias::Ctx8 => f.write_str("Ctx8"),
853 BuiltinAlias::Pubkey => f.write_str("Pubkey"),
854 BuiltinAlias::Message => f.write_str("Message"),
855 BuiltinAlias::Message64 => f.write_str("Message64"),
856 BuiltinAlias::Signature => f.write_str("Signature"),
857 BuiltinAlias::Scalar => f.write_str("Scalar"),
858 BuiltinAlias::Fe => f.write_str("Fe"),
859 BuiltinAlias::Ge => f.write_str("Ge"),
860 BuiltinAlias::Gej => f.write_str("Gej"),
861 BuiltinAlias::Point => f.write_str("Point"),
862 BuiltinAlias::Height => f.write_str("Height"),
863 BuiltinAlias::Time => f.write_str("Time"),
864 BuiltinAlias::Distance => f.write_str("Distance"),
865 BuiltinAlias::Duration => f.write_str("Duration"),
866 BuiltinAlias::Lock => f.write_str("Lock"),
867 BuiltinAlias::Outpoint => f.write_str("Outpoint"),
868 BuiltinAlias::Confidential1 => f.write_str("Confidential1"),
869 BuiltinAlias::ExplicitAsset => f.write_str("ExplicitAsset"),
870 BuiltinAlias::Asset1 => f.write_str("Asset1"),
871 BuiltinAlias::ExplicitAmount => f.write_str("ExplicitAmount"),
872 BuiltinAlias::Amount1 => f.write_str("Amount1"),
873 BuiltinAlias::ExplicitNonce => f.write_str("ExplicitNonce"),
874 BuiltinAlias::Nonce => f.write_str("Nonce"),
875 BuiltinAlias::TokenAmount1 => f.write_str("TokenAmount1"),
876 }
877 }
878}
879
880impl FromStr for BuiltinAlias {
881 type Err = String;
882
883 fn from_str(s: &str) -> Result<Self, Self::Err> {
884 match s {
885 "Ctx8" => Ok(BuiltinAlias::Ctx8),
886 "Pubkey" => Ok(BuiltinAlias::Pubkey),
887 "Message" => Ok(BuiltinAlias::Message),
888 "Message64" => Ok(BuiltinAlias::Message64),
889 "Signature" => Ok(BuiltinAlias::Signature),
890 "Scalar" => Ok(BuiltinAlias::Scalar),
891 "Fe" => Ok(BuiltinAlias::Fe),
892 "Ge" => Ok(BuiltinAlias::Ge),
893 "Gej" => Ok(BuiltinAlias::Gej),
894 "Point" => Ok(BuiltinAlias::Point),
895 "Height" => Ok(BuiltinAlias::Height),
896 "Time" => Ok(BuiltinAlias::Time),
897 "Distance" => Ok(BuiltinAlias::Distance),
898 "Duration" => Ok(BuiltinAlias::Duration),
899 "Lock" => Ok(BuiltinAlias::Lock),
900 "Outpoint" => Ok(BuiltinAlias::Outpoint),
901 "Confidential1" => Ok(BuiltinAlias::Confidential1),
902 "ExplicitAsset" => Ok(BuiltinAlias::ExplicitAsset),
903 "Asset1" => Ok(BuiltinAlias::Asset1),
904 "ExplicitAmount" => Ok(BuiltinAlias::ExplicitAmount),
905 "Amount1" => Ok(BuiltinAlias::Amount1),
906 "ExplicitNonce" => Ok(BuiltinAlias::ExplicitNonce),
907 "Nonce" => Ok(BuiltinAlias::Nonce),
908 "TokenAmount1" => Ok(BuiltinAlias::TokenAmount1),
909 _ => Err("Unknown alias".to_string()),
910 }
911 }
912}
913
914#[derive(Clone, PartialEq, Eq, Hash)]
917pub struct StructuralType(Arc<Final>);
918
919impl AsRef<Final> for StructuralType {
920 fn as_ref(&self) -> &Final {
921 &self.0
922 }
923}
924
925impl From<StructuralType> for Arc<Final> {
926 fn from(value: StructuralType) -> Self {
927 value.0
928 }
929}
930
931impl From<Arc<Final>> for StructuralType {
932 fn from(value: Arc<Final>) -> Self {
933 Self(value)
934 }
935}
936
937impl TreeLike for StructuralType {
938 fn as_node(&self) -> Tree<Self> {
939 match self.0.bound() {
940 CompleteBound::Unit => Tree::Nullary,
941 CompleteBound::Sum(l, r) | CompleteBound::Product(l, r) => {
942 Tree::Binary(Self(l.clone()), Self(r.clone()))
943 }
944 }
945 }
946}
947
948impl fmt::Debug for StructuralType {
949 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
950 write!(f, "{}", &self.0)
951 }
952}
953
954impl fmt::Display for StructuralType {
955 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
956 write!(f, "{}", &self.0)
957 }
958}
959
960impl From<UIntType> for StructuralType {
961 fn from(value: UIntType) -> Self {
962 let inner = match value {
963 UIntType::U1 => Final::two_two_n(0),
964 UIntType::U2 => Final::two_two_n(1),
965 UIntType::U4 => Final::two_two_n(2),
966 UIntType::U8 => Final::two_two_n(3),
967 UIntType::U16 => Final::two_two_n(4),
968 UIntType::U32 => Final::two_two_n(5),
969 UIntType::U64 => Final::two_two_n(6),
970 UIntType::U128 => Final::two_two_n(7),
971 UIntType::U256 => Final::two_two_n(8),
972 };
973 Self(inner)
974 }
975}
976
977impl From<&ResolvedType> for StructuralType {
978 fn from(value: &ResolvedType) -> Self {
979 let mut output = vec![];
980 for data in value.post_order_iter() {
981 match &data.node.0 {
982 TypeInner::Either(_, _) => {
983 let right = output.pop().unwrap();
984 let left = output.pop().unwrap();
985 output.push(StructuralType::either(left, right));
986 }
987 TypeInner::Option(_) => {
988 let inner = output.pop().unwrap();
989 output.push(StructuralType::option(inner));
990 }
991 TypeInner::Boolean => output.push(StructuralType::boolean()),
992 TypeInner::UInt(integer) => output.push(StructuralType::from(*integer)),
993 TypeInner::Tuple(_) => {
994 let size = data.node.n_children();
995 let elements = output.split_off(output.len() - size);
996 debug_assert_eq!(elements.len(), size);
997 output.push(StructuralType::tuple(elements));
998 }
999 TypeInner::Array(_, size) => {
1000 let element = output.pop().unwrap();
1001 output.push(StructuralType::array(element, *size));
1002 }
1003 TypeInner::List(_, bound) => {
1004 let element = output.pop().unwrap();
1005 output.push(StructuralType::list(element, *bound));
1006 }
1007 }
1008 }
1009 debug_assert_eq!(output.len(), 1);
1010 output.pop().unwrap()
1011 }
1012}
1013
1014impl TypeConstructible for StructuralType {
1015 fn either(left: Self, right: Self) -> Self {
1016 Self(Final::sum(left.0, right.0))
1017 }
1018
1019 fn option(inner: Self) -> Self {
1020 Self::either(Self::unit(), inner)
1021 }
1022
1023 fn boolean() -> Self {
1024 Self::either(Self::unit(), Self::unit())
1025 }
1026
1027 fn tuple<I: IntoIterator<Item = Self>>(elements: I) -> Self {
1028 let elements: Vec<_> = elements.into_iter().collect();
1029 let tree = BTreeSlice::from_slice(&elements);
1030 tree.fold(Self::product).unwrap_or_else(Self::unit)
1031 }
1032
1033 fn unit() -> Self {
1035 Self(Final::unit())
1036 }
1037
1038 fn product(left: Self, right: Self) -> Self {
1040 Self(Final::product(left.0, right.0))
1041 }
1042
1043 fn array(element: Self, size: usize) -> Self {
1044 let elements = vec![element; size];
1046 let tree = BTreeSlice::from_slice(&elements);
1047 tree.fold(Self::product).unwrap_or_else(Self::unit)
1048 }
1049
1050 fn list(element: Self, bound: NonZeroPow2Usize) -> Self {
1051 let el_vector = vec![element.0; bound.get() - 1];
1053 let partition = Partition::from_slice(&el_vector, bound);
1054 debug_assert!(partition.is_complete());
1055 let process = |block: &[Arc<Final>], size: usize| -> Arc<Final> {
1056 debug_assert_eq!(block.len(), size);
1057 let tree = BTreeSlice::from_slice(block);
1058 let array = tree.fold(Final::product).unwrap();
1059 Final::sum(Final::unit(), array)
1060 };
1061 let inner = partition.fold(process, Final::product);
1062 Self(inner)
1063 }
1064}
1065
1066impl StructuralType {
1067 pub fn to_unfinalized(
1069 &self,
1070 inference_context: &simplicity::types::Context,
1071 ) -> simplicity::types::Type {
1072 simplicity::types::Type::complete(inference_context, self.0.clone())
1073 }
1074}
1075
1076#[cfg(test)]
1077mod tests {
1078 use super::*;
1079
1080 #[test]
1081 fn display_type() {
1082 let unit = ResolvedType::unit();
1083 assert_eq!("()", &unit.to_string());
1084 let singleton = ResolvedType::tuple([ResolvedType::u1()]);
1085 assert_eq!("(u1,)", &singleton.to_string());
1086 let pair = ResolvedType::tuple([ResolvedType::u1(), ResolvedType::u8()]);
1087 assert_eq!("(u1, u8)", &pair.to_string());
1088 let triple =
1089 ResolvedType::tuple([ResolvedType::u1(), ResolvedType::u8(), ResolvedType::u16()]);
1090 assert_eq!("(u1, u8, u16)", &triple.to_string());
1091 let empty_array = ResolvedType::array(ResolvedType::unit(), 0);
1092 assert_eq!("[(); 0]", &empty_array.to_string());
1093 let array = ResolvedType::array(ResolvedType::unit(), 3);
1094 assert_eq!("[(); 3]", &array.to_string());
1095 let list = ResolvedType::list(ResolvedType::unit(), NonZeroPow2Usize::TWO);
1096 assert_eq!("List<(), 2>", &list.to_string());
1097 }
1098}