pulsar_frontend/
ty.rs

1// Copyright (C) 2024 Ethan Uppal. All rights reserved.
2use lazy_static::lazy_static;
3use pulsar_utils::{id::Id, mutcell::MutCell};
4use std::{fmt::Display, hash::Hash};
5
6lazy_static! {
7    pub static ref UNIT_TYPE_CELL: TypeCell = TypeCell::new(Type::Unit);
8    pub static ref INT64_TYPE_CELL: TypeCell = TypeCell::new(Type::Int64);
9}
10
11pub const ARRAY_TYPE_UNKNOWN_SIZE: isize = -1;
12
13#[derive(Clone, Hash, PartialEq, Eq, Debug)]
14pub enum Type {
15    Unknown,
16    Unit,
17    Var(Id),
18    Name(String),
19    Int64,
20
21    /// A negative size indicates that the size is not yet known.
22    Array(TypeCell, isize),
23
24    Function {
25        is_pure: bool,
26        args: Vec<Type>,
27        ret: Box<Type>
28    }
29}
30
31impl Type {
32    pub fn unwrap(self) -> Self {
33        match self {
34            Self::Unknown => panic!("Type::unwrap failed"),
35            other => other
36        }
37    }
38
39    pub fn is_known(self) -> bool {
40        !matches!(self, Self::Unknown)
41    }
42
43    pub fn make_unknown() -> TypeCell {
44        TypeCell::new(Self::Unknown)
45    }
46
47    pub fn int64_singleton() -> TypeCell {
48        INT64_TYPE_CELL.to_owned()
49    }
50
51    pub fn unit_singleton() -> TypeCell {
52        UNIT_TYPE_CELL.to_owned()
53    }
54
55    /// The number of bytes to store one instance of a value of the current
56    /// type.
57    pub fn size(&self) -> usize {
58        match &self {
59            Type::Unknown => panic!("Type::Unknown does not have a size"),
60            Type::Unit => 0,
61            Type::Var(_) => {
62                panic!("Type::Var should have been resolved by type inference")
63            }
64            Type::Name(_) => todo!("Need to figure out user-defined types"),
65            Type::Int64 => 8,
66            Type::Array(element_type, element_count) => {
67                element_type.as_ref().size() * (*element_count as usize)
68            }
69            Type::Function {
70                is_pure: _,
71                args: _,
72                ret: _
73            } => 8
74        }
75    }
76
77    pub fn as_array_type(&self) -> (TypeCell, isize) {
78        match &self {
79            Self::Array(element_type, size) => (element_type.clone(), *size),
80            _ => panic!(
81                "{}",
82                format!(
83                    "Type::as_array_type called on non-array type `{}`",
84                    &self
85                )
86            )
87        }
88    }
89
90    pub fn mangle(&self) -> String {
91        match &self {
92            Type::Unknown | Type::Var(_) => panic!(),
93            Type::Unit => "u".into(),
94            Type::Name(name) => format!("{}{}", name.len(), name),
95            Type::Int64 => "q".into(),
96            Type::Array(element_type, count) => {
97                format!("A{}{}", count, element_type)
98            }
99            Type::Function {
100                is_pure: _,
101                args: _,
102                ret: _
103            } => todo!()
104        }
105    }
106}
107
108impl Display for Type {
109    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
110        match self {
111            Self::Unknown => write!(f, "?"),
112            Self::Unit => write!(f, "Unit"),
113            Self::Var(var) => write!(f, "'t{}", var),
114            Self::Name(name) => write!(f, "{}", name),
115            Self::Int64 => write!(f, "Int64"),
116            Self::Array(tcell, size) => write!(
117                f,
118                "{}[{}]",
119                tcell,
120                if *size == ARRAY_TYPE_UNKNOWN_SIZE {
121                    "?".into()
122                } else {
123                    size.to_string()
124                }
125            ),
126            Self::Function { is_pure, args, ret } => write!(
127                f,
128                "{}({}) -> {}",
129                if *is_pure { "pure " } else { "" },
130                args.iter()
131                    .map(|ty| ty.to_string())
132                    .collect::<Vec<_>>()
133                    .join(", "),
134                ret,
135            )
136        }
137    }
138}
139
140#[derive(Clone, PartialEq, Eq)]
141pub enum StmtTermination {
142    Terminal,
143    Nonterminal
144}
145
146impl Display for StmtTermination {
147    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
148        match self {
149            Self::Terminal => "Terminal",
150            Self::Nonterminal => "Nonterminal"
151        }
152        .fmt(f)
153    }
154}
155
156#[derive(Clone, PartialEq, Eq)]
157pub struct StmtType {
158    pub termination: StmtTermination,
159    pub is_pure: bool,
160    is_unknown: bool
161}
162
163impl StmtType {
164    pub fn from(termination: StmtTermination, is_pure: bool) -> StmtType {
165        StmtType {
166            termination,
167            is_pure,
168            is_unknown: false
169        }
170    }
171
172    pub fn make_unknown() -> StmtTypeCell {
173        StmtTypeCell::new(StmtType {
174            termination: StmtTermination::Nonterminal,
175            is_pure: false,
176            is_unknown: true
177        })
178    }
179}
180
181impl Display for StmtType {
182    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
183        write!(f, "{}", if self.is_pure { "Pure" } else { "Impure" })?;
184        write!(f, "{}", self.termination)
185    }
186}
187
188pub type TypeCell = MutCell<Type>;
189pub type StmtTypeCell = MutCell<StmtType>;