1pub mod eval;
2
3#[cfg(test)]
4mod test;
5
6use std::{
7 collections::{BTreeMap, BTreeSet},
8 error::Error,
9 fmt::Display,
10};
11
12use crate::{
13 matching::get_match_bindings,
14 parser::{self, ParseError},
15};
16
17#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
18pub enum Token {
19 Element(String),
21
22 Literal(String),
25}
26
27impl Display for Token {
28 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
29 use termion::{
30 color::{Fg, LightMagenta},
31 style::Reset,
32 };
33 match self {
34 Token::Element(element) => write!(f, "{}{element}{}", Fg(LightMagenta), Reset)?,
35
36 Token::Literal(literal) => write!(f, "{literal}")?,
38 }
39
40 Ok(())
41 }
42}
43
44#[derive(Debug, PartialEq, Eq, Clone)]
45pub enum PatternToken {
46 Concrete(Token),
48
49 Variable(String),
51
52 SpreadVariable(String),
54}
55
56impl Display for PatternToken {
57 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
58 use termion::style::{Bold, Italic, Reset};
59
60 match self {
61 Self::Concrete(token) => write!(f, "{token}"),
62 Self::Variable(name) => write!(f, "{}{name}{}", Bold, Reset),
63 Self::SpreadVariable(name) => write!(f, "{}{}{name}{}", Bold, Italic, Reset),
64 }
65 }
66}
67
68#[derive(Debug, PartialEq, Eq, Clone)]
69pub struct Expression {
70 pub tokens: Vec<Token>,
71}
72
73impl Expression {
74 pub fn new(tokens: Vec<Token>) -> Self {
75 Self { tokens }
76 }
77}
78
79impl PartialOrd for Expression {
80 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
81 match self.tokens.len().partial_cmp(&other.tokens.len())? {
82 std::cmp::Ordering::Equal => self.tokens.partial_cmp(&other.tokens),
83 ordering => ordering.into(),
84 }
85 }
86}
87
88impl Ord for Expression {
89 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
90 match self.tokens.len().cmp(&other.tokens.len()) {
91 std::cmp::Ordering::Equal => self.tokens.cmp(&other.tokens),
92 ordering => ordering,
93 }
94 }
95}
96
97impl From<&[Token]> for Expression {
98 fn from(tokens: &[Token]) -> Self {
99 Self {
100 tokens: tokens.to_vec(),
101 }
102 }
103}
104
105impl Display for Expression {
106 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
107 for token in &self.tokens {
108 write!(f, "{} ", token)?;
109 }
110
111 Ok(())
112 }
113}
114
115#[derive(Debug, PartialEq, Eq, Clone)]
116pub struct Definition {
120 low: Vec<PatternToken>,
121 high: Vec<PatternToken>,
122}
123
124impl Definition {
125 pub fn new(lhs: Vec<PatternToken>, rhs: Vec<PatternToken>) -> Self {
127 Self {
128 high: lhs,
129 low: rhs,
130 }
131 }
132
133 fn transform<'a>(
135 from: &[PatternToken],
136 to: &[PatternToken],
137 expression: &'a [Token],
138 ) -> Option<Expression> {
139 let (single_bindings, spread_bindings) = get_match_bindings(from, expression)?;
140
141 let mut result = Vec::new();
142
143 for token in to {
144 match token {
145 PatternToken::Concrete(token) => result.push(token.clone()),
146 PatternToken::Variable(name) => {
147 let binding = *single_bindings.get(name)?;
148 result.push(binding.clone());
149 }
150 PatternToken::SpreadVariable(name) => {
151 let binding = spread_bindings.get(name)?;
152 result.extend_from_slice(binding);
153 }
154 };
155 }
156
157 Some(Expression::new(result))
158 }
159
160 pub fn lower(&self, expression: &[Token]) -> Option<Expression> {
161 Self::transform(&self.high, &self.low, expression)
162 }
163
164 pub fn raise(&self, expression: &[Token]) -> Option<Expression> {
165 Self::transform(&self.low, &self.high, expression)
166 }
167}
168
169impl Display for Definition {
170 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
171 for token in &self.high {
172 write!(f, "{} ", token)?;
173 }
174
175 write!(f, "=> ")?;
176
177 for token in &self.low {
178 write!(f, "{} ", token)?;
179 }
180
181 Ok(())
182 }
183}
184
185#[derive(Debug, PartialEq, Eq, Clone)]
186pub struct Structure {
187 domain: BTreeSet<String>,
188 reserved: BTreeSet<String>,
189 definitions: Vec<Definition>,
190}
191
192impl Structure {
193 pub fn create(
197 domain: BTreeSet<String>,
198 reserved: BTreeSet<String>,
199 definitions: Vec<Definition>,
200 ) -> Result<Self, StructureError> {
201 if let Some(culprit) = domain.iter().find(|d| reserved.contains(*d)) {
202 return Err(StructureError::DomainAndReservedOverlap {
203 culprit: culprit.to_owned(),
204 });
205 }
206
207 Ok(Self {
208 domain,
209 reserved,
210 definitions,
211 })
212 }
213
214 pub fn intrinsic() -> Self {
218 let reserved = BTreeSet::from(["{", "}", ",", "(", ")", "="].map(|s| s.to_owned()));
219
220 Structure {
221 domain: BTreeSet::new(),
222 reserved,
223 definitions: Vec::new(),
224 }
225 }
226
227 pub fn empty() -> Self {
229 Structure {
230 domain: BTreeSet::new(),
231 reserved: BTreeSet::new(),
232 definitions: Vec::new(),
233 }
234 }
235
236 pub fn get_reserved(&self) -> &BTreeSet<String> {
237 &self.reserved
238 }
239
240 pub fn get_domain(&self) -> &BTreeSet<String> {
241 &self.domain
242 }
243}
244
245impl Display for Structure {
246 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
247 let domain: Vec<_> = self.domain.iter().cloned().collect();
248 writeln!(f, "Domain: {{ {} }}", domain.join(", "))?;
249
250 let reserved: Vec<_> = self.reserved.iter().cloned().collect();
251 writeln!(f, "Reserved: {{ {} }}", reserved.join(", "))?;
252
253 writeln!(f, "Definitions: ")?;
254
255 for definition in &self.definitions {
256 writeln!(f, "- {definition};")?;
257 }
258
259 Ok(())
260 }
261}
262
263#[derive(Debug, PartialEq, Eq)]
265pub enum StructureError {
266 DomainAndReservedOverlap { culprit: String },
267}
268
269impl Display for StructureError {
270 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
271 match self {
272 StructureError::DomainAndReservedOverlap { culprit } => {
273 write!(
274 f,
275 "Domain and reserved keywords overlap (\"{}\" appears in both)",
276 culprit
277 )
278 }
279 }
280 }
281}
282
283impl Error for StructureError {}
284
285#[derive(Debug, Clone, PartialEq, Eq)]
286pub struct Runtime {
287 pub structures: BTreeMap<String, Structure>,
288}
289
290impl Runtime {
291 pub fn new(structures: BTreeMap<String, Structure>) -> Self {
292 Self { structures }
293 }
294
295 pub fn domain(&self) -> impl Iterator<Item = &String> + '_ {
297 self.structures
298 .iter()
299 .flat_map(|(_name, structure)| structure.domain.iter())
300 }
301
302 pub fn reserved(&self) -> impl Iterator<Item = &String> + '_ {
304 self.structures
305 .iter()
306 .flat_map(|(_name, structure)| structure.reserved.iter())
307 }
308
309 pub fn definitions(&self) -> impl Iterator<Item = &Definition> + '_ {
311 self.structures
312 .iter()
313 .flat_map(|(_name, structure)| structure.definitions.iter())
314 }
315
316 pub fn contains(&self, name: &str) -> bool {
317 self.structures.contains_key(name)
318 }
319
320 pub fn insert(&mut self, name: String, structure: Structure) -> Option<Structure> {
321 self.structures.insert(name, structure)
322 }
323
324 pub fn from_partial(structures: &BTreeMap<String, Option<Structure>>) -> Self {
325 let mut runtime = Runtime::new(BTreeMap::new());
326
327 for (name, structure) in structures {
328 if let Some(structure) = structure {
329 runtime.insert(name.to_owned(), structure.to_owned());
330 }
331 }
332
333 runtime
334 }
335
336 pub fn parse_expression(&self, expression: &str) -> Result<Expression, ParseError> {
337 parser::expression(expression, self)
338 }
339}
340
341impl Display for Runtime {
342 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
343 for (name, structure) in &self.structures {
344 writeln!(f, "{name}:")?;
345 writeln!(f, "{structure}")?;
346 }
347
348 Ok(())
349 }
350}