mimium_lang/
pattern.rs

1use crate::interner::{ExprNodeId, Symbol, TypeNodeId};
2//todo! need to replace with interned string.
3use crate::types::Type;
4use crate::utils::metadata::{Location, Span};
5use crate::utils::miniprint::MiniPrint;
6
7#[derive(Debug, Clone, PartialEq)]
8pub enum Pattern {
9    Single(Symbol),
10    Tuple(Vec<Self>),
11    Record(Vec<(Symbol, Self)>),
12    Error,
13}
14
15impl std::fmt::Display for Pattern {
16    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
17        match self {
18            Pattern::Single(id) => write!(f, "{id}"),
19            Pattern::Tuple(vec) => {
20                let s = vec
21                    .iter()
22                    .map(|p| p.to_string())
23                    .collect::<Vec<_>>()
24                    .join(",");
25                write!(f, "({s})")
26            }
27            Pattern::Record(items) => {
28                if items.is_empty() {
29                    write!(f, "{{}}")
30                } else {
31                    let s = items
32                        .iter()
33                        .map(|(k, v)| format!("{k}: {v}"))
34                        .collect::<Vec<_>>()
35                        .join(", ");
36                    write!(f, "{{{s}}}")
37                }
38            }
39            Pattern::Error => {
40                write!(f, "<error pattern>")
41            }
42        }
43    }
44}
45
46#[derive(Clone, Debug, PartialEq)]
47pub struct TypedId {
48    pub id: Symbol,
49    // TypeNodeId is always issued even if the expression doesn't have the type
50    // specification at all. This can be used for querying for the span.
51    pub ty: TypeNodeId,
52    // Optional default value for function parameters
53    pub default_value: Option<ExprNodeId>,
54}
55
56impl TypedId {
57    // Constructor that initializes a TypedId with default values
58    pub fn new(id: Symbol, ty: TypeNodeId) -> Self {
59        TypedId {
60            id,
61            ty,
62            default_value: None,
63        }
64    }
65
66    // Constructor that includes a default value
67    pub fn with_default(id: Symbol, ty: TypeNodeId, default_value: ExprNodeId) -> Self {
68        TypedId {
69            id,
70            ty,
71            default_value: Some(default_value),
72        }
73    }
74
75    pub fn to_span(&self) -> Span {
76        self.ty.to_span()
77    }
78
79    pub fn is_unknown(&self) -> bool {
80        self.ty.to_type() == Type::Unknown
81    }
82}
83
84impl std::fmt::Display for TypedId {
85    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
86        if !self.is_unknown() {
87            write!(f, "{} :{}", self.id, self.ty.to_type())
88        } else {
89            write!(f, "{}", self.id)
90        }
91    }
92}
93
94impl MiniPrint for TypedId {
95    fn simple_print(&self) -> String {
96        if !self.is_unknown() {
97            format!("(tid {} {})", self.id, self.ty.to_type())
98        } else {
99            self.id.to_string()
100        }
101    }
102}
103
104#[derive(Clone, Debug, PartialEq)]
105pub struct TypedPattern {
106    pub pat: Pattern,
107    pub ty: TypeNodeId,
108    pub default_value: Option<ExprNodeId>,
109}
110impl TypedPattern {
111    pub fn new(pat: Pattern, ty: TypeNodeId) -> Self {
112        TypedPattern {
113            pat,
114            ty,
115            default_value: None,
116        }
117    }
118}
119
120impl TypedPattern {
121    pub fn to_span(&self) -> Span {
122        self.ty.to_span()
123    }
124    pub fn to_loc(&self) -> Location {
125        self.ty.to_loc()
126    }
127
128    pub fn is_unknown(&self) -> bool {
129        self.ty.to_type() == Type::Unknown
130    }
131}
132
133#[derive(Debug)]
134pub struct ConversionError;
135impl std::fmt::Display for ConversionError {
136    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
137        write!(
138            f,
139            "Failed to convert pattern. The pattern did not matched to single identifier."
140        )
141    }
142}
143impl std::error::Error for ConversionError {}
144
145impl From<TypedId> for TypedPattern {
146    fn from(value: TypedId) -> Self {
147        TypedPattern {
148            pat: Pattern::Single(value.id),
149            ty: value.ty,
150            default_value: value.default_value, // Default value is optional
151        }
152    }
153}
154impl TryFrom<TypedPattern> for TypedId {
155    type Error = ConversionError;
156
157    fn try_from(value: TypedPattern) -> Result<Self, Self::Error> {
158        match value.pat {
159            Pattern::Single(id) => Ok(TypedId {
160                id,
161                ty: value.ty,
162                default_value: value.default_value,
163            }),
164            _ => Err(ConversionError),
165        }
166    }
167}
168
169impl MiniPrint for TypedPattern {
170    fn simple_print(&self) -> String {
171        if !self.is_unknown() {
172            format!("(tpat {} {})", self.pat, self.ty.to_type())
173        } else {
174            self.pat.to_string()
175        }
176    }
177}
178impl std::fmt::Display for TypedPattern {
179    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
180        if !self.is_unknown() {
181            write!(f, "{} :{}", self.pat, self.ty.to_type())
182        } else {
183            write!(f, "{}", self.pat)
184        }
185    }
186}