ftml_solver/rules/sequences/mod.rs
1use ftml_ontology::terms::{
2 ApplicationTerm, Argument, MaybeSequence, Numeric, Term, Variable,
3 sequences::{Sequence, SequenceType},
4};
5use ftml_solver_trace::SizedSolverRule;
6
7use crate::{
8 CheckRef,
9 rules::{
10 EqualityRule, InferenceRule, InhabitableRule, UniverseRule,
11 operators::numbers::{NumberRule, NumberType},
12 },
13 split::SplitStrategy,
14};
15
16pub mod fold;
17pub mod map;
18
19/*
20pub enum Sequence<'t> {
21 Var(&'t Variable),
22 SequenceExpression(&'t [Term]),
23 Map(Box<Self>, &'t Term),
24 Concatenation(Vec<Self>),
25}
26impl Sequence<'_> {
27 pub fn to_term(&self) -> Term {
28 match self {
29 Self::Var(v) => Term::Var {
30 variable: (*v).clone(),
31 presentation: None,
32 },
33 Self::SequenceExpression(ts) => Term::into_seq(ts.iter().cloned()),
34 Self::Map(s, f) => Term::Application(ApplicationTerm::new(
35 ftml_uris::metatheory::SEQUENCE_MAP.clone().into(),
36 Box::new([
37 Argument::Simple(s.to_term()),
38 Argument::Simple((*f).clone()),
39 ]),
40 None,
41 )),
42 Self::Concatenation(ts) => Term::Application(ApplicationTerm::new(
43 ftml_uris::metatheory::SEQUENCE_CONC.clone().into(),
44 Box::new([Argument::Sequence(MaybeSequence::Seq(
45 ts.iter().map(Self::to_term).collect(),
46 ))]),
47 None,
48 )),
49 }
50 }
51 #[must_use]
52 pub fn is_concrete(&self) -> bool {
53 match self {
54 Self::Var(_) => false,
55 Self::SequenceExpression(_) => true,
56 Self::Map(s, _) => s.is_concrete(),
57 Self::Concatenation(v) => v.iter().all(Self::is_concrete),
58 }
59 }
60 #[must_use]
61 pub fn to_concrete(&self) -> Option<Vec<Term>> {
62 match self {
63 Self::Var(_) => None,
64 Self::SequenceExpression(es) => Some(es.to_vec()),
65 Self::Map(seq, f) => seq.to_concrete().map(|seq| {
66 seq.into_iter()
67 .map(|a| {
68 Term::Application(ApplicationTerm::new(
69 (*f).clone(),
70 Box::new([Argument::Simple(a)]),
71 None,
72 ))
73 })
74 .collect()
75 }),
76 Self::Concatenation(v) => {
77 let mut ret = Vec::new();
78 for v in v {
79 ret.extend(v.to_concrete()?);
80 }
81 Some(ret)
82 }
83 }
84 }
85}
86
87pub enum SequenceType<'t> {
88 Var(&'t Variable),
89 SequenceExpression(&'t [Term]),
90 Map(Sequence<'t>, &'t Term),
91 SeqType(&'t Term, Option<&'t [Term]>),
92}
93
94pub trait TermExtSeq: Sized {
95 fn is_sequence_variable(&self) -> bool;
96 fn is_sequence(&self) -> bool;
97 fn as_sequence(&self) -> Option<Sequence<'_>>;
98 fn into_seq(seqs: impl Iterator<Item = Self>) -> Self;
99 fn as_sequence_type(&self) -> Option<SequenceType<'_>>;
100 #[must_use]
101 fn into_seq_type(self) -> Self;
102 #[must_use]
103 fn into_ranged_seq_type(self, range: impl IntoIterator<Item = Term>) -> Self;
104 /*
105 fn as_sequence(&self) -> Option<&[Self]>;
106 fn is_concrete_sequence(&self) -> bool;
107 fn make_concrete_sequence(&self) -> Option<Vec<Self>>;
108 */
109}
110impl TermExtSeq for Term {
111 fn is_sequence_variable(&self) -> bool {
112 matches!(
113 self,
114 Self::Var {
115 variable: Variable::Ref {
116 is_sequence: Some(true),
117 ..
118 },
119 ..
120 }
121 )
122 }
123 fn is_sequence(&self) -> bool {
124 if self.is_sequence_variable() {
125 return true;
126 }
127 let Self::Application(app) = self else {
128 return false;
129 };
130 let Self::Symbol { uri, .. } = &app.head else {
131 return false;
132 };
133 if *uri == *ftml_uris::metatheory::SEQUENCE_EXPRESSION
134 && let [Argument::Sequence(MaybeSequence::Seq(_))] = &*app.arguments
135 {
136 true
137 } else if *uri == *ftml_uris::metatheory::SEQUENCE_MAP {
138 if let [
139 Argument::Simple(seq) | Argument::Sequence(MaybeSequence::One(seq)),
140 Argument::Simple(_),
141 ] = &*app.arguments
142 && seq.is_sequence()
143 {
144 true
145 } else {
146 false
147 }
148 } else if *uri == *ftml_uris::metatheory::SEQUENCE_CONC {
149 if let [Argument::Sequence(MaybeSequence::Seq(seq))] = &*app.arguments
150 && seq.iter().all(Self::is_sequence)
151 {
152 true
153 } else {
154 false
155 }
156 } else {
157 false
158 }
159 }
160 fn as_sequence(&self) -> Option<Sequence<'_>> {
161 if let Self::Var {
162 variable:
163 v @ Variable::Ref {
164 is_sequence: Some(true),
165 ..
166 },
167 ..
168 } = self
169 {
170 return Some(Sequence::Var(v));
171 }
172 let Self::Application(app) = self else {
173 return None;
174 };
175 let Self::Symbol { uri, .. } = &app.head else {
176 return None;
177 };
178 if *uri == *ftml_uris::metatheory::SEQUENCE_EXPRESSION
179 && let [Argument::Sequence(MaybeSequence::Seq(seq))] = &*app.arguments
180 {
181 Some(Sequence::SequenceExpression(seq))
182 } else if *uri == *ftml_uris::metatheory::SEQUENCE_MAP {
183 if let [
184 Argument::Simple(seq) | Argument::Sequence(MaybeSequence::One(seq)),
185 Argument::Simple(f),
186 ] = &*app.arguments
187 && let Some(seq) = seq.as_sequence()
188 {
189 Some(Sequence::Map(Box::new(seq), f))
190 } else {
191 None
192 }
193 } else if *uri == *ftml_uris::metatheory::SEQUENCE_CONC {
194 if let [Argument::Sequence(MaybeSequence::Seq(seq))] = &*app.arguments
195 && seq.iter().all(Self::is_sequence)
196 {
197 Some(Sequence::Concatenation(
198 seq.iter().filter_map(Term::as_sequence).collect(),
199 ))
200 } else {
201 None
202 }
203 } else {
204 None
205 }
206 }
207 fn into_seq(seqs: impl Iterator<Item = Self>) -> Self {
208 Self::Application(ApplicationTerm::new(
209 Self::Symbol {
210 uri: ftml_uris::metatheory::SEQUENCE_EXPRESSION.clone(),
211 presentation: None,
212 },
213 Box::new([Argument::Sequence(MaybeSequence::Seq(seqs.collect()))]),
214 None,
215 ))
216 }
217
218 fn as_sequence_type(&self) -> Option<SequenceType<'_>> {
219 if let Self::Application(app) = self
220 && let Self::Symbol { uri, .. } = &app.head
221 {
222 if *uri == *ftml_uris::metatheory::SEQUENCE_TYPE
223 && let [Argument::Simple(t)] = &*app.arguments
224 {
225 Some(SequenceType::SeqType(t, None))
226 } else if *uri == *ftml_uris::metatheory::RANGED_SEQUENCE_TYPE
227 && let [
228 Argument::Simple(t),
229 Argument::Sequence(MaybeSequence::Seq(range)),
230 ] = &*app.arguments
231 {
232 Some(SequenceType::SeqType(t, Some(&**range)))
233 } else if *uri == *ftml_uris::metatheory::SEQUENCE_MAP
234 && let [
235 Argument::Simple(seq) | Argument::Sequence(MaybeSequence::One(seq)),
236 Argument::Simple(f),
237 ] = &*app.arguments
238 {
239 Some(SequenceType::Map(seq.as_sequence()?, f))
240 } else {
241 None
242 }
243 } else if let Self::Var {
244 variable:
245 v @ Variable::Ref {
246 is_sequence: Some(true),
247 ..
248 },
249 ..
250 } = self
251 {
252 // TODO check that variable is inhabitable?
253 Some(SequenceType::Var(v))
254 } else {
255 None
256 }
257 }
258
259 fn into_seq_type(self) -> Self {
260 Self::Application(ApplicationTerm::new(
261 Self::Symbol {
262 uri: ftml_uris::metatheory::SEQUENCE_TYPE.clone(),
263 presentation: None,
264 },
265 Box::new([Argument::Simple(self)]),
266 None,
267 ))
268 }
269
270 fn into_ranged_seq_type(self, range: impl IntoIterator<Item = Self>) -> Self {
271 Self::Application(ApplicationTerm::new(
272 Self::Symbol {
273 uri: ftml_uris::metatheory::RANGED_SEQUENCE_TYPE.clone(),
274 presentation: None,
275 },
276 Box::new([
277 Argument::Simple(self),
278 Argument::Sequence(MaybeSequence::Seq(range.into_iter().collect())),
279 ]),
280 None,
281 ))
282 }
283
284 /*
285 fn is_concrete_sequence(&self) -> bool {
286 let Self::Application(app) = self else {
287 return false;
288 };
289 let Self::Symbol { uri, .. } = &app.head else {
290 return false;
291 };
292 if *uri == *ftml_uris::metatheory::SEQUENCE_EXPRESSION {
293 return matches!(&*app.arguments, [Argument::Sequence(MaybeSequence::Seq(_))]);
294 }
295 if *uri == *ftml_uris::metatheory::SEQUENCE_MAP {
296 let [
297 Argument::Simple(seq) | Argument::Sequence(MaybeSequence::One(seq)),
298 Argument::Simple(_),
299 ] = &*app.arguments
300 else {
301 return false;
302 };
303 seq.is_concrete_sequence()
304 } else {
305 false
306 }
307 }
308 fn make_concrete_sequence(&self) -> Option<Vec<Self>> {
309 let Self::Application(app) = self else {
310 return None;
311 };
312 let Self::Symbol { uri, .. } = &app.head else {
313 return None;
314 };
315 if *uri == *ftml_uris::metatheory::SEQUENCE_EXPRESSION {
316 let [Argument::Sequence(MaybeSequence::Seq(ts))] = &*app.arguments else {
317 return None;
318 };
319 return Some(ts.to_vec());
320 }
321 if *uri == *ftml_uris::metatheory::SEQUENCE_MAP {
322 let [
323 Argument::Simple(seq) | Argument::Sequence(MaybeSequence::One(seq)),
324 Argument::Simple(f),
325 ] = &*app.arguments
326 else {
327 return None;
328 };
329 Some(
330 seq.make_concrete_sequence()?
331 .into_iter()
332 .map(|a| {
333 Self::Application(ApplicationTerm::new(
334 f.clone(),
335 Box::new([Argument::Simple(a)]),
336 None,
337 ))
338 })
339 .collect(),
340 )
341 } else {
342 None
343 }
344 }
345 */
346}
347 */
348
349#[allow(clippy::match_like_matches_macro)]
350const fn is_index(t: &Argument) -> bool {
351 match t {
352 Argument::Simple(Term::Number(Numeric::Int(_))) => true,
353 _ => false,
354 }
355}
356
357#[derive(Debug, Clone, Copy, PartialEq, Eq)]
358pub struct SeqConcatInferenceRule;
359impl SizedSolverRule for SeqConcatInferenceRule {
360 fn priority(&self) -> isize {
361 1000
362 }
363 fn display(&self) -> Vec<crate::trace::Displayable> {
364 ftml_solver_trace::trace!("sequence concatenation inference")
365 }
366}
367impl<Split: SplitStrategy> InferenceRule<Split> for SeqConcatInferenceRule {
368 fn applicable(&self, term: &Term) -> bool {
369 if let Term::Application(app) = term
370 && app.head.is(&*ftml_uris::metatheory::SEQUENCE_CONC)
371 && let [Argument::Sequence(MaybeSequence::Seq(seq))] = &*app.arguments
372 && seq.iter().all(|s| s.is_sequence())
373 {
374 true
375 } else {
376 false
377 }
378 }
379 fn infer<'t>(&self, mut checker: CheckRef<'t, '_, Split>, term: &'t Term) -> Option<Term> {
380 let Term::Application(app) = term else {
381 return None;
382 };
383 let [Argument::Sequence(MaybeSequence::Seq(seq))] = &*app.arguments else {
384 return None;
385 };
386 let mut curr = None;
387 for s in seq {
388 let tp = checker.infer_type(s)?;
389 if let Some(otp) = curr.as_ref() {
390 if checker.scoped(|c| c.check_equality(otp, &tp)) != Some(true) {
391 return None;
392 }
393 } else {
394 curr = Some(tp);
395 }
396 }
397 curr
398 }
399}
400
401#[derive(Debug, Clone, Copy, PartialEq, Eq)]
402pub struct SeqIndexRule;
403impl SizedSolverRule for SeqIndexRule {
404 fn priority(&self) -> isize {
405 1000
406 }
407 fn display(&self) -> Vec<crate::trace::Displayable> {
408 ftml_solver_trace::trace!("sequence index")
409 }
410}
411impl<Split: SplitStrategy> InferenceRule<Split> for SeqIndexRule {
412 fn applicable(&self, term: &Term) -> bool {
413 matches!(term,Term::Application(app) if app.head.is_sequence_variable() && app.arguments.len() == 1
414 && matches!(app.arguments.first(),Some(Argument::Simple(_)))
415 //&& app.arguments.first().is_some_and(is_index)
416 )
417 }
418 fn infer<'t>(&self, mut checker: CheckRef<'t, '_, Split>, term: &'t Term) -> Option<Term> {
419 let Term::Application(app) = term else {
420 return None;
421 };
422 let tp = checker.infer_type(&app.head)?;
423 if let SequenceType::SeqType(t, _) = tp.as_sequence_type()? {
424 Some(t.clone())
425 } else {
426 let Some(Argument::Simple(index)) = app.arguments.first() else {
427 checker.failure("First argument is not simple");
428 return None;
429 }; //.clone();
430 let indextp = checker.infer_type(index)?;
431 if NumberRule::is_number_term(&indextp, &checker)
432 .is_none_or(|t| !(t <= NumberType::Integers))
433 {
434 checker.failure("index is not an ordinal type");
435 return None;
436 }
437 Some(Term::Application(ApplicationTerm::new(
438 tp,
439 Box::new([Argument::Simple(index.clone())]),
440 None,
441 )))
442 }
443 }
444}
445
446#[derive(Debug, Clone, Copy, PartialEq, Eq)]
447pub struct SeqUniverseRule;
448impl SizedSolverRule for SeqUniverseRule {
449 fn display(&self) -> Vec<crate::trace::Displayable> {
450 ftml_solver_trace::trace!("sequences of inhabitables/universes are inhabitable/universes")
451 }
452}
453impl<Split: SplitStrategy> UniverseRule<Split> for SeqUniverseRule {
454 fn applicable(&self, term: &Term) -> bool {
455 term.as_sequence_type().is_some()
456 }
457 fn apply<'t>(&self, mut checker: CheckRef<'t, '_, Split>, term: &'t Term) -> Option<bool> {
458 match term.as_sequence_type()? {
459 SequenceType::SeqType(univ, _) => checker.check_universe(univ),
460 SequenceType::SequenceExpression(expr) => {
461 for e in expr {
462 if checker.check_universe(e) != Some(true) {
463 return None;
464 }
465 }
466 Some(true)
467 }
468 _ => None, // TODO?
469 }
470 }
471}
472impl<Split: SplitStrategy> InhabitableRule<Split> for SeqUniverseRule {
473 fn applicable(&self, term: &Term) -> bool {
474 term.as_sequence_type().is_some()
475 }
476 fn apply<'t>(&self, mut checker: CheckRef<'t, '_, Split>, term: &'t Term) -> Option<bool> {
477 //let univ = term.as_sequence_type()?;
478 match term.as_sequence_type()? {
479 SequenceType::SeqType(inh, _) => checker.check_inhabitable(inh),
480 SequenceType::SequenceExpression(expr) => {
481 for e in expr {
482 if checker.check_inhabitable(e) != Some(true) {
483 return None;
484 }
485 }
486 Some(true)
487 }
488 _ => None, // TODO?
489 }
490 }
491}
492
493#[derive(Debug, Clone, Copy, PartialEq, Eq)]
494pub struct SeqInferenceRule;
495impl SizedSolverRule for SeqInferenceRule {
496 fn display(&self) -> Vec<crate::trace::Displayable> {
497 ftml_solver_trace::trace!("sequences have sequence types")
498 }
499}
500impl<Split: SplitStrategy> InferenceRule<Split> for SeqInferenceRule {
501 fn applicable(&self, term: &Term) -> bool {
502 matches!(term.as_sequence(), Some(Sequence::SequenceExpression(_)))
503 }
504 fn infer<'t>(&self, mut checker: CheckRef<'t, '_, Split>, term: &'t Term) -> Option<Term> {
505 //checker.comment(format!("Here: {:?}", term.debug_short()));
506 let Some(Sequence::SequenceExpression(elems)) = term.as_sequence() else {
507 return None;
508 };
509 let mut curr = None;
510 for e in elems {
511 if let Some(tp) = &curr {
512 if checker.scoped(|checker| checker.check_type(e, tp)) != Some(true) {
513 return None;
514 }
515 } else {
516 curr = Some(checker.infer_type(e)?);
517 }
518 }
519 curr.map(Term::into_seq_type)
520 }
521}
522
523/*
524#[derive(Debug, Clone, Copy, PartialEq, Eq)]
525pub struct SeqTypeEqRule;
526impl SizedSolverRule for SeqTypeEqRule {
527 fn display(&self) -> Vec<crate::trace::Displayable> {
528 ftml_solver_trace::trace!("sequences of types are sequence types")
529 }
530}
531impl<Split: SplitStrategy> EqualityRule<Split> for SeqTypeEqRule {
532 fn applicable(&self, lhs: &Term, rhs: &Term) -> bool {
533 (lhs.as_sequence_type().is_some() && rhs.as_sequence().is_some_and(|r| r.is_concrete()))
534 || (rhs.as_sequence_type().is_some()
535 && lhs.as_sequence().is_some_and(|r| r.is_concrete()))
536 }
537 fn apply<'t>(
538 &self,
539 mut checker: CheckRef<'t, '_, Split>,
540 lhs: &'t Term,
541 rhs: &'t Term,
542 ) -> Option<bool> {
543 if rhs.as_sequence_type().is_some() && lhs.as_sequence().is_some_and(|r| r.is_concrete()) {
544 return self.apply(checker, rhs, lhs);
545 }
546 let Some(SequenceType::SeqType(seqtp, _)) = lhs.as_sequence_type() else {
547 return None;
548 };
549 let seq = rhs.as_sequence()?.to_concrete()?;
550 checker.comment(format!(
551 "Here: {seq:#?}\n Type: {:?}",
552 seqtp.debug_short()
553 ));
554 for t in seq {
555 if checker.scoped(|c| c.check_equality(&t, seqtp)) != Some(true) {
556 return None;
557 }
558 }
559 Some(true)
560 }
561}
562 */