wright/ast/
ty.rs

1//! AST models for type signatures in wright source.
2
3use crate::{ast::path::Path, source_tracking::fragment::Fragment};
4
5/// A type signature in source code.
6#[derive(Debug)]
7#[allow(missing_docs)]
8pub enum Type {
9    Atomic(AtomicTy),
10    Reference(ReferenceTy),
11    Constrained(ConstrainedTy),
12}
13
14impl Type {
15    /// Get the matching source for this type signature in source code.
16    pub fn matching_source(&self) -> &Fragment {
17        match self {
18            Type::Atomic(atomic_ty) => &atomic_ty.matching_source,
19            Type::Reference(reference_ty) => &reference_ty.matching_source,
20            Type::Constrained(constrained_ty) => &constrained_ty.matching_source,
21        }
22    }
23
24    /// Attempt to "downcast" this to an atomic type signature if it is one.
25    pub fn downcast_primitive(&self) -> Option<&AtomicTy> {
26        match self {
27            Type::Atomic(atomic) => Some(atomic),
28            _ => None,
29        }
30    }
31
32    /// Attempt to "downcast" this to a reference type signature if it is one.
33    pub fn downcast_reference(&self) -> Option<&ReferenceTy> {
34        match self {
35            Type::Reference(reference) => Some(reference),
36            _ => None,
37        }
38    }
39
40    /// Attempt to "downcast" this to a constrained type signature if it is one.
41    pub fn downcast_constrained_ty(&self) -> Option<&ConstrainedTy> {
42        match self {
43            Type::Constrained(constrained) => Some(constrained),
44            _ => None,
45        }
46    }
47}
48
49/// The atomic types of wright -- primitive numeric types, boolean, char, etc.
50#[derive(Clone, Copy, Debug, PartialEq, Eq)]
51#[allow(missing_docs)]
52pub enum AtomicTyVariant {
53    Bool,
54    U8,
55    I8,
56    U16,
57    I16,
58    U32,
59    I32,
60    U64,
61    I64,
62    F32,
63    F64,
64    Char,
65}
66
67/// An atomic type signature in wright source code.
68#[derive(Debug)]
69#[allow(missing_docs)]
70pub struct AtomicTy {
71    pub variant: AtomicTyVariant,
72    pub matching_source: Fragment,
73}
74
75/// Source code for a reference type signature, such as `@u64`.
76#[derive(Debug)]
77pub struct ReferenceTy {
78    /// The source code of the target type.
79    pub target_ty: Box<Type>,
80    /// The fragment of the whole reference.
81    pub matching_source: Fragment,
82}
83
84/// A type with a given set of constraints.
85///
86/// Constraints in wright are functions that the compiler can verify are strictly [pure]
87/// (which is informally defined here, and a point of further work eventually).
88///
89/// A constrained type declaration lists a base type and then one or more "strictly pure"
90/// functions that have a signature exactly matching T -> bool (where T is the constrained type).
91///
92/// An example of this could be
93/// ```text
94/// pure func is_even(i: u8) -> bool {
95///     i % 2 == 0
96/// }
97///
98/// type EvenU8 = u8 constrain is_even;
99/// ```
100///
101/// The wright compiler can then optimize agressively around these constraints later on (I hope).
102///
103/// [pure]: https://en.wikipedia.org/w/index.php?title=Pure_function&oldid=1291437073
104#[derive(Debug)]
105pub struct ConstrainedTy {
106    /// The entire type signature from the beginning of the base type
107    /// to the end of the last constraining item.
108    pub matching_source: Fragment,
109
110    /// The type being constrained.
111    pub base_ty: Box<Type>,
112
113    /// The functions constraining it.
114    pub constraining_items: Vec<Path>,
115}