Skip to main content

mimium_lang/
pattern.rs

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