1use crate::jbo_prop::{JboRel, JboTerm, JboQuantifier, JboTag, JboModalOp, JboVPred, JboNPred, JboPred, SideType};
15use std::sync::Arc;
16use crate::jbo_syntax::{SumtiAtom, SumtiQualifier, TanruUnit, Lerfu, Selbri};
17use crate::logic::Prop;
18use std::collections::{HashMap, HashSet};
19use std::hash::Hash;
20
21pub type JboProp = Prop<JboRel, JboTerm, String, crate::jbo_prop::JboModalOp, JboQuantifier>;
22
23pub type Bridi = Box<dyn Fn(&Args) -> JboProp + Send + Sync>;
26
27#[derive(Clone)]
31pub struct ParseState {
32 pub sumbasti_bindings: SumbastiBindings,
33 pub bribasti_bindings: BribastiBindings,
34 pub backcount_stack: Vec<i32>,
35 pub next_fresh_var: i32,
36 pub next_fresh_rvar: i32,
37 pub variable_domains: HashMap<i32, VariableDomain>,
38 pub next_fresh_constant: i32,
39 pub referenced_vars: HashSet<i32>,
40 pub questions: Vec<Question>,
41 pub lambdas: HashMap<LambdaPos, i32>,
42 pub side_texticules: Vec<Texticule>,
43 pub pending_prop_transforms: Vec<PropTransform>,
44 pub non_veridical_props: Vec<JboProp>,
45 pub var_bindings: VarBindings,
46 pub rvar_bindings: RVarBindings,
47 pub indicator_texticules: bool,
48}
49
50impl std::fmt::Debug for ParseState {
51 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
52 f.debug_struct("ParseState")
53 .field("sumbasti_bindings", &self.sumbasti_bindings)
54 .field("bribasti_bindings_len", &self.bribasti_bindings.len())
55 .field("backcount_stack", &self.backcount_stack)
56 .field("next_fresh_var", &self.next_fresh_var)
57 .field("next_fresh_rvar", &self.next_fresh_rvar)
58 .field("variable_domains", &self.variable_domains)
59 .field("next_fresh_constant", &self.next_fresh_constant)
60 .field("referenced_vars", &self.referenced_vars)
61 .field("questions", &self.questions)
62 .field("lambdas", &self.lambdas)
63 .field("side_texticules", &self.side_texticules)
64 .field("pending_prop_transforms", &self.pending_prop_transforms)
65 .field("non_veridical_props", &self.non_veridical_props)
66 .field("var_bindings", &self.var_bindings)
67 .field("rvar_bindings", &self.rvar_bindings)
68 .field("indicator_texticules", &self.indicator_texticules)
69 .finish()
70 }
71}
72
73#[derive(Clone)]
75#[allow(clippy::large_enum_variant)]
76pub enum PropTransform {
77 Quantify(JboTerm, JboQuantifier, Option<Arc<dyn Fn(i32) -> JboProp + Send + Sync>>),
78 ConnectQuantify {
79 conn: crate::jbo_syntax::LogJboConnective,
80 fresh: JboTerm,
81 left_quant: JboQuantifier,
82 right_quant: JboQuantifier,
83 restriction: Option<Arc<dyn Fn(i32) -> JboProp + Send + Sync>>,
84 },
85 ConnectQuantifyTagged {
86 conn: crate::jbo_syntax::LogJboConnective,
87 fresh: JboTerm,
88 left_quant: JboQuantifier,
89 right_quant: JboQuantifier,
90 restriction: Option<Arc<dyn Fn(i32) -> JboProp + Send + Sync>>,
91 event_fresh: Option<JboTerm>,
92 left_modal: Option<JboModalOp>,
93 right_modal: Option<JboModalOp>,
94 },
95 RQuantify(JboRel, JboQuantifier),
96 SubstituteTerm(JboTerm, JboTerm),
97 LogicalConnectBranches {
98 conn: crate::jbo_syntax::LogJboConnective,
99 fresh: JboTerm,
100 left_term: JboTerm,
101 left_transforms: Vec<PropTransform>,
102 right_term: JboTerm,
103 right_transforms: Vec<PropTransform>,
104 },
105 ConnectBranches {
106 conn: crate::jbo_syntax::Connective,
107 left_args: Args,
108 right_args: Args,
109 continuation_position: i32,
110 left_transforms: Vec<PropTransform>,
111 right_transforms: Vec<PropTransform>,
112 outer_transforms: Vec<PropTransform>,
113 },
114 ConnectTagBranches {
115 conn: crate::jbo_prop::JboConnective,
116 left_transforms: Vec<PropTransform>,
117 right_transforms: Vec<PropTransform>,
118 },
119 Negate,
120 ApplyModal(JboModalOp),
121}
122
123impl Default for ParseState {
124 fn default() -> Self {
125 Self::new()
126 }
127}
128
129impl ParseState {
130 pub fn new() -> Self {
131 ParseState {
132 sumbasti_bindings: HashMap::new(),
133 bribasti_bindings: HashMap::new(),
134 backcount_stack: Vec::new(),
135 next_fresh_var: 0,
136 next_fresh_rvar: 0,
137 variable_domains: HashMap::new(),
138 next_fresh_constant: 0,
139 referenced_vars: HashSet::new(),
140 questions: Vec::new(),
141 lambdas: HashMap::new(),
142 side_texticules: Vec::new(),
143 pending_prop_transforms: Vec::new(),
144 non_veridical_props: Vec::new(),
145 var_bindings: HashMap::new(),
146 rvar_bindings: HashMap::new(),
147 indicator_texticules: false,
148 }
149 }
150
151 pub fn map_prop(&mut self, transform: PropTransform) {
153 self.pending_prop_transforms.push(transform);
154 }
155
156 pub fn apply_transforms(&mut self, mut prop: JboProp) -> JboProp {
158 for transform in self.pending_prop_transforms.drain(..).rev() {
159 prop = apply_transform(transform, prop);
160 }
161 prop
162 }
163
164 pub fn get_fresh_var(&mut self, dom: VariableDomain) -> JboTerm {
166 let n = self.next_fresh_var;
167 self.next_fresh_var += 1;
168 self.variable_domains.insert(n, dom);
169 JboTerm::Var(n)
170 }
171
172 pub fn get_fresh_constant(&mut self) -> JboTerm {
174 let n = self.next_fresh_constant;
175 self.next_fresh_constant += 1;
176 JboTerm::Constant(n, Vec::new())
177 }
178
179 pub fn get_fresh_rvar(&mut self) -> JboRel {
181 let n = self.next_fresh_rvar;
182 self.next_fresh_rvar += 1;
183 JboRel::RVar(n)
184 }
185
186 pub fn get_sumbasti(&self, atom: &SumtiAtom) -> JboTerm {
189 get_sumbasti_binding(&self.sumbasti_bindings, atom)
190 }
191
192 pub fn set_sumbasti(&mut self, sumbasti: Sumbasti, term: JboTerm) {
195 self.sumbasti_bindings.insert(sumbasti, term);
196 }
197
198 pub fn update_ri(&mut self, o: &JboTerm) {
199 let mut new_bindings = HashMap::new();
200 for (key, val) in self.sumbasti_bindings.iter() {
201 if let SumtiAtom::Ri(n) = &key.atom {
202 let new_key = Sumbasti {
203 explicitly_assigned: key.explicitly_assigned,
204 atom: SumtiAtom::Ri(n + 1),
205 };
206 new_bindings.insert(new_key, val.clone());
207 } else {
208 new_bindings.insert(key.clone(), val.clone());
209 }
210 }
211 self.sumbasti_bindings = new_bindings;
212 let count = self.backcount_stack.first().copied().unwrap_or(0);
213 let sumbasti = Sumbasti {
214 explicitly_assigned: false,
215 atom: SumtiAtom::Ri(count),
216 };
217 self.set_sumbasti(sumbasti, o.clone());
218 }
219
220 pub fn update_sumbasti_with_sumti_atom(&mut self, sa: &SumtiAtom, o: &JboTerm) {
223 if crate::jbo_parse::gets_ri(sa) {
224 let count = self.pop_backcount();
225 self.sumbasti_bindings = set_shunting(
226 &|n| Sumbasti {
227 explicitly_assigned: false,
228 atom: SumtiAtom::Ri(count + n as i32),
229 },
230 o.clone(),
231 &self.sumbasti_bindings,
232 );
233 }
234
235 if let SumtiAtom::Name(_, _, name) = sa {
237 if let Some(first_char) = name.chars().next() {
238 let lerfu = SumtiAtom::LerfuString(vec![Lerfu::LerfuChar(first_char)]);
239 let sumbasti = Sumbasti {
240 explicitly_assigned: false,
241 atom: lerfu,
242 };
243 self.set_sumbasti(sumbasti, o.clone());
244 }
245 }
246
247 if let SumtiAtom::Description(_, _, _, crate::jbo_syntax::EitherSelbriSumti::Selbri(sb), _, _) = sa {
248 for lerfu in crate::jbo_syntax::lerfu_strings_of_selbri(sb) {
249 let sumbasti = Sumbasti {
250 explicitly_assigned: false,
251 atom: SumtiAtom::LerfuString(lerfu),
252 };
253 self.set_sumbasti(sumbasti, o.clone());
254 }
255 }
256 }
257
258 pub fn push_backcount(&mut self) {
261 let new_stack: Vec<i32> = std::iter::once(0)
262 .chain(self.backcount_stack.iter().map(|n| n + 1))
263 .collect();
264 self.backcount_stack = new_stack;
265 }
266
267 pub fn pop_backcount(&mut self) -> i32 {
270 if self.backcount_stack.is_empty() {
271 return 0;
272 }
273 self.backcount_stack.remove(0)
274 }
275
276 pub fn set_referenced(&mut self, n: i32) {
279 self.referenced_vars.insert(n);
280 }
281
282 pub fn referenced(&self, n: i32) -> bool {
285 self.referenced_vars.contains(&n)
286 }
287
288 pub fn put_lambda(&mut self, mlev: Option<i32>, mnum: Option<i32>) -> JboTerm {
291 let lev = mlev.unwrap_or(1);
292 let next = self.lambdas.keys().filter_map(|pos| if pos.level == lev { Some(pos.num) } else { None })
293 .max()
294 .unwrap_or(0) + 1;
295 let num = mnum.unwrap_or(next);
296 let pos = LambdaPos { level: lev, num };
297
298 if let Some(&n) = self.lambdas.get(&pos) {
299 return JboTerm::Var(n);
300 }
301
302 let fresh = self.get_fresh_var(VariableDomain::UnrestrictedDomain);
303 if let JboTerm::Var(n) = fresh {
304 self.lambdas.insert(pos, n);
305 JboTerm::Var(n)
306 } else {
307 fresh
308 }
309 }
310}
311
312#[derive(Debug, Clone)]
315pub struct BridiParseState {
316 pub arglist: Arglist,
317 pub var_bindings: VarBindings,
318 pub rvar_bindings: RVarBindings,
319 pub is_sub_bridi: bool,
320}
321
322impl Default for BridiParseState {
323 fn default() -> Self {
324 Self::new()
325 }
326}
327
328impl BridiParseState {
329 pub fn new() -> Self {
330 BridiParseState {
331 arglist: Arglist::new(),
332 var_bindings: HashMap::new(),
333 rvar_bindings: HashMap::new(),
334 is_sub_bridi: false,
335 }
336 }
337}
338
339#[derive(Debug, Clone, PartialEq, Eq, Hash)]
341pub struct Sumbasti {
342 pub explicitly_assigned: bool,
343 pub atom: SumtiAtom,
344}
345
346pub type SumbastiBindings = HashMap<Sumbasti, JboTerm>;
347pub type StoredBridi = Arc<dyn Fn(&Args) -> JboProp + Send + Sync>;
348pub type BribastiBindings = HashMap<TanruUnit, StoredBridi>;
349
350#[derive(Debug, Clone)]
352pub struct Question {
353 pub kau_depth: Option<i32>,
354 pub info: QInfo,
355}
356
357pub enum QInfo {
359 QTruth,
360 QSumti(JboTerm, Option<JboPred>),
361 QBridi(JboRel),
362}
363
364impl Clone for QInfo {
365 fn clone(&self) -> Self {
366 match self {
367 QInfo::QTruth => QInfo::QTruth,
368 QInfo::QSumti(term, dom) => QInfo::QSumti(term.clone(), dom.clone()),
369 QInfo::QBridi(rel) => QInfo::QBridi(rel.clone()),
370 }
371 }
372}
373
374impl std::fmt::Debug for QInfo {
375 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
376 match self {
377 QInfo::QTruth => write!(f, "QTruth"),
378 QInfo::QSumti(term, _) => write!(f, "QSumti({:?})", term),
379 QInfo::QBridi(rel) => write!(f, "QBridi({:?})", rel),
380 }
381 }
382}
383
384#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
386pub struct LambdaPos {
387 pub level: i32,
388 pub num: i32,
389}
390
391pub enum VariableDomain {
393 UnrestrictedDomain,
394 PredDomain(JboPred),
395 FiniteDomain(Vec<JboTerm>),
396}
397
398impl Clone for VariableDomain {
399 fn clone(&self) -> Self {
400 match self {
401 VariableDomain::UnrestrictedDomain => VariableDomain::UnrestrictedDomain,
402 VariableDomain::PredDomain(pred) => VariableDomain::PredDomain(pred.clone()),
403 VariableDomain::FiniteDomain(os) => VariableDomain::FiniteDomain(os.clone()),
404 }
405 }
406}
407
408impl std::fmt::Debug for VariableDomain {
409 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
410 match self {
411 VariableDomain::UnrestrictedDomain => write!(f, "UnrestrictedDomain"),
412 VariableDomain::PredDomain(_) => write!(f, "PredDomain(<fn>)"),
413 VariableDomain::FiniteDomain(os) => f.debug_tuple("FiniteDomain").field(os).finish(),
414 }
415 }
416}
417
418#[derive(Debug, Clone)]
420pub struct Arglist {
421 pub args: Args,
422 pub position: i32,
423}
424
425impl Default for Arglist {
426 fn default() -> Self {
427 Self::new()
428 }
429}
430
431impl Arglist {
432 pub fn new() -> Self {
433 Arglist {
434 args: HashMap::new(),
435 position: 1,
436 }
437 }
438}
439
440pub type Args = HashMap<ArgPos, JboTerm>;
441
442#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
444pub enum ArgPos {
445 NPos(i32),
446 JaiPos,
447 UnfilledPos(i32),
448}
449
450pub type VarBindings = HashMap<SumtiAtom, JboTerm>;
451pub type RVarBindings = HashMap<TanruUnit, JboRel>;
452
453#[derive(Debug, Clone)]
455#[allow(clippy::large_enum_variant)]
456pub enum Texticule {
457 TexticuleProp(JboProp),
458 TexticuleSide(SideType, Box<Texticule>),
459}
460
461pub fn args_to_jboterms(args: &Args) -> Vec<JboTerm> {
463 let max_n = args.keys()
464 .filter_map(|k| match k {
465 ArgPos::NPos(n) => Some(*n),
466 _ => None,
467 })
468 .max()
469 .unwrap_or(0);
470
471 (1..=max_n)
472 .map(|n| args.get(&ArgPos::NPos(n)).cloned().unwrap_or(JboTerm::Unfilled))
473 .collect()
474}
475
476pub fn jbo_rel_to_bridi(rel: JboRel) -> Bridi {
483 Box::new(move |args: &Args| {
484 let terms = args_to_jboterms(args);
485 Prop::Rel(rel.clone(), terms)
486 })
487}
488
489pub fn apply_transforms_to_bridi(bridi: Bridi, state: &mut ParseState) -> Bridi {
491 let transforms = state.pending_prop_transforms.drain(..).collect::<Vec<_>>();
492 apply_transform_list_to_bridi(bridi, transforms)
493}
494
495pub fn apply_transform_list_to_bridi(bridi: Bridi, transforms: Vec<PropTransform>) -> Bridi {
496 if transforms.is_empty() {
497 return bridi;
498 }
499
500 Box::new(move |args: &Args| {
501 let mut prop = bridi(args);
502 for transform in transforms.iter().rev() {
503 prop = apply_transform(transform.clone(), prop);
504 }
505 prop
506 })
507}
508
509pub fn with_jai_as_tag(jtag: crate::jbo_prop::JboTag, bridi: Bridi) -> Bridi {
512 Box::new(move |args: &Args| {
513 let jai_term = args.get(&ArgPos::JaiPos).cloned();
514 let mut new_args = args.clone();
515 new_args.remove(&ArgPos::JaiPos);
516
517 let inner_prop = bridi(&new_args);
518 Prop::Modal(
519 crate::jbo_prop::JboModalOp::Tagged(jtag.clone(), jai_term),
520 Box::new(inner_prop)
521 )
522 })
523}
524
525pub fn with_jai_as_raising(bridi: Bridi) -> Bridi {
528 Box::new(move |args: &Args| {
529 if let Some(jai_term) = args.get(&ArgPos::JaiPos) {
530 let mut new_args = args.clone();
531 new_args.remove(&ArgPos::JaiPos);
532
533 let qualified = JboTerm::QualifiedTerm(
534 SumtiQualifier::LAhE("tu'a".to_string()),
535 Box::new(jai_term.clone()),
536 );
537 new_args.insert(ArgPos::NPos(1), qualified);
538
539 bridi(&new_args)
540 } else {
541 bridi(args)
542 }
543 })
544}
545
546pub fn partially_resolve_bridi(bridi: Bridi, arglist: &Args) -> Bridi {
550 let captured_args = arglist.clone();
551 Box::new(move |extra_args: &Args| {
552 let joined = join_args(extra_args, &captured_args);
553 bridi(&joined)
554 })
555}
556
557pub fn join_args(new: &Args, old: &Args) -> Args {
560 let mut result = old.clone();
561
562 let mut old_positions: Vec<i32> = old.keys()
563 .filter_map(|k| match k {
564 ArgPos::NPos(n) => Some(*n),
565 _ => None,
566 })
567 .collect();
568 old_positions.sort();
569
570 let mut implicit_args: Vec<(i32, JboTerm)> = new.iter()
571 .filter_map(|(k, v)| match k {
572 ArgPos::UnfilledPos(n) if !matches!(v, JboTerm::Unfilled) => Some((*n, v.clone())),
573 _ => None,
574 })
575 .collect();
576 implicit_args.sort_by_key(|(n, _)| *n);
577
578 for (n, value) in implicit_args.into_iter().rev() {
579 let mut gap = 1;
580 let mut seen = 0;
581 loop {
582 if !old_positions.contains(&gap) {
583 if seen == n {
584 result.insert(ArgPos::NPos(gap), value);
585 break;
586 }
587 seen += 1;
588 }
589 gap += 1;
590 }
591 }
592
593 for (k, v) in new.iter() {
594 if !matches!(k, ArgPos::UnfilledPos(_)) {
595 result.insert(k.clone(), v.clone());
596 }
597 }
598
599 result
600}
601
602pub fn swap_args(p1: &ArgPos, p2: &ArgPos, args: &Args) -> Args {
605 args.iter()
606 .map(|(k, v)| {
607 let new_k = if k == p1 {
608 p2.clone()
609 } else if k == p2 {
610 p1.clone()
611 } else {
612 k.clone()
613 };
614 (new_k, v.clone())
615 })
616 .collect()
617}
618
619pub fn set_arg(pos: ArgPos, term: JboTerm, args: &Args) -> Args {
622 let mut result = args.clone();
623 result.insert(pos, term);
624 result
625}
626
627pub fn add_fai_to_arglist(term: JboTerm, arglist: &Arglist) -> Arglist {
630 let mut new_args = arglist.args.clone();
631 new_args.insert(ArgPos::JaiPos, term);
632 Arglist {
633 args: new_args,
634 position: arglist.position,
635 }
636}
637
638pub fn close_bridi(bridi: Bridi) -> Bridi {
641 Box::new(move |args: &Args| {
642 let terms = args_to_jboterms(args);
643 let mut new_args: Args = terms.iter()
644 .enumerate()
645 .map(|(i, t)| (ArgPos::UnfilledPos(i as i32), t.clone()))
646 .collect();
647
648 if let Some(jai_term) = args.get(&ArgPos::JaiPos) {
650 new_args.insert(ArgPos::JaiPos, jai_term.clone());
651 }
652
653 bridi(&new_args)
654 })
655}
656
657pub fn swap_terms(terms: &[JboTerm], n: i32, m: i32) -> Vec<JboTerm> {
660 crate::util::swap_finite_with_default(JboTerm::Unfilled, terms, (n - 1) as usize, (m - 1) as usize)
661}
662
663impl ParseState {
664 pub fn add_side_texticule(&mut self, texticule: Texticule) {
667 self.side_texticules.insert(0, texticule);
668 }
669
670 pub fn take_side_texticules(&mut self) -> Vec<Texticule> {
673 std::mem::take(&mut self.side_texticules)
674 }
675
676 pub fn add_sumti_question(&mut self, kau_depth: Option<i32>) -> JboTerm {
679 let var = self.get_fresh_var(VariableDomain::UnrestrictedDomain);
680 self.questions.insert(0, Question {
681 kau_depth,
682 info: QInfo::QSumti(var.clone(), None),
683 });
684 var
685 }
686
687 pub fn add_bridi_question(&mut self, kau_depth: Option<i32>) -> JboRel {
690 let rvar = self.get_fresh_rvar();
691 self.questions.insert(0, Question {
692 kau_depth,
693 info: QInfo::QBridi(rvar.clone()),
694 });
695 rvar
696 }
697
698 pub fn add_question(&mut self, question: Question) {
701 self.questions.insert(0, question);
702 }
703
704 pub fn modify_questions<F>(&mut self, f: F)
707 where
708 F: FnOnce(Vec<Question>) -> Vec<Question>,
709 {
710 let questions = std::mem::take(&mut self.questions);
711 self.questions = f(questions);
712 }
713}
714
715impl BridiParseState {
716 pub fn advance_arg_pos_to_selbri(&mut self) {
719 if self.arglist.args.is_empty() {
720 self.arglist.position = 2;
721 }
722 }
723
724 pub fn set_arg_in_arglist(&mut self, pos: ArgPos, term: JboTerm) {
727 self.arglist.args.insert(pos, term);
728 }
729
730 pub fn set_arg_pos(&mut self, pos: i32) {
733 self.arglist.position = pos;
734 }
735}
736
737pub fn shunt_lambdas(parse_state: &mut ParseState, delta: i32) {
743 let mut new_lambdas = HashMap::new();
744 for (pos, v) in parse_state.lambdas.iter() {
745 if pos.level > 0 {
746 let new_pos = LambdaPos {
747 level: pos.level + delta,
748 num: pos.num,
749 };
750 new_lambdas.insert(new_pos, *v);
751 }
752 }
753 parse_state.lambdas = new_lambdas;
754}
755
756pub fn bridi_to_jbo_vpred(bridi: Bridi) -> JboVPred {
761 Arc::new(move |os: &[JboTerm]| {
762 let args: Args = os.iter()
763 .enumerate()
764 .map(|(n, o)| (ArgPos::UnfilledPos(n as i32), o.clone()))
765 .collect();
766 bridi(&args)
767 })
768}
769
770pub fn bridi_to_jbo_pred(bridi: Bridi) -> JboPred {
771 v_pred_to_pred(bridi_to_jbo_vpred(bridi))
772}
773
774pub fn with_questions<P: PreProp>(top: bool, parse_state: &mut ParseState, p: P) -> P {
779 let saved_questions = parse_state.questions.clone();
780 parse_state.questions.clear();
781 let result = do_questions(top, parse_state, p);
782 parse_state.questions.extend(saved_questions);
783 result
784}
785
786pub fn do_questions<P: PreProp>(top: bool, parse_state: &mut ParseState, p: P) -> P {
787 let qinfos = de_kau(top, parse_state);
788 qinfos.into_iter().fold(p, |acc, qinfo| do_q_info(qinfo, acc))
789}
790
791pub fn do_q_info<P: PreProp>(qinfo: QInfo, p: P) -> P {
792 match qinfo {
793 QInfo::QSumti(qv, dom) => {
794 let qv_clone = qv.clone();
795 p.lift_to_prop(Box::new(move |prop: JboProp| {
796 let qv_inner = qv_clone.clone();
797 let restriction = dom.clone().map(|pred| {
798 Arc::new(move |v: i32| pred(&JboTerm::BoundVar(v))) as Arc<dyn Fn(i32) -> JboProp + Send + Sync>
799 });
800 Prop::Quantified(
801 JboQuantifier::QuestionQuantifier,
802 restriction,
803 Arc::new(move |v: i32| sub_term(&qv_inner, &JboTerm::BoundVar(v), &prop)),
804 )
805 }))
806 }
807 QInfo::QBridi(qv) => {
808 let qv_clone = qv.clone();
809 p.lift_to_prop(Box::new(move |prop: JboProp| {
810 let qv_inner = qv_clone.clone();
811 Prop::Quantified(
812 JboQuantifier::RelQuantifier(Box::new(JboQuantifier::QuestionQuantifier)),
813 None,
814 Arc::new(move |v: i32| sub_rel(&qv_inner, &JboRel::BoundRVar(v), &prop)),
815 )
816 }))
817 }
818 QInfo::QTruth => {
819 p.lift_to_prop(Box::new(|prop: JboProp| {
820 Prop::Modal(JboModalOp::QTruthModal, Box::new(prop))
821 }))
822 }
823 }
824}
825
826pub fn de_kau(top: bool, parse_state: &mut ParseState) -> Vec<QInfo> {
827 let mut out_qs = Vec::new();
828 let mut remaining_qs = Vec::new();
829
830 for q in parse_state.questions.iter() {
831 if top || q.kau_depth == Some(1) {
832 out_qs.push(q.info.clone());
833 } else {
834 let mut new_q = q.clone();
835 if let Some(depth) = new_q.kau_depth {
836 new_q.kau_depth = Some(depth - 1);
837 }
838 remaining_qs.push(new_q);
839 }
840 }
841
842 parse_state.questions = remaining_qs;
843 out_qs
844}
845
846pub fn add_arg(arg: Arg, bridi_state: &mut BridiParseState, parse_state: &mut ParseState) {
851 match arg {
852 Arg::FAITagged(o) => {
853 bridi_state.arglist.args.insert(ArgPos::JaiPos, o);
854 }
855 Arg::Untagged(o) => {
856 let n = bridi_state.arglist.position;
857 set_arg_in_arglist(ArgPos::NPos(n), o.clone(), bridi_state);
858 if !bridi_state.is_sub_bridi {
859 parse_state.map_prop(PropTransform::SubstituteTerm(
860 JboTerm::UnboundSumbasti(crate::jbo_syntax::SumtiAtom::MainBridiSumbasti(n)),
861 o,
862 ));
863 }
864 set_arg_pos(n + 1, bridi_state);
865 }
866 Arg::FATagged(n, o) => {
867 let n = n as i32;
868 set_arg_in_arglist(ArgPos::NPos(n), o.clone(), bridi_state);
869 if !bridi_state.is_sub_bridi {
870 parse_state.map_prop(PropTransform::SubstituteTerm(
871 JboTerm::UnboundSumbasti(crate::jbo_syntax::SumtiAtom::MainBridiSumbasti(n)),
872 o,
873 ));
874 }
875 set_arg_pos(n + 1, bridi_state);
876 }
877 }
878}
879
880pub fn set_arg_in_arglist(pos: ArgPos, term: JboTerm, bridi_state: &mut BridiParseState) {
881 bridi_state.arglist.args.insert(pos, term);
882}
883
884pub fn set_arg_pos(n: i32, bridi_state: &mut BridiParseState) {
885 bridi_state.arglist.position = n;
886}
887
888pub fn shunt_vars<K: Eq + Clone + Hash, V: Clone, F: Fn(usize) -> K>(
893 var_fn: &F,
894 bindings: &HashMap<K, V>,
895) -> HashMap<K, V> {
896 let mut result = bindings.clone();
897
898 let max_bound = (1..)
900 .find(|&n| !bindings.contains_key(&var_fn(n)))
901 .unwrap_or(1);
902
903 for n in 1..max_bound {
905 if let Some(v) = bindings.get(&var_fn(n)) {
906 result.insert(var_fn(n + 1), v.clone());
907 }
908 }
909
910 result
911}
912
913pub fn set_shunting<K: Eq + Clone + Hash, V: Clone, F: Fn(usize) -> K>(
914 var_fn: &F,
915 value: V,
916 bindings: &HashMap<K, V>,
917) -> HashMap<K, V> {
918 let mut result = shunt_vars(var_fn, bindings);
919 result.insert(var_fn(1), value);
920 result
921}
922
923pub trait PreProp: Clone {
928 fn lift_to_prop(self, f: Box<dyn Fn(JboProp) -> JboProp + Send + Sync>) -> Self;
929 fn lift_to_prop2(self, other: Self, f: Box<dyn Fn(JboProp, JboProp) -> JboProp + Send + Sync>) -> Self;
930 fn dummy_pre_prop() -> Self;
931}
932
933impl PreProp for JboProp {
934 fn lift_to_prop(self, f: Box<dyn Fn(JboProp) -> JboProp + Send + Sync>) -> Self {
935 f(self)
936 }
937
938 fn lift_to_prop2(self, other: Self, f: Box<dyn Fn(JboProp, JboProp) -> JboProp + Send + Sync>) -> Self {
939 f(self, other)
940 }
941
942 fn dummy_pre_prop() -> Self {
943 Prop::Eet
944 }
945}
946
947impl PreProp for JboPred {
948 fn lift_to_prop(self, f: Box<dyn Fn(JboProp) -> JboProp + Send + Sync>) -> Self {
949 Arc::new(move |o: &JboTerm| f(self(o)))
950 }
951
952 fn lift_to_prop2(self, other: Self, f: Box<dyn Fn(JboProp, JboProp) -> JboProp + Send + Sync>) -> Self {
953 Arc::new(move |o: &JboTerm| f(self(o), other(o)))
954 }
955
956 fn dummy_pre_prop() -> Self {
957 Arc::new(|_| Prop::Eet)
958 }
959}
960
961impl PreProp for JboNPred {
962 fn lift_to_prop(self, f: Box<dyn Fn(JboProp) -> JboProp + Send + Sync>) -> Self {
963 let pred = self.pred;
964 JboNPred {
965 arity: self.arity,
966 pred: Arc::new(move |os: &[JboTerm]| f(pred(os))),
967 }
968 }
969
970 fn lift_to_prop2(self, other: Self, f: Box<dyn Fn(JboProp, JboProp) -> JboProp + Send + Sync>) -> Self {
971 if self.arity != other.arity {
972 panic!("mismatched JboNPred arities in lift_to_prop2");
973 }
974 let pred1 = self.pred;
975 let pred2 = other.pred;
976 JboNPred {
977 arity: self.arity,
978 pred: Arc::new(move |os: &[JboTerm]| f(pred1(os), pred2(os))),
979 }
980 }
981
982 fn dummy_pre_prop() -> Self {
983 JboNPred {
984 arity: 0,
985 pred: Arc::new(|_| Prop::Eet),
986 }
987 }
988}
989
990fn sub_term(old: &JboTerm, new: &JboTerm, prop: &JboProp) -> JboProp {
995 crate::jbo_prop::sub_term(old, new, prop.clone())
996}
997
998fn sub_rel(old: &JboRel, new: &JboRel, prop: &JboProp) -> JboProp {
999 crate::jbo_prop::sub_rel(old, new, prop.clone())
1000}
1001
1002fn jbo_pred_to_loj_pred(pred: &JboPred) -> Arc<dyn Fn(i32) -> JboProp + Send + Sync> {
1003 crate::jbo_prop::jbo_pred_to_loj_pred(pred)
1004}
1005
1006fn v_pred_to_pred(vpred: JboVPred) -> JboPred {
1007 crate::jbo_prop::v_pred_to_pred(vpred)
1008}
1009
1010
1011#[derive(Debug, Clone)]
1016pub enum Arg {
1017 Untagged(JboTerm),
1018 FATagged(usize, JboTerm),
1019 FAITagged(JboTerm),
1020}
1021
1022pub fn do_lambdas(vpred: JboVPred, parse_state: &mut ParseState) -> JboNPred {
1028 let ls = parse_state.lambdas.clone();
1029 let arity = ls.keys()
1030 .filter_map(|pos| if pos.level == 1 { Some(pos.num) } else { None })
1031 .max()
1032 .unwrap_or(0)
1033 .max(1);
1034
1035 shunt_lambdas(parse_state, -1);
1036
1037 JboNPred {
1038 arity: arity as usize,
1039 pred: Arc::new(move |os: &[JboTerm]| {
1040 let mut current: JboVPred = vpred.clone();
1041 for (idx, o) in os.iter().enumerate() {
1042 let num = (idx + 1) as i32;
1043 if let Some(v) = ls.get(&LambdaPos { level: 1, num }) {
1044 let previous = current.clone();
1045 let old = JboTerm::Var(*v);
1046 let new = o.clone();
1047 current = Arc::new(move |rest: &[JboTerm]| {
1048 crate::jbo_prop::sub_term(&old, &new, previous(rest))
1049 });
1050 } else {
1051 let previous = current.clone();
1052 let head = o.clone();
1053 current = Arc::new(move |rest: &[JboTerm]| {
1054 let mut args = vec![head.clone()];
1055 args.extend_from_slice(rest);
1056 previous(&args)
1057 });
1058 }
1059 }
1060 current(&[])
1061 }),
1062 }
1063}
1064
1065pub fn m_pred_to_v_dom(pred: Option<JboPred>) -> VariableDomain {
1072 match pred {
1073 Some(p) => VariableDomain::PredDomain(p),
1074 None => VariableDomain::UnrestrictedDomain,
1075 }
1076}
1077
1078pub fn get_sumbasti_binding(bs: &SumbastiBindings, atom: &SumtiAtom) -> JboTerm {
1081 let key_ref = Sumbasti { explicitly_assigned: true, atom: atom.clone() };
1082 if let Some(term) = bs.get(&key_ref) {
1083 return term.clone();
1084 }
1085 let key_unref = Sumbasti { explicitly_assigned: false, atom: atom.clone() };
1086 if let Some(term) = bs.get(&key_unref) {
1087 return term.clone();
1088 }
1089 JboTerm::UnboundSumbasti(atom.clone())
1090}
1091
1092pub fn get_bribasti_binding(bs: &BribastiBindings, tu: &TanruUnit) -> Bridi {
1095 if let Some(stored) = bs.get(tu) {
1096 let stored = stored.clone();
1097 return Box::new(move |args: &Args| stored(args));
1098 }
1099 let rel = match tu {
1100 TanruUnit::TUBrivla(s) => JboRel::Brivla(s.clone()),
1101 _ => JboRel::UnboundBribasti(tu.clone()),
1102 };
1103 jbo_rel_to_bridi(rel)
1104}
1105
1106pub fn add_side_texticule(side: Texticule, parse_state: &mut ParseState) {
1109 parse_state.side_texticules.insert(0, side);
1110}
1111
1112pub fn take_side_texticules(parse_state: &mut ParseState) -> Vec<Texticule> {
1115 let result = parse_state.side_texticules.clone();
1116 parse_state.side_texticules.clear();
1117 result
1118}
1119
1120pub fn add_sumti_question(
1123 kau: Option<i32>,
1124 dom: Option<&JboPred>,
1125 parse_state: &mut ParseState,
1126) -> JboTerm {
1127 let v_dom = match dom {
1128 Some(pred) => VariableDomain::PredDomain(pred.clone()),
1129 None => VariableDomain::UnrestrictedDomain,
1130 };
1131 let var = get_fresh_var(&v_dom, parse_state);
1132 let q_info = QInfo::QSumti(var.clone(), dom.cloned());
1133 let question = Question {
1134 kau_depth: kau,
1135 info: q_info,
1136 };
1137 parse_state.questions.insert(0, question);
1138 var
1139}
1140
1141pub fn add_bridi_question(kau: Option<i32>, parse_state: &mut ParseState) -> JboRel {
1144 let rvar = get_fresh_rvar(parse_state);
1145 let q_info = QInfo::QBridi(rvar.clone());
1146 let question = Question {
1147 kau_depth: kau,
1148 info: q_info,
1149 };
1150 parse_state.questions.push(question);
1151 rvar
1152}
1153
1154fn get_fresh_var(dom: &VariableDomain, parse_state: &mut ParseState) -> JboTerm {
1156 let v = parse_state.next_fresh_var;
1157 parse_state.next_fresh_var += 1;
1158 parse_state.variable_domains.insert(v, dom.clone());
1159 JboTerm::Var(v)
1160}
1161
1162fn get_fresh_rvar(parse_state: &mut ParseState) -> JboRel {
1164 let v = parse_state.next_fresh_rvar;
1165 parse_state.next_fresh_rvar += 1;
1166 JboRel::RVar(v)
1167}
1168
1169pub fn advance_arg_pos_to_selbri(bridi_state: &mut BridiParseState) {
1176 if bridi_state.arglist.args.is_empty() {
1177 bridi_state.arglist.position = 2;
1178 }
1179}
1180
1181pub fn ignoring_args<F, R>(bridi_state: &mut BridiParseState, f: F) -> R
1184where
1185 F: FnOnce(&mut BridiParseState) -> R,
1186{
1187 let saved_arglist = bridi_state.arglist.clone();
1188 let result = f(bridi_state);
1189 bridi_state.arglist = saved_arglist;
1190 result
1191}
1192
1193pub fn update_referenced(term: &JboTerm, parse_state: &mut ParseState) {
1196 if let JboTerm::Var(n) = term {
1197 parse_state.referenced_vars.insert(*n);
1198 }
1199}
1200
1201pub fn do_assigns(
1204 term: JboTerm,
1205 assigns: &[Either<SumtiAtom, JboTerm>],
1206 parse_state: &mut ParseState,
1207) -> JboTerm {
1208 let mut result = term;
1209 for assign in assigns {
1210 result = do_assign(result, assign, parse_state);
1211 }
1212 result
1213}
1214
1215pub fn do_assign(
1218 term: JboTerm,
1219 assign: &Either<SumtiAtom, JboTerm>,
1220 parse_state: &mut ParseState,
1221) -> JboTerm {
1222 match (&term, assign) {
1223 (JboTerm::UnboundSumbasti(a), Either::Right(assto)) if is_assignable(a) => {
1224 let key = Sumbasti {
1225 explicitly_assigned: true,
1226 atom: a.clone(),
1227 };
1228 parse_state.sumbasti_bindings.insert(key, assto.clone());
1229 assto.clone()
1230 }
1231 (_, Either::Left(ass)) => {
1232 let key = Sumbasti {
1233 explicitly_assigned: true,
1234 atom: ass.clone(),
1235 };
1236 parse_state.sumbasti_bindings.insert(key, term.clone());
1237 term
1238 }
1239 _ => term,
1240 }
1241}
1242
1243fn is_assignable(atom: &SumtiAtom) -> bool {
1246 matches!(
1247 atom,
1248 SumtiAtom::Assignable(_) | SumtiAtom::LerfuString(_) | SumtiAtom::Name(_, _, _)
1249 )
1250}
1251
1252#[derive(Debug, Clone)]
1254pub enum Either<L, R> {
1255 Left(L),
1256 Right(R),
1257}
1258
1259pub fn do_incidentals(
1262 term: JboTerm,
1263 incidentals: &[JboPred],
1264 parse_state: &mut ParseState,
1265) -> JboTerm {
1266 let Some(pred) = crate::jbo_prop::and_m_pred(incidentals.to_vec()) else {
1267 return term;
1268 };
1269
1270 let (pred, term) = quantify_out_frees(true, pred, term, parse_state);
1271 let prop = pred(&term);
1272 extract_non_veridical(&prop, &term, parse_state);
1273 parse_state.add_side_texticule(Texticule::TexticuleProp(prop));
1274 term
1275}
1276
1277fn quantify_out_frees(
1278 add_params: bool,
1279 pred: JboPred,
1280 term: JboTerm,
1281 parse_state: &mut ParseState,
1282) -> (JboPred, JboTerm) {
1283 let frees = crate::jbo_prop::free_vars(&pred(&term));
1284 if frees.is_empty() {
1285 return (pred, term);
1286 }
1287
1288 let term = if add_params {
1289 match term {
1290 JboTerm::Constant(n, params) => {
1291 let mut new_params = frees.iter().rev().cloned().collect::<Vec<_>>();
1292 new_params.extend(params);
1293 JboTerm::Constant(n, new_params)
1294 }
1295 other => other,
1296 }
1297 } else {
1298 term
1299 };
1300
1301 let mut pred = pred;
1302 for free in frees {
1303 let domain = match free {
1304 JboTerm::Var(n) => parse_state.variable_domains.get(&n).cloned().unwrap_or(VariableDomain::UnrestrictedDomain),
1305 _ => VariableDomain::UnrestrictedDomain,
1306 };
1307 pred = quantify_out_free(pred, free, domain);
1308 }
1309
1310 quantify_out_frees(false, pred, term, parse_state)
1311}
1312
1313fn quantify_out_free(pred: JboPred, free: JboTerm, domain: VariableDomain) -> JboPred {
1314 Arc::new(move |x: &JboTerm| {
1315 let body = pred(x);
1316 let free_for_body = free.clone();
1317 let restriction = restr_of_domain(domain.clone());
1318 Prop::Quantified(
1319 JboQuantifier::LojQuantifier(crate::logic::LojQuantifier::Forall),
1320 restriction.map(|r| {
1321 Arc::new(move |v: i32| r(&JboTerm::BoundVar(v))) as Arc<dyn Fn(i32) -> JboProp + Send + Sync>
1322 }),
1323 Arc::new(move |v: i32| crate::jbo_prop::sub_term(&free_for_body, &JboTerm::BoundVar(v), body.clone())),
1324 )
1325 })
1326}
1327
1328fn restr_of_domain(domain: VariableDomain) -> Option<JboPred> {
1329 match domain {
1330 VariableDomain::UnrestrictedDomain => None,
1331 VariableDomain::PredDomain(pred) => Some(pred),
1332 VariableDomain::FiniteDomain(os) => {
1333 let first = os.first()?.clone();
1334 let rest = os[1..].to_vec();
1335 Some(Arc::new(move |x: &JboTerm| {
1336 rest.iter().rev().fold(
1337 Prop::Rel(JboRel::Equal, vec![x.clone(), first.clone()]),
1338 |acc, o| Prop::Connected(
1339 crate::logic::Connective::Or,
1340 Box::new(Prop::Rel(JboRel::Equal, vec![x.clone(), o.clone()])),
1341 Box::new(acc),
1342 ),
1343 )
1344 }))
1345 }
1346 }
1347}
1348
1349fn extract_non_veridical(prop: &JboProp, _term: &JboTerm, parse_state: &mut ParseState) {
1351 if let Prop::Modal(JboModalOp::NonVeridical, inner) = prop {
1352 parse_state.non_veridical_props.push(inner.as_ref().clone());
1353 }
1354}
1355
1356pub fn apply_transform_list(transforms: Vec<PropTransform>, mut prop: JboProp) -> JboProp {
1357 for transform in transforms.into_iter().rev() {
1358 prop = apply_transform(transform, prop);
1359 }
1360 prop
1361}
1362
1363fn continuation_args_from_prop(prop: &JboProp, start_position: i32) -> Args {
1364 let Prop::Rel(_, terms) = prop else {
1365 return Args::new();
1366 };
1367 terms
1368 .iter()
1369 .enumerate()
1370 .filter_map(|(idx, term)| {
1371 let position = idx as i32 + 1;
1372 if position >= start_position {
1373 Some((ArgPos::UnfilledPos(position - start_position), term.clone()))
1374 } else {
1375 None
1376 }
1377 })
1378 .collect()
1379}
1380
1381fn fill_args_in_prop(prop: JboProp, args: &Args) -> JboProp {
1382 let terms = args_to_jboterms(args);
1383 match prop {
1384 Prop::Rel(rel, _) => Prop::Rel(rel, terms),
1385 Prop::Not(p) => Prop::Not(Box::new(fill_args_in_prop(*p, args))),
1386 Prop::Connected(c, p1, p2) => Prop::Connected(
1387 c,
1388 Box::new(fill_args_in_prop(*p1, args)),
1389 Box::new(fill_args_in_prop(*p2, args)),
1390 ),
1391 Prop::NonLogConnected(j, p1, p2) => Prop::NonLogConnected(
1392 j,
1393 Box::new(fill_args_in_prop(*p1, args)),
1394 Box::new(fill_args_in_prop(*p2, args)),
1395 ),
1396 Prop::Modal(m, p) => Prop::Modal(m, Box::new(fill_args_in_prop(*p, args))),
1397 Prop::Quantified(q, pred, body) => {
1398 let args = args.clone();
1399 Prop::Quantified(q, pred, Arc::new(move |v| fill_args_in_prop(body(v), &args)))
1400 }
1401 Prop::Eet => Prop::Eet,
1402 }
1403}
1404
1405fn apply_transform(transform: PropTransform, prop: JboProp) -> JboProp {
1407 match transform {
1408 PropTransform::Quantify(fresh_var, quantifier, restriction) => {
1409 if let JboTerm::Var(n) = fresh_var {
1410 let pred = restriction.map(|f| {
1411 Arc::new(move |v: i32| f(v)) as Arc<dyn Fn(i32) -> JboProp + Send + Sync>
1412 });
1413 Prop::Quantified(
1414 quantifier,
1415 pred,
1416 Arc::new(move |v: i32| crate::jbo_prop::sub_term(&JboTerm::Var(n), &JboTerm::BoundVar(v), prop.clone()))
1417 )
1418 } else {
1419 prop
1420 }
1421 }
1422 PropTransform::ConnectQuantify { conn, fresh, left_quant, right_quant, restriction } => {
1423 let left_fresh = fresh.clone();
1424 let left_prop = prop.clone();
1425 let left_restriction = restriction.clone();
1426 let left = Prop::Quantified(
1427 left_quant,
1428 left_restriction,
1429 Arc::new(move |v: i32| crate::jbo_prop::sub_term(&left_fresh, &JboTerm::BoundVar(v), left_prop.clone())),
1430 );
1431 let right = Prop::Quantified(
1432 right_quant,
1433 restriction,
1434 Arc::new(move |v: i32| crate::jbo_prop::sub_term(&fresh, &JboTerm::BoundVar(v), prop.clone())),
1435 );
1436 crate::jbo_prop::conn_to_fol(&conn, left, right)
1437 }
1438 PropTransform::ConnectQuantifyTagged { conn, fresh, left_quant, right_quant, restriction, event_fresh, left_modal, right_modal } => {
1439 let left_fresh = fresh.clone();
1440 let left_prop = prop.clone();
1441 let left_restriction = restriction.clone();
1442 let left = Prop::Quantified(
1443 left_quant,
1444 left_restriction,
1445 Arc::new(move |v: i32| crate::jbo_prop::sub_term(&left_fresh, &JboTerm::BoundVar(v), left_prop.clone())),
1446 );
1447 let left = if let Some(modal) = left_modal {
1448 Prop::Modal(modal, Box::new(left))
1449 } else {
1450 left
1451 };
1452 let right = Prop::Quantified(
1453 right_quant,
1454 restriction,
1455 Arc::new(move |v: i32| crate::jbo_prop::sub_term(&fresh, &JboTerm::BoundVar(v), prop.clone())),
1456 );
1457 let right = if let Some(modal) = right_modal {
1458 Prop::Modal(modal, Box::new(right))
1459 } else {
1460 right
1461 };
1462 let connected = crate::jbo_prop::conn_to_fol(&conn, left, right);
1463 if let Some(JboTerm::Var(n)) = event_fresh {
1464 Prop::Quantified(
1465 JboQuantifier::LojQuantifier(crate::logic::LojQuantifier::Exists),
1466 None,
1467 Arc::new(move |v: i32| crate::jbo_prop::sub_term(&JboTerm::Var(n), &JboTerm::BoundVar(v), connected.clone()))
1468 )
1469 } else {
1470 connected
1471 }
1472 }
1473 PropTransform::RQuantify(fresh_rel, quantifier) => {
1474 Prop::Quantified(
1475 quantifier,
1476 None,
1477 Arc::new(move |v: i32| crate::jbo_prop::sub_rel(&fresh_rel, &JboRel::BoundRVar(v), prop.clone()))
1478 )
1479 }
1480 PropTransform::SubstituteTerm(old_term, new_term) => crate::jbo_prop::sub_term(&old_term, &new_term, prop),
1481 PropTransform::LogicalConnectBranches { conn, fresh, left_term, left_transforms, right_term, right_transforms } => {
1482 let left_base = crate::jbo_prop::sub_term(&fresh, &left_term, prop.clone());
1483 let right_base = crate::jbo_prop::sub_term(&fresh, &right_term, prop);
1484 let left = apply_transform_list(left_transforms, left_base);
1485 let right = apply_transform_list(right_transforms, right_base);
1486 crate::jbo_prop::conn_to_fol(&conn, left, right)
1487 }
1488 PropTransform::ConnectBranches { conn, left_args, right_args, continuation_position, left_transforms, right_transforms, outer_transforms } => {
1489 let continuation_args = continuation_args_from_prop(&prop, continuation_position);
1490 let left_args = join_args(&continuation_args, &left_args);
1491 let right_args = join_args(&continuation_args, &right_args);
1492 let left = apply_transform_list(left_transforms, fill_args_in_prop(prop.clone(), &left_args));
1493 let right = apply_transform_list(right_transforms, fill_args_in_prop(prop, &right_args));
1494 let connected = match conn {
1495 crate::jbo_syntax::Connective::JboConnLog(_, lcon) => crate::jbo_prop::conn_to_fol(&lcon, left, right),
1496 crate::jbo_syntax::Connective::JboConnJoik(_, joik) => crate::jbo_prop::joik_to_fol(joik, left, right),
1497 };
1498 apply_transform_list(outer_transforms, connected)
1499 }
1500 PropTransform::ConnectTagBranches { conn, left_transforms, right_transforms } => {
1501 let left = apply_transform_list(left_transforms, prop.clone());
1502 let right = apply_transform_list(right_transforms, prop);
1503 match conn {
1504 crate::jbo_prop::JboConnective::JboConnLog(_, lcon) => crate::jbo_prop::conn_to_fol(&lcon, left, right),
1505 crate::jbo_prop::JboConnective::JboConnJoik(_, joik) => crate::jbo_prop::joik_to_fol(joik, left, right),
1506 }
1507 }
1508 PropTransform::Negate => Prop::Not(Box::new(prop)),
1509 PropTransform::ApplyModal(modal_op) => Prop::Modal(modal_op, Box::new(prop)),
1510 }
1511}
1512
1513impl std::fmt::Debug for PropTransform {
1514 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1515 match self {
1516 PropTransform::Quantify(term, quant, _) => write!(f, "Quantify({:?}, {:?}, <fn>)", term, quant),
1517 PropTransform::ConnectQuantify { conn, fresh, .. } => write!(f, "ConnectQuantify({:?}, {:?})", conn, fresh),
1518 PropTransform::ConnectQuantifyTagged { conn, fresh, .. } => write!(f, "ConnectQuantifyTagged({:?}, {:?})", conn, fresh),
1519 PropTransform::RQuantify(rel, quant) => write!(f, "RQuantify({:?}, {:?})", rel, quant),
1520 PropTransform::SubstituteTerm(old_term, new_term) => write!(f, "SubstituteTerm({:?}, {:?})", old_term, new_term),
1521 PropTransform::LogicalConnectBranches { conn, fresh, left_term, right_term, .. } => write!(f, "LogicalConnectBranches({:?}, {:?}, {:?}, {:?})", conn, fresh, left_term, right_term),
1522 PropTransform::ConnectBranches { conn, .. } => write!(f, "ConnectBranches({:?})", conn),
1523 PropTransform::ConnectTagBranches { conn, .. } => write!(f, "ConnectTagBranches({:?})", conn),
1524 PropTransform::Negate => write!(f, "Negate"),
1525 PropTransform::ApplyModal(op) => write!(f, "ApplyModal({:?})", op),
1526 }
1527 }
1528}