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, Identifier};
11use crate::unstable::impl_require_feature;
12
13#[derive(Debug, PartialEq, Eq, Hash, Clone)]
15#[non_exhaustive]
16pub enum TypeInner<A> {
17 Either(A, A),
19 Option(A),
21 Boolean,
23 UInt(UIntType),
25 Tuple(Arc<[A]>),
27 Array(A, usize),
29 List(A, NonZeroPow2Usize),
31 Enum(EnumInfo),
34}
35
36#[derive(Debug, PartialEq, Eq, Hash, Clone)]
41pub struct EnumVariantInfo {
42 name: Identifier,
43 payload: Arc<[ResolvedType]>,
44 payload_ty: ResolvedType,
48}
49
50impl EnumVariantInfo {
51 pub(crate) fn new(name: Identifier, payload: Arc<[ResolvedType]>) -> Self {
52 let payload_ty = match payload.len() {
53 0 => ResolvedType::unit(),
54 1 => payload[0].clone(),
55 _ => ResolvedType::tuple(payload.iter().cloned()),
56 };
57 Self {
58 name,
59 payload,
60 payload_ty,
61 }
62 }
63
64 pub const fn name(&self) -> &Identifier {
66 &self.name
67 }
68
69 pub fn payload(&self) -> &[ResolvedType] {
72 &self.payload
73 }
74
75 pub fn payload_type(&self) -> &ResolvedType {
77 &self.payload_ty
78 }
79
80 pub(crate) fn structural_payload(&self) -> StructuralType {
83 StructuralType::from(&self.payload_ty)
84 }
85}
86
87#[derive(Debug, PartialEq, Eq, Hash, Clone)]
100pub struct EnumInfo {
101 name: Arc<str>,
102 variants: Arc<[EnumVariantInfo]>,
103}
104
105impl EnumInfo {
106 pub(crate) fn new(name: Arc<str>, variants: Arc<[EnumVariantInfo]>) -> Self {
112 debug_assert!(!variants.is_empty());
113 Self { name, variants }
114 }
115
116 pub fn name(&self) -> &str {
118 &self.name
119 }
120
121 pub fn variants(&self) -> &[EnumVariantInfo] {
123 &self.variants
124 }
125
126 pub fn variant(&self, name: &Identifier) -> Option<(usize, &EnumVariantInfo)> {
131 self.variants
132 .iter()
133 .enumerate()
134 .find(|(_, v)| v.name() == name)
135 }
136
137 pub(crate) fn structural_variants(&self) -> Vec<StructuralType> {
140 self.variants
141 .iter()
142 .map(EnumVariantInfo::structural_payload)
143 .collect()
144 }
145}
146
147impl<A> TypeInner<A> {
148 fn display(&self, f: &mut fmt::Formatter<'_>, n_children_yielded: usize) -> fmt::Result {
152 match self {
153 TypeInner::Either(_, _) => match n_children_yielded {
154 0 => f.write_str("Either<"),
155 1 => f.write_str(", "),
156 n => {
157 debug_assert_eq!(n, 2);
158 f.write_str(">")
159 }
160 },
161 TypeInner::Option(_) => match n_children_yielded {
162 0 => f.write_str("Option<"),
163 n => {
164 debug_assert_eq!(n, 1);
165 f.write_str(">")
166 }
167 },
168 TypeInner::Boolean => f.write_str("bool"),
169 TypeInner::UInt(ty) => write!(f, "{ty}"),
170 TypeInner::Tuple(elements) => match n_children_yielded {
171 0 => {
172 f.write_str("(")?;
173 if elements.is_empty() {
174 f.write_str(")")?;
175 }
176 Ok(())
177 }
178 n if n == elements.len() => {
179 if n == 1 {
180 f.write_str(",")?;
181 }
182 f.write_str(")")
183 }
184 n => {
185 debug_assert!(n < elements.len());
186 f.write_str(", ")
187 }
188 },
189 TypeInner::Array(_, size) => match n_children_yielded {
190 0 => f.write_str("["),
191 n => {
192 debug_assert_eq!(n, 1);
193 write!(f, "; {size}]")
194 }
195 },
196 TypeInner::List(_, bound) => match n_children_yielded {
197 0 => f.write_str("List<"),
198 n => {
199 debug_assert_eq!(n, 1);
200 write!(f, ", {bound}>")
201 }
202 },
203 TypeInner::Enum(info) => write!(f, "{}", info.name()),
204 }
205 }
206}
207
208#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
210#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
211pub enum UIntType {
212 U1,
214 U2,
216 U4,
218 U8,
220 U16,
222 U32,
224 U64,
226 U128,
228 U256,
230}
231
232impl UIntType {
233 pub const fn two_n(n: u32) -> Option<Self> {
235 match n {
236 0 => Some(UIntType::U1),
237 1 => Some(UIntType::U2),
238 2 => Some(UIntType::U4),
239 3 => Some(UIntType::U8),
240 4 => Some(UIntType::U16),
241 5 => Some(UIntType::U32),
242 6 => Some(UIntType::U64),
243 7 => Some(UIntType::U128),
244 8 => Some(UIntType::U256),
245 _ => None,
246 }
247 }
248
249 pub const fn bit_width(self) -> Pow2Usize {
251 let bit_width: usize = match self {
252 UIntType::U1 => 1,
253 UIntType::U2 => 2,
254 UIntType::U4 => 4,
255 UIntType::U8 => 8,
256 UIntType::U16 => 16,
257 UIntType::U32 => 32,
258 UIntType::U64 => 64,
259 UIntType::U128 => 128,
260 UIntType::U256 => 256,
261 };
262 debug_assert!(bit_width.is_power_of_two());
263 Pow2Usize::new_unchecked(bit_width)
264 }
265
266 pub const fn from_bit_width(bit_width: Pow2Usize) -> Option<Self> {
268 match bit_width.get() {
269 1 => Some(UIntType::U1),
270 2 => Some(UIntType::U2),
271 4 => Some(UIntType::U4),
272 8 => Some(UIntType::U8),
273 16 => Some(UIntType::U16),
274 32 => Some(UIntType::U32),
275 64 => Some(UIntType::U64),
276 128 => Some(UIntType::U128),
277 256 => Some(UIntType::U256),
278 _ => None,
279 }
280 }
281
282 pub const fn byte_width(self) -> usize {
286 self.bit_width().get() / 8
287 }
288}
289
290impl fmt::Debug for UIntType {
291 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
292 write!(f, "{}", self)
293 }
294}
295
296impl fmt::Display for UIntType {
297 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
298 match self {
299 UIntType::U1 => f.write_str("u1"),
300 UIntType::U2 => f.write_str("u2"),
301 UIntType::U4 => f.write_str("u4"),
302 UIntType::U8 => f.write_str("u8"),
303 UIntType::U16 => f.write_str("u16"),
304 UIntType::U32 => f.write_str("u32"),
305 UIntType::U64 => f.write_str("u64"),
306 UIntType::U128 => f.write_str("u128"),
307 UIntType::U256 => f.write_str("u256"),
308 }
309 }
310}
311
312impl FromStr for UIntType {
313 type Err = String;
314
315 fn from_str(s: &str) -> Result<Self, Self::Err> {
316 match s {
317 "u1" => Ok(UIntType::U1),
318 "u2" => Ok(UIntType::U2),
319 "u4" => Ok(UIntType::U4),
320 "u8" => Ok(UIntType::U8),
321 "u16" => Ok(UIntType::U16),
322 "u32" => Ok(UIntType::U32),
323 "u64" => Ok(UIntType::U64),
324 "u128" => Ok(UIntType::U128),
325 "u256" => Ok(UIntType::U256),
326 _ => Err("Unknown integer type".to_string()),
327 }
328 }
329}
330
331impl TryFrom<&StructuralType> for UIntType {
332 type Error = ();
333
334 fn try_from(value: &StructuralType) -> Result<Self, Self::Error> {
335 let mut current = value.as_ref();
336 let mut n = 0;
337 while let Some((left, right)) = current.as_product() {
338 if left.tmr() != right.tmr() {
339 return Err(());
340 }
341 current = left;
342 n += 1;
343 }
344 if let Some((left, right)) = current.as_sum() {
345 if left.is_unit() && right.is_unit() {
346 return UIntType::two_n(n).ok_or(());
347 }
348 }
349 Err(())
350 }
351}
352
353impl TryFrom<&ResolvedType> for UIntType {
354 type Error = ();
355
356 fn try_from(value: &ResolvedType) -> Result<Self, Self::Error> {
357 UIntType::try_from(&StructuralType::from(value))
358 }
359}
360
361macro_rules! construct_int {
362 ($name: ident, $ty: ident, $text: expr) => {
363 #[doc = "Create the type of"]
364 #[doc = $text]
365 #[doc = "integers."]
366 fn $name() -> Self {
367 Self::from(UIntType::$ty)
368 }
369 };
370}
371
372pub trait TypeConstructible: Sized + From<UIntType> {
374 fn either(left: Self, right: Self) -> Self;
376
377 fn option(inner: Self) -> Self;
379
380 fn boolean() -> Self;
382
383 fn tuple<I: IntoIterator<Item = Self>>(elements: I) -> Self;
388
389 fn unit() -> Self {
391 Self::tuple([])
392 }
393
394 fn product(left: Self, right: Self) -> Self {
396 Self::tuple([left, right])
397 }
398
399 fn array(element: Self, size: usize) -> Self;
401
402 fn byte_array(size: usize) -> Self {
404 Self::array(Self::u8(), size)
405 }
406
407 fn list(element: Self, bound: NonZeroPow2Usize) -> Self;
409
410 construct_int!(u1, U1, "1-bit");
411 construct_int!(u2, U2, "2-bit");
412 construct_int!(u4, U4, "4-bit");
413 construct_int!(u8, U8, "8-bit");
414 construct_int!(u16, U16, "16-bit");
415 construct_int!(u32, U32, "32-bit");
416 construct_int!(u64, U64, "64-bit");
417 construct_int!(u128, U128, "128-bit");
418 construct_int!(u256, U256, "256-bit");
419}
420
421pub trait TypeDeconstructible: Sized {
426 fn as_either(&self) -> Option<(&Self, &Self)>;
428
429 fn as_option(&self) -> Option<&Self>;
431
432 fn is_boolean(&self) -> bool;
434
435 fn as_integer(&self) -> Option<UIntType>;
437
438 fn as_tuple(&self) -> Option<&[Arc<Self>]>;
440
441 fn is_unit(&self) -> bool {
443 matches!(self.as_tuple(), Some(components) if components.is_empty())
444 }
445
446 fn as_array(&self) -> Option<(&Self, usize)>;
448
449 fn as_list(&self) -> Option<(&Self, NonZeroPow2Usize)>;
451}
452
453#[derive(PartialEq, Eq, Hash, Clone)]
455pub struct ResolvedType(TypeInner<Arc<Self>>);
456
457impl ResolvedType {
458 pub fn as_inner(&self) -> &TypeInner<Arc<Self>> {
460 &self.0
461 }
462}
463
464impl ResolvedType {
475 pub const fn enumeration(info: EnumInfo) -> Self {
477 Self(TypeInner::Enum(info))
478 }
479
480 pub const fn as_enum(&self) -> Option<&EnumInfo> {
482 match &self.0 {
483 TypeInner::Enum(info) => Some(info),
484 _ => None,
485 }
486 }
487
488 pub fn contains_enum(&self) -> bool {
490 self.post_order_iter()
491 .any(|data| data.node.as_enum().is_some())
492 }
493}
494
495impl TypeConstructible for ResolvedType {
496 fn either(left: Self, right: Self) -> Self {
497 Self(TypeInner::Either(Arc::new(left), Arc::new(right)))
498 }
499
500 fn option(inner: Self) -> Self {
501 Self(TypeInner::Option(Arc::new(inner)))
502 }
503
504 fn boolean() -> Self {
505 Self(TypeInner::Boolean)
506 }
507
508 fn tuple<I: IntoIterator<Item = Self>>(elements: I) -> Self {
509 Self(TypeInner::Tuple(
510 elements.into_iter().map(Arc::new).collect(),
511 ))
512 }
513
514 fn array(element: Self, size: usize) -> Self {
515 Self(TypeInner::Array(Arc::new(element), size))
516 }
517
518 fn list(element: Self, bound: NonZeroPow2Usize) -> Self {
519 Self(TypeInner::List(Arc::new(element), bound))
520 }
521}
522
523impl TypeDeconstructible for ResolvedType {
524 fn as_either(&self) -> Option<(&Self, &Self)> {
525 match self.as_inner() {
526 TypeInner::Either(ty_l, ty_r) => Some((ty_l, ty_r)),
527 _ => None,
528 }
529 }
530
531 fn as_option(&self) -> Option<&Self> {
532 match self.as_inner() {
533 TypeInner::Option(ty) => Some(ty),
534 _ => None,
535 }
536 }
537
538 fn is_boolean(&self) -> bool {
539 matches!(self.as_inner(), TypeInner::Boolean)
540 }
541
542 fn as_integer(&self) -> Option<UIntType> {
543 match self.as_inner() {
544 TypeInner::UInt(ty) => Some(*ty),
545 _ => None,
546 }
547 }
548
549 fn as_tuple(&self) -> Option<&[Arc<Self>]> {
550 match self.as_inner() {
551 TypeInner::Tuple(components) => Some(components),
552 _ => None,
553 }
554 }
555
556 fn as_array(&self) -> Option<(&Self, usize)> {
557 match self.as_inner() {
558 TypeInner::Array(ty, size) => Some((ty, *size)),
559 _ => None,
560 }
561 }
562
563 fn as_list(&self) -> Option<(&Self, NonZeroPow2Usize)> {
564 match self.as_inner() {
565 TypeInner::List(ty, bound) => Some((ty, *bound)),
566 _ => None,
567 }
568 }
569}
570
571impl TreeLike for &ResolvedType {
572 fn as_node(&self) -> Tree<Self> {
573 match &self.0 {
574 TypeInner::Boolean | TypeInner::UInt(..) | TypeInner::Enum(..) => Tree::Nullary,
575 TypeInner::Option(l) | TypeInner::Array(l, _) | TypeInner::List(l, _) => Tree::Unary(l),
576 TypeInner::Either(l, r) => Tree::Binary(l, r),
577 TypeInner::Tuple(elements) => Tree::Nary(elements.iter().map(Arc::as_ref).collect()),
578 }
579 }
580}
581
582impl fmt::Debug for ResolvedType {
583 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
584 write!(f, "{}", self)
585 }
586}
587
588impl fmt::Display for ResolvedType {
589 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
590 for data in self.verbose_pre_order_iter() {
591 data.node.0.display(f, data.n_children_yielded)?;
592 }
593 Ok(())
594 }
595}
596
597impl From<UIntType> for ResolvedType {
598 fn from(value: UIntType) -> Self {
599 Self(TypeInner::UInt(value))
600 }
601}
602
603#[cfg(feature = "arbitrary")]
604impl crate::ArbitraryRec for ResolvedType {
605 fn arbitrary_rec(u: &mut arbitrary::Unstructured, budget: usize) -> arbitrary::Result<Self> {
610 use arbitrary::Arbitrary;
611
612 match budget.checked_sub(1) {
613 None => match u.int_in_range(0..=1)? {
614 0 => Ok(Self::boolean()),
615 1 => UIntType::arbitrary(u).map(Self::from),
616 _ => unreachable!(),
617 },
618 Some(new_budget) => match u.int_in_range(0..=6)? {
619 0 => Ok(Self::boolean()),
620 1 => UIntType::arbitrary(u).map(Self::from),
621 2 => Self::arbitrary_rec(u, new_budget).map(Self::option),
622 3 => {
623 let left = Self::arbitrary_rec(u, new_budget)?;
624 let right = Self::arbitrary_rec(u, new_budget)?;
625 Ok(Self::either(left, right))
626 }
627 4 => {
628 let len = u.int_in_range(0..=3)?;
629 (0..len)
630 .map(|_| Self::arbitrary_rec(u, new_budget))
631 .collect::<arbitrary::Result<Vec<Self>>>()
632 .map(Self::tuple)
633 }
634 5 => {
635 let element = Self::arbitrary_rec(u, new_budget)?;
636 let size = u.int_in_range(0..=3)?;
637 Ok(Self::array(element, size))
638 }
639 6 => {
640 let element = Self::arbitrary_rec(u, new_budget)?;
641 let exp = u.int_in_range(1u32..=4)?;
642 let bound = NonZeroPow2Usize::new_unchecked(2usize.saturating_pow(exp));
643 Ok(Self::list(element, bound))
644 }
645 _ => unreachable!(),
646 },
647 }
648 }
649}
650
651#[cfg(feature = "arbitrary")]
652impl<'a> arbitrary::Arbitrary<'a> for ResolvedType {
653 fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
654 <Self as crate::ArbitraryRec>::arbitrary_rec(u, 3)
655 }
656}
657
658#[derive(PartialEq, Eq, Hash, Clone)]
660pub struct AliasedType(AliasedInner);
661
662#[derive(Debug, PartialEq, Eq, Hash, Clone)]
666enum AliasedInner {
667 Alias(AliasName),
669 Builtin(BuiltinAlias),
671 Inner(TypeInner<Arc<AliasedType>>),
673}
674
675#[derive(Copy, Clone, PartialEq, Eq, Hash)]
677#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
678pub enum BuiltinAlias {
679 Ctx8,
680 Pubkey,
681 Message,
682 Message64,
683 Signature,
684 Scalar,
685 Fe,
686 Ge,
687 Gej,
688 Point,
689 Height,
690 Time,
691 Distance,
692 Duration,
693 Lock,
694 Outpoint,
695 Confidential1,
696 ExplicitAsset,
697 Asset1,
698 ExplicitAmount,
699 Amount1,
700 ExplicitNonce,
701 Nonce,
702 TokenAmount1,
703}
704
705impl AliasedType {
706 pub const fn as_alias(&self) -> Option<&AliasName> {
708 match &self.0 {
709 AliasedInner::Alias(name) => Some(name),
710 _ => None,
711 }
712 }
713
714 pub const fn as_builtin(&self) -> Option<&BuiltinAlias> {
716 match &self.0 {
717 AliasedInner::Builtin(builtin) => Some(builtin),
718 _ => None,
719 }
720 }
721
722 pub const fn alias(name: AliasName) -> Self {
724 Self(AliasedInner::Alias(name))
725 }
726
727 pub const fn builtin(builtin: BuiltinAlias) -> Self {
729 Self(AliasedInner::Builtin(builtin))
730 }
731
732 pub fn resolve<F, E>(&self, mut get_alias: F) -> Result<ResolvedType, E>
734 where
735 F: FnMut(&AliasName) -> Result<ResolvedType, E>,
736 {
737 let mut output = vec![];
738 for data in self.post_order_iter() {
739 match &data.node.0 {
740 AliasedInner::Alias(name) => {
741 let resolved = get_alias(name)?;
742 output.push(resolved);
743 }
744 AliasedInner::Builtin(builtin) => {
745 let resolved = builtin.resolve();
746 output.push(resolved);
747 }
748 AliasedInner::Inner(inner) => match inner {
749 TypeInner::Either(_, _) => {
750 let right = output.pop().unwrap();
751 let left = output.pop().unwrap();
752 output.push(ResolvedType::either(left, right));
753 }
754 TypeInner::Option(_) => {
755 let inner = output.pop().unwrap();
756 output.push(ResolvedType::option(inner));
757 }
758 TypeInner::Boolean => output.push(ResolvedType::boolean()),
759 TypeInner::UInt(integer) => output.push(ResolvedType::from(*integer)),
760 TypeInner::Tuple(_) => {
761 let size = data.node.n_children();
762 let elements = output.split_off(output.len() - size);
763 debug_assert_eq!(elements.len(), size);
764 output.push(ResolvedType::tuple(elements));
765 }
766 TypeInner::Array(_, size) => {
767 let element = output.pop().unwrap();
768 output.push(ResolvedType::array(element, *size));
769 }
770 TypeInner::List(_, bound) => {
771 let element = output.pop().unwrap();
772 output.push(ResolvedType::list(element, *bound));
773 }
774 TypeInner::Enum(info) => {
776 output.push(ResolvedType::enumeration(info.clone()));
777 }
778 },
779 }
780 }
781 debug_assert_eq!(output.len(), 1);
782 Ok(output.pop().unwrap())
783 }
784
785 pub fn resolve_builtin(&self) -> Result<ResolvedType, AliasName> {
787 self.resolve(|name: &AliasName| Err(name.clone()))
788 }
789}
790
791impl_require_feature!(AliasedType {
792 recurse: 0;
793});
794
795impl_require_feature!(AliasedInner {
796 variants:
797 Alias(_),
798 Builtin(_),
799 Inner(inner),
800});
801
802impl_require_feature!(TypeInner<Arc<AliasedType>> {
803 variants:
804 Either(left, right),
805 Option(element),
806 Boolean,
807 UInt(_),
808 Tuple(elements),
809 Array(element, _),
810 List(element, _),
811 Enum(_),
812});
813
814impl TypeConstructible for AliasedType {
815 fn either(left: Self, right: Self) -> Self {
816 Self(AliasedInner::Inner(TypeInner::Either(
817 Arc::new(left),
818 Arc::new(right),
819 )))
820 }
821
822 fn option(inner: Self) -> Self {
823 Self(AliasedInner::Inner(TypeInner::Option(Arc::new(inner))))
824 }
825
826 fn boolean() -> Self {
827 Self(AliasedInner::Inner(TypeInner::Boolean))
828 }
829
830 fn tuple<I: IntoIterator<Item = Self>>(elements: I) -> Self {
831 Self(AliasedInner::Inner(TypeInner::Tuple(
832 elements.into_iter().map(Arc::new).collect(),
833 )))
834 }
835
836 fn array(element: Self, size: usize) -> Self {
837 Self(AliasedInner::Inner(TypeInner::Array(
838 Arc::new(element),
839 size,
840 )))
841 }
842
843 fn list(element: Self, bound: NonZeroPow2Usize) -> Self {
844 Self(AliasedInner::Inner(TypeInner::List(
845 Arc::new(element),
846 bound,
847 )))
848 }
849}
850
851impl TypeDeconstructible for AliasedType {
852 fn as_either(&self) -> Option<(&Self, &Self)> {
853 match &self.0 {
854 AliasedInner::Inner(TypeInner::Either(ty_l, ty_r)) => Some((ty_l, ty_r)),
855 _ => None,
856 }
857 }
858
859 fn as_option(&self) -> Option<&Self> {
860 match &self.0 {
861 AliasedInner::Inner(TypeInner::Option(ty)) => Some(ty),
862 _ => None,
863 }
864 }
865
866 fn is_boolean(&self) -> bool {
867 matches!(&self.0, AliasedInner::Inner(TypeInner::Boolean))
868 }
869
870 fn as_integer(&self) -> Option<UIntType> {
871 match &self.0 {
872 AliasedInner::Inner(TypeInner::UInt(ty)) => Some(*ty),
873 _ => None,
874 }
875 }
876
877 fn as_tuple(&self) -> Option<&[Arc<Self>]> {
878 match &self.0 {
879 AliasedInner::Inner(TypeInner::Tuple(components)) => Some(components),
880 _ => None,
881 }
882 }
883
884 fn as_array(&self) -> Option<(&Self, usize)> {
885 match &self.0 {
886 AliasedInner::Inner(TypeInner::Array(ty, size)) => Some((ty, *size)),
887 _ => None,
888 }
889 }
890
891 fn as_list(&self) -> Option<(&Self, NonZeroPow2Usize)> {
892 match &self.0 {
893 AliasedInner::Inner(TypeInner::List(ty, bound)) => Some((ty, *bound)),
894 _ => None,
895 }
896 }
897}
898
899impl TreeLike for &AliasedType {
900 fn as_node(&self) -> Tree<Self> {
901 match &self.0 {
902 AliasedInner::Alias(_) | AliasedInner::Builtin(_) => Tree::Nullary,
903 AliasedInner::Inner(inner) => match inner {
904 TypeInner::Boolean | TypeInner::UInt(..) | TypeInner::Enum(..) => Tree::Nullary,
905 TypeInner::Option(l) | TypeInner::Array(l, _) | TypeInner::List(l, _) => {
906 Tree::Unary(l)
907 }
908 TypeInner::Either(l, r) => Tree::Binary(l, r),
909 TypeInner::Tuple(elements) => {
910 Tree::Nary(elements.iter().map(Arc::as_ref).collect())
911 }
912 },
913 }
914 }
915}
916
917impl fmt::Debug for AliasedType {
918 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
919 write!(f, "{}", self)
920 }
921}
922
923impl fmt::Display for AliasedType {
924 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
925 for data in self.verbose_pre_order_iter() {
926 match &data.node.0 {
927 AliasedInner::Alias(alias) => write!(f, "{alias}")?,
928 AliasedInner::Builtin(builtin) => write!(f, "{builtin}")?,
929 AliasedInner::Inner(inner) => inner.display(f, data.n_children_yielded)?,
930 }
931 }
932 Ok(())
933 }
934}
935
936impl From<UIntType> for AliasedType {
937 fn from(value: UIntType) -> Self {
938 Self(AliasedInner::Inner(TypeInner::UInt(value)))
939 }
940}
941
942impl From<AliasName> for AliasedType {
943 fn from(value: AliasName) -> Self {
944 Self::alias(value)
945 }
946}
947
948impl From<BuiltinAlias> for AliasedType {
949 fn from(value: BuiltinAlias) -> Self {
950 Self::builtin(value)
951 }
952}
953
954#[cfg(feature = "arbitrary")]
955impl crate::ArbitraryRec for AliasedType {
956 fn arbitrary_rec(u: &mut arbitrary::Unstructured, budget: usize) -> arbitrary::Result<Self> {
957 use arbitrary::Arbitrary;
958
959 match budget.checked_sub(1) {
960 None => match u.int_in_range(0..=3)? {
961 0 => AliasName::arbitrary(u).map(Self::alias),
962 1 => BuiltinAlias::arbitrary(u).map(Self::builtin),
963 2 => Ok(Self::boolean()),
964 3 => UIntType::arbitrary(u).map(Self::from),
965 _ => unreachable!(),
966 },
967 Some(new_budget) => match u.int_in_range(0..=8)? {
968 0 => AliasName::arbitrary(u).map(Self::alias),
969 1 => BuiltinAlias::arbitrary(u).map(Self::builtin),
970 2 => Ok(Self::boolean()),
971 3 => UIntType::arbitrary(u).map(Self::from),
972 4 => Self::arbitrary_rec(u, new_budget).map(Self::option),
973 5 => {
974 let left = Self::arbitrary_rec(u, new_budget)?;
975 let right = Self::arbitrary_rec(u, new_budget)?;
976 Ok(Self::either(left, right))
977 }
978 6 => {
979 let len = u.int_in_range(0..=3)?;
980 (0..len)
981 .map(|_| Self::arbitrary_rec(u, new_budget))
982 .collect::<arbitrary::Result<Vec<Self>>>()
983 .map(Self::tuple)
984 }
985 7 => {
986 let element = Self::arbitrary_rec(u, new_budget)?;
987 let size = u.int_in_range(0..=3)?;
988 Ok(Self::array(element, size))
989 }
990 8 => {
991 let element = Self::arbitrary_rec(u, new_budget)?;
992 let bound = NonZeroPow2Usize::arbitrary(u)?;
993 Ok(Self::list(element, bound))
994 }
995 _ => unreachable!(),
996 },
997 }
998 }
999}
1000
1001#[cfg(feature = "arbitrary")]
1002impl<'a> arbitrary::Arbitrary<'a> for AliasedType {
1003 fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
1004 <Self as crate::ArbitraryRec>::arbitrary_rec(u, 3)
1005 }
1006}
1007
1008impl BuiltinAlias {
1009 pub fn resolve(self) -> ResolvedType {
1010 use BuiltinAlias as B;
1011 use UIntType::*;
1012
1013 match self {
1014 B::Ctx8 => ResolvedType::tuple([
1015 ResolvedType::list(U8.into(), NonZeroPow2Usize::new(64).unwrap()),
1016 ResolvedType::tuple([U64.into(), U256.into()]),
1017 ]),
1018 B::Pubkey | B::Message | B::Scalar | B::Fe | B::ExplicitAsset | B::ExplicitNonce => {
1019 U256.into()
1020 }
1021 B::Message64 | B::Signature => ResolvedType::array(U8.into(), 64),
1022 B::Ge => ResolvedType::tuple([U256.into(), U256.into()]),
1023 B::Gej => {
1024 ResolvedType::tuple([ResolvedType::tuple([U256.into(), U256.into()]), U256.into()])
1025 }
1026 B::Point | B::Confidential1 => ResolvedType::tuple([U1.into(), U256.into()]),
1027 B::Height | B::Time | B::Lock => U32.into(),
1028 B::Distance | B::Duration => U16.into(),
1029 B::Outpoint => ResolvedType::tuple([U256.into(), U32.into()]),
1030 B::Asset1 | B::Nonce => {
1031 ResolvedType::either(ResolvedType::tuple([U1.into(), U256.into()]), U256.into())
1032 }
1033 B::ExplicitAmount => U64.into(),
1034 B::Amount1 | B::TokenAmount1 => {
1035 ResolvedType::either(ResolvedType::tuple([U1.into(), U256.into()]), U64.into())
1036 }
1037 }
1038 }
1039}
1040
1041impl fmt::Debug for BuiltinAlias {
1042 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1043 write!(f, "{}", self)
1044 }
1045}
1046
1047impl fmt::Display for BuiltinAlias {
1048 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1049 match self {
1050 BuiltinAlias::Ctx8 => f.write_str("Ctx8"),
1051 BuiltinAlias::Pubkey => f.write_str("Pubkey"),
1052 BuiltinAlias::Message => f.write_str("Message"),
1053 BuiltinAlias::Message64 => f.write_str("Message64"),
1054 BuiltinAlias::Signature => f.write_str("Signature"),
1055 BuiltinAlias::Scalar => f.write_str("Scalar"),
1056 BuiltinAlias::Fe => f.write_str("Fe"),
1057 BuiltinAlias::Ge => f.write_str("Ge"),
1058 BuiltinAlias::Gej => f.write_str("Gej"),
1059 BuiltinAlias::Point => f.write_str("Point"),
1060 BuiltinAlias::Height => f.write_str("Height"),
1061 BuiltinAlias::Time => f.write_str("Time"),
1062 BuiltinAlias::Distance => f.write_str("Distance"),
1063 BuiltinAlias::Duration => f.write_str("Duration"),
1064 BuiltinAlias::Lock => f.write_str("Lock"),
1065 BuiltinAlias::Outpoint => f.write_str("Outpoint"),
1066 BuiltinAlias::Confidential1 => f.write_str("Confidential1"),
1067 BuiltinAlias::ExplicitAsset => f.write_str("ExplicitAsset"),
1068 BuiltinAlias::Asset1 => f.write_str("Asset1"),
1069 BuiltinAlias::ExplicitAmount => f.write_str("ExplicitAmount"),
1070 BuiltinAlias::Amount1 => f.write_str("Amount1"),
1071 BuiltinAlias::ExplicitNonce => f.write_str("ExplicitNonce"),
1072 BuiltinAlias::Nonce => f.write_str("Nonce"),
1073 BuiltinAlias::TokenAmount1 => f.write_str("TokenAmount1"),
1074 }
1075 }
1076}
1077
1078impl FromStr for BuiltinAlias {
1079 type Err = String;
1080
1081 fn from_str(s: &str) -> Result<Self, Self::Err> {
1082 match s {
1083 "Ctx8" => Ok(BuiltinAlias::Ctx8),
1084 "Pubkey" => Ok(BuiltinAlias::Pubkey),
1085 "Message" => Ok(BuiltinAlias::Message),
1086 "Message64" => Ok(BuiltinAlias::Message64),
1087 "Signature" => Ok(BuiltinAlias::Signature),
1088 "Scalar" => Ok(BuiltinAlias::Scalar),
1089 "Fe" => Ok(BuiltinAlias::Fe),
1090 "Ge" => Ok(BuiltinAlias::Ge),
1091 "Gej" => Ok(BuiltinAlias::Gej),
1092 "Point" => Ok(BuiltinAlias::Point),
1093 "Height" => Ok(BuiltinAlias::Height),
1094 "Time" => Ok(BuiltinAlias::Time),
1095 "Distance" => Ok(BuiltinAlias::Distance),
1096 "Duration" => Ok(BuiltinAlias::Duration),
1097 "Lock" => Ok(BuiltinAlias::Lock),
1098 "Outpoint" => Ok(BuiltinAlias::Outpoint),
1099 "Confidential1" => Ok(BuiltinAlias::Confidential1),
1100 "ExplicitAsset" => Ok(BuiltinAlias::ExplicitAsset),
1101 "Asset1" => Ok(BuiltinAlias::Asset1),
1102 "ExplicitAmount" => Ok(BuiltinAlias::ExplicitAmount),
1103 "Amount1" => Ok(BuiltinAlias::Amount1),
1104 "ExplicitNonce" => Ok(BuiltinAlias::ExplicitNonce),
1105 "Nonce" => Ok(BuiltinAlias::Nonce),
1106 "TokenAmount1" => Ok(BuiltinAlias::TokenAmount1),
1107 _ => Err("Unknown alias".to_string()),
1108 }
1109 }
1110}
1111
1112#[derive(Clone, PartialEq, Eq, Hash)]
1115pub struct StructuralType(Arc<Final>);
1116
1117impl AsRef<Final> for StructuralType {
1118 fn as_ref(&self) -> &Final {
1119 &self.0
1120 }
1121}
1122
1123impl From<StructuralType> for Arc<Final> {
1124 fn from(value: StructuralType) -> Self {
1125 value.0
1126 }
1127}
1128
1129impl From<Arc<Final>> for StructuralType {
1130 fn from(value: Arc<Final>) -> Self {
1131 Self(value)
1132 }
1133}
1134
1135impl TreeLike for StructuralType {
1136 fn as_node(&self) -> Tree<Self> {
1137 match self.0.bound() {
1138 CompleteBound::Unit => Tree::Nullary,
1139 CompleteBound::Sum(l, r) | CompleteBound::Product(l, r) => {
1140 Tree::Binary(Self(l.clone()), Self(r.clone()))
1141 }
1142 }
1143 }
1144}
1145
1146impl fmt::Debug for StructuralType {
1147 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1148 write!(f, "{}", self.0)
1149 }
1150}
1151
1152impl fmt::Display for StructuralType {
1153 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1154 write!(f, "{}", self.0)
1155 }
1156}
1157
1158impl From<UIntType> for StructuralType {
1159 fn from(value: UIntType) -> Self {
1160 let inner = match value {
1161 UIntType::U1 => Final::two_two_n(0),
1162 UIntType::U2 => Final::two_two_n(1),
1163 UIntType::U4 => Final::two_two_n(2),
1164 UIntType::U8 => Final::two_two_n(3),
1165 UIntType::U16 => Final::two_two_n(4),
1166 UIntType::U32 => Final::two_two_n(5),
1167 UIntType::U64 => Final::two_two_n(6),
1168 UIntType::U128 => Final::two_two_n(7),
1169 UIntType::U256 => Final::two_two_n(8),
1170 };
1171 Self(inner)
1172 }
1173}
1174
1175impl From<&ResolvedType> for StructuralType {
1176 fn from(value: &ResolvedType) -> Self {
1177 let mut output = vec![];
1178 for data in value.post_order_iter() {
1179 match &data.node.0 {
1180 TypeInner::Either(_, _) => {
1181 let right = output.pop().unwrap();
1182 let left = output.pop().unwrap();
1183 output.push(StructuralType::either(left, right));
1184 }
1185 TypeInner::Option(_) => {
1186 let inner = output.pop().unwrap();
1187 output.push(StructuralType::option(inner));
1188 }
1189 TypeInner::Boolean => output.push(StructuralType::boolean()),
1190 TypeInner::UInt(integer) => output.push(StructuralType::from(*integer)),
1191 TypeInner::Tuple(_) => {
1192 let size = data.node.n_children();
1193 let elements = output.split_off(output.len() - size);
1194 debug_assert_eq!(elements.len(), size);
1195 output.push(StructuralType::tuple(elements));
1196 }
1197 TypeInner::Array(_, size) => {
1198 let element = output.pop().unwrap();
1199 output.push(StructuralType::array(element, *size));
1200 }
1201 TypeInner::List(_, bound) => {
1202 let element = output.pop().unwrap();
1203 output.push(StructuralType::list(element, *bound));
1204 }
1205 TypeInner::Enum(info) => {
1206 output.push(StructuralType::balanced_sum(info.structural_variants()));
1207 }
1208 }
1209 }
1210 debug_assert_eq!(output.len(), 1);
1211 output.pop().unwrap()
1212 }
1213}
1214
1215impl TypeConstructible for StructuralType {
1216 fn either(left: Self, right: Self) -> Self {
1217 Self(Final::sum(left.0, right.0))
1218 }
1219
1220 fn option(inner: Self) -> Self {
1221 Self::either(Self::unit(), inner)
1222 }
1223
1224 fn boolean() -> Self {
1225 Self::either(Self::unit(), Self::unit())
1226 }
1227
1228 fn tuple<I: IntoIterator<Item = Self>>(elements: I) -> Self {
1229 let elements: Vec<_> = elements.into_iter().collect();
1230 let tree = BTreeSlice::from_slice(&elements);
1231 tree.fold(Self::product).unwrap_or_else(Self::unit)
1232 }
1233
1234 fn unit() -> Self {
1236 Self(Final::unit())
1237 }
1238
1239 fn product(left: Self, right: Self) -> Self {
1241 Self(Final::product(left.0, right.0))
1242 }
1243
1244 fn array(element: Self, size: usize) -> Self {
1245 let elements = vec![element; size];
1247 let tree = BTreeSlice::from_slice(&elements);
1248 tree.fold(Self::product).unwrap_or_else(Self::unit)
1249 }
1250
1251 fn list(element: Self, bound: NonZeroPow2Usize) -> Self {
1252 let el_vector = vec![element.0; bound.get() - 1];
1254 let partition = Partition::from_slice(&el_vector, bound);
1255 debug_assert!(partition.is_complete());
1256 let process = |block: &[Arc<Final>], size: usize| -> Arc<Final> {
1257 debug_assert_eq!(block.len(), size);
1258 let tree = BTreeSlice::from_slice(block);
1259 let array = tree.fold(Final::product).unwrap();
1260 Final::sum(Final::unit(), array)
1261 };
1262 let inner = partition.fold(process, Final::product);
1263 Self(inner)
1264 }
1265}
1266
1267impl StructuralType {
1268 pub(crate) fn balanced_sum(leaves: Vec<Self>) -> Self {
1279 BTreeSlice::from_slice(&leaves)
1280 .fold(Self::either)
1281 .expect("at least one leaf")
1282 }
1283
1284 pub fn to_unfinalized<'brand>(
1286 &self,
1287 inference_context: &simplicity::types::Context<'brand>,
1288 ) -> simplicity::types::Type<'brand> {
1289 simplicity::types::Type::complete(inference_context, self.0.clone())
1290 }
1291}
1292
1293#[cfg(test)]
1294mod tests {
1295 use super::*;
1296 use crate::str::Identifier;
1297
1298 #[test]
1299 fn display_type() {
1300 let unit = ResolvedType::unit();
1301 assert_eq!("()", &unit.to_string());
1302 let singleton = ResolvedType::tuple([ResolvedType::u1()]);
1303 assert_eq!("(u1,)", &singleton.to_string());
1304 let pair = ResolvedType::tuple([ResolvedType::u1(), ResolvedType::u8()]);
1305 assert_eq!("(u1, u8)", &pair.to_string());
1306 let triple =
1307 ResolvedType::tuple([ResolvedType::u1(), ResolvedType::u8(), ResolvedType::u16()]);
1308 assert_eq!("(u1, u8, u16)", &triple.to_string());
1309 let empty_array = ResolvedType::array(ResolvedType::unit(), 0);
1310 assert_eq!("[(); 0]", &empty_array.to_string());
1311 let array = ResolvedType::array(ResolvedType::unit(), 3);
1312 assert_eq!("[(); 3]", &array.to_string());
1313 let list = ResolvedType::list(ResolvedType::unit(), NonZeroPow2Usize::TWO);
1314 assert_eq!("List<(), 2>", &list.to_string());
1315 let either = ResolvedType::either(ResolvedType::unit(), ResolvedType::u32());
1316 assert_eq!("Either<(), u32>", &either.to_string());
1317 }
1318
1319 #[test]
1320 fn enum_variant_info_payload_types() {
1321 let unit = EnumVariantInfo::new(Identifier::from_str_unchecked("Unit"), Arc::from([]));
1322 assert_eq!(&ResolvedType::unit(), unit.payload_type());
1323
1324 let single = EnumVariantInfo::new(
1325 Identifier::from_str_unchecked("Single"),
1326 Arc::from([ResolvedType::boolean()]),
1327 );
1328 assert_eq!(&ResolvedType::boolean(), single.payload_type());
1329
1330 let pair = EnumVariantInfo::new(
1331 Identifier::from_str_unchecked("Pair"),
1332 Arc::from([ResolvedType::boolean(), ResolvedType::boolean()]),
1333 );
1334 assert_eq!(
1335 &ResolvedType::tuple([ResolvedType::boolean(), ResolvedType::boolean()]),
1336 pair.payload_type()
1337 );
1338
1339 let info = EnumInfo::new(Arc::from("Test"), Arc::from([unit, single, pair]));
1340 assert_eq!("Test", info.name());
1341 assert_eq!(3, info.structural_variants().len());
1342 let (index, variant) = info
1343 .variant(&Identifier::from_str_unchecked("Pair"))
1344 .expect("Pair is a declared variant");
1345 assert_eq!(2, index);
1346 assert_eq!("Pair", variant.name().as_inner());
1347 }
1348}